Membaca file * .wav dengan Python


90

Saya perlu menganalisis suara yang ditulis dalam file .wav. Untuk itu saya perlu mengubah file ini menjadi kumpulan angka (array, misalnya). Saya rasa saya perlu menggunakan paket gelombang. Namun, saya tidak tahu bagaimana tepatnya cara kerjanya. Misalnya saya melakukan yang berikut:

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

Sebagai hasil dari kode ini saya berharap untuk melihat tekanan suara sebagai fungsi waktu. Sebaliknya, saya melihat banyak simbol aneh dan misterius (yang bukan merupakan angka heksadesimal). Adakah yang bisa, mohon, bantu saya dengan itu?

Jawaban:


110

Berdasarkan dokumentasi , scipy.io.wavfile.read(somefile)mengembalikan tupel dari dua item: yang pertama adalah laju pengambilan sampel dalam sampel per detik, yang kedua adalah numpylarik dengan semua data yang dibaca dari file:

from scipy.io import wavfile
samplerate, data = wavfile.read('./output/audio.wav')

Anda dapat menggabungkan ini dengan alat konversi baris perintah untuk membuka format lain.
endolith

11
Ini benar-benar kekurangan jumlah saluran. Bagaimana Anda bisa bekerja dengan audio tanpa mengetahui jumlah saluran?
bastibe

melemparkan beberapa kesalahan pembongkaran struct aneh di komputer saya. Saya pikir itu menggunakan struct.unpack ('<i', data) daripada struct.unpack ('<h', data) nak digunakan di bawah ini.
Alex S

1
Apakah perpustakaan ini berfungsi? Saya mengalami sejumlah masalah: scipy.io.wavfile.read ('/ usr / lib / python2.7 / dist-packages / pygame / contoh / data / house_lo.wav') -> Tidak ada data. scipy.io.wavfile.read ('/ usr / lib / python2.7 / dist-packages / pygame / contoh / data / secosmic_lo.wav') -> ZeroDivisionError: pembagian integer atau modulo dengan nol
Finn Årup Nielsen

6
@bastibe dataadalah array numpy 2-D sehingga data.shapemengembalikan tupel dari (num_samples, num_channels)
hobs

63

Dengan menggunakan structmodul , Anda dapat mengambil frame gelombang (yang berada dalam biner komplementer 2 antara -32768 dan 32767 (yaitu 0x8000dan 0x7FFF). Ini membaca file MONO, 16-BIT, WAVE. Saya menemukan halaman web ini cukup berguna dalam merumuskan ini:

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]))

Cuplikan ini membaca 1 bingkai. Untuk membaca lebih dari satu bingkai (mis., 13), gunakan

wavedata = wavefile.readframes(13)
data = struct.unpack("<13h", wavedata)

2
bagaimana menangani file stereo 24bits?
Basj

14
ini memberi saya kesalahan: "struct.error: unpack memerlukan argumen string dengan panjang 2"
Coder404

1
Jika Anda menjalankan bagian kode ini dengan file audio yang sangat besar. Komputer Anda akan mati karena kebutuhan memori oleh program ini. Perlu memproses file audio dengan blok untuk file audio besar
ArthurLambert

@ Coder404 Anda mungkin memiliki file gelombang stereo, atau kedalaman bit yang berbeda.
jmilloy

3
Bagi mereka yang, seperti saya, bertanya-tanya apa itu biner komplementer 2, lihat di sini stackoverflow.com/questions/1049722/what-is-2s-complement
Dennis Golomazov

34

Modul Python yang berbeda untuk membaca wav:

Setidaknya ada pustaka berikut ini untuk membaca file audio wave:

Contoh paling sederhana:

Ini adalah contoh sederhana dengan SoundFile:

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

Format keluaran:

Peringatan, data tidak selalu dalam format yang sama, itu bergantung pada pustaka. Contohnya:

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)

Keluaran:

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]

SoundFile dan Audiolab kembali mengapung antara -1 dan 1 (seperti yang dilakukan matab, itu adalah konvensi untuk sinyal audio). Scipy dan wave return integer, yang dapat Anda ubah menjadi float sesuai dengan jumlah bit pengkodean, misalnya:

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 

14

IMHO, cara termudah untuk mendapatkan data audio dari file suara ke dalam array NumPy adalah SoundFile :

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

Ini juga mendukung file 24-bit di luar kotak.

Ada banyak pustaka file suara yang tersedia, saya telah menulis ikhtisar di mana Anda dapat melihat beberapa pro dan kontra. Ia juga memiliki halaman yang menjelaskan bagaimana membaca file wav 24-bit dengan wavemodul .


Catatan: soundfile.read () dinormalisasi dengan 2 ^ (n_bits - 1) seperti dalam contoh scipy.io.wavfile sandoval
Quetzalcoatl

9

Anda dapat melakukannya dengan menggunakan modul scikits.audiolab . Ini membutuhkan NumPy dan SciPy untuk berfungsi, dan juga libsndfile.

Catatan, saya hanya bisa membuatnya berfungsi di Ubunutu dan bukan di OSX.

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

Sekarang Anda memiliki data wav


scikits.audiolabbelum diperbarui sejak 2010 dan mungkin hanya Python 2.
Boris

4

Jika Anda ingin memproses audio blok demi blok, beberapa solusi yang diberikan cukup buruk dalam arti bahwa mereka menyiratkan memuat seluruh audio ke dalam memori menghasilkan banyak cache yang meleset dan memperlambat program Anda. python-wavefile menyediakan beberapa konstruksi pythonic untuk melakukan pemrosesan blok-demi-blok NumPy menggunakan manajemen blok yang efisien dan transparan melalui generator. Kelebihan pythonic lainnya adalah pengelola konteks untuk file, metadata sebagai properti ... dan jika Anda menginginkan seluruh antarmuka file, karena Anda sedang mengembangkan prototipe cepat dan Anda tidak peduli dengan efisiensi, seluruh antarmuka file masih ada.

Contoh pemrosesan sederhana adalah:

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)

Contoh tersebut menggunakan kembali blok yang sama untuk membaca seluruh file, bahkan dalam kasus blok terakhir yang biasanya berukuran kurang dari ukuran yang diperlukan. Dalam hal ini Anda mendapatkan sepotong blok. Jadi percayalah pada panjang blok yang dikembalikan alih-alih menggunakan ukuran 512 yang di-hardcode untuk pemrosesan lebih lanjut.


1

Jika Anda akan melakukan transfer pada data bentuk gelombang maka mungkin Anda harus menggunakan SciPy , secara khusus scipy.io.wavfile.


2
BAIK. Saya baru saja menginstal SciPy tetapi saya tidak dapat menemukan contoh penggunaan scipy.io.wavfile.
Roman

6
Tidak ada yang seperti penerjemah interaktif untuk mencari tahu bagaimana segala sesuatunya bekerja! Jadilah orang yang ambisius!
Ignacio Vazquez-Abrams

1

Saya perlu membaca file WAV 24-bit 1 saluran. Postingan Nak di atas sangat bermanfaat. Namun, seperti yang disebutkan di atas oleh basj 24-bit tidak langsung. Saya akhirnya berhasil menggunakan cuplikan berikut:

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

Beberapa penskalaan tambahan diperlukan jika Anda membutuhkan hasil antara -1 dan +1. Mungkin beberapa dari Anda di luar sana mungkin menganggap ini berguna


0

jika hanya ada dua file dan kecepatan sampel sangat tinggi, Anda dapat menyisipkannya.

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

Anda juga dapat menggunakan import wavioperpustakaan sederhana. Anda juga perlu memiliki pengetahuan dasar tentang suara.


0

PyDub ( http://pydub.com/ ) belum disebutkan dan itu harus diperbaiki. IMO ini adalah pustaka paling komprehensif untuk membaca file audio dengan Python saat ini, meskipun bukan tanpa kesalahannya. Membaca file 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. Contohnya adalah tentang membaca file wav, tetapi PyDub dapat menangani banyak format yang berbeda di luar kotak. Peringatannya adalah ini didasarkan pada dukungan asli Python wav dan ffmpeg, jadi Anda harus menginstal ffmpeg dan banyak kapabilitas pydub bergantung pada versi ffmpeg. Biasanya jika ffmpeg bisa melakukannya, begitu pula pydub (yang cukup kuat).

Non-disclaimer: Saya tidak terkait dengan proyek ini, tetapi saya adalah pengguna berat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.