mirror of
https://github.com/correl/dejavu.git
synced 2024-11-23 19:19:53 +00:00
waive add
This commit is contained in:
parent
8b200c39f7
commit
2c961cc43f
2 changed files with 143 additions and 8 deletions
|
@ -2,6 +2,7 @@ import os
|
|||
import fnmatch
|
||||
import numpy as np
|
||||
from pydub import AudioSegment
|
||||
from pydub.utils import audioop
|
||||
import wavio
|
||||
|
||||
def find_files(path, extensions):
|
||||
|
@ -26,6 +27,8 @@ def read(filename, limit=None):
|
|||
|
||||
returns: (channels, samplerate)
|
||||
"""
|
||||
# pydub does not support 24-bit wav files, use wavio when this occurs
|
||||
try:
|
||||
audiofile = AudioSegment.from_file(filename)
|
||||
|
||||
if limit:
|
||||
|
@ -37,7 +40,18 @@ def read(filename, limit=None):
|
|||
for chn in xrange(audiofile.channels):
|
||||
channels.append(data[chn::audiofile.channels])
|
||||
|
||||
return channels, audiofile.frame_rate
|
||||
fs = audiofile.frame_rate
|
||||
except audioop.error:
|
||||
fs, _, audiofile = wavio.readwav(filename)
|
||||
|
||||
audiofile = audiofile.T
|
||||
audiofile = audiofile.astype(np.int16)
|
||||
|
||||
channels = []
|
||||
for chn in audiofile:
|
||||
channels.append(chn)
|
||||
|
||||
return channels, fs
|
||||
|
||||
|
||||
def path_to_songname(path):
|
||||
|
|
121
dejavu/wavio.py
Normal file
121
dejavu/wavio.py
Normal file
|
@ -0,0 +1,121 @@
|
|||
# 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('<i4').reshape(a.shape[:-1])
|
||||
else:
|
||||
# 8 bit samples are stored as unsigned ints; others as signed ints.
|
||||
dt_char = 'u' if sampwidth == 1 else 'i'
|
||||
a = _np.fromstring(data, dtype='<%s%d' % (dt_char, sampwidth))
|
||||
result = a.reshape(-1, nchannels)
|
||||
return result
|
||||
|
||||
|
||||
def readwav(file):
|
||||
"""
|
||||
Read a WAV file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
file : string or file object
|
||||
Either the name of a file or an open file pointer.
|
||||
|
||||
Return Values
|
||||
-------------
|
||||
rate : float
|
||||
The sampling frequency (i.e. frame rate)
|
||||
sampwidth : float
|
||||
The sample width, in bytes. E.g. for a 24 bit WAV file,
|
||||
sampwidth is 3.
|
||||
data : numpy array
|
||||
The array containing the data. The shape of the array is
|
||||
(num_samples, num_channels). num_channels is the number of
|
||||
audio channels (1 for mono, 2 for stereo).
|
||||
|
||||
Notes
|
||||
-----
|
||||
This function uses the `wave` module of the Python standard libary
|
||||
to read the WAV file, so it has the same limitations as that library.
|
||||
In particular, the function does not read compressed WAV files.
|
||||
|
||||
"""
|
||||
wav = _wave.open(file)
|
||||
rate = wav.getframerate()
|
||||
nchannels = wav.getnchannels()
|
||||
sampwidth = wav.getsampwidth()
|
||||
nframes = wav.getnframes()
|
||||
data = wav.readframes(nframes)
|
||||
wav.close()
|
||||
array = _wav2array(nchannels, sampwidth, data)
|
||||
return rate, sampwidth, array
|
||||
|
||||
|
||||
def writewav24(filename, rate, data):
|
||||
"""
|
||||
Create a 24 bit wav file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : string
|
||||
Name of the file to create.
|
||||
rate : float
|
||||
The sampling frequency (i.e. frame rate) of the data.
|
||||
data : array-like collection of integer or floating point values
|
||||
data must be "array-like", either 1- or 2-dimensional. If it
|
||||
is 2-d, the rows are the frames (i.e. samples) and the columns
|
||||
are the channels.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The data is assumed to be signed, and the values are assumed to be
|
||||
within the range of a 24 bit integer. Floating point values are
|
||||
converted to integers. The data is not rescaled or normalized before
|
||||
writing it to the file.
|
||||
|
||||
Example
|
||||
-------
|
||||
Create a 3 second 440 Hz sine wave.
|
||||
|
||||
>>> 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()
|
Loading…
Reference in a new issue