From 42833b02cef54e9aaa84350fd7dd6c1cece47221 Mon Sep 17 00:00:00 2001 From: Guillaume Pellerin Date: Tue, 11 Feb 2014 23:03:55 +0100 Subject: [PATCH] cleanup, put Mainloop outside GstEncoder --- tests/sandbox/test_analyzer_stack.py | 18 ++++++++++ tests/sandbox/test_live.py | 28 ++++++++++++++++ ...g_bad.py => test_lolevel_streaming_mp3.py} | 33 ++++++++++--------- tests/sandbox/test_wav_resample.py | 12 +++++++ timeside/encoder/core.py | 29 +++++++++------- timeside/encoder/mp3.py | 9 ++--- timeside/tools/gstutils.py | 7 ++-- 7 files changed, 98 insertions(+), 38 deletions(-) create mode 100644 tests/sandbox/test_analyzer_stack.py create mode 100644 tests/sandbox/test_live.py rename tests/sandbox/{test_lolevel_streaming_bad.py => test_lolevel_streaming_mp3.py} (51%) create mode 100644 tests/sandbox/test_wav_resample.py diff --git a/tests/sandbox/test_analyzer_stack.py b/tests/sandbox/test_analyzer_stack.py new file mode 100644 index 0000000..06ea0e8 --- /dev/null +++ b/tests/sandbox/test_analyzer_stack.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +import timeside +import sys + +analyzers = [timeside.analyzer.Level(), + timeside.analyzer.AubioTemporal(),] + +source = sys.argv[-1] +print "Processing %s" % source +pipe = timeside.decoder.FileDecoder(source, stack=True) +print 'format: ', pipe.format() +for analyzer in analyzers: + pipe |= analyzer + +pipe.run() +print pipe.results + diff --git a/tests/sandbox/test_live.py b/tests/sandbox/test_live.py new file mode 100644 index 0000000..2a9e79e --- /dev/null +++ b/tests/sandbox/test_live.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +import timeside +import matplotlib.pyplot as plt +import numpy as np + + +d = timeside.decoder.LiveDecoder(num_buffers=256) +w = timeside.analyzer.Waveform() +s = timeside.analyzer.Spectrogram() +m = timeside.encoder.Mp3Encoder('/tmp/test_live.mp3', overwrite=True) +v = timeside.encoder.VorbisEncoder('/tmp/test_live.ogg', overwrite=True) + +(d | w | s | m | v).run() + +plt.figure(1) +plt.plot(w.results['waveform_analyzer'].time, w.results['waveform_analyzer'].data) + +plt.figure(2) +sr = s.results['spectrogram_analyzer'] +N = sr.parameters['FFT_SIZE'] +plt.imshow(20 * np.log10(sr.data.T), + origin='lower', + extent=[sr.time[0], sr.time[-1], 0, + (N // 2 + 1) / N * sr.frame_metadata.samplerate], + aspect='auto') + +plt.show() diff --git a/tests/sandbox/test_lolevel_streaming_bad.py b/tests/sandbox/test_lolevel_streaming_mp3.py similarity index 51% rename from tests/sandbox/test_lolevel_streaming_bad.py rename to tests/sandbox/test_lolevel_streaming_mp3.py index e414ead..1039ad2 100644 --- a/tests/sandbox/test_lolevel_streaming_bad.py +++ b/tests/sandbox/test_lolevel_streaming_mp3.py @@ -1,42 +1,45 @@ # -*- coding: utf-8 -*- +import os, sys, time + from timeside.core import * from timeside.decoder import * from timeside.analyzer import * from timeside.encoder import * from timeside.api import * -import sys + if len(sys.argv) > 1: source = sys.argv[1] else: import os.path - source= os.path.join (os.path.dirname(__file__), "../samples/sweep.wav") + source= os.path.join(os.path.dirname(__file__), "../samples/sweep.wav") -decoder = FileDecoder(source) -print "Creating decoder with id=%s for: %s" % (decoder.id(), source) -decoder.setup() -channels = decoder.channels() -print 'channels :', channels -samplerate = decoder.samplerate() -nframes = decoder.nframes() +streaming = True dest1 = "/tmp/test_filesink.mp3" dest2 = "/tmp/test_appsink.mp3" f = open(dest2,'w') -streaming=True -encoder = Mp3Encoder(dest1, streaming=True) -encoder.setup(channels=channels, samplerate=samplerate) +decoder = FileDecoder(source) +decoder.setup() + +encoder = Mp3Encoder(dest1, streaming=streaming, overwrite=True) +encoder.setup(channels=decoder.channels(), samplerate=decoder.samplerate(), + blocksize=decoder.blocksize(), totalframes=decoder.totalframes()) print encoder.pipe while True: encoder.process(*decoder.process()) + # time.sleep(0.1) if streaming: - f.write(encoder.chunk) - if encoder.eod : + f.write(encoder.chunk) + if encoder.eod: break +decoder.release() +encoder.release() f.close() -print encoder.pipe + +os.system('ls -tl /tmp/test*') \ No newline at end of file diff --git a/tests/sandbox/test_wav_resample.py b/tests/sandbox/test_wav_resample.py new file mode 100644 index 0000000..e30f103 --- /dev/null +++ b/tests/sandbox/test_wav_resample.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +import timeside +import os.path + +source = os.path.join(os.path.dirname(__file__), "../samples/sweep.wav") +dest = os.path.join(os.path.dirname(__file__), "../results/sweep_wav_48000.wav") + +decoder = timeside.decoder.FileDecoder(source) +decoder.output_samplerate = 48000 +encoder = timeside.encoder.WavEncoder(dest) +(decoder | encoder).run() diff --git a/timeside/encoder/core.py b/timeside/encoder/core.py index 7b1e0d3..24cc823 100644 --- a/timeside/encoder/core.py +++ b/timeside/encoder/core.py @@ -25,6 +25,17 @@ from timeside.api import IEncoder from timeside.tools import * from gst import _gst as gst +import threading + + +class MainloopThread(threading.Thread): + + def __init__(self, mainloop): + threading.Thread.__init__(self) + self.mainloop = mainloop + + def run(self): + self.mainloop.run() class GstEncoder(Processor): @@ -49,9 +60,7 @@ class GstEncoder(Processor): if not self.filename and not self.streaming: raise Exception('Must give an output') - import threading self.end_cond = threading.Condition(threading.Lock()) - self.eod = False self.metadata = None self.num_samples = 0 @@ -91,14 +100,6 @@ class GstEncoder(Processor): self.bus.add_signal_watch() self.bus.connect("message", self._on_message_cb) - import threading - class MainloopThread(threading.Thread): - def __init__(self, mainloop): - threading.Thread.__init__(self) - self.mainloop = mainloop - - def run(self): - self.mainloop.run() self.mainloop = gobject.MainLoop() self.mainloopthread = MainloopThread(self.mainloop) self.mainloopthread.start() @@ -126,6 +127,10 @@ class GstEncoder(Processor): self.end_cond.notify() self.end_cond.release() + @interfacedoc + def set_metadata(self, metadata): + self.metadata = metadata + @interfacedoc def process(self, frames, eod=False): self.eod = eod @@ -133,7 +138,7 @@ class GstEncoder(Processor): self.num_samples += frames.shape[0] else: self.num_samples += self.blocksize() - buf = numpy_array_to_gst_buffer(frames, frames.shape[0],self.num_samples, self.samplerate()) + buf = numpy_array_to_gst_buffer(frames, frames.shape[0], self.num_samples, self.samplerate()) self.src.emit('push-buffer', buf) if self.eod: self.src.emit('end-of-stream') @@ -146,4 +151,4 @@ if __name__ == "__main__": # Run doctest from __main__ and unittest from test_analyzer_preprocessors from tests import test_encoding, test_transcoding from tests.unit_timeside import run_test_module - run_test_module([test_encoding, test_transcoding]) \ No newline at end of file + run_test_module([test_encoding, test_transcoding]) diff --git a/timeside/encoder/mp3.py b/timeside/encoder/mp3.py index b108e67..61b9e4c 100644 --- a/timeside/encoder/mp3.py +++ b/timeside/encoder/mp3.py @@ -29,7 +29,6 @@ from timeside.encoder.core import GstEncoder from timeside.api import IEncoder from timeside.tools import * -import mutagen class Mp3Encoder(GstEncoder): """ gstreamer-based mp3 encoder """ @@ -84,13 +83,11 @@ class Mp3Encoder(GstEncoder): def mime_type(): return "audio/mpeg" - @interfacedoc - def set_metadata(self, metadata): - self.metadata = metadata - def write_metadata(self): """Write all ID3v2.4 tags to file from self.metadata""" + import mutagen from mutagen import id3 + id3 = id3.ID3(self.filename) for tag in self.metadata.keys(): value = self.metadata[tag] @@ -103,5 +100,3 @@ class Mp3Encoder(GstEncoder): id3.save() except: raise IOError('EncoderError: cannot write tags') - - diff --git a/timeside/tools/gstutils.py b/timeside/tools/gstutils.py index c5605f4..cb64068 100644 --- a/timeside/tools/gstutils.py +++ b/timeside/tools/gstutils.py @@ -7,14 +7,13 @@ import gobject gobject.threads_init() -def numpy_array_to_gst_buffer(frames, CHUNK_SIZE, num_samples, SAMPLE_RATE): +def numpy_array_to_gst_buffer(frames, chunk_size, num_samples, sample_rate): from gst import Buffer """ gstreamer buffer to numpy array conversion """ buf = Buffer(getbuffer(frames.astype("float32"))) #Set its timestamp and duration - buf.timestamp = gst.util_uint64_scale(num_samples, gst.SECOND, SAMPLE_RATE) - buf.duration = gst.util_uint64_scale(CHUNK_SIZE, gst.SECOND, SAMPLE_RATE) - + buf.timestamp = gst.util_uint64_scale(num_samples, gst.SECOND, sample_rate) + buf.duration = gst.util_uint64_scale(chunk_size, gst.SECOND, sample_rate) return buf -- 2.39.5