From 0ca0eb3972798a5074ac709ffa3939c345ad134d Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Sun, 20 Apr 2014 12:51:11 +0200 Subject: [PATCH] Add open(), read() and write() functions This is the combination of a few commits from #18, plus a few more things. See also #14. --- pysoundfile.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/pysoundfile.py b/pysoundfile.py index e6fbb1a..908daf0 100644 --- a/pysoundfile.py +++ b/pysoundfile.py @@ -700,6 +700,74 @@ def write(self, data): self.seek(curr, SEEK_SET, 'w') +def open(*args, **kwargs): + """Return a new SoundFile object. + + Takes the same arguments as SoundFile.__init__(). + + """ + return SoundFile(*args, **kwargs) + + +def read(file, frames=-1, start=None, stop=None, **kwargs): + """Read a sound file and return its contents as NumPy array. + + The number of frames to read can be specified with frames, the + position to start reading can be specified with start. + By default, the whole file is read from the beginning. + Alternatively, a range can be specified with start and stop. + Both start and stop accept negative indices to specify positions + relative to the end of the file. + + The keyword arguments out, dtype, fill_value and always_2d are + forwarded to SoundFile.read(). + All further arguments are forwarded to SoundFile.__init__(). + + """ + from inspect import getargspec + + if frames >= 0 and stop is not None: + raise RuntimeError("Only one of {frames, stop} may be used") + + read_kwargs = {} + for arg in getargspec(SoundFile.read).args: + if arg in kwargs: + read_kwargs[arg] = kwargs.pop(arg) + with SoundFile(file, 'r', **kwargs) as f: + start, stop, _ = slice(start, stop).indices(f.frames) + if stop < start: + stop = start + if frames < 0: + frames = stop - start + f.seek(start, SEEK_SET) + data = f.read(frames, **read_kwargs) + return data, f.sample_rate + + +def write(data, file, sample_rate, *args, **kwargs): + """Write data from a NumPy array into a sound file. + + If file exists, it will be overwritten! + + If data is one-dimensional, a mono file is written. + For two-dimensional data, the columns are interpreted as channels. + All further arguments are forwarded to SoundFile.__init__(). + + Example usage: + + import pysoundfile as sf + sf.write(myarray, 'myfile.wav', 44100, 'PCM_24') + + """ + data = _np.asarray(data) + if data.ndim == 1: + channels = 1 + else: + channels = data.shape[1] + with SoundFile(file, 'w', sample_rate, channels, *args, **kwargs) as f: + f.write(data) + + def default_subtype(format): """Return default subtype for given format.""" return _default_subtypes.get(str(format).upper())