Muszę przeanalizować dźwięk zapisany w pliku .wav. W tym celu muszę przekształcić ten plik w zestaw liczb (na przykład tablice). Myślę, że muszę skorzystać z pakietu Wave. Nie wiem jednak, jak to dokładnie działa. Na przykład wykonałem następujące czynności:
import wave
w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r')
for i in range(w.getnframes()):
frame = w.readframes(i)
print frame
W wyniku tego kodu spodziewałem się zobaczyć ciśnienie akustyczne jako funkcję czasu. Dla kontrastu widzę wiele dziwnych, tajemniczych symboli (które nie są liczbami szesnastkowymi). Czy ktoś może mi w tym pomóc, proszę?
data
to dwuwymiarowa tablica numpy, więcdata.shape
zwraca krotkę (num_samples, num_channels)Korzystając z
struct
modułu , możesz wziąć ramki wave (które są w binarnych komplementarnych 2 między -32768 a 32767 (tj.0x8000
I0x7FFF
). Czyta to plik MONO, 16-BIT, WAVE. Ta strona internetowa jest bardzo przydatna przy formułowaniu tego: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]))
Ten fragment odczytuje 1 ramkę. Aby odczytać więcej niż jedną ramkę (np. 13), użyj
wavedata = wavefile.readframes(13) data = struct.unpack("<13h", wavedata)
źródło
Różne moduły Pythona do odczytu plików wav:
Istnieją co najmniej następujące biblioteki do odczytu plików audio Wave:
Najprostszy przykład:
Oto prosty przykład z SoundFile:
import soundfile as sf data, samplerate = sf.read('existing_file.wav')
Format wyjścia:
Uwaga, dane nie zawsze mają ten sam format, który zależy od biblioteki. Na przykład:
from scikits import audiolab from scipy.io import wavfile from sys import argv for filepath in argv[1:]: x, fs, nb_bits = audiolab.wavread(filepath) print('Reading with scikits.audiolab.wavread:', x) fs, x = wavfile.read(filepath) print('Reading with scipy.io.wavfile.read:', x)
Wynik:
Reading with scikits.audiolab.wavread: [ 0. 0. 0. ..., -0.00097656 -0.00079346 -0.00097656] Reading with scipy.io.wavfile.read: [ 0 0 0 ..., -32 -26 -32]
Zwrot SoundFile i Audiolab płynie między -1 a 1 (tak jak robi to matab, jest to konwencja dla sygnałów audio). Scipy i Wave zwracają liczby całkowite, które można przekonwertować na liczby zmiennoprzecinkowe w zależności od liczby bitów kodowania, na przykład:
from scipy.io.wavfile import read as wavread samplerate, x = wavread(audiofilename) # x is a numpy array of integers, 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) # samples is a numpy array of floats representing the samples
źródło
IMHO, najłatwiejszym sposobem na pobranie danych audio z pliku dźwiękowego do tablicy NumPy jest SoundFile :
import soundfile as sf data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')
Obsługuje również pliki 24-bitowe po wyjęciu z pudełka.
Dostępnych jest wiele bibliotek plików dźwiękowych, napisałem przegląd, w którym można zobaczyć kilka zalet i wad. Zawiera również stronę wyjaśniającą, jak odczytać 24-bitowy plik WAV za pomocą
wave
modułu .źródło
Możesz to osiągnąć za pomocą modułu scikits.audiolab . Do działania wymaga NumPy i SciPy, a także libsndfile.
Uwaga, udało mi się uruchomić go tylko na Ubunutu, a nie na OSX.
from scikits.audiolab import wavread filename = "testfile.wav" data, sample_frequency,encoding = wavread(filename)
Teraz masz dane wav
źródło
scikits.audiolab
nie był aktualizowany od 2010 roku i prawdopodobnie jest to tylko Python 2.Jeśli chcesz przetwarzać dźwięk blok po bloku, niektóre z podanych rozwiązań są dość okropne w tym sensie, że implikują ładowanie całego dźwięku do pamięci, powodując wiele błędów w pamięci podręcznej i spowalniając program. python-wavefile zapewnia pewne konstrukcje Pythona do przetwarzania NumPy blok po bloku przy użyciu wydajnego i przejrzystego zarządzania blokami za pomocą generatorów. Inne niuanse Pythona to menedżer kontekstu dla plików, metadane jako właściwości ... i jeśli chcesz mieć cały interfejs pliku, ponieważ tworzysz szybki prototyp i nie zależy Ci na wydajności, cały interfejs pliku jest nadal dostępny.
Prostym przykładem przetwarzania byłoby:
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)
Przykład ponownie wykorzystuje ten sam blok do odczytu całego pliku, nawet w przypadku ostatniego bloku, który jest zwykle mniejszy niż wymagany rozmiar. W tym przypadku otrzymasz kawałek bloku. Dlatego zaufaj zwróconej długości bloku zamiast używać zakodowanego na stałe rozmiaru 512 do dalszego przetwarzania.
źródło
Jeśli masz zamiar wykonywania przelewów na danych falowych to może należy użyć scipy konkretnie
scipy.io.wavfile
.źródło
Musiałem odczytać 1-kanałowy 24-bitowy plik WAV. Powyższy post Naka był bardzo przydatny. Jednak, jak wspomniano powyżej, 24-bitowy basj nie jest prosty. W końcu udało mi się go uruchomić, używając następującego fragmentu kodu:
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
Jeśli potrzebujesz wyników między -1 a +1, wymagane jest dodatkowe skalowanie. Może niektórym z was może się to przydać
źródło
jeśli to tylko dwa pliki, a częstotliwość próbkowania jest znacznie wysoka, możesz je po prostu przeplatać.
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)
źródło
Możesz również skorzystać z prostej
import wavio
biblioteki, ale musisz mieć podstawową wiedzę na temat dźwięku.źródło
PyDub ( http://pydub.com/ ) nie został wspomniany i należy to naprawić. IMO to obecnie najbardziej wszechstronna biblioteka do odczytywania plików audio w Pythonie, choć nie jest pozbawiona wad. Czytanie pliku wav:
from pydub import AudioSegment audio_file = AudioSegment.from_wav('path_to.wav') # or audio_file = AudioSegment.from_file('path_to.wav') # do whatever you want with the audio, change bitrate, export, convert, read info, etc. # Check out the API docs http://pydub.com/
PS. Przykład dotyczy czytania pliku wav, ale PyDub może obsługiwać wiele różnych formatów po wyjęciu z pudełka. Zastrzeżenie polega na tym, że jest on oparty zarówno na natywnej obsłudze formatu wav Pythona, jak i na ffmpeg, więc musisz mieć zainstalowany ffmpeg, a wiele funkcji pydub zależy od wersji ffmpeg. Zwykle jeśli ffmpeg może to zrobić, tak samo może być pydub (który jest dość potężny).
Brak zastrzeżenia: nie jestem związany z projektem, ale jestem ciężkim użytkownikiem.
źródło