4

vDSP_zripとAudioUnitの使用法と構成に問題があります。実際、パックされたデータをfloatとして保存するようにAudioUnitを構成しました。循環バッファーを作成し、このバッファーがいっぱいになると、fftを計算します。結果はありますが、fft出力が悪い理由がわかりません(図を参照)

AudioUnit構成:

// describe format
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate       = 44100;
audioFormat.mFormatID         = kAudioFormatLinearPCM;
audioFormat.mFormatFlags      = kAudioFormatFlagsNativeEndian|kAudioFormatFlagIsPacked|kAudioFormatFlagIsFloat|kAudioFormatFlagIsNonInterleaved;
audioFormat.mFramesPerPacket  = 1;
audioFormat.mChannelsPerFrame = 1; // mono
audioFormat.mBitsPerChannel   = sizeof(float) * 8;
audioFormat.mBytesPerFrame    = audioFormat.mChannelsPerFrame * sizeof(float);
audioFormat.mBytesPerPacket   = audioFormat.mFramesPerPacket * audioFormat.mBytesPerFrame;

循環バッファ:

_audioSample = new AudioSample(8192, 44100);
// in recording callback :
for(int i = 0; i < bufferList.mNumberBuffers; ++i)
{
    if(!status)
    {
        if(_sample->needData())
            _sample->put((float*)bufferList.mBuffers[i].mData,
                    bufferList.mBuffers[i].mDataByteSize);
        [...]
    }
}

vDSP呼び出し:

  // get a split complex vector (real signal divided into an even-odd config
  vDSP_ctoz((COMPLEX *)sample.get(), 2, &_complex, 1, _fftsize);
  vDSP_fft_zrip(_fftsetup, &_complex, 1, _log2n, kFFTDirection_Forward);
  // scale (from vDSP reference)
  float scale = 1.0 / (2.0 * _samples);
  vDSP_vsmul(_complex.realp, 1, &scale, _complex.realp, 1, _fftsize);
  vDSP_vsmul(_complex.imagp, 1, &scale, _complex.imagp, 1, _fftsize);
  _complex.imagp[0] = 0.0;

どこ_fftsize = _audioSample.capacity()/2

形

4

1 に答える 1

9

あなたの出力はかなり合理的に見えるので、私はあなたの質問を「これらの結果をどのようにクリーンアップするのですか?」

1)おそらく長方形のウィンドウを使用しています

これは、ウィンドウ処理を行っていないことを意味します。これにより、結果にノイズが発生します。vDSPには、ウィンドウ処理を実行するためのいくつかの関数が付属しており、次のように使用できます。

// N = number of samples in your buffer
int N = _audioSample.capacity();

// allocate space for a hamming window
float * hammingWindow = (float *) malloc(sizeof(float) * N);

// generate the window values and store them in the hamming window buffer
vDSP_hamm_window(hammingWindow, N, 0);

次に、FFTを実行するときは常に、最初にサンプルをウィンドウ処理します(vDSP_ctoz呼び出しの前にこれを実行します)。

 vDSP_vmul(sample.get(), 1, hammingWindow, 1, sample.get(), 1, N);

2)結果に対してマグニチュード関数を実行することをお勧めします

これにより、標準のFFT棒グラフ音楽ビジュアライザーで見られるものと同様の結果が得られます。FFTのにこれを行います:

vDSP_zvmags(&_complex, 1, &_complex.realp, 1, _fftsize);

その後、_complex.realpは、各FFTビンの大きさを表すfloat値の配列になります。

于 2012-09-28T17:00:21.347 に答える