Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2019:audio-resample

Převzorkování zvukového signálu

Autor: Filip Šterc

Zadání

Realizujte algoritmus pro převzorkování audio signálu s vhodným poměrem, např. z 8kHz na 12kHz. Maximálně optimalizujte použitý kód, příp. vhodně využijte matematické knihovny a DSP rozšíření. Vstup a výstup signálu z vývojové desky realizujte přes DMA pomocí periferií ADC a DAC.

Teorie

V této části se budeme zabývat teorií kolem převzorkování signálu z jednoho kmitočtu na druhý pomocí celočíselného poměru vzorkovacích frekvencí. V tomto projektu je konkrétně použit poměr 2:3 s frekvencemi 8 kHz a 12 kHz. Avšak tento algoritmus s poměrem 2:3 lze bez jakýcholiv změn použít i pro další frekvence vzorkování v tomto poměru.

Interpolace

Pro převzorkování signálu na jiný kmitočet je nutné kmitočet nejdříve interpolovat na nejbližší společný celočíselný násobek kmitočtů (vstupního a výstupního), v tomto případě se jedná o kmitočet 24kHz. Toto je provedeno přidáním nulových vzorků mezi každý vzorek vstupního signálu. Pro interpolaci na N*fvz kmitočet je třeba přidat N-1 nul mezi každý vzorek.

x1…x2…x3…x4…x5… → x1…0…0…x2…0…0…x3…0…0…x4…0…0…x5…0…

Toto sice způsobí přesun vzorkovacího kmitočtu na N násobek původního kmitočtu, ale spektra přítomna na nižších násobcích vzorkovací frekvence zůstanou stále přítomna a zároveň způsobují nulovou úroveň nově přidaných vzorků. Proto je pro rekonstrukci signálu potřeba tyto spektra odfiltrovat pomocí vhodného FIR filtru.

Decimace

Po interpolaci je potřeba signál decimovat a tím snížit vzorkovací frekvenci na požadovanou úroveň. Decimaci na vzorkovací kmitočet fvz/N, je možné provést pomocí vybrání pouze každého Ntého vzorku. V tomto případě je potřeba decimace 2x, to znamená vybrání každého druhého vzorku.

y1…y2…y3…y4…y5…y6…y7… → y1…y3…y5…y7…

Ve spektru, takováto decimace, způsobí nakopírování spektra z původní frekvence na frekvenci novou. Aby nedošlo k aliasingu, je třeba zajistit, aby bylo spektrum signálu před decimací prázdné na frekvencích vyšších jak polovina nového vzorkovacího kmitočtu.

Převzorkování

Během převzorkování je, dle teorie, třeba signál filtrovat pomocí 2 různých FIR filtrů. Jeden pro rekonstrukci signálu po interpolaci a druhý pro předejití aliasingu před decimací. Tyto filtry jsou však kaskádně zařazeny hned za s sebou a proto je v praxi možné je nahradit pomocí jediného filtru s nejmenším potřebným mezním kmitočtem.

Pro interpolaci je třeba filtrovat veškerý signál od poloviny vzorkovacího kmitočtu vstupního signálu.
V tomto případě: fvz1/2 = 8 kHz/2 = 4 kHz.

Pro decimaci je třeba filtrovat veškerý signál od poloviny vzorkovacího kmitočtu výstupního signálu.
V tomto případě: fvz2/2 = 12 kHz/2 = 6 kHz.

Nižší kmitočet je 4 kHz, proto bude v tomto projektu použit FIR filtr s pásmem nepropusti od této frekvence.

V přechozí kapitole bylo řečeno, že pro převzorkování bude třeba filtr s pásmem nepropustnosti od frekvence 4 kHz. Pro využití co největšího pásma spektra je vhodné volit mezní kmitočet taktéž blízko tohoto kmitočtu. Avšak příliš krátká přechodová oblast mezi těmito kmitočty zase znamená velký počet koeficientů FIR filtru, proto je třeba tento kmitočet volit rozumně. Pro tento případ byl zvolen mezní kmitočet fmez = 3,75 kHz. V kombinaci s definovanou úrovní potlačení -80 dB je řád filtru n = 243. Samotný FIR filtr je navržen pomocí programu Matlab v rozšíření Filter Designer s následujícími parametry:

Koeficienty navrženého filtru byly uloženy do souboru „FIR_mat.mat“, a poté převedeny na hlavičkový soubor jazyka C „fir_coef.h“ pomocí matlabovského skriptu „FIR_test.m“.

Schéma zapojení

Signál ze zvukové karty počítače je v napěťovém rozmezí (-1 - 1) V. Použitý procesor však zvládá zpracovávat pouze kladná napětí, proto je třeba úroveň signálu nejdříve zvednout nad zem. Toto lze snadno vyřešit pomocí sériového kondenzátoru a napěťového děliče, který úroveň signálu posune na úroveň poloviny napájecího napětí 3V.

Při výběru hodnot kondenzátoru, je třeba brát ohled na frekvenci signálu. Pro signál se toto zapojení jeví jako filtr horní propusti s odpory zapojenými paralelně, proto pro vybrané hodnoty je mezní frekvence fmez = 1/(2*pi*0,5R*C) = 28,9 Hz. Pro člověka je slyšitelný pouze zvuk v rozmezí 16 Hz - 20 kHz, tudíž kromě malé krajní oblasti mezi (16 - 29) Hz, slyšitelný signál může projít beze změny.

Implementace

Pro realizaci kódu jsem použil prostředí EmBitz, společně s nástrojem STM32CubeMX pro generování inicializačního kódu procesorů od STMicroelectronics.

Systém funguje následujícím způsobem. Vstupní signál je vzorkován periferií ADC1, kanál 1 (PA1), pomocí ovladače DMA, který ukládá data vždy do vrchní poloviny bufferu adc_buffer[]. Po naplnění bufferu jsou tyto data přesunuta do spodní poloviny odkud jsou čteny pomocí periferie DAC, kanálu 1 (PA4), opět přes ovladač DMA. Tento výstup slouží pouze pro srovnání s později převzorkovaným signálem. Oba ovladače DMA jsou řízeny pomocí timeru TIM2 nastaveného na frekvenci 8 kHz. Aby bylo možné data zpracovávat každých 100 ms, je celková délka adc_bufferu nastavena na 2*800 vzorků.

Při přesunu dat mezi polovinami adc_bufferu, jsou tyto vzorky zároveň zkopírovány do bufferu upsample_buffer[], společně s 82 starými vzorky a proloženy dvěma nulami, pro realizaci nadvzorkování 3x. Dodatečných 82 vzorků z nižší poloviny adc_bufferu se zde nachází kvůli FIR filtru, který vyžaduje paměť 244 předchozích vzorků. (Po nadvzorkování je 82*3 = 246).
Přesun dat je realizován funkcí buffer_prepare():

void buffer_prepare(void){
    for(uint16_t i = 0; i < (ADC_BUFFER_LEN + 82); i++){
        upsample_buffer[i*3] = adc_buffer[ADC_BUFFER_LEN - 82 + i];
        if(i >= 82){
            adc_buffer[i - 82] = adc_buffer[ADC_BUFFER_LEN - 82 + i];
        }
    }
}

Po přesunu dat do upsample_buffer[] jsou tyto data následně interpolována FIR filtrem. Pro snížení náročnosti je společně s interpolací okamžitě prováděna decimace zpracováním pouze každého druhého vzorku (liché vzorky by stejně byly zahozeny). Převzorkované data jsou ukládány do posledního bufferu dac_buffer[]. Aby se zamezila nutnost čekání mezi navzorkováním nových dat a jejich převzorkováním, je použit buffer dvojnásobné délky 2*1200 vzorků, kdy do jedné poloviny jsou ukládány zpracovávané data a z druhé poloviny jsou data čtena do kanálu 2 (PA5), periferie DAC. Čtení je prováděno ovladačem DMA, který je řízen timerem TIM4 s frekvencí 12 kHz.
Převzorkování je umístěno ve funkci resample() se vstupním argumentem dac_buff_side, který určuje do které poloviny dac_bufferu mají být data ukládána:

void resample(uint8_t dac_buff_side){
    float sum;
    uint16_t out;
    uint16_t readBuf;
 
    for(uint16_t i = 0; i < DAC_BUFFER_LEN*2; i+=2){        //inkrementování read pointeru +2 pro decimaci 2*
        sum = 0;
        out = 0;
        readBuf = i + 246;				    //uložení ukazatele pro ctení
 
        for(uint8_t j = 0; j < FIR_LENGTH; j++){            //rekonstrukce interpolovaného signálu
            sum += upsample_buffer[readBuf-j]*fxcoef[j];
        }
 
        if(sum > 4095){			                    //prevedení na 32 bit hodnotu požadovanou DAC, se saturací
            out = 4095;
        }else if(sum < 0){
            out = 0;
        }else{
            out = (uint32_t)(sum);
        }
        dac_buffer[dac_buff_side*DAC_BUFFER_LEN + (i>>1)] = out;
    }
 
}

Video

Na následujícím videu je ukázána funkčnost tohoto projektu při zpracování signálu o frekvenci 1 kHz. Na osciloskopu jsou zobrazeny signály od vrchu dolů:
CH3 - vstupní signál na pinu PA1,
CH1 - nepřevzorkovaný výstupní signál na pinu PA4,
CH2 - převzorkovaný výstupní signál na pinu PA5.
Na nastavení osciloskopu je možné si všimnou, že i přes to, že se signály zdají být podobné, tak převzorkovaný signál na CH2 má rozlišení pouze 200mV/div, oproti ostatním s 500mV/div. Tato nižší amplituda je vlastností interpolace, kdy je prováděna rekonstrukce signálu odfiltrováním přebytečných kopií spektra, což způsobí pokles energie signálu (pro interpolaci 3x, pokles energie na 1/3). Pokud by bylo požadavkem zachování amplitudy signálu, bylo by třeba převzorkovaný signál vynásobit třemi, což ale vede i ke zvýšení šumu signálu.

Video ukázka

Soubory

EmBitz projekt
Matlab soubory
2019/audio-resample.txt · Poslední úprava: 2020/01/20 19:41 autor: Filip Šterc