Пиковый фильтр имеет щелчки и всплывающие окна - PullRequest
5 голосов
/ 30 января 2011
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; 
} 

Наличие кликов / поп-проблем.Кто-то, ПОЖАЛУЙСТА, ПОМОГИТЕ ... Я не знаю, что я делаю неправильно.Это в Xcode с использованием C в Objective-C.Я пытался сделать Coeff Global и Static, но безуспешно.Использование аудиофайла - это .caf. Я попробовал .wav, но все равно ничего не получится ....

Спасибо, извините за общий призыв о помощи.Я новичок в этом сайте ... Я пытаюсь добавить фильтр пиков в свое приложение, но каждый раз, когда я использую ползунок или просто оставляю усиление на 1, я получаю щелчки.Кажется, что все есть и работает должным образом, если держать предыдущие образцы и т. Д. Я также получаю некоторый тип фазы при изменении частоты или ширины полосы.Я так растерялся, изучая dsp уже несколько месяцев, и думаю, что это что-то с Objective-C и небольшой ошибкой пользователя.Кажется, он исчезает при изменении сэмпла на SInt32, но левый канал исчезает при изменении частоты.

Dsp.h

typedef struct { 

  void* audioData; 

   UInt32 audioDataByteCount; 

   SInt16 *samplePtr; 

} MusicPlaybackState; 

Ответы [ 4 ]

4 голосов
/ 30 января 2011

Согласно ответу hotpaw2, вот график ответа вашего фильтра:

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

Пиковое усиление установлено на 1,1220184543 (т. Е. 1 дБ).Вы можете видеть, как фильтр вызывает усиление большей части звукового диапазона, превышающего 1.

Редактировать 2: Если это для регулируемого эквалайзера, то пользователь должен установить усиление, которое позволяет избежать искажений,Кроме того, я сомневаюсь, что крайняя проблема, которую вы описываете, будет вызвана небольшим усилением в 1 дБ в узкой полосе для типичной звуковой дорожки.Я думаю, что это потому, что в вашем аудио есть чередующиеся стереоданные.Каждый из этих каналов должен быть отфильтрован отдельно.Я предпринял попытку изменить ваш вложенный цикл, чтобы выполнить это:

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; 
    }
}
2 голосов
/ 30 января 2011

одна важная проблема заключается в том, что ваше состояние фильтра должно храниться в состоянии refcon (по крайней мере, это очевидное лучшее место в типичных случаях).

без этого ваш фильтр перестраивается и инициализируетсяпри каждом вызове обратного вызова, что означает, что состояние не будет сохраняться правильно, и у вас будут глюки на границах каждого обратного вызова, кроме первого.

1 голос
/ 30 января 2011

В дополнение к превосходным ответам, которые уже были даны, я просто добавлю общий совет - вы должны выделить и отделить свою процедуру фильтрации от обратного вызова (то есть сделать ее отдельной функцией без каких-либо зависимостей от вашегокод iOS).Таким образом, вы можете поместить его в тестовый комплект и упростить его отладку (в контексте не в реальном времени), отдельно от проблем, связанных с iOS, которые могут осложнить ситуацию.

1 голос
/ 30 января 2011

Похоже, вы используете рецепт двухрядной поваренной книги RBJ.

Биквадический фильтр с пиковым коэффициентом усиления со средним коэффициентом усиления 1,0 имеет усиление выше 1,0 на определенных частотах.Если вы не хотите ограничивать, вы должны либо использовать усиление менее 1,0, либо использовать аттенюатор или AGC на входе, чтобы пиковое повышение частоты никогда не достигало уровня, который будет ограничивать.

Это проблема без AGC, так как некоторые клиенты ожидают, что фильтр пиковых или низких частот сделает звук громче, и вам придется ослабить средний уровень, чтобы фактически снизить его, чтобы полностью предотвратить отсечение при пиковой частоте.*

...