Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

De-interleave and interleave buffer with vDSP_ctoz() and vDSP_ztoz()?

How do I de-interleave the float *newAudio into float *channel1 and float* channel2 and interleave it back into 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
}];

What would these two lines of code look like? I don't understand the syntax of ctoz/ztoz.

like image 494
sougonde Avatar asked Apr 28 '12 08:04

sougonde


Video Answer


1 Answers

What I do in Novocaine's accessory classes, like the Ringbuffer, for de-interleaving:

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

for interleaving:

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

The more general way to do things is to have an array of arrays, like

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);
    }
}];

which is what I use internally a lot in the RingBuffer accessory classes for Novocaine. I timed the speed of vDSP_vsadd versus memcpy, and (very, very surprisingly), there's no speed difference.

Of course, you can always just use a ring buffer, and save yourself the hassle

#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);
}];

Hope that helps.

like image 64
alexbw Avatar answered Oct 19 '22 01:10

alexbw