From 8ccd29ad23bb13d8a988e683c6bb21e5b3573aaa Mon Sep 17 00:00:00 2001 From: Andrey Zholos Date: Tue, 21 Jul 2015 23:25:01 +0000 Subject: [PATCH] read audio data directly in Au format to eliminate SciPy dependency --- setup.py | 2 +- wavcmp/track.py | 24 +++++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index 924989e..f2da0f9 100644 --- a/setup.py +++ b/setup.py @@ -42,5 +42,5 @@ entry_points={ "console_scripts": ["wavcmp=wavcmp.cmdline:main"] }, - install_requires=["numpy", "scipy"] + install_requires=["numpy"] ) diff --git a/wavcmp/track.py b/wavcmp/track.py index e5f98da..d443cb3 100644 --- a/wavcmp/track.py +++ b/wavcmp/track.py @@ -1,5 +1,4 @@ -import os, os.path, tempfile, subprocess, json, warnings -import scipy.io.wavfile +import os, os.path, subprocess, struct, json, warnings import numpy as np from .cmp import cmp_track, cmp_album @@ -111,24 +110,19 @@ def _probe(self): duration_accuracy = 1 # +/- seconds def _read_data(self): - with tempfile.NamedTemporaryFile(suffix=".wav") as temp: - subprocess.check_call( - ["ffmpeg", "-v", "quiet", "-i", self.filename, - "-f", "wav", "-y", temp.name], - stdin=open(os.devnull, "r")) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - # WavFileWarning because "fmt" chunk is size 18, - # as ffmpeg always outputs it - rate, data = scipy.io.wavfile.read(temp.name) - - assert data.ndim == 2 + out = subprocess.check_output( + ["ffmpeg", "-v", "quiet", "-i", self.filename, + "-f", "au", "-acodec", "pcm_s16be", "pipe:"], + stdin=open(os.devnull, "r"), bufsize=-1) + magic, offset, _, codec, rate, channels = struct.unpack(">6I", out[:24]) + assert magic == 0x2e736e64 and codec == 3 and offset > 24 + data = np.frombuffer(out, offset=offset, dtype=">i2") + data = data.reshape((-1, channels)).astype(np.int16, order="F") if rate != self.rate or data.shape[1] != 2 or \ abs(data.shape[0] - self.duration) > \ self.duration_accuracy * rate: raise RuntimeError( "Data didn't match probe on file: '{}'".format(self.filename)) - assert data.dtype == np.int16 return data def data(self):