2010-03-01 4 views
10

J'ai utilisé Audiolab pour importer des fichiers son dans le passé, et cela a très bien fonctionné. Cependant:Importer des fichiers audio en Python sous forme de matrices NumPy (alternatives à audiolab)

-

In [2]: from scikits import audiolab 
-------------------------------------------------------------------- 

ImportError        Traceback (most recent call last) 

C:\Python26\Scripts\<ipython console> in <module>() 

C:\Python26\lib\site-packages\scikits\audiolab\__init__.py in <module>() 
    23 __version__ = _version 
    24 
---> 25 from pysndfile import formatinfo, sndfile 
    26 from pysndfile import supported_format, supported_endianness, \ 
    27      supported_encoding, PyaudioException, \ 

C:\Python26\lib\site-packages\scikits\audiolab\pysndfile\__init__.py in <module>() 
----> 1 from _sndfile import Sndfile, Format, available_file_formats, available_encodings 
     2 from compat import formatinfo, sndfile, PyaudioException, PyaudioIOError 
     3 from compat import supported_format, supported_endianness, supported_encoding 

ImportError: DLL load failed: The specified module could not be found.`` 

Donc je voudrais soit:

  • Figure pourquoi il ne fonctionne pas dans 2.6 (quelque chose de mal avec _sndfile.pyd?) Et peut-être trouver un moyen de l'étendre à travailler avec des formats non pris en charge
  • Trouver un remplacement complet pour AudioLab
+0

Le problème est spécifique à python 2.6 sur Windows (c'est-à-dire que vous ne le verrez pas sur python 2.5). Je n'ai pas encore trouvé le moyen de le réparer –

+2

Et j'ai finalement pris le temps entre deux vols, ça a fini par être un bug mingw. J'ai posté une nouvelle version 0.11.0, qui devrait résoudre ce problème. –

+1

David, vous avez fait un outil merveilleux dans audiolab! Je l'utilise souvent. Je vous remercie. –

Répondre

0

J'utilise PySoundFile récemment au lieu de Audiolab. Il s'installe facilement avec conda.

Il , comme la plupart des choses. Le MP3 n'est plus breveté, donc il n'y a aucune raison pour qu'il ne puisse pas le supporter; quelqu'un doit juste write support into libsndfile.

9

Audiolab est travailler pour moi sur Ubuntu 9.04 avec Python 2.6.2, donc ce pourrait être un problème de Windows. Dans votre lien vers le forum, l'auteur suggère également qu'il s'agit d'une erreur Windows.

Dans le passé, cette option a fonctionné pour moi aussi:

from scipy.io import wavfile 
fs, data = wavfile.read(filename) 

méfiez-vous juste que data peut avoir int type de données, il est donc pas mis à l'échelle dans les [-1,1). Par exemple, si data est int16, vous devez diviser data par 2**15 à l'échelle [-1,1,1).

+0

Est-ce que scipy.io peut lire des WAV 24 bits? – endolith

+0

Je ne suis pas certain à ce sujet. 16 ou 32 bits devrait être bien, mais je ne sais pas sur 24 bits. –

+0

Il ne lit pas grand-chose. Même les fichiers 16 bits sortent inversés, avec des erreurs d'enveloppement pour une valeur de -1. 24 bits obtient "TypeError: type de données non compris" Sûrement il y a quelque chose de mieux ... – endolith

5

Sox http://sox.sourceforge.net/ peut être votre ami pour ça. Il peut lire de nombreux formats différents et les afficher en tant que brut quel que soit le type de données que vous préférez. En fait, j'ai juste écrit le code pour lire un bloc de données d'un fichier audio dans un tableau numpy.

J'ai décidé de suivre cette voie pour la portabilité (sox est très largement disponible) et de maximiser la flexibilité des types d'entrée audio que je pourrais utiliser. En fait, il semble d'après les tests initiaux qu'il n'est pas sensiblement plus lent pour ce que je l'utilise pour ... ce qui est la lecture courte (quelques secondes) de l'audio à partir de très longs (heures) fichiers.

variables dont vous avez besoin:

SOX_EXEC# the sox/sox.exe executable filename 
filename # the audio filename of course 
num_channels # duh... the number of channels 
out_byps # Bytes per sample you want, must be 1, 2, 4, or 8 

start_samp # sample number to start reading at 
len_samp # number of samples to read 

Le code actuel est vraiment simple. Si vous souhaitez extraire le fichier entier, vous pouvez supprimer les éléments start_samp, len_samp et 'trim'.

import subprocess # need the subprocess module 
import numpy as NP # I'm lazy and call numpy NP 

cmd = [SOX_EXEC, 
     filename,    # input filename 
     '-t','raw',   # output file type raw 
     '-e','signed-integer', # output encode as signed ints 
     '-L',     # output little endin 
     '-b',str(out_byps*8), # output bytes per sample 
     '-',     # output to stdout 
     'trim',str(start_samp)+'s',str(len_samp)+'s'] # only extract requested part 

data = NP.fromstring(subprocess.check_output(cmd),'<i%d'%(out_byps)) 
data = data.reshape(len(data)/num_channels, num_channels) # make samples x channels 

PS: Voici le code à lire des trucs des en-têtes de fichier audio à l'aide sox ...

info = subprocess.check_output([SOX_EXEC,'--i',filename]) 
    reading_comments_flag = False 
    for l in info.splitlines(): 
     if(not l.strip()): 
      continue 
     if(reading_comments_flag and l.strip()): 
      if(comments): 
       comments += '\n' 
      comments += l 
     else: 
      if(l.startswith('Input File')): 
       input_file = l.split(':',1)[1].strip()[1:-1] 
      elif(l.startswith('Channels')): 
       num_channels = int(l.split(':',1)[1].strip()) 
      elif(l.startswith('Sample Rate')): 
       sample_rate = int(l.split(':',1)[1].strip()) 
      elif(l.startswith('Precision')): 
       bits_per_sample = int(l.split(':',1)[1].strip()[0:-4]) 
      elif(l.startswith('Duration')): 
       tmp = l.split(':',1)[1].strip() 
       tmp = tmp.split('=',1) 
       duration_time = tmp[0] 
       duration_samples = int(tmp[1].split(None,1)[0]) 
      elif(l.startswith('Sample Encoding')): 
       encoding = l.split(':',1)[1].strip() 
      elif(l.startswith('Comments')): 
       comments = '' 
       reading_comments_flag = True 
      else: 
       if(other): 
        other += '\n'+l 
       else: 
        other = l 
       if(output_unhandled): 
        print >>sys.stderr, "Unhandled:",l 
       pass 
+0

Intéressant, bien que gentil de kludgy et peut-être pas multiplate-forme? Il y a [pysox] (http://pypi.python.org/pypi/pysox) pour s'interfacer directement avec la bibliothèque [libSoX] (http://sox.sourceforge.net/libsox.html). On dirait que [SoX supporte un tas de formats en lui-même] (http://sox.sourceforge.net/Docs/Features) et peut utiliser plusieurs autres bibliothèques pour en savoir plus. J'ai eu beaucoup de problèmes à faire fonctionner audiolab, et il ne supporte pas les MP3, etc., donc pysox pourrait valoir la peine d'essayer. – endolith

+1

Je vais regarder pysox ... merci. Bien que l'approche du sous-processus utilisant sox ne soit pas vraiment pythonique ou jolie, elle est très puissante et relativement portable (puisque les binaires/installateurs sox peuvent être trouvés pour la plupart des systèmes). – travc

3

FFmpeg prend en charge les fichiers MP3 et fonctionne sous Windows (http://zulko.github.io/blog/2013/10/04/read-and-write-audio-files-in-python-using-ffmpeg/).

Lecture d'un fichier mp3:

import subprocess as sp 

FFMPEG_BIN = "ffmpeg.exe" 

command = [ FFMPEG_BIN, 
     '-i', 'mySong.mp3', 
     '-f', 's16le', 
     '-acodec', 'pcm_s16le', 
     '-ar', '44100', # ouput will have 44100 Hz 
     '-ac', '2', # stereo (set to '1' for mono) 
     '-'] 
pipe = sp.Popen(command, stdout=sp.PIPE, bufsize=10**8) 

données de format en tableau numpy:

raw_audio = pipe.proc.stdout.read(88200*4) 

import numpy 

audio_array = numpy.fromstring(raw_audio, dtype="int16") 
audio_array = audio_array.reshape((len(audio_array)/2,2)) 
0

Si vous voulez faire pour MP3

Voici ce que j'utilise: Il utilise pydub et scipy.

configuration complète (sur Mac, peuvent varier sur d'autres systèmes):

import tempfile 
import os 
import pydub 
import scipy 
import scipy.io.wavfile 


def read_mp3(file_path, as_float = False): 
    """ 
    Read an MP3 File into numpy data. 
    :param file_path: String path to a file 
    :param as_float: Cast data to float and normalize to [-1, 1] 
    :return: Tuple(rate, data), where 
     rate is an integer indicating samples/s 
     data is an ndarray(n_samples, 2)[int16] if as_float = False 
      otherwise ndarray(n_samples, 2)[float] in range [-1, 1] 
    """ 

    path, ext = os.path.splitext(file_path) 
    assert ext=='.mp3' 
    mp3 = pydub.AudioSegment.from_mp3(FILEPATH) 
    _, path = tempfile.mkstemp() 
    mp3.export(path, format="wav") 
    rate, data = scipy.io.wavfile.read(path) 
    os.remove(path) 
    if as_float: 
     data = data/(2**15) 
    return rate, data 

Crédit James Thompson's blog