Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Peak Filter has clicks and pops

OSStatus MusicPlayerCallback ( 
                       void *                     inRefCon, 
                       AudioUnitRenderActionFlags *   ioActionFlags, 
                       const AudioTimeStamp *         inTimeStamp, 
                       UInt32                     inBusNumber, 
                       UInt32                     inNumberFrames, 
                       AudioBufferList *            ioData) { 


MusicPlaybackState *musicPlaybackState = (MusicPlaybackState*) inRefCon; 

double sampleinp; 

double A,omega,sn,cs,alpha,Bandwidth; 

double dbGain; 

double   a0,a1,a2,b0,b1,b2; 

dbGain = 1.0; 

A=pow(10.0,dbGain/40.0); 

Bandwidth = 2.0; 

omega=2 * M_PI * 800.0/44100.0; 

sn=sin(omega); 

cs=cos(omega); 

alpha=sn*sinh(((M_LN2/2)*Bandwidth*omega)/sn); 


//Peak Filter Biquad 

b0 =1.0 + alpha * A; 

b1 = (-2.0 * cs); 

b2 = 1.0 - alpha * A; 

a0 = 1.0 + (alpha /A); 

a1 = -2.0 * cs; 

a2 = 1.0 - (alpha /A); 



double b0a0, b1a0, b2a0, a1a0, a2a0; 

double static x1; 

double static x2; 

double static y1; 

double static y2; 


b0a0=b0/a0;   

b1a0=b1/a0; 

b2a0=b2/a0; 

a1a0=a1/a0; 

a2a0=a2/a0; 


for (int i = 0 ; i < ioData->mNumberBuffers; i++){ 


  AudioBuffer buffer = ioData->mBuffers[i]; 
  AudioSampleType *outSample = buffer.mData; 

  for (int j = 0; j < inNumberFrames*2; j++){ 

     sampleinp = *musicPlaybackState->samplePtr++; 

     outSample[j] =  b0a0 * sampleinp + 
     b1a0 * x1 + 
     b2a0 * x2 - 
     a1a0 * y1 - 
     a2a0 * y2; 


     x2=x1; 
     x1=sampleinp; 

     y2=y1; 
     y1=outSample[j]; 

  }} 





return noErr; 
} 

Having Clicks/pop problems. Someone PLEASE HELP... I don't know what I'm doing wrong. This is in Xcode using C in Objective-C. I tried making the Coeff Global and Static but no luck. The Audio file using is a .caf I tried .wav but still no good....

Thanks, sorry for the general cry for help. I'm new to this site.. I'm trying to add an Peak filter in my app but everytime I use a slider or just leave the gain at 1 I get pops and clicks. It seems as everthing is there and working properly as far as holding the previous samples etc. I also get some type of phase when changing the frequency or the bandwidth. I'm so confused been studying dsp for a few months now, I think it's something with Objective-C and a lil user error. It seem to go away when changing the sample to a SInt32 but the left channel disappears when changing freq.

Dsp.h

typedef struct { 

  void* audioData; 

   UInt32 audioDataByteCount; 

   SInt16 *samplePtr; 

} MusicPlaybackState; 
like image 682
Cocell Avatar asked Jan 30 '11 00:01

Cocell


People also ask

What causes pops and clicks in audio?

Pops and clicks are unwanted audio artifacts caused by the powering up and down of components within the audio subsystem. This is noticeable on PCs when an audio module is either loaded or unloaded (at module load time the sound card is powered up and causes a popping noise on the speakers).


1 Answers

As per hotpaw2's answer, here's the plot of your filter's response:

from pylab import *
import scipy.signal as signal

def biquad_peak(omega, gain_db, bandwidth):
    sn = sin(omega)
    cs = cos(omega)
    alpha = sn * sinh(log(2) / 2 * bandwidth * omega / sn)
    gain_sqrt = 10.0 ** (gain_db / 40.0)

    # feed-forward coefficients
    b0 = 1.0 + alpha * gain_sqrt
    b1 = -2.0 * cs
    b2 = 1.0 - alpha * gain_sqrt
    # feedback coefficients
    a0 = 1.0 + (alpha / gain_sqrt)
    a1 = -2.0 * cs
    a2 = 1.0 - (alpha / gain_sqrt)
    # normalize by a0
    B = array([b0, b1, b2]) / a0
    A = array([a0, a1, a2]) / a0
    return B, A

omega = 2 * pi * 800.0 / 44100.0
gain_db = 1.0
bandwidth = 2.0

B, A = biquad_peak(omega, gain_db, bandwidth)
w, H = signal.freqz(B, A)
f = w / pi * 22050.0
plot(f, abs(H), 'r')
gain = 10.0 ** (gain_db / 20.0)
print  "Gain:", gain
plot(f, gain*ones(len(f)), 'b--'); grid()

biquad peak filter response

The peak gain is set to 1.1220184543 (i.e. 1 dB). You can see how the filter causes most of the audible range to have a gain greater than 1.

Edit 2: If this is for an adjustable EQ, then it's up to the user to set the gain that avoids distortion. Plus I doubt the extreme problem you describe would be caused by a mild gain of 1 dB over a narrow band for a typical audio track. I think instead it's because your audio has interleaved stereo data. Each of these channels needs to be filtered separately. I've taken a crack at modifying your nested loop to accomplish this:

a0 = 1.0 + alpha / A; 
a1 = -2.0 * cs / a0;     
a2 = (1.0 - alpha / A) / a0; 
b0 = (1.0 + alpha * A) / a0; 
b1 = -2.0 * cs / a0; 
b2 = (1.0 - alpha * A) / a0;

double static x11, x12, x21, x22;
double static y11, y12, y21, y22;
double x0, y0;

for (int i = 0; i < ioData->mNumberBuffers; i++) {  

    AudioBuffer buffer = ioData->mBuffers[i]; 
    AudioSampleType *outSample = buffer.mData; 

    for (int j = 0; j < inNumberFrames*2; j++) { 

        /* x0 is in the range of SInt16: -32768 to 32767 */

        x0 = *musicPlaybackState->samplePtr++;

        y0 = b0 * x0 + 
             b1 * x11 + 
             b2 * x12 - 
             a1 * y11 - 
             a2 * y12; 

        outSample[j] = fmax(fmin(y0, 32767.0), -32768.0); 

        x12 = x11; 
        x11 = x0;
        y12 = y11;
        y11 = y0
        j++;          

        x0 = *musicPlaybackState->samplePtr++;

        y0 =  b0 * x0 + 
              b1 * x21 + 
              b2 * x22 - 
              a1 * y21 - 
              a2 * y22; 

        outSample[j] = fmax(fmin(y0, 32767.0), -32768.0); 

        x22 = x21; 
        x21 = x0;          
        y22 = y21; 
        y21 = y0; 
    }
}
like image 172
Eryk Sun Avatar answered Sep 20 '22 23:09

Eryk Sun