# wavio.py # Author: Warren Weckesser # License: BSD 3-Clause (http://opensource.org/licenses/BSD-3-Clause) # Synopsis: A Python module for reading and writing 24 bit WAV files. # Github: github.com/WarrenWeckesser/wavio import wave as _wave import numpy as _np def _wav2array(nchannels, sampwidth, data): """data must be the string containing the bytes from the wav file.""" num_samples, remainder = divmod(len(data), sampwidth * nchannels) if remainder > 0: raise ValueError('The length of data is not a multiple of ' 'sampwidth * num_channels.') if sampwidth > 4: raise ValueError("sampwidth must not be greater than 4.") if sampwidth == 3: a = _np.empty((num_samples, nchannels, 4), dtype=_np.uint8) raw_bytes = _np.fromstring(data, dtype=_np.uint8) a[:, :, :sampwidth] = raw_bytes.reshape(-1, nchannels, sampwidth) a[:, :, sampwidth:] = (a[:, :, sampwidth - 1:sampwidth] >> 7) * 255 result = a.view('>> rate = 22050 # samples per second >>> T = 3 # sample duration (seconds) >>> f = 440.0 # sound frequency (Hz) >>> t = np.linspace(0, T, T*rate, endpoint=False) >>> x = (2**23 - 1) * np.sin(2 * np.pi * f * t) >>> writewav24("sine24.wav", rate, x) """ a32 = _np.asarray(data, dtype=_np.int32) if a32.ndim == 1: # Convert to a 2D array with a single column. a32.shape = a32.shape + (1,) # By shifting first 0 bits, then 8, then 16, the resulting output # is 24 bit little-endian. a8 = (a32.reshape(a32.shape + (1,)) >> _np.array([0, 8, 16])) & 255 wavdata = a8.astype(_np.uint8).tostring() w = _wave.open(filename, 'wb') w.setnchannels(a32.shape[1]) w.setsampwidth(3) w.setframerate(rate) w.writeframes(wavdata) w.close()