Ma chère, si j'ai bien compris ce que vous recherchez, vous vous lancez dans un domaine théorique appelé Digital Signal Processing (DSP). Ce domaine d'ingénierie va de la simple analyse de signaux à temps discret à des filtres adaptatifs complexes. Une bonne idée est de considérer les signaux à temps discret comme un vecteur, où chaque élément de ce vecteur est une valeur échantillonnée du signal original à temps continu. Une fois que vous avez obtenu les échantillons sous forme de vecteur, vous pouvez appliquer différentes techniques de signaux numériques à ce vecteur.
Malheureusement, sous Python, le passage des fichiers audio aux tableaux NumPy est assez lourd, comme vous pouvez le constater... Si vous n'idolâtrez pas un langage de programmation plutôt qu'un autre, je vous suggère fortement d'essayer MatLab/Octave. Matlab facilite l'accès aux échantillons à partir de fichiers. audioread()
vous confie cette tâche :) Et il existe de nombreuses boîtes à outils conçues spécifiquement pour le DSP.
Néanmoins, si vous avez vraiment l'intention de vous mettre à Python pour cela, je vais vous donner un pas-à-pas pour vous guider.
1. Obtenir les échantillons
La façon la plus simple d'obtenir les échantillons de la base de données .wav
est :
from scipy.io import wavfile
sampling_rate, samples = wavfile.read(f'/path/to/file.wav')
Vous pouvez également utiliser la fonction wave
y struct
pour obtenir les échantillons :
import numpy as np
import wave, struct
wav_file = wave.open(f'/path/to/file.wav', 'rb')
# from .wav file to binary data in hexadecimal
binary_data = wav_file.readframes(wav_file.getnframes())
# from binary file to samples
s = np.array(struct.unpack('{n}h'.format(n=wav_file.getnframes()*wav_file.getnchannels()), binary_data))
Réponse à votre question : binary_data
est un bytes
qui n'est pas lisible par l'homme et ne peut avoir de sens que pour une machine. Vous pouvez valider cette déclaration en tapant type(binary_data)
. Si vous voulez vraiment en savoir un peu plus sur cette bande de personnages bizarres, cliquez sur aquí .
Si votre audio est stéréo (c'est-à-dire qu'il a 2 canaux), vous pouvez remodeler ce signal pour obtenir le même format que celui obtenu avec scipy.io
s_like_scipy = s.reshape(-1, wav_file.getnchannels())
Chaque colonne est un canal. Dans les deux cas, les échantillons obtenus à partir des .wav
peut être utilisé pour tracer et comprendre le comportement temporel du signal.
Dans les deux cas, les échantillons obtenus à partir des fichiers sont représentés dans le fichier Modulation linéaire par code d'impulsion (LPCM)
2. Effectuer un traitement numérique du signal sur les échantillons audio
Je vous laisse décider de cette partie :) Mais c'est un beau livre pour vous guider dans la DSP. Malheureusement, je ne connais pas de bons livres sur Python, ce sont généralement des livres horribles... Mais ne vous inquiétez pas, la théorie peut être appliquée de la même manière en utilisant n'importe quel langage de programmation, tant que vous maîtrisez ce langage.
Quel que soit le livre que vous choisirez, tenez-vous en aux auteurs classiques, tels que Proakis, Oppenheim, et ainsi de suite... Ne vous souciez pas du langage de programmation qu'ils utilisent. Pour un guide plus pratique de DPS pour l'audio utilisant Python, voir cette page.
3. Lire les échantillons audio filtrés
import pyaudio
p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(wav_file.getsampwidth()),
channels = wav_file.getnchannels(),
rate = wav_file.getframerate(),
output = True)
# from samples to the new binary file
new_binary_data = struct.pack('{}h'.format(len(s)), *s)
stream.write(new_binary_data)
où wav_file.getsampwidth()
est le nombre d'octets par échantillon, et wav_file.getframerate()
est le taux d'échantillonnage. Il suffit d'utiliser les mêmes paramètres que ceux de l'audio d'entrée.
4. Enregistrer le résultat dans un nouveau .wav
fichier
wav_file=wave.open('/phat/to/new_file.wav', 'w')
wav_file.setparams((nchannels, sampwidth, sampling_rate, nframes, "NONE", "not compressed"))
for sample in s:
wav_file.writeframes(struct.pack('h', int(sample)))
où nchannels
est le nombre de canaux, sampwidth
est le nombre d'octets par échantillon, sampling_rate
est le taux d'échantillonnage, nframes
est le nombre total d'échantillons.