2014-07-03 64 views
0

作爲一種學習練習,我使用AudioQueue來生成並播放300 Hz的正弦波。 (據我所知,有各種工具可以生成和播放音頻,但是,這只是構建我的Core Audio音色,並且這個任務都是關於AudioQueue的。)簡單的AudioQueue正弦波 - 爲什麼失真?

音樂播放,但帶有失真。記錄和繪製聲音表明,在緩衝區邊界處(每半秒)有一些失真,除此之外還有其他短暫的失真突發。我已經在下面包含了我的代碼。如果有人能夠解決這個問題,那將是驚人的 - 感謝閱讀!

編輯:發現問題。它應該讀取bufferByteSize = numPacketsForTime * asbd.mBytesPerPacket;

static void MyAQOutputCallback(void *inUserData, 
           AudioQueueRef inAQ, 
           AudioQueueBufferRef inCompleteAQBuffer){ 

    int i; 
    MyWave *inData=(MyWave*)inUserData; 

    // synth params 
    int phaseL =inData->sampleCount; 
    float FL = (2.0 * 3.14159265 * 300.0)/44100.0; 
    float amp = 0.5; 
    int frameCount=22050; 

    // Get the info struct and a pointer to our output data 
    short *coreAudioBuffer = (short*) inCompleteAQBuffer->mAudioData; 

    // Need to set this 
    inCompleteAQBuffer->mAudioDataByteSize = 2*frameCount; // two shorts per frame, one frame per packet 
    // For each frame/packet (the same in our example) 
    for(i=0;i<frameCount;i++) { 
     // Render the sine waves - signed interleaved shorts (-32767 -> 32767), 16 bit stereo 
     float sampleL = (amp * sin(FL * (float)phaseL)); 
     short sampleIL = (int)(sampleL * 32767.0); 
     coreAudioBuffer[i ] = sampleIL; 
     phaseL++; 
    } 
    // "Enqueue" the buffer 
    AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL); 
    inData->sampleCount=phaseL; 


} 

int main(int argc, const char * argv[]) 
{ 

    // Open an audio file 
    MyWave thisWave={0}; 
    // Set up format 
    AudioStreamBasicDescription asbd; 
    memset(&asbd,0,sizeof(asbd)); 
    asbd.mSampleRate=SAMPLE_RATE; 
    asbd.mFormatID=kAudioFormatLinearPCM; 
    asbd.mFormatFlags=kLinearPCMFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked; 
    asbd.mBitsPerChannel=16; 
    asbd.mChannelsPerFrame=1; 
    asbd.mFramesPerPacket=1; 
    asbd.mBytesPerFrame=2; 
    asbd.mBytesPerPacket=2; 

    // Set up queue 
    AudioQueueRef queue; 
    CheckError(AudioQueueNewOutput(&asbd, 
            MyAQOutputCallback, 
            &thisWave, 
            NULL, 
            NULL, 
            0, 
            &queue), 
       "AudioQueueNewOutput failed"); 

    UInt32 bufferByteSize; 
    Float64 numPacketsForTime=asbd.mSampleRate/asbd.mFramesPerPacket*0.5; 
    bufferByteSize=numPacketsForTime; 
    AudioQueueBufferRef buffers[kNumberPlaybackBuffers]; 
    int i; 
    for (i=0;i<kNumberPlaybackBuffers;++i){ 
     CheckError(AudioQueueAllocateBuffer(queue, 
              bufferByteSize, 
              &buffers[i]), 
        "AudioQueueAllocateBuffer failed"); 
     MyAQOutputCallback(&thisWave, queue, buffers[i]); 
    } 


    // Start queue 
    CheckError(AudioQueueStart(queue, 
           NULL), 
       "AudioQueueStart failed"); 
    printf("Playing...\n"); 
    do 
    { 
     CFRunLoopRunInMode(kCFRunLoopDefaultMode, 
          0.25, 
          false); 
    }while (1==1); 
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2, false); 

    // Clean up queue when finished 
    CheckError(AudioQueueStop(queue, 
           TRUE), 
       "AudioQueueStop failed"); 
    AudioQueueDispose(queue, TRUE); 
    return 0; 
} 

回答

0

發現問題,應改爲:

bufferByteSize = numPacketsForTime*asbd.mBytesPerPacket; 

在這裏我要離開這個了,因爲有人可能會覺得有用的代碼!