2011-01-30 15 views
5
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; 
} 

Avere problemi con Clic/pop. Qualcuno PER FAVORE AIUTA ... Non so cosa sto sbagliando. Questo è in Xcode usando C in Objective-C. Ho provato a creare Coeff Global e Static ma non ho avuto fortuna. Il file audio che utilizza è un .caf che ho provato .wav ma ancora non va bene ....Filtro di picco con clic e pop

Grazie, scusa per il grido generale di aiuto. Sono nuovo di questo sito .. Sto provando ad aggiungere un filtro Peak nella mia app ma ogni volta che uso uno slider o semplicemente il guadagno a 1 ottengo pop e click. Sembra che ci sia tutto e funzioni correttamente per quanto riguarda il mantenimento dei campioni precedenti, ecc. Ho anche ottenuto un certo tipo di fase quando si modifica la frequenza o la larghezza di banda. Sono così confuso che ho studiato dsp per alcuni mesi, penso che sia qualcosa con Objective-C e un errore utente lil. Sembra che vada via quando si cambia il campione in uno SInt32, ma il canale sinistro scompare quando si cambia freq.

Dsp.h

typedef struct { 

    void* audioData; 

    UInt32 audioDataByteCount; 

    SInt16 *samplePtr; 

} MusicPlaybackState; 
+1

Non riesco a immaginare perché qualcuno stia votando per chiudere questo. – ocodo

+0

@ Silomojo: Non penso che la domanda debba essere chiusa, ma non è molto ben presentata così com'è, e posso capire perché potrebbe ottenere voti ravvicinati. @Cocell: potresti voler migliorare la domanda per evitare ulteriori voti ravvicinati - prova a dare maggiori dettagli sul problema e su ciò che hai provato, e fargli una singola domanda specifica piuttosto che un "grido d'aiuto" generale. –

+1

@Paul R - Sono d'accordo sul fatto che la domanda dovrebbe essere posta in modo più efficace, ma il voto di chiusura del tutto silenzioso è inappropriato. È del 100% evidente che Cocell è un nuovo utente di SO e, semplicemente, vuole risolvere un problema spinoso. Non è possibile per qualcuno con meno di 2k rep per votare per la chiusura, quindi è estremamente deludente quando ciò accade. È arbitrario, inutile e francamente maleducato, un commento che richiede maggiori informazioni se è necessario è tutto ciò che è necessario qui, non un "VIAGGIARE, LA TUA DOMANDA È INDESIDERATA", che è esattamente ciò che esprime un voto ravvicinato. – ocodo

risposta

4

Come per la risposta di hotpaw2, ecco la trama di risposta del filtro:

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

Il guadagno di picco è impostato su 1,1220,184543 millions (vale a dire 1 dB). Puoi vedere come il filtro fa sì che la maggior parte della gamma udibile abbia un guadagno maggiore di 1.

Modifica 2: Se questo è per un EQ regolabile, allora è l'utente a impostare il guadagno che evita la distorsione. Inoltre, dubito che l'estremo problema che descriveresti sarebbe causato da un leggero guadagno di 1 dB su una banda ristretta per una traccia audio tipica. Penso invece sia perché il tuo audio ha dati stereo interlacciati. Ciascuno di questi canali deve essere filtrato separatamente. Ho preso una crepa a modificare il ciclo nidificato per raggiungere questo obiettivo:

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; 
    } 
} 
+0

Si noti che anche se si garantisce che il guadagno sia <= 1.0 a tutte le frequenze, si possono comunque ottenere picchi di uscita più grandi dei picchi di input. –

+0

Quindi, come potrei aumentare un freq a 10000kHz, ad esempio con un picco a 12 dB senza clic e pop se si dice che deve essere inferiore a 1 dB? – Cocell

+0

@eryksun Non lo uso solo per un esempio. Mi stavo solo chiedendo cosa succederebbe se volessi potenziare 12dB @ un certo freq, che potrebbe causare lo stesso problema? Apprezzo il vostro aiuto. – Cocell

1

Sembra che si sta utilizzando la ricetta biquad libro di ricette di RBJ.

Un filtro di picco biquad con un guadagno medio di 1,0 ha un guadagno superiore a 1,0 a determinate frequenze. Se non si desidera ritagliare, è necessario utilizzare un guadagno inferiore a 1.0 o utilizzare un attenuatore o AGC sull'ingresso in modo che l'aumento della frequenza di picco non raggiunga mai un livello che si aggancia.

È un problema senza AGC, dal momento che alcuni clienti si aspettano un filtro di amplificazione del picco o del picco per rendere le cose più rumorose, e si deve attenuare il livello medio effettivamente abbassandosi per evitare completamente il clipping alla frequenza di picco.

+0

Ok, proverò ad aggiungere un AGC. Quindi, in sostanza, il motivo per cui sta facendo i suoni è perché il guadagno a frequenze diverse è superiore a 1.0 in Magnitude non dB come menzionato da eryksun? – Cocell

2

un problema importante è che lo stato del filtro deve essere memorizzato all'interno dello stato refcon (almeno, questo è il posto migliore ovvio in casi tipici).

senza che il filtro venga ricostruito e inizializzato ad ogni richiamo del callback, il che significa che lo stato non verrà conservato correttamente e si avranno dei problemi ai limiti di ogni callback diverso dal primo.

1

In aggiunta alle eccellenti risposte che sono già state date, ti basta aggiungere una parola generale del consiglio - si dovrebbe scomporre e disaccoppiare la routine del filtro dal callback (cioè rendilo una funzione separata senza dipendenze dal tuo codice iOS). In questo modo puoi metterlo in una selleria di test e più facilmente eseguirne il debug (in un contesto non in tempo reale), separato da eventuali problemi specifici di iOS che potrebbero complicare le cose.

+0

Grazie ce l'ho così nella mia seconda versione e ancora lo stesso problema. Ho appena messo tutto insieme per rendere più facile l'aiuto. – Cocell

+0

@Cocell: OK: quando la routine viene implementata separatamente, scrivere un cablaggio di test che può generare un segnale di ingresso, ad es.onda sinusoidale a data ampiezza e frequenza, e quindi scaricare l'output in un formato che può essere tracciato - rende il debugging molto più semplice. –

Problemi correlati