14.1 audioop --- Manipuler des données audio brutes

Le module audioop contient des opérations utiles sur des fragments sonores. Il travaille sur des fragments sonores qui consistent en échantillons d'entiers signés de 8, 16 ou 32 bits, stockés dans des chaînes de caractères Python. C'est le même format que celui utilisé pour les modules al et sunaudiodev. Tous les éléments scalaires sont des entiers, sauf indication contraire

Ce module fournit un support pour les codages en loi u et Intel/DVI ADPCM.

Quelques-unes des opérations les plus complexes n'admettent que des échantillons de 16 bits, sinon la taille de l'échantillon (en octets) est toujours un paramètre de l'opération.

Le module définit les variables et fonctions suivantes :

error
Cette exception est déclenchée sur toutes les erreurs, telles qu'un nombre inconnu d'octets par échantillon, etc.

add(fragment1, fragment2, taille)
Retourne un fragment qui est l'addition des deux échantillons passés en paramètre. taille est la taille de l'échantillon en octets, soit 1, 2 ou 4. Les deux fragments doivent avoir la même longueur.

adpcm2lin(adpcmfragment, taille, etat)
Décode un fragement codé en Intel/DVI ADPCM en un fragment linéaire. Voir la description de lin2adpcm() pour des détails sur le codage ADPCM. Retourne un tuple (echantillon, nouveletat) où l'échantillon a la taille spécifiée par taille.

adpcm32lin(adpcmfragment, taille, etat)
Décode un autre code ADPCM à 3 bits. Voir lin2adpcm3() pour les détails.

avg(fragment, taille)
Retourne la moyenne de tous les échantillons du fragment.

avgpp(fragment, taille)
Retourne la valeur moyenne crête-crête sur tous les échantillons du fragment. Aucun filtrage n'est effectué, l'utilité de cette routine est donc discutable.

bias(fragment, taille, biais)
Retourne un fragment qui est le fragment original avec un biais ajouté à chaque échantillon.

cross(fragment, taille)
Retourne le nombre de passages à zéro dans le fragment passé en argument.

findfactor(fragment, reference)
Retourne un facteur F tel que rms(add(fragment, mul(reference, -F))) est minimal, c'est-à-dire retourne le facteur avec lequel il faudrait multiplier reference pour qu'il corresponde le mieux possible à fragment. Les fragments doivent tous les deux contenir des échantillons sur 2 octets.

Le temps pris par cette routine est proportionnel à len(fragment).

findfit(fragment, reference)
Essaie de faire correspondre reference aussi bien que possible avec une portion de fragment (qui doit être le fragment le plus long). Ceci est effectué (conceptuellement) en prenant des tranches de fragment, en utilisant findfactor() pour calculer la meilleure correspondance, et en minimisant le résultat. Renvoie un tuple (decalage, facteur)decalage est le décalage (entier) dans fragment où la meilleure correspondance commence, et facteur est le facteur (nombre flottant) comme dans findfactor().

findmax(fragment, longueur)
Cherche dans fragment une portion de longueur longueur exprimée en nombre d'échantillons (pas d'octets !) d'énergie maximale, c'est-à-dire retourne i pour lequel rms(fragment[i*2:(i+length)*2]) est maximum. Les fragments doivent contenir des échantillons de deux octets.

La routine prend un temps proportionnel à len(fragment).

getsample(fragment, taille, index)
Retourne la valeur de l'échantillon index du fragment.

lin2lin(fragment, taille, nouvelletaille)
Convertit des échantillons entre les formats 1, 2 ou 4 octets.

lin2adpcm(fragment, taille, etat)
Convertit des échantillons au format ADPCM d'Intel/DVI à 4 bits. Le codage ADPCM est un système de codage adaptatif, dans lequel chaque nombre de 4 bits est la différence entre un échantillon et le suivant, divisé par un coefficient variable. L'algorithme ADPCM d'Intel/DVI a été retenu par l'IMA, il se pourrait donc bien qu'il devienne un standard.

etat est un tuple contenant l'état du codeur. Le codeur retourne un tuple (fragadpcm, nouveletat), et le nouveletat doit être passé au prochain appel de lin2adpcm(). Pour l'appel initial, None peut être passé dans l'état. fragadpcm est le fragment ADPCM codé compressé à deux valeurs de 4 bits par octet.

lin2adpcm3(fragment, taille, etat)
Il s'agit d'un autre codeur ADPCM qui n'utilise que 3 bits par échantillon. Il n'est pas compatible avec le codeur ADPCM d'Intel/DVI et son résultat n'est pas compressé (l'auteur a eu la flemme). Son utilisation est déconseillée.

lin2ulaw(fragment, taille)
Convertit des échantillons du fragment audio en codage loi u (ou loi mu) et retourne le résultat sous forme d'une chaîne de caractères Python. La loi u est un format d'encodage audio qui permet une gamme dynamique d'environ 14 bits en n'utilisant que des échantillons de 8 bits. Il est utilisé par le matériel audio de Sun, entre autres.

max(fragment, taille)
Retourne le maximum de la valeur absolue de tous les échantillons d'un fragment.

maxpp(fragment, taille)
Retourne la valeur maximum **crête-crête** dans le fragment sonore.

mul(fragment, taille, facteur)
Retourne un fragment construit en multipliant tous les échantillons du fragment original par la valeur flottante factor. Le débordement n'est pas traité ni signalé.

ratecv(fragment, taille, nbrecanaux, freqentree, freqsortie, etat[, poidsA[, poidsB]])
Convertit la fréquence d'échantillonnage du fragment en entrée.

etat est un tuple qui contient l'état du convertisseur. Le convertisseur retourne un tuple (nouveaufragment, nouveletat), et nouveletat doit être passé lors de l'appel suivant à ratecv().

Les arguments poidsA et poidsB sont des paramètres pour un simple filtre numérique et prennent par défaut les valeurs 1 et 0 respectivement.

reverse(fragment, taille)
Inverse les échantillons dans un fragment et retourne le fragment modifié.

rms(fragment, taille)
Retourne le "root-mean-square" (racine de la moyenne des carrés), c'est-à-dire
\catcode`_=8
\sqrt{\frac{\sum{{S_{i}}^{2}}}{n}}
Il s'agit d'une mesure de la puissance d'un signal audio.

tomono(fragment, taille, facteurg, facteurd)
Convertit un fragment stéréo en fragment mono. Le canal de gauche est multiplié par facteurg et le canal de droite par facteurd avant d'ajouter les deux canaux pour donner un signal mono.

tostereo(fragment, taille, facteurg, facteurd)
Génère un fragment stéréo à partir d'un fragment mono. Chaque paire d'échantillons dans le fragment stéréo est calculée à partir de l'échantillon mono en multipliant par facteurg pour obtenir l'échantillon sur le canal gauche et par facteurd pour le canal de droite.

ulaw2lin(fragment, taille)
Convertit des fragments sonores codés en loi u en fragments sonores codés linéairement. Le codage loi u utilise des échantillons de 8 bits, donc taille ne concerne ici que la taille des échantillons du fragment en sortie.

Notez bien que des opérations telles que mul() ou max() ne distinguent pas les fragments mono et stéréo, c'est-à-dire que tous les échantillons sont traités de la même façon. Si cela pose un problème, alors le fragment stéréo doit d'abord être séparé en deux fragments mono, qui sont recombinés ensuite. Voici un exemple de la façon de procéder :

def mul_stereo(echantillon, taille, facteurg, facteurd):
    echantillong = audioop.tomono(echantillon, taille, 1, 0)
    echantillond = audioop.tomono(echantillon, taille, 0, 1)
    echantillong = audioop.mul(echantillon, taille, facteurg)
    echantillond = audioop.mul(echantillon, taille, facteurd)
    echantillong = audioop.tostereo(echantillong, taille, 1, 0)
    echantillond = audioop.tostereo(echantillond, taille, 0, 1)
    return audioop.add(echantillong, echantillond, taille)

Si vous utilisez le codeur ADPCM pour construire des paquets réseau et que vous voulez que votre protocole soit sans état (c'est-à-dire qu'il puisse tolérer des pertes de paquets) vous ne devez pas seulement transmettre les données mais aussi l'état. Notez que vous devez envoyer l'état initial (celui que vous avez passé à lin2adpcm()) au décodeur, pas l'état final (celui qui est retourné par le codeur). Si vous voulez utiliser struct.struct() pour stocker l'état en binaire vous pouvez coder le premier élément (la valeur prévue) sur 16 bits et le second (l'index du delta) sur 8.

Les codeurs ADPCM n'ont jamais été essayés sur d'autres codeurs ADPCM, seulement sur eux-mêmes. Il se pourrait bien que j'aie mal interprété les standards, auquel cas ils ne seront pas interopérables avec les standards respectifs.

Les routines find*() peuvent paraître assez curieuses au premier abord. Elles ont pour objet principal l'annulation d'écho. Une façon raisonnablement rapide de le faire est de prélever la partie la plus énergique de l'échantillon de sortie, de le localiser dans l'échantillon d'entrée et de soustraire tout l'échantillon de sortie de l'échantillon d'entrée :

def annuleecho(donneessortie, donneesentree):
    pos = audioop.findmax(donneessortie, 800)    # un dixième de seconde
    test_sortie = donneessortie[pos*2:]
    test_entree = donneesentree[pos*2:]
    ipos, facteur = audioop.findfit(test_entree, test_sortie)
    # Optionnal (pour une meilleure annulation):
    # facteur = audioop.findfactor(test_entree[ipos*2:ipos*2+len(test_sortie)], 
    #              test_sortie)
    prebourrage = '\0'*(pos+ipos)*2
    postbourrage = '\0'*(len(donneesentree)-len(prebourrage)-len(donneessortie))
    donneessortie = prebourrage + audioop.mul(donneessortie,2,-factor) + postbourrage
    return audioop.add(donneesentree, donneessortie, 2)