Đọc tệp * .wav bằng Python


90

Tôi cần phân tích âm thanh được viết trong tệp .wav. Để làm được điều đó, tôi cần chuyển đổi tệp này thành tập hợp các số (ví dụ: mảng). Tôi nghĩ rằng tôi cần phải sử dụng gói sóng. Tuy nhiên, tôi không biết chính xác nó hoạt động như thế nào. Ví dụ, tôi đã làm như sau:

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

Theo kết quả của mã này, tôi mong đợi áp suất âm thanh là hàm của thời gian. Ngược lại, tôi thấy rất nhiều biểu tượng kỳ lạ, bí ẩn (không phải là số thập lục phân). Có ai có thể giúp tôi với?

Câu trả lời:


109

Theo tài liệu , scipy.io.wavfile.read(somefile)trả về một bộ gồm hai mục: đầu tiên là tốc độ lấy mẫu tính theo mẫu mỗi giây, mục thứ hai là một numpymảng có tất cả dữ liệu được đọc từ tệp:

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

Bạn có thể kết hợp điều này với các công cụ chuyển đổi dòng lệnh để mở các định dạng khác.
endolith

11
Nó thiếu nghiêm trọng số lượng kênh. Làm thế nào bạn có thể làm việc với âm thanh mà không cần biết số lượng kênh?
bastibe

ném một số lỗi giải nén cấu trúc kỳ lạ trên máy tính của tôi. Tôi nghĩ nó đang sử dụng struct.unpack ('<i', data) thay vì struct.unpack ('<h', data) nak được sử dụng bên dưới.
Alex S,

1
Thư viện này có hoạt động không? Tôi gặp phải một số vấn đề: scipy.io.wavfile.read ('/ usr / lib / python2.7 / dist-pack / pygame /amples / data / house_lo.wav') -> Không có dữ liệu. scipy.io.wavfile.read ('/ usr / lib / python2.7 / dist-pack / pygame /amples / data / secosmic_lo.wav') -> ZeroDivisionError: chia số nguyên hoặc modulo bằng 0
Finn Årup Nielsen

6
@bastibe datalà một NumPy mảng 2-D để data.shapetrả về một tuple của (num_samples, NUM_CHANNELS)
Hobs

63

Sử dụng structmô-đun , bạn có thể lấy các khung sóng (ở dạng nhị phân bổ sung của 2 từ -32768 đến 32767 (tức là 0x80000x7FFF). Điều này đọc tệp MONO, 16-BIT, WAVE. Tôi thấy trang web này khá hữu ích trong việc tạo công thức này:

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

Đoạn mã này đọc 1 khung. Để đọc nhiều hơn một khung (ví dụ: 13), hãy sử dụng

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

2
làm thế nào để xử lý các tệp âm thanh nổi 24bits?
Basj

14
này mang lại cho tôi những lỗi: "struct.error: giải nén đòi hỏi một đối số chuỗi có độ dài 2"
Coder404

1
Nếu bạn chạy đoạn mã này với một tệp âm thanh rất lớn. Máy tính của bạn sẽ chết do chương trình này cần bộ nhớ. Cần xử lý file audio bằng khối cho tập tin âm thanh lớn
ArthurLambert

@ Coder404 Có thể bạn có tệp sóng âm thanh nổi hoặc độ sâu bit khác.
jmilloy

3
Đối với những người, như tôi, đang tự hỏi là những gì 2s nhị phân bổ, xem tại đây stackoverflow.com/questions/1049722/what-is-2s-complement
Dennis Golomazov

34

Các mô-đun Python khác nhau để đọc wav:

Có ít nhất các thư viện sau để đọc các tệp âm thanh sóng:

Ví dụ đơn giản nhất:

Đây là một ví dụ đơn giản với SoundFile:

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

Định dạng của đầu ra:

Cảnh báo, dữ liệu không phải lúc nào cũng ở cùng một định dạng, điều đó phụ thuộc vào thư viện. Ví dụ:

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)

Đầu ra:

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]

Trả về SoundFile và Audiolab nổi giữa -1 và 1 (như matab, đó là quy ước cho tín hiệu âm thanh). Các số nguyên trả về dạng sóng và dạng sóng mà bạn có thể chuyển đổi thành số nổi theo số bit mã hóa, ví dụ:

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, cách dễ nhất để lấy dữ liệu âm thanh từ tệp âm thanh vào mảng NumPy là SoundFile :

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

Điều này cũng hỗ trợ các tệp 24-bit.

Có rất nhiều thư viện tệp âm thanh có sẵn, tôi đã viết một bài tổng quan để bạn có thể thấy một số ưu và nhược điểm. Nó cũng có trang giải thích cách đọc tệp wav 24 bit bằng wavemô-đun .


Lưu ý: soundfile.read () chuẩn hóa bằng 2 ^ (n_bits - 1) như trong ví dụ scipy.io.wavfile của sandoval
Quetzalcoatl

9

Bạn có thể thực hiện điều này bằng cách sử dụng mô-đun scikits.audiolab . Nó yêu cầu NumPy và SciPy hoạt động, và cả libsndfile.

Lưu ý, tôi chỉ có thể làm cho nó hoạt động trên Ubunutu chứ không phải trên OSX.

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

Bây giờ bạn có dữ liệu wav


scikits.audiolabđã không được cập nhật kể từ năm 2010 và nó có thể chỉ là Python 2.
Boris

4

Nếu bạn muốn xử lý từng khối âm thanh, một số giải pháp được đưa ra khá khủng khiếp theo nghĩa là chúng ngụ ý tải toàn bộ âm thanh vào bộ nhớ, tạo ra nhiều bộ nhớ cache và làm chậm chương trình của bạn. python-wavefile cung cấp một số cấu trúc pythonic để thực hiện xử lý từng khối NumPy bằng cách sử dụng quản lý khối hiệu quả và minh bạch bằng trình tạo. Các tính năng tuyệt vời khác của pythonic là trình quản lý ngữ cảnh cho tệp, siêu dữ liệu làm thuộc tính ... và nếu bạn muốn toàn bộ giao diện tệp, vì bạn đang phát triển một nguyên mẫu nhanh và bạn không quan tâm đến hiệu quả, toàn bộ giao diện tệp vẫn ở đó.

Một ví dụ đơn giản về xử lý sẽ là:

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)

Ví dụ sử dụng lại cùng một khối để đọc toàn bộ tệp, ngay cả trong trường hợp khối cuối cùng thường nhỏ hơn kích thước yêu cầu. Trong trường hợp này, bạn nhận được một lát của khối. Vì vậy, hãy tin tưởng độ dài khối được trả về thay vì sử dụng kích thước 512 mã cứng cho bất kỳ quá trình xử lý nào tiếp theo.


1

Nếu bạn định thực hiện chuyển dữ liệu dạng sóng thì có lẽ bạn nên sử dụng SciPy , cụ thể là scipy.io.wavfile.


2
ĐỒNG Ý. Tôi vừa cài đặt SciPy nhưng tôi không thể tìm thấy bất kỳ ví dụ nào về cách sử dụng scipy.io.wavfile.
Roman

6
Không có gì giống như trình thông dịch tương tác để tìm ra cách mọi thứ hoạt động! Hãy tham vọng!
Ignacio Vazquez-Abrams

1

Tôi cần đọc tệp WAV 24-bit 1 kênh. Bài viết trên của Nak rất hữu ích. Tuy nhiên, như đã đề cập ở trên bởi basj 24-bit không đơn giản. Cuối cùng tôi đã làm cho nó hoạt động bằng cách sử dụng đoạn mã sau:

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

Cần có một số tỷ lệ bổ sung nếu bạn cần kết quả từ -1 đến +1. Có thể một số bạn ở ngoài đó có thể thấy điều này hữu ích


0

nếu nó chỉ là hai tệp và tỷ lệ mẫu cao đáng kể, bạn có thể chỉ cần xen kẽ chúng.

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

u cũng có thể sử dụng import waviothư viện đơn giản u cũng cần có một số kiến ​​thức cơ bản về âm thanh.


0

PyDub ( http://pydub.com/ ) chưa được đề cập và điều đó sẽ được sửa. IMO, đây là thư viện toàn diện nhất để đọc các tệp âm thanh bằng Python ngay bây giờ, mặc dù không phải là không có lỗi của nó. Đọc tệp 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/

Tái bút. Ví dụ là về việc đọc một tệp wav, nhưng PyDub có thể xử lý rất nhiều định dạng khác nhau. Lưu ý là nó dựa trên cả hỗ trợ Python wav gốc và ffmpeg, vì vậy bạn phải cài đặt ffmpeg và rất nhiều khả năng pydub dựa trên phiên bản ffmpeg. Thông thường nếu ffmpeg có thể làm điều đó, thì pydub cũng vậy (khá mạnh).

Không từ chối trách nhiệm: Tôi không liên quan đến dự án, nhưng tôi là một người dùng nặng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.