How do I synthesize sounds with CoreAudio on iPhone/Mac

后端 未结 3 621
清歌不尽
清歌不尽 2021-01-30 05:38

I\'d like to play a synthesised sound in an iPhone. Instead of using a pre-recorded sound and using SystemSoundID to play an existing binary, I\'d like to synthesise it. Partial

3条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-01-30 06:33

    What you want to do it probably to setup an AudioQueue. It allows you to fill a buffer with synthesized audio data in a callback. You would setup the AudeioQueue to run in a new thread as such:

    #define BUFFER_SIZE 16384
    #define BUFFER_COUNT 3
    static AudioQueueRef audioQueue;
    void SetupAudioQueue() {
        OSStatus err = noErr;
        // Setup the audio device.
        AudioStreamBasicDescription deviceFormat;
        deviceFormat.mSampleRate = 44100;
        deviceFormat.mFormatID = kAudioFormatLinearPCM;
        deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
        deviceFormat.mBytesPerPacket = 4;
        deviceFormat.mFramesPerPacket = 1;
        deviceFormat.mBytesPerFrame = 4;
        deviceFormat.mChannelsPerFrame = 2;
        deviceFormat.mBitsPerChannel = 16;
        deviceFormat.mReserved = 0;
        // Create a new output AudioQueue for the device.
        err = AudioQueueNewOutput(&deviceFormat, AudioQueueCallback, NULL,
                                  CFRunLoopGetCurrent(), kCFRunLoopCommonModes,
                                  0, &audioQueue);
        // Allocate buffers for the AudioQueue, and pre-fill them.
        for (int i = 0; i < BUFFER_COUNT; ++i) {
            AudioQueueBufferRef mBuffer;
            err = AudioQueueAllocateBuffer(audioQueue, BUFFER_SIZE, mBuffer);
            if (err != noErr) break;
            AudioQueueCallback(NULL, audioQueue, mBuffer);
        }
        if (err == noErr) err = AudioQueueStart(audioQueue, NULL);
        if (err == noErr) CFRunLoopRun();
      }
    

    You callback method AudioQueueCallback will then be called whenever the AudioQueue needs more data. Implement with something like:

    void AudioQueueCallback(void* inUserData, AudioQueueRef inAQ,
                            AudioQueueBufferRef inBuffer) {
        void* pBuffer = inBuffer->mAudioData;
        UInt32 bytes = inBuffer->mAudioDataBytesCapacity;
        // Write max  bytes of audio to 
        outBuffer->mAudioDataByteSize = actualNumberOfBytesWritten
        err = AudioQueueEnqueueBuffer(audioQueue, inBuffer, 0, NULL);
    }
    

提交回复
热议问题