iOSaudio单元在某些频率之上切断声音

我收到声音(UDP WiFi)有一些问题,我想尽可能多地清除它。 所以在开始的时候,我想把一些频率以上的声音切断。 很明显,我从套接字获得原始数据,然后将其复制到输出缓冲区。 我敢肯定,确切的切断应该在那里完成。

你能build议我吗?

我目前的callback代码

static OSStatus outputCallback(void *udata, AudioUnitRenderActionFlags *flags, const AudioTimeStamp *ts, UInt32 busnum, UInt32 nframes, AudioBufferList *buflist) { NXAudioDevice *dev = (__bridge NXAudioDevice *) udata; AudioBuffer *buf = buflist->mBuffers; // Here I get new audioBufferData NSData *data = [dev getAudioData]; if (!data) { buf->mDataByteSize = 0; return -1; } else { [data getBytes:buf->mData length:buf->mDataByteSize]; } return noErr; } 

UPDATE

我发现这样的rendercallback,atm我想为outputCallback添加类似的东西。

 OSStatus RenderFFTCallback (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { RIOInterface* THIS = (RIOInterface *)inRefCon; COMPLEX_SPLIT A = THIS->A; void *dataBuffer = THIS->dataBuffer; float *outputBuffer = THIS->outputBuffer; FFTSetup fftSetup = THIS->fftSetup; uint32_t log2n = THIS->log2n; uint32_t n = THIS->n; uint32_t nOver2 = THIS->nOver2; uint32_t stride = 1; int bufferCapacity = THIS->bufferCapacity; SInt16 index = THIS->index; AudioUnit rioUnit = THIS->ioUnit; OSStatus renderErr; UInt32 bus1 = 1; renderErr = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, bus1, inNumberFrames, THIS->bufferList); if (renderErr < 0) { return renderErr; } // Fill the buffer with our sampled data. If we fill our buffer, run the // fft. int read = bufferCapacity - index; if (read > inNumberFrames) { memcpy((SInt16 *)dataBuffer + index, THIS->bufferList->mBuffers[0].mData, inNumberFrames*sizeof(SInt16)); THIS->index += inNumberFrames; } else { // If we enter this conditional, our buffer will be filled and we should // perform the FFT. memcpy((SInt16 *)dataBuffer + index, THIS->bufferList->mBuffers[0].mData, read*sizeof(SInt16)); // Reset the index. THIS->index = 0; /*************** FFT ***************/ // We want to deal with only floating point values here. ConvertInt16ToFloat(THIS, dataBuffer, outputBuffer, bufferCapacity); /** Look at the real signal as an interleaved complex vector by casting it. Then call the transformation function vDSP_ctoz to get a split complex vector, which for a real signal, divides into an even-odd configuration. */ vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2); // Carry out a Forward FFT transform. vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD); // The output signal is now in a split real form. Use the vDSP_ztoc to get // a split real vector. vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2); // Determine the dominant frequency by taking the magnitude squared and // saving the bin which it resides in. float dominantFrequency = 0; int bin = -1; for (int i=0; i<n; i+=2) { float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]); if (curFreq > dominantFrequency) { dominantFrequency = curFreq; bin = (i+1)/2; } } memset(outputBuffer, 0, n*sizeof(SInt16)); // Update the UI with our newly acquired frequency value. [THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)]; printf("Dominant frequency: %f bin: %d \n", bin*(THIS->sampleRate/bufferCapacity), bin); } return noErr; } 

这并不像看起来那么简单。 一种方法是使用FFT将数据移入频域,去除高频,然后利用反向FFT返回到时域。 在iOS中有FFTfunction。 请参见使用傅立叶变换vDSP编程指南 。

一个起点是苹果公司的示例代码aurioTouch2 。

在回答一个评论:一个字节没有一个频率,只是一个幅度(响度)。 基本上有以44100Hz的周期性频率的幅度采样。 低通audio的一个天真的方法是删除所有其他的样本,但这是行不通的,它只是将较高的频率混淆成较低的频率。

你可以使用AudioUnit来做到这一点:

 @constant kAudioUnitSubType_LowPassFilter A filter that passes frequencies below a specified cut-off frequency @constant kAudioUnitSubType_HighPassFilter A filter that passes frequencies above a specified cut-off frequency @constant kAudioUnitSubType_BandPassFilter A filter that passes frequencies between a low and high cut-off frequency.