简单的 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 正弦波——为啥会失真?的主要内容,如果未能解决你的问题,请参考以下文章