【问题标题】:De-interleave and interleave buffer with vDSP_ctoz() and vDSP_ztoz()?使用 vDSP_ctoz() 和 vDSP_ztoz() 去交错和交错缓冲区?
【发布时间】:2012-05-08 20:54:35
【问题描述】:

如何将float *newAudio 解交织成float *channel1float* channel2 并将其交织回newAudio

Novocaine *audioManager = [Novocaine audioManager];

__block float *channel1;
__block float *channel2;
[audioManager setInputBlock:^(float *newAudio, UInt32 numSamples, UInt32 numChannels) {
  // Audio comes in interleaved, so, 
  // if numChannels = 2, newAudio[0] is channel 1, newAudio[1] is channel 2, newAudio[2] is channel 1, etc. 

      // Deinterleave with vDSP_ctoz()/vDSP_ztoz(); and fill channel1 and channel2
      // ... processing on channel1 & channel2
      // Interleave channel1 and channel2 with vDSP_ctoz()/vDSP_ztoz(); to newAudio
}];

这两行代码会是什么样子?我不明白ctoz/ztoz的语法。

【问题讨论】:

    标签: objective-c signal-processing core-audio accelerate-framework


    【解决方案1】:

    sbooth 回答了如何使用 vDSP_ctoz 去交错。这是补充操作,即使用 vDSP_ztoc 进行交织。

    #include <stdio.h>
    #include <Accelerate/Accelerate.h>
    
    int main(int argc, const char * argv[])
    {
        const int NUM_FRAMES = 16;
        const int NUM_CHANNELS = 2;
    
        // Buffers for left/right channels
        float xL[NUM_FRAMES];
        float xR[NUM_FRAMES];
    
        // Initialize with some identifiable data
        for (int i = 0; i < NUM_FRAMES; i++)
        {
            xL[i] = 2*i;    // Even
            xR[i] = 2*i+1;  // Odd
        }
    
        // Buffer for interleaved data
        float stereo[NUM_CHANNELS*NUM_FRAMES];
        vDSP_vclr(stereo, 1, NUM_CHANNELS*NUM_FRAMES);
    
        // Interleave - take separate left & right buffers, and combine into
        // single buffer alternating left/right/left/right, etc.
        DSPSplitComplex    x = {xL, xR};
        vDSP_ztoc(&x, 1, (DSPComplex*)stereo, 2, NUM_FRAMES);
    
        // Print the result for verification. Should give output like
        //    i:     L,     R
        //    0:  0.00,  1.00
        //    1:  2.00,  3.00
        //    etc...
        printf(" i:     L,     R\n");
        for (int i = 0; i < NUM_FRAMES; i++)
        {
            printf("%2d: %5.2f, %5.2f\n", i, stereo[2*i], stereo[2*i+1]);
        }
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      我在 Novocaine 的附件类(如 Ringbuffer)中用于解交错的操作:

      float zero = 0.0;  
      vDSP_vsadd(data, numChannels, &zero, leftSampleData, 1, numFrames);   
      vDSP_vsadd(data+1, numChannels, &zero, rightSampleData, 1, numFrames);  
      

      用于交错:

      float zero = 0.0;  
      vDSP_vsadd(leftSampleData, 1, &zero, data, numChannels, numFrames);   
      vDSP_vsadd(rightSampleData, 1, &zero, data+1, numChannels, numFrames);  
      

      更一般的做事方式是有一个数组数组,比如

      int maxNumChannels = 2; 
      int maxNumFrames = 1024;
      float **arrays = (float **)calloc(maxNumChannels, sizeof(float *));  
      for (int i=0; i < maxNumChannels; ++i) {  
          arrays[i] = (float *)calloc(maxNumFrames, sizeof(float));
      }
      
      [[Novocaine audioManager] setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
          float zero = 0.0;
          for (int iChannel = 0; iChannel < numChannels; ++iChannel) {
              vDSP_vsadd(data, numChannels, &zero, arrays[iChannel], 1, numFrames);
          }
      }];
      

      这是我在内部用于 Novocaine 的 RingBuffer 附件类中经常使用的。我对 vDSP_vsadd 与 memcpy 的速度进行了计时,并且(非常非常令人惊讶)没有速度差异。

      当然,你总是可以只使用环形缓冲区,省去你自己的麻烦

      #import "RingBuffer.h"
      
      int maxNumFrames = 4096
      int maxNumChannels = 2
      RingBuffer *ringBuffer = new RingBuffer(maxNumFrames, maxNumChannels)
      
      [[Novocaine audioManager] setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
          ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels);
      }];
      
      [[Novocaine audioManager] setOuputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
          ringBuffer->FetchInterleavedData(data, numFrames, numChannels);
      }];
      

      希望对您有所帮助。

      【讨论】:

      • 谢谢,这看起来很干净!
      • Alex,请看一下this 问题,我正在尝试通过允许它读取 VBR 数据(在 SInt16 中而不是浮点中)来添加到您的 novacaine 示例中
      【解决方案3】:

      这是一个例子:

      #include <Accelerate/Accelerate.h>
      
      int main(int argc, const char * argv[])
      {
          // Bogus interleaved stereo data
          float stereoInput [1024];
          for(int i = 0; i < 1024; ++i)
              stereoInput[i] = (float)i;
      
          // Buffers to hold the deinterleaved data
          float leftSampleData [1024 / 2];
          float rightSampleData [1024 / 2];
      
          DSPSplitComplex output = {
              .realp = leftSampleData,
              .imagp = rightSampleData
          };
      
          // Split the data.  The left (even) samples will end up in leftSampleData, and the right (odd) will end up in rightSampleData
          vDSP_ctoz((const DSPComplex *)stereoInput, 2, &output, 1, 1024 / 2);
      
          // Print the result for verification
          for(int i = 0; i < 512; ++i)
              printf("%d: %f + %f\n", i, leftSampleData[i], rightSampleData[i]);
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2011-01-21
        • 1970-01-01
        • 1970-01-01
        • 2011-12-30
        • 1970-01-01
        • 2015-04-22
        • 2014-10-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多