2013-05-27 28 views
10

Tôi muốn tạo tệp âm thanh định dạng WAV 24 bit bằng Python 2.7 từ một mảng giá trị dấu phẩy động nằm giữa -1 và 1. Tôi không thể sử dụng scipy.io.wavfile.write vì nó chỉ hỗ trợ 16 hoặc 32 bit. Tài liệu dành cho mô-đun wave của Python không chỉ định định dạng dữ liệu cần thiết.Làm cách nào để ghi tệp WAV 24 bit bằng Python?

Vì vậy, có thể thực hiện điều này bằng Python?

Trả lời

3

Một tùy chọn khác có sẵn trong wavio (cũng trên PyPI: https://pypi.python.org/pypi/wavio), một mô-đun nhỏ mà tôi tạo ra như một công việc xung quanh vấn đề scipy chưa hỗ trợ tệp bit 24 bit. Tệp wavio.py chứa hàm write, ghi một mảng numpy vào một tệp WAV. Để viết tệp 24 bit, hãy sử dụng đối số sampwidth=3. Sự phụ thuộc duy nhất của wavio là yếu tố; wavio sử dụng thư viện chuẩn wave để xử lý định dạng tệp WAV.

Ví dụ,

In [21]: import numpy as np 

In [22]: import wavio 

In [23]: rate = 22050    # samples per second 

In [24]: T = 3     # sample duration (seconds) 

In [25]: f = 440.0    # sound frequency (Hz) 

In [26]: t = np.linspace(0, T, T*rate, endpoint=False) 

In [27]: sig = np.sin(2 * np.pi * f * t) 

In [28]: wavio.write("sine24.wav", sig, rate, sampwidth=3) 
2

Thử wave mô-đun:

In [1]: import wave 

In [2]: w = wave.open('foo.wav', 'w') # open for writing 

In [3]: w.setsampwidth(3) # 3 bytes/sample 

Python chỉ có thể đóng gói nguyên trong 2 và 4 kích thước cắn. Vì vậy, bạn có thể sử dụng một mảng NumPy với một dtype trên int32, và sử dụng một danh sách hiểu biết để có được 3/4 của các byte của mỗi số nguyên:

In [14]: d = np.array([1,2,3,4], dtype=np.int32) 

In [15]: d 
Out[15]: array([1, 2, 3, 4], dtype=int32) 

In [16]: [d.data[i:i+3] for i in range(0,len(d)*d.dtype.itemsize, d.dtype.itemsize)] 
Out[16]: ['\x01\x00\x00', '\x02\x00\x00', '\x03\x00\x00', '\x04\x00\x00'] 
+0

Tôi nên đưa gì cho hàm 'writeframes'? – detly

+0

@detly: nếu bạn bắt đầu với một mảng numpy của 'int32' loại, bạn chỉ có thể lấy các byte bạn cần, xem ở trên. –

+0

Câu hỏi đặt ra là cách viết các khung hình, nhưng không có các ví dụ về khung hình. – Greg

2

Sử dụng các module wave, các Wave_write.writeframes chức năng hy vọng dữ liệu WAV được được đóng gói thành chuỗi 3 byte ở định dạng nhỏ. Các mã sau hiện các trick:

import wave 
from contextlib import closing 
import struct 

def wavwrite_24(fname, fs, data): 
    data_as_bytes = (struct.pack('<i', int(samp*(2**23-1))) for samp in data) 
    with closing(wave.open(fname, 'wb')) as wavwriter: 
     wavwriter.setnchannels(1) 
     wavwriter.setsampwidth(3) 
     wavwriter.setframerate(fs) 
     for data_bytes in data_as_bytes: 
      wavwriter.writeframes(data_bytes[0:3]) 
+0

Tôi nghĩ rằng tỷ lệ của bạn nên là '(2 ** 23-1)' hoặc mẫu của bạn sẽ ký lật khi 'samp == 1.0' – papahabla

+1

Hmm, khéo léo. Đó là một vấn đề cố hữu ở điểm cố định - -1 có thể được biểu diễn, nhưng +1 không thể. Chia tỷ lệ theo '2 ** 23-1' có nghĩa là -1 bản đồ thành' -2 ** 23 + 1', đó là sai ... nhưng có lẽ ít sai hơn so với dấu lật. (Clipping tại '2 ** 23-1' sẽ tốt hơn, nhưng tôi nghĩ nó có thể thêm rất nhiều mã.) – detly

+0

Theo kinh nghiệm của tôi, đó là thực hành khá chuẩn để chỉ cần mở rộng quy mô. Về mặt kỹ thuật, mọi giá trị cũng đang được sàn. Chuyển đổi 'lý tưởng' thành số nguyên sẽ bao gồm làm tròn. – papahabla

2

Bạn nên cố gắng scikits.audiolab:

import numpy as np 
from scikits.audiolab import Sndfile, Format 

sig = np.array([0, 1, 0, -1, 0], dtype=np.float32) 
f = Sndfile('test_pcm24.wav', 'w', Format('wav', 'pcm24'), 1, 44100) 
f.write_frames(sig) 
f.close() # use contextlib.closing in real code 

Và để đọc nó một lần nữa:

f = Sndfile('test_pcm24.wav') 
sig = f.read_frames(f.nframes, dtype=np.float32) 
f.close() # use contextlib.closing in real code 

scikits.audiolab sử dụng libsndfile, vì vậy ngoài ra thành file WAV, bạn cũng có thể sử dụng FLAC, OGG và một số định dạng tệp khác.

+0

+1 Làm thế nào tôi bỏ lỡ điều này? – detly

+0

Lưu ý rằng hiện có (audiolab phiên bản 0.11.0) một lỗi trong 'read_frames()' khi chỉ định một loại khác với 'float64': https://github.com/cournape/audiolab/issues/3 – Matthias

+2

Tôi chỉ mới phát hiện ra thực sự khủng khiếp như thế nào khi thử cài đặt nó trên Windows. Thay đổi câu trả lời thành 'wavio'. – detly

3

Tôi đã submitted an answer to this question 2 năm trước đây, nơi tôi khuyến cáo scikits.audiolab. Trong khi chờ đợi, tình hình đã thay đổi và hiện tại có một thư viện có sẵn dễ sử dụng hơn và dễ cài đặt hơn nhiều, thậm chí nó còn có bản sao thư viện libsndfile riêng cho Windows và OSX (trên Linux là dễ dàng cài đặt anyway): PySoundFile!

Nếu bạn có CFFI và NumPy cài đặt, bạn có thể cài đặt PySoundFile chỉ đơn giản bằng cách chạy

pip install soundfile --user 

Viết một tập tin WAV 24-bit là dễ dàng:

import soundfile as sf 
sf.write('my_24bit_file.wav', my_audio_data, 44100, 'PCM_24') 

Trong ví dụ này, my_audio_data phải là một mảng NumPy với dtype'float64', 'float32', 'int32' hoặc 'int16'.

BTW, tôi đã thực hiện overview page nơi tôi đã cố gắng so sánh nhiều thư viện Python có sẵn để đọc/ghi tệp âm thanh.

0

Dưới đây là một phiên bản cập nhật của scipy.io.wavfile đó cho biết thêm:

  • 24 bit file .wav hỗ trợ cho đọc/ghi,
  • truy cập để mở khóa cho các dấu hiệu,
  • nhãn cue marker,
  • số siêu dữ liệu khác như quảng cáo chiêu hàng (nếu được xác định), v.v.

wavfile.py (enhanced)

Các vấn đề liên quan