• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: vDSP distortion/buzzing
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: vDSP distortion/buzzing


  • Subject: Re: vDSP distortion/buzzing
  • From: Aristotel Digenis <email@hidden>
  • Date: Sat, 17 Jul 2004 17:26:46 +0100

Hello Urs,

Thanks for the quick reply! Your explanation makes sense and will prove useful soon. But first I should point out that the buzz/distortion appears to be a result of ctozD() and ztocD(). As mentioned in my first post, I have tried commenting different parts of the processing to pin point the source of the noise.

1) incoming signal - ctozD() - FFT - multiply with HRTF - iFFT - ztocD() - outgoing signal
Result: There is the audio signal but also buzz/distortion added.

2) incoming signal - ctozD() - FFT - iFFT - ztocD() - outgoing signal
Result: There is the audio signal but also buzz/distortion added.

3) incoming signal - ctozD() - ztocD() - outgoing signal
Result: There is the audio signal but also buzz/distortion added. However the noise is less obvious.

It appears that using ctoZD() and then ztocD() is the course of the noise. Adding FFT and iFFT in between seems to exadurate that noise. Ofcourse this seems crazy as these are Apple's functions which logically work correctly (especialy as it seems others have managed to use them fine). My processing is done in the same way that it is done in Apple's example code that comes with the Acceleration framework.

Once again thank you!!! 8-)

Aristotel

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// BBinaural::BBinaural
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BBinaural::BBinaural(AudioUnit component) : AUEffectBase(component)
{ log2n = 9;
n = 1 << log2n;
nOver2 = n / 2;
stride = 1;
fft512Setup = create_fftsetupD(log2n, kFFTRadix2);
scale = (float) 1.0 / (2 * n);
bufferCount = 0;
//// HRTF_0Degree0ElevationSplitDoubleComplex declared in header
HRTF_0Degree0ElevationSplitDoubleComplex.realp = (double*) malloc(nOver2 * sizeof(double));
HRTF_0Degree0ElevationSplitDoubleComplex.imagp = (double*) malloc(nOver2 * sizeof(double));
//// Convert real data array to Double Complex Split
ctozD((DOUBLE_COMPLEX *) front0elevation0, 2, &HRTF_0Degree0ElevationSplitDoubleComplex, 1, nOver2);
//// Convert the HRTF inpulse response to frequency domain
fft_zripD(fft512Setup, &HRTF_0Degree0ElevationSplitDoubleComplex, stride, log2n, kFFTDirection_Forward);

//// DOUBLE_COMPLEX_SPLIT speakersSplitDoubleComplex declared in header
speakersSplitDoubleComplex.realp = (double*) malloc(nOver2 * sizeof(double));
speakersSplitDoubleComplex.imagp = (double*) malloc(nOver2 * sizeof(double));

//// double array declared in header, now initialized
for(int a = 0; a < 512; a++)
{
speakerTempBuffer[a] = 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// BBinaural::ProcessBufferLists
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

OSStatus BBinaural::ProcessBufferLists(AudioUnitRenderActionFlags& iFlags, const AudioBufferList& inBufferList, AudioBufferList& outBufferList, UInt32 iFrames)
{
float* audioData = (float*) inBufferList.mBuffers[0].mData;

for(UInt32 j = 0; j < iFrames; j++)
{
audioData[j] = audioData[j];
if(bufferCount < 512)
{
speakerTempBuffer[bufferCount] = audioData[j];
bufferCount++;
}
if(bufferCount == 512)
{
//// Split the 512 samples into odd-even complex double array
ctozD((DOUBLE_COMPLEX *) speakerTempBuffer, 2, &speakersSplitDoubleComplex, 1, nOver2);
//// Convert the 512 samples to frequency domain
fft_zripD(fft512Setup, &speakersSplitDoubleComplex, stride, log2n, kFFTDirection_Forward);
//// Multiply the frequency spectrum of the input with the spectrum of the HRTF zvmulD(&speakersSplitDoubleComplex, stride, &HRTF_0Degree0ElevationSplitDoubleComplex, stride, &speakersSplitDoubleComplex, stride, log2n, 1);
//// Convert the 512 samples to time domain
fft_zripD(fft512Setup, &speakersSplitDoubleComplex, stride, log2n, kFFTDirection_Inverse);
//// Split the 512 samples into properly ordered array
ztocD(&speakersSplitDoubleComplex, 1, (DOUBLE_COMPLEX *) speakerTempBuffer, 2, nOver2);
//// Place 512 samples into audioData
for(int a = 0; a < (int) log2n; a++)
{
audioData[a] = speakerTempBuffer[a];
}
//// Reset this counter so that the next 512 samples can be stored at the beginning of the speakerTempBuffer array
bufferCount = 0;
}
}
outBufferList.mBuffers[0].mData = audioData;

return noErr;
}


Urs Heckmann wrote:

Aristotel Digenis:

In ProcessBufferLists() incoming data is stored into an array[size 512]. Once 512 samples have been stored on the temporary buffer, they are converted to the frequency domain in the same manner the HRTF samples were. The 512 frequency domain samples of the incoming audio signal are multiplied with the 512 frequency domain samples. The results are converted back to the time domain, back to normal array from Double Complex Split. Lastly the results are assigned to the output stream.


Hiya Aristotel,

I think the buzzing problem is fundamental thing...

What you actually try to do is convolution in the time domain by multiplication in the frequency domain.

When convolving two buffers of sizes N and M in the time domain, you get a result of length N+M-1. The result has a tail, so to say. In FFT - Multiply - iFFT convolution you have 2 identically sized buffers, and a same sized output, but not an output of double length. What happens here is, the tail from the time domain representation doesn't disappear magically, it actually "wraps around" and populates the same buffer. IIRC this is called frequency aliasing.

What you have to do to avoid this phenomenon is called Overlap-Add Method (if you google for Overlap Add, you get a lot of useful hits about the problem...).

Basically, instead of two 512 sized buffers, you would use two 1024 sized ones, with the additional samples set to 0.0 (aka "zero padding"). Then, after the convolution, you have the "immediate" signal in the first 512 samples of the output and another chunk of 512 (in fact only 511 samples, but don't worry about that) containing the tail, which has to be added to the next buffer (after convolution, of course).

I think the easiest way to do this is setting up 2 input/output buffers that you compute alternatively, and then output the first 512 samples of your current output buffer with the second 512 samples of your alternative buffer added. Dunno.

I hope this helps and that my lack of coffee (8:30am here) doesn't make me confuse things...

Cheers,

;) Urs


urs heckmann
email@hidden
www.u-he.com
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.


References: 
 >vDSP distortion/buzzing (From: Aristotel Digenis <email@hidden>)
 >Re: vDSP distortion/buzzing (From: Urs Heckmann <email@hidden>)

  • Prev by Date: Re: vDSP distortion/buzzing
  • Next by Date: Re: bus count and channel info confusion
  • Previous by thread: Re: vDSP distortion/buzzing
  • Next by thread: Saving the output of an AUGraph under Java
  • Index(es):
    • Date
    • Thread