在ObjectiveC中连接audio缓冲区

首先我是c和c的新蜜蜂

我尝试去掉一个audio缓冲区并绘制它的graphics。 我使用audio单元callback来获取audio缓冲区。 callback带来了512帧,但471帧后,它带来0.(我不知道这是正常的,它用来带471帧充满数字,但现在不知怎的512帧47之后0。请让我知道如果这是正常的)

无论如何。 我可以从callback中获取缓冲区,应用fft并绘制它。 这工作完美。 下面是结果。 只要我在每个callback中获得缓冲区,graphics就非常平滑

在这里输入图像说明

但在我的情况下,我需要3秒的缓冲区,以应用fft和绘制。 所以我尝试连接来自两个callback的缓冲区,然后应用fft并绘制它。 但结果并不像我所期望的那样。 而上面的一个在logging过程中非常stream畅和精确(只有在18和19 kHz的幅度变化),当我连接两个缓冲区时,仿真器主要显示两个不同的视图,它们之间交换的速度非常快。 他们显示在下面。 当然,他们基本上显示18和19千赫兹。 但我需要精确的khz,所以我可以为我工作的应用程序应用更多的algorithm。

在这里输入图像说明在这里输入图像说明

这是我的代码在callback

//FFTInputBufferLen, FFTInputBufferFrameIndex is gloabal //also tempFilteredBuffer is allocated in global //by the way FFTInputBufferLen = 1024; static OSStatus performRender (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { UInt32 bus1 = 1; CheckError(AudioUnitRender(effectState.rioUnit, ioActionFlags, inTimeStamp, bus1, inNumberFrames, ioData), "Couldn't render from RemoteIO unit"); Float32 * renderBuff = ioData->mBuffers[0].mData; ViewController *vc = (__bridge ViewController *) inRefCon; // inNumberFrames comes 512 as I described above for (int i = 0; i < inNumberFrames ; i++) { //I defined InputBuffers[5] in global. //then added 5 Float32 InputBuffers and allocated in global InputBuffers[bufferCount][FFTInputBufferFrameIndex] = renderBuff[i]; FFTInputBufferFrameIndex ++; if(FFTInputBufferFrameIndex == FFTInputBufferLen) { int bufCount = bufferCount; dispatch_async( dispatch_get_main_queue(), ^{ tempFilteredBuffer = [vc FilterData_rawSamples:InputBuffers[bufCount] numSamples:FFTInputBufferLen]; [vc CalculateFFTwithPlotting_Data:tempFilteredBuffer NumberofSamples:FFTInputBufferLen ]; free(InputBuffers[bufCount]); InputBuffers[bufCount] = (Float32*)malloc(sizeof(Float32) * FFTInputBufferLen); }); FFTInputBufferFrameIndex = 0; bufferCount ++; if (bufferCount == 5) { bufferCount = 0; } } } return noErr; } 

这里是我的AudioUnit设置

 - (void)setupIOUnit { AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AudioComponent comp = AudioComponentFindNext(NULL, &desc); CheckError(AudioComponentInstanceNew(comp, &_rioUnit), "couldn't create a new instance of AURemoteIO"); UInt32 one = 1; CheckError(AudioUnitSetProperty(_rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof(one)), "could not enable input on AURemoteIO"); // I removed this in order to not getting recorded audio back on speakers! Am I right? //CheckError(AudioUnitSetProperty(_rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &one, sizeof(one)), "could not enable output on AURemoteIO"); UInt32 maxFramesPerSlice = 4096; CheckError(AudioUnitSetProperty(_rioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(UInt32)), "couldn't set max frames per slice on AURemoteIO"); UInt32 propSize = sizeof(UInt32); CheckError(AudioUnitGetProperty(_rioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, &propSize), "couldn't get max frames per slice on AURemoteIO"); AudioUnitElement bus1 = 1; AudioStreamBasicDescription myASBD; myASBD.mSampleRate = 44100; myASBD.mChannelsPerFrame = 1; myASBD.mFormatID = kAudioFormatLinearPCM; myASBD.mBytesPerFrame = sizeof(Float32) * myASBD.mChannelsPerFrame ; myASBD.mFramesPerPacket = 1; myASBD.mBytesPerPacket = myASBD.mFramesPerPacket * myASBD.mBytesPerFrame; myASBD.mBitsPerChannel = sizeof(Float32) * 8 ; myASBD.mFormatFlags = 9 | 12 ; // I also remove this for not getting audio back!! // CheckError(AudioUnitSetProperty (_rioUnit, // kAudioUnitProperty_StreamFormat, // kAudioUnitScope_Input, // bus0, // &myASBD, // sizeof (myASBD)), "Couldn't set ASBD for RIO on input scope / bus 0"); CheckError(AudioUnitSetProperty (_rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, bus1, &myASBD, sizeof (myASBD)), "Couldn't set ASBD for RIO on output scope / bus 1"); effectState.rioUnit = _rioUnit; AURenderCallbackStruct renderCallback; renderCallback.inputProc = performRender; renderCallback.inputProcRefCon = (__bridge void *)(self); CheckError(AudioUnitSetProperty(_rioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(renderCallback)), "couldn't set render callback on AURemoteIO"); CheckError(AudioUnitInitialize(_rioUnit), "couldn't initialize AURemoteIO instance"); } 

我的问题是:为什么会发生这种情况,当我连接两个缓冲区时,为什么有两个主要不同的输出视图。 还有另一种收集缓冲区和应用DSP的方法吗? 我做错了什么! 如果我连接的方式是正确的,我的逻辑是不正确的? (虽然我多次查过)

在这里我试着说:如何在完美的状态下获得3 sn的缓冲区

我真的需要帮助,最好的问候

您的呈现callback可能会将数据写入到正在另一个线程(主队列)中处理的同一个缓冲区中,从而覆盖和更改正在处理的部分数据。

尝试使用多个缓冲区。 不要写入正在处理的缓冲区(通过你的filter&fft方法)。 FFT计算方法结束后,可能需要重新使用缓冲区才能重新使用。

我已成功cancatenated没有任何不稳定的graphics的缓冲区。 我怎么做才是从logging转换AVAudioSession类别到PlayAndRecord。 那么我已经注释掉了两个AudioUnitSetProperty行。 那么我开始得到每个渲染470〜471帧。 那么我喜欢他们就像我已经发布的代码。 我也在代码中使用了缓冲区。 现在起作用了。 但现在它通过声音播放。 为了closures它,我使用了下面的代码

 for (UInt32 i=0; i<ioData->mNumberBuffers; ++i) { memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize); } 

然后我开始得到3秒的缓冲区。 当我将其绘制在屏幕上时,我得到了第一张图的相似视图