简单的 AudioQueue 正弦波——为啥会失真?

Posted

技术标签:

【中文标题】简单的 AudioQueue 正弦波——为啥会失真?【英文标题】:Simple AudioQueue sine wave—why the distortion?简单的 AudioQueue 正弦波——为什么会失真? 【发布时间】:2014-07-03 10:58:37 【问题描述】:

作为学习练习,我使用 AudioQueue 来生成和播放 300 Hz 正弦波。 (我知道有多种工具可以生成和播放音频,但是是的,这只是为了建立我的核心音频印章,而这个任务就是关于音频队列的。)

波浪播放,但失真。记录和绘制声音显示缓冲区之间的边界处存在一些失真(每半秒),此外还有其他短暂的失真突发。我在下面包含了我的代码。如果有人能对这个问题有所了解,那就太棒了——感谢阅读!

编辑:发现问题。它应该读取 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;

【问题讨论】:

【参考方案1】:

发现问题,应该是:

 bufferByteSize = numPacketsForTime*asbd.mBytesPerPacket;

我将把它留在这里,因为有人可能会发现代码很有用!

【讨论】:

您的帖子很有帮助。就我而言,我错过了指定 mAudioDataByteSize 所以回调永远不会被调用,可能是因为 AQ 在看到空缓冲区时退出。

以上是关于简单的 AudioQueue 正弦波——为啥会失真?的主要内容,如果未能解决你的问题,请参考以下文章

用FPGA产生正弦波

OpenAL 失真的常见来源?

在mac上生成音调/正弦波的简单方法? (红宝石会很好)

使用 AudioQueue 在 iOS 上进行失真(机器人)音频录制

PWM波经过RC低通滤波器后得到的为啥是正弦波?

[Matlab]在信号调幅过程中用方波进行调幅还是正弦波?为啥?