2014-07-03 30 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; 

在这里我要离开这个了,因为有人可能会觉得有用的代码!