2015-12-16 11 views
5

Şu anda Apple'a özgü (Accelerate) vDSP işlevi vDSP_deq22'yi Android'e (Accelerate mevcut değil) kullanan bir filterbank portu yapıyorum. Filterbank, her biri kendi bantları için RMS büyüklüğünü döndüren bir grup bant geçiren filtrelerdir. Şu anda (NVDSP uyarlanmıştır ObjectiveC++) kodu aşağıdaki gibidir:Biquad IIR için Reimplement vDSP_deq22 El ile filtrele

- (float) filterContiguousData: (float *)data numFrames:(UInt32)numFrames channel:(UInt32)channel { 

    // Init float to store RMS volume 
    float rmsVolume = 0.0f; 

    // Provide buffer for processing 
    float tInputBuffer[numFrames + 2]; 
    float tOutputBuffer[numFrames + 2]; 

    // Copy the two frames we stored into the start of the inputBuffer, filling the rest with the current buffer data 
    memcpy(tInputBuffer, gInputKeepBuffer[channel], 2 * sizeof(float)); 
    memcpy(tOutputBuffer, gOutputKeepBuffer[channel], 2 * sizeof(float)); 
    memcpy(&(tInputBuffer[2]), data, numFrames * sizeof(float)); 

    // Do the processing 
    vDSP_deq22(tInputBuffer, 1, coefficients, tOutputBuffer, 1, numFrames); 
    vDSP_rmsqv(tOutputBuffer, 1, &rmsVolume, numFrames); 

    // Copy the last two data points of each array to be put at the start of the next buffer. 
    memcpy(gInputKeepBuffer[channel], &(tInputBuffer[numFrames]), 2 * sizeof(float)); 
    memcpy(gOutputKeepBuffer[channel], &(tOutputBuffer[numFrames]), 2 * sizeof(float)); 

    return rmsVolume; 
} 

here görüldüğü gibi, deq22 özyinelemeli fonksiyonu ile belirli bir giriş vektör üzerinde bir süzgecinin filtre uygular. vDSP_deq22

  • A =: Bu dokümanlar ile ilgili fonksiyon açıklaması tek hassas gerçek giriş vektörü
  • IA =: 5 tek hassasiyetli: A.
  • B = Stride girişler (filtre katsayıları), adım 1 ile.
  • C =: Tek duyarlıklı gerçek çıkış vektörü.
  • IC =: C için adım
  • N =: Üretilecek yeni çıkış öğelerinin sayısı.

    // N is fixed on init to be the same size as buffer.count, below 
    // 'input' and 'output' are initialised with (N+2) length and filled with 0s 
    
    func getFilteredRMSMagnitudeFromBuffer(var buffer: [Float]) -> Float { 
        let inputStride = 1 // hardcoded for now 
        let outputStride = 1 
    
        input[0] = input[N] 
        input[1] = input[N+1] 
        output[0] = output[N] 
        output[1] = output[N+1] 
    
        // copy the current buffer into input 
        input[2 ... N+1] = buffer[0 ..< N] 
    
        // Not sure if this is neccessary, just here to duplicate NVDSP behaviour: 
        output[2 ... N+1] = [Float](count: N, repeatedValue: 0)[0 ..< N] 
    
        // Again duplicating NVDSP behaviour, can probably just start at 0: 
        var sumOfSquares = (input[0] * input[0]) + (input[1] * input[1]) 
    
        for n in (2 ... N+1) { 
         let sumG = (0...2).reduce(Float(0)) { total, p in 
          return total + input[(n - p) * inputStride] * coefficients[p] 
         } 
    
         let sumH = (3...4).reduce(Float(0)) { total, p in 
          return total + output[(n - p + 2) * outputStride] * coefficients[p] 
         } 
    
         let filteredFrame = sumG - sumH 
         output[n] = filteredFrame 
         sumOfSquares = filteredFrame * filteredFrame 
        } 
    
        let meanSquare = sumOfSquares/Float(N + 2) // we added 2 values by hand, before the loop 
        let rootMeanSquare = sqrt(meanSquare) 
        return rootMeanSquare 
    } 
    

    filtre olsa deq22 için farklı büyüklük çıktıyı verir:

Bu şimdiye kadar (o zaten Android üzerinde çalışan var kod temeli kalanı gibi, Swift öyle) ne var ve içinde döngüsel bir ısınma dairesel 'gürültü' var gibi görünüyor (sabit bir giriş tonuyla, frekansın büyüklüğü aşağı yukarı pompalanır).

Katsayılar dizilerinin her uygulama arasında aynı olduğundan emin olmak için kontrol ettik. Her filtre aslında doğru frekansı (ve sadece bu frekansı) seçmesiyle "çalışır" gibi görünür ve bu sadece bu pompalamadır ve RMS büyüklük çıktısı vDSP'lerden çok daha büyüktür, çoğunlukla büyüklük sırasına göre:

Naive | vDSP 
3.24305e-06 0.000108608 
1.57104e-06 5.53645e-05 
1.96445e-06 4.33506e-05 
2.05422e-06 2.09781e-05 
1.44778e-06 1.8729e-05 
4.28997e-07 2.72648e-05 

Mantığımla ilgili herhangi bir sorun görülebilir mi?

Düzenleme: Burada, sabit bir 440Hz tonu olan sonucun bir gif videosudur. Çeşitli yeşil çubuklar bireysel filtre bantlarıdır. 3. bant (burada gösterilmektedir) 440Hz'e ayarlanmış olanıdır.

Pumping

NVDSP versiyonu sadece beklenen giriş hacmi ile orantılı okuma sabit (dışı dalgalı) büyüklüğünü göstermektedir.

cevap

4

Tamam, sumOfSquares = filteredFrame * filteredFrame satırı, bir ödev değil, bir += olmalıdır. Dolayısıyla sadece son kareler hesaplanıyordu, çok açıklıyor;)

Swift'de biquad filtrelemesi yapmak istiyorsanız bunu kullanabilirsiniz. Bundan önce NVDSP gibi MIT Lisansı.

+0

Bu harika! :) – bartolsthoorn

+1

@bartolsthoorn teşekkürler :) Bakınız [burada] (https: // orta.com/@ ephemer/neden-we-put-an-app-in-the-android-play-mağaza-kullanarak-swift-96ac87c88dfc) Eğer neden bu – ephemer

+1

harika bir hikaye yapıyor endişeli ve NVDSP için teşekkürler hehe;) Bu arada, 2013 yılında NVDSP yaratma mücadelesi hakkında kendime bir not yazdım (doğru anladınız, Google çeviri yapmak zorunda olduğum çok az doküman vardı): https://medium.com/ @ bartolsthoorn/cesur ses filtreleri-1964521efbc7 # .vdsj4j83m – bartolsthoorn