14.1 audioop -- Manipolare i dati audio grezzi

Il modulo audioop contiene alcune utili operazioni sulla frammentazione del suono. Esso opera su frammenti di suono consistenti di 8, 16 o 32 bit interi firmati, immagazzinati in stringhe Python. Questo è lo stesso formato usato dai moduli al e sunaudiodev. Tutti gli elementi scalari sono interi, a meno che non altrimenti specificato.

Questo modulo fornisce supporto per la codifica u-LAW e Intel/DVI ADPCM.

Alcune delle operazioni più complicate prelevano soltanto i campioni a 16 bit, altrimenti la dimensione del campione (in byte) è sempre un parametro dell'operazione.

Il modulo definisce le seguenti variabili e funzioni:

exception error
Questa eccezione viene sollevata per tutti gli errori, come un numero sconosciuto di byte per campione, etc. etc..

add( fragment1, fragment2, width)
Restituisce un frammento che è la somma dei due campioni passati come parametro. width è la lunghezza del campione passata in byte che può essere 1 e 2 o 4. Entrambi i frammenti dovrebbero avere la stessa lunghezza.

adpcm2lin( adpcmfragment, width, state)
Decodifica un frammento codificato con Intel/DVI ADPCM in un frammento lineare. Vedere la descrizione di lin2adpcm() per i dettagli sulla codifica ADPCM. Restituisce una tupla (sample, newstate) dove sample ha la larghezza specificata in width.

adpcm32lin( adpcmfragment, width, state)
Decodifica un codice a 3-bit ADPCM alternativo. Vedere lin2adpcm3() per i dettagli.

avg( fragment, width)
Restituisce la media su tutti i campioni nei frammenti.

avgpp( fragment, width)
Restituisce il valore medio del peak-peak su tutti i campioni del frammento. Non viene applicato alcun filtraggio, così l'utilità di questa routine rimane discutibile.

bias( fragment, width, bias)
Restituisce un frammento che è il frammento originale con un bias aggiunto ad ogni campione.

cross( fragment, width)
Restituisce il numero di zero attraversati nel frammento passati come un argomento.

findfactor( fragment, reference)
Restituisce un fattore F come quello rms(add(fragment, mul(reference, -F))), è minimale, per campione restituisce il fattore con il quale si dovrebbe moltiplicare il riferimento reference per farlo confrontare il meglio possibile con il frammento fragment. I frammenti dovrebbero contenere campioni a 2-byte.

Il tempo preso da questa routine è proporzionale a len(fragment).

findfit( fragment, reference)
Cerca la corrispondenza tra reference e una porzione di fragment (che dovrebbe essere il frammento più lungo). Questo è (concettualmente) fatto per estrarre porzioni del frammento, usando findfactor() per calcolare la migliore corrispondenza e minimizzare il risultato. I frammenti dovrebbero contenere entrambi campioni a 2-byte. Restituisce una tupla (offset, factor) dove offset è l'offset (intero) in fragment, da dove inizia la corrispondenza ottimale e factor è il fattore (in virgola mobile) come per findfactor().

findmax( fragment, length)
Cerca fragment per una fetta della lunghezza del campione length (non in byte!) con la massima energia, per campione restituisce i per cui rms(fragment[i*2:(i+length)*2]) è massimale. I frammenti dovrebbero contenere entrambi campioni ad 2-byte.

La routine prende il tempo proporzionalmente a len(fragment).

getsample( fragment, width, index)
Restituisce il valore del campione index dal frammento.

lin2lin( fragment, width, newwidth)
Converte campioni tra formati a 1-, 2- e 4-byte.

lin2adpcm( fragment, width, state)
Converte campioni a 4 bit codificati Intel/DVI ADPCM. La codifica ADPCM è uno schema di codifica adattabile, per cui ogni numero a 4 bit è la differenza tra un campione ed il prossimo, diviso da un passo (variabile). L'algoritmo Intel/DVI ADPCM è stato selezionato per essere usato dalla IMA, così avrà buone possibilità di divenire lo standard.

state è una tupla contenente lo stato del codificatore. Il codificatore restituisce una tupla (adpcmfrag, newstate), e newstate dovrebbe essere passato per la prossima chiamata di lin2adpcm(). Nella chiamata iniziale, None può essere passato come state. adpcmfrag è il frammento codificato ADPCM pacchettizzato con valori 2 4-bit per byte.

lin2adpcm3( fragment, width, state)
Questo è un codificatore alternativo ADPCM che usa solo 3 bit per campione. Non è compatibile con il codificatore Intel/DVI ADPCM e il suo output non è pacchettizzato (dovuto alla pigrezza dell'autore). Il suo uso è scoraggiato.

lin2ulaw( fragment, width)
Converte campioni in frammentazione audio, nella codifica u-LAW, e li restituisce come una stringa Python. u-LAW è un formato di codifica audio con il quale si può prendere un intervallo dinamico di circa 14 bit usando solo campioni ad 8 bit. Viene usato dall'hardware audio della Sun, tra gli altri.

minmax( fragment, width)
Restituisce una tupla consistente nei minimi a massimi valori di tutti i campioni nel frammento di suono.

max( fragment, width)
Restituisce il massimo del valore assoluto di tutti i campioni in un frammento.

maxpp( fragment, width)
Restituisce il massimo valore di peak-peak nel frammento di suono.

mul( fragment, width, factor)
Restituisce un frammento che ha tutti i campioni nel frammento originale, moltiplicati per il valore in virgola mobile di factor. L'overflow viene silenziosamente ignorato.

ratecv( fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])
Converte il frame rate del frammento di input.

state è la tupla contenente lo stato del convertitore. Il convertitore restituisce una tupla (newfragment, newstate), e newstate) dovrebbe essere passato per la prossima chiamata di ratecv(). La chiamata iniziale dovrebbe passare None per state.

Gli argomenti weightA e weightB sono parametri per un semplice filtro digitale ed il loro valore predefinito è rispettivamente 1 e 0.

reverse( fragment, width)
Inverte l'esempio in un frammento e restituisce il frammento modificato.

rms( fragment, width)
Restituisce la root-mean-square di un frammento, per es.

\begin{displaymath}
\catcode\lq _=8
\sqrt{\frac{\sum{{S_{i}}^{2}}}{n}}
\end{displaymath}

Questa è la misura della potenza in un segnale audio.

tomono( fragment, width, lfactor, rfactor)
Converte un frammento stereo in un frammento mono. Il canale di sinistra viene moltiplicato per lfactor ed il canale di destra per rfactor, prima di aggiungere i due canali per fornire un segnale mono.

tostereo( fragment, width, lfactor, rfactor)
Genera un frammento stereo da un frammento mono. Ogni coppia di campionature nel frammento stereo viene computata dal campione mono, laddove il canale sinistro viene moltiplicato per lfactor ed il canale destro per rfactor.

ulaw2lin( fragment, width)
Converte frammenti di suono. La codifica u-LAW usa sempre campioni a 8 bit, così la dimensione width fa riferimento solo alla dimensione del campione del frammento di output presente.

Notare che operazioni come mul() o max() non fanno distinzione tra frammenti mono e stereo, per esempio tutti i campioni sono trattati allo stesso modo. Se questo è un problema, il frammento stereo dovrebbe essere prima diviso in due frammenti mono, e dopo ricombinato. Qui c'è un esempio di come fare questo:

def mul_stereo(sample, width, lfactor, rfactor):
    lsample = audioop.tomono(sample, width, 1, 0)
    rsample = audioop.tomono(sample, width, 0, 1)
    lsample = audioop.mul(sample, width, lfactor)
    rsample = audioop.mul(sample, width, rfactor)
    lsample = audioop.tostereo(lsample, width, 1, 0)
    rsample = audioop.tostereo(rsample, width, 0, 1)
    return audioop.add(lsample, rsample, width)

Se si usa il codificatore ADPCM per costruire pacchetti di rete e volete che il vostro protocollo sia indipendente (per esempio per tollerare la perdita di pacchetti), non dovreste solamente trasmettere i dati ma anche lo stato dei dati. Notare che si potrebbe inviare lo stato iniziale, initial, (quello passato a lin2adpcm()) attraverso il decodificatore e non lo stato finale (come restituito dal codificatore). Se si vuole usare struct.struct() per conservare lo stato in forma binaria, si può codificare il primo elemento (il valore previsto) a 16 bit e il secondo (l'indice delta) in 8.

I codificatori ADPCM non sono mai stati confrontati con altri codificatori ADPCM, ma solamente con sé stessi. Potrebbe benissimo essere che abbia interpretato male lo standard, in questo caso non saranno interoperabili con i rispettivi standard.

Le routine find*() possono sembrare un po' buffe a prima vista. Sono significanti per fare da echo alle cancellazioni. Un modo ragionevolmente veloce per fare questo è prendere il pezzo più energetico del campione di output, posizionarlo nel campione di input e sottrarre l'intero campione di output dal campione di input:

def echocancel(outputdata, inputdata):
    pos = audioop.findmax(outputdata, 800)    # one tenth second
    out_test = outputdata[pos*2:]
    in_test = inputdata[pos*2:]
    ipos, factor = audioop.findfit(in_test, out_test)
    # Optional (for better cancellation):
    # factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)], 
    #              out_test)
    prefill = '\0'*(pos+ipos)*2
    postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
    outputdata = prefill + audioop.mul(outputdata,2,-factor) + postfill
    return audioop.add(inputdata, outputdata, 2)
Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.