web-dev-qa-db-fra.com

Lecture de fichiers * .wav dans Python

J'ai besoin d'analyser le son écrit dans un fichier .wav. Pour cela, je dois transformer ce fichier en un ensemble de nombres (des tableaux, par exemple). Je pense que je dois utiliser le paquet wave. Cependant, je ne sais pas comment cela fonctionne exactement. Par exemple, j'ai fait ce qui suit:

import wave
w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r')
for i in range(w.getnframes()):
    frame = w.readframes(i)
    print frame

À la suite de ce code, je m'attendais à voir la pression acoustique en fonction du temps. En revanche, je vois beaucoup de symboles étranges et mystérieux (qui ne sont pas des nombres hexadécimaux). Quelqu'un peut-il, s'il vous plaît, m'aider avec ça?

72
Roman

Per les sources , scipy.io.wavfile.read(somefile) renvoie un tuple de deux éléments: le premier est le taux d'échantillonnage en échantillons par seconde, le second est un tableau numpy avec tous les données lues à partir du fichier. Semble assez facile à utiliser!

par exemple:

from scipy.io import wavfile
fs, data = wavfile.read('./output/audio.wav')
80
Alex Martelli

J'ai fait des recherches ce soir et j'ai compris ceci:

import wave, struct

waveFile = wave.open('sine.wav', 'r')

length = waveFile.getnframes()
for i in range(0,length):
    waveData = waveFile.readframes(1)
    data = struct.unpack("<h", waveData)
    print(int(data[0]))

Espérons que cet extrait aide quelqu'un. Détails: en utilisant le struct module , vous pouvez prendre les trames wave (qui sont en binaire complémentaire à 2s entre -32768; 0x8000 et 32767; 0x7FFF). Cela lit un fichier MONO, 16-BIT, WAVE. J'ai trouvé cette page Web très utile pour formuler cela.

Cet extrait lit 1 image. Pour lire plus d’une image (par exemple 13), utilisez

waveData = waveFile.readframes(13)
data = struct.unpack("<13h", waveData)
60
nak

Différent python modules à lire wav:

Il existe au moins les bibliothèques suivantes pour lire le fichier audio wave:

L'exemple le plus simple:

Voici un exemple simple avec Pysoundfile:

import soundfile as sf
data, samplerate = sf.read('existing_file.wav') 

Format de la sortie:

Attention, les données ne sont pas toujours au même format, cela dépend de la bibliothèque. Par exemple:

from scikits import audiolab
from scipy.io import wavfile
from sys import argv
for filetest in argv[1:]:
    [x, fs, nbBits] = audiolab.wavread(filePath)
    print '\nReading with scikits.audiolab.wavread: ', x
    [fs, x] = wavfile.read(filetest)
    print '\nReading with scipy.io.wavfile.read: ', x

Lecture avec scikits.audiolab.wavread: [0. 0. 0. ..., -0.00097656 -0.00079346 -0.00097656] Lecture avec scipy.io.wavfile.read: [0 0 0 ..., -32 -26 -32]

PySoundFile et Audiolab renvoient un float compris entre -1 et 1 (comme le fait Matab, c'est la convention du signal audio). Des nombres entiers Scipy et wave, qui peuvent être convertis en float en fonction du nombre de bits d'encodage.

Par exemple:

from scipy.io.wavfile import read as wavread
[samplerate, x] = wavread(audiofilename) # x is a numpy array of integer, representing the samples 
# scale to -1.0 -- 1.0
if x.dtype == 'int16':
    nb_bits = 16 # -> 16-bit wav files
Elif x.dtype == 'int32':
    nb_bits = 32 # -> 32-bit wav files
max_nb_bit = float(2 ** (nb_bits - 1))
samples = x / (max_nb_bit + 1.0) # samples is a numpy array of float representing the samples 
28
PatriceG

IMHO, le moyen le plus simple d'obtenir des données audio d'un fichier son dans un tableau NumPy est PySoundFile :

import soundfile as sf
data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')

Cela prend également en charge les fichiers 24 bits prêts à l'emploi.

Il existe de nombreuses bibliothèques de fichiers son disponibles, j'ai écrit n aperç où vous pouvez voir quelques avantages et inconvénients. Il comporte également une page expliquant comment lire un fichier wav 24 bits avec le module wave .

12
Matthias

Vous pouvez accomplir cela en utilisant le module scikits.audiolab . NumPy et SciPy sont nécessaires pour fonctionner, ainsi que libsndfile.

Notez que je n'ai pu le faire fonctionner que sur Ubunutu et non sur OSX.

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

Maintenant vous avez les données wav

8
ch3rryc0ke

Si vous voulez traiter un bloc audio par bloc, certaines des solutions proposées sont assez horribles dans le sens où elles impliquent de charger tout l’audio dans la mémoire, ce qui produit de nombreuses erreurs de cache et ralentit votre programme. python-wavefile fournit des constructions Pythonic permettant de traiter NumPy bloc par bloc en utilisant une gestion de blocs efficace et transparente à l'aide de générateurs. D'autres finesses Pythonic sont le gestionnaire de contexte pour les fichiers, les métadonnées en tant que propriétés ... et si vous voulez toute l'interface de fichier, parce que vous développez un prototype rapide et que vous ne vous souciez pas de l'efficacité, toute l'interface de fichier est toujours là.

Un exemple simple de traitement serait:

import sys
from wavefile import WaveReader, WaveWriter

with WaveReader(sys.argv[1]) as r :
    with WaveWriter(
            'output.wav',
            channels=r.channels,
            samplerate=r.samplerate,
            ) as w :

        # Just to set the metadata
        w.metadata.title = r.metadata.title + " II"
        w.metadata.artist = r.metadata.artist

        # This is the prodessing loop
        for data in r.read_iter(size=512) :
            data[1] *= .8     # lower volume on the second channel
            w.write(data)

L'exemple réutilise le même bloc pour lire le fichier entier, même dans le cas du dernier bloc qui est généralement inférieur à la taille requise. Dans ce cas, vous obtenez une tranche du bloc. Faites donc confiance à la longueur de bloc renvoyée au lieu d'utiliser une taille codée en dur pour tout traitement ultérieur.

4
vokimon

J'avais besoin de lire un fichier WAV 24 bits à 1 canal. Le message ci-dessus de Nak était très utile. Cependant, comme mentionné ci-dessus par basj 24 bits n'est pas simple. Je l'ai finalement obtenu en utilisant l'extrait suivant:

from scipy.io import wavfile
TheFile = 'example24bit1channelFile.wav'
[fs, x] = wavfile.read(TheFile)

# convert the loaded data into a 24bit signal

nx = len(x)
ny = nx/3*4    # four 3-byte samples are contained in three int32 words

y = np.zeros((ny,), dtype=np.int32)    # initialise array

# build the data left aligned in order to keep the sign bit operational.
# result will be factor 256 too high

y[0:ny:4] = ((x[0:nx:3] & 0x000000FF) << 8) | \
  ((x[0:nx:3] & 0x0000FF00) << 8) | ((x[0:nx:3] & 0x00FF0000) << 8)
y[1:ny:4] = ((x[0:nx:3] & 0xFF000000) >> 16) | \
  ((x[1:nx:3] & 0x000000FF) << 16) | ((x[1:nx:3] & 0x0000FF00) << 16)
y[2:ny:4] = ((x[1:nx:3] & 0x00FF0000) >> 8) | \
  ((x[1:nx:3] & 0xFF000000) >> 8) | ((x[2:nx:3] & 0x000000FF) << 24)
y[3:ny:4] = (x[2:nx:3] & 0x0000FF00) | \
  (x[2:nx:3] & 0x00FF0000) | (x[2:nx:3] & 0xFF000000)

y = y/256   # correct for building 24 bit data left aligned in 32bit words

Une mise à l'échelle supplémentaire est nécessaire si vous souhaitez obtenir des résultats compris entre -1 et +1. Peut-être que certains d'entre vous pourraient trouver cela utile

1
ProgJos

Si vous souhaitez effectuer des transferts sur les données de forme d'onde, vous devriez peut-être utiliser SciPy , plus précisément scipy.io.wavfile .

1

si ce ne sont que deux fichiers et que le taux d'échantillonnage est considérablement élevé, vous pouvez simplement les entrelacer.

from scipy.io import wavfile
rate1,dat1 = wavfile.read(File1)
rate2,dat2 = wavfile.read(File2)

if len(dat2) > len(dat1):#swap shortest
    temp = dat2
    dat2 = dat1
    dat1 = temp

output = dat1
for i in range(len(dat2)/2): output[i*2]=dat2[i*2]

wavfile.write(OUTPUT,rate,dat)
0
leec

vous pouvez également utiliser simple import wavio _ bibliothèque Vous devez également avoir des connaissances de base du son.

0
yunus