Il problema dell'allineamento dell'audio

Ascoltando tracce audio diverse spesso percepiamo differenti livelli di volume. Questi continui sbalzi di volume tra una traccia e la successiva possono essere molto fastidiosi, possono farci perdere la concentrazione e constringerci a cambiare in continuazione il livello del volume manualmente. Il problema riguarda tutti quei casi in cui è necessario concatenare tracce audio/video (Simple Media Player, TV, ecc...)

Cosa fare?

Ci proponiamo di bilanciare il livello di volume tra differenti sorgenti sonore.

Il primo problema è trovare una funzione che descriva nel modo migliore possibile il livello di pressione sonora di un suono. Il livello di pressione sonora ($$L_p$$) è la misura logaritmica della pressione sonora rispetto ad un valore di riferimento: $$L_p = 10\log_{10}(p/p_0)^2$$ La pressione sonora è un parametro, espresso in Pa, che rappresenta il cambiamento di pressione rispetto ad una condizione di pace.

Useremo la funzione Root Mean Square (RMS) per trovare il livello di pressione sonora di uno stream, si calcola in questo modo; dato un inzieme $$X = \{x_1, x_2, ..., x_n\}$$ la RMS è:

$$ X_{rms} = \sqrt{\frac{1}{n} \sum_{i=1}^{n}{x_i^2}} $$

Mentre se dobbiamo calcolarla su una funzione continua $$f$$ nell'intervallo $$ t_0, t_1 $$ la sua $$f_{rms}$$ sarà:

$$ f_{rms} = \sqrt{\frac{1}{t_1 - t_0}\int_{t_0}^{t_1}[f(x)]^2 dx} $$

Di quanto modificare il volume?

Con la funzione RMS possiamo calcolare il livello sonoro medio di tutto uno stream ottenedo così $$M_{s}$$. Sia $$v$$ il fattore di amplificazione e $$M_{rms}$$ il valore medio del volume dedio che vorremmo in output, allora:

$$ M_{rms} \sim v M_s $$

$$ v \sim \frac{M_{rms}}{M_s} $$

Il fattore di amplificazione andrà da $$ 0 $$ ad $$1$$ per attenuare il volume, $$1$$ per lasciarlo invariato e maggiore di $$1$$ per amplificarlo.

Conclusioni

Se abbiamo più stream audio con livelli di volume differenti possiamo allinearli portandoli tutti ad uno stesso volume medio. Per fare quanto dobbiamo prima analizzare ogni stream in ingresso, calcolare la sua $$M_s$$, da questa ricavare il fattore di amplificazione $$v$$ e applicarlo alla traccia stessa.

Ho scritto un piccolo programmino in Python che fa al caso nostro. Consiste in una libreria che si occupa di tutte le trasformazioni del volume dell'audio ed in un piccolo eseguibile per eseguire delle prove con file audio.

Esempi

Vediamo l'output di qualche esempio.

$ ./testgain --help ./testgain vesion 0.2

Usage: ./testgain [OPTINS] [MP3/OGG FILE...] This program is used for testing volumegain library.

OPTIONS: -p --play : play the stream -r --rms : set the default normalized rms and apply it to the stream -q --quiet : quiet mode -v --verbose : more verbose -V --version : print version info and exit -h --help : display this help end exit

Report bugs to danilo.abbasciano@gmail.com

$ ./testgain -v audio\ example/1.ogg Audio file: audio example/1.ogg Type: ogg Channel: 0 Mean RMS: 0.198368826507 Pa Mean RMS: -14.0505315166 dB Channel: 1 Mean RMS: 0.229194515258 Pa Mean RMS: -12.7959155894 dB Mean: All channel Mean RMS: 0.213781670882 Pa

$ ./testgain audio\ example/[1-3].ogg -r 0.12 Audio file: audio example/1.ogg All channel Mean RMS: 0.213781662184 Pa

Audio file: audio example/2.ogg All channel Mean RMS: 0.0407199536201 Pa

Audio file: audio example/3.ogg All channel Mean RMS: 0.206117526775 Pa

-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ Changing volume. File: audio example/1.ogg All channel Mean RMS: 0.119991210077 Pa

-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ Changing volume. File: audio example/2.ogg All channel Mean RMS: 0.119997166635 Pa

-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ Changing volume. File: audio example/3.ogg All channel Mean RMS: 0.119992128875 Pa

Downloads

Se vuoi saperne di più scarica la presentazione in PDF (in inglese) quì: [download file='volumegain-summercamp-presentation.pdf' name='volumegain presentation']

Se vuoi programma compreso di librerie, testgain ed esempi scarica questo archivio: [download file='volumegain-0.2.tgz' name='volumegain-0.2.tgz' version='0.2']