From: yomguy Date: Tue, 31 Aug 2010 13:11:54 +0000 (+0000) Subject: add m4a encoder draft, fix joydiv for awdio X-Git-Tag: 0.3.2~109 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=abb5f34695cfb26577549e49668f9ec19d765dab;p=timeside.git add m4a encoder draft, fix joydiv for awdio --- diff --git a/timeside/encoder/__init__.py b/timeside/encoder/__init__.py index 169d959..1332cec 100644 --- a/timeside/encoder/__init__.py +++ b/timeside/encoder/__init__.py @@ -4,4 +4,5 @@ from core import * from ogg import * from wav import * from mp3 import * +from m4a import * #from timeside.encoder.flac import * diff --git a/timeside/encoder/m4a.py b/timeside/encoder/m4a.py new file mode 100644 index 0000000..f3aa280 --- /dev/null +++ b/timeside/encoder/m4a.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 Paul Brossier +# Copyright (c) 2010 Guillaume Pellerin + +# This file is part of TimeSide. + +# TimeSide is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# TimeSide is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with TimeSide. If not, see . + + +from timeside.core import Processor, implements, interfacedoc +from timeside.api import IEncoder +from numpy import array, frombuffer, getbuffer, float32 + +import pygst +pygst.require('0.10') +import gst +import gobject +gobject.threads_init () + + +class AacEncoder(Processor): + """ gstreamer-based AAC encoder """ + implements(IEncoder) + + def __init__(self, output): + self.file = None + if isinstance(output, basestring): + self.filename = output + else: + raise Exception("Streaming not supported") + + @interfacedoc + def setup(self, channels=None, samplerate=None, nframes=None): + super(AacEncoder, self).setup(channels, samplerate, nframes) + # TODO open file for writing + # the output data format we want + pipeline = gst.parse_launch(''' appsrc name=src + ! audioconvert + ! faac + ! filesink location=%s ''' % self.filename) + # store a pointer to appsink in our encoder object + self.src = pipeline.get_by_name('src') + srccaps = gst.Caps("""audio/x-raw-float, + endianness=(int)1234, + channels=(int)%s, + width=(int)32, + rate=(int)%d""" % (int(channels), int(samplerate))) + self.src.set_property("caps", srccaps) + + # start pipeline + pipeline.set_state(gst.STATE_PLAYING) + self.pipeline = pipeline + + @staticmethod + @interfacedoc + def id(): + return "gst_aac_enc" + + @staticmethod + @interfacedoc + def description(): + return "AAC GStreamer based encoder" + + @staticmethod + @interfacedoc + def format(): + return "AAC" + + @staticmethod + @interfacedoc + def file_extension(): + return "m4a" + + @staticmethod + @interfacedoc + def mime_type(): + return "audio/x-m4a" + + @interfacedoc + def set_metadata(self, metadata): + #TODO + pass + + @interfacedoc + def process(self, frames, eod=False): + buf = self.numpy_array_to_gst_buffer(frames) + self.src.emit('push-buffer', buf) + if eod: self.src.emit('end-of-stream') + return frames, eod + + def numpy_array_to_gst_buffer(self, frames): + """ gstreamer buffer to numpy array conversion """ + buf = gst.Buffer(getbuffer(frames)) + return buf + + + diff --git a/timeside/grapher/core.py b/timeside/grapher/core.py index 8e0f251..51a4552 100644 --- a/timeside/grapher/core.py +++ b/timeside/grapher/core.py @@ -260,7 +260,7 @@ class WaveformImageJoyContour(WaveformImage): WaveformImage.__init__(self, image_width, image_height, nframes, samplerate, fft_size, bg_color, color_scheme, filename=filename) self.contour = numpy.zeros(self.image_width) self.centroids = numpy.zeros(self.image_width) - self.ndiv = 6 + self.ndiv = 4 self.x = numpy.r_[0:self.image_width-1:1] self.dx1 = self.x[1]-self.x[0] @@ -315,12 +315,14 @@ class WaveformImageJoyContour(WaveformImage): for j in range(0,self.image_width-1): #line_color = self.color_lookup[int(self.centroids[j]*255.0)] x = self.x[j] - y = contour[j]*(self.image_height-1) + y = contour[j]*(self.image_height-2)/2+self.image_height/2 if self.previous_y: self.draw.line([self.previous_x, self.previous_y, x, y], line_color) + self.draw.line([self.previous_x, -self.previous_y+self.image_height, x, -y+self.image_height], line_color) else: self.draw.point((x, y), line_color) self.draw_anti_aliased_pixels(x, y, y, line_color) + self.draw_anti_aliased_pixels(x, -y+self.image_height, -y+self.image_height, line_color) self.previous_x, self.previous_y = x, y def process(self, frames, eod): @@ -338,13 +340,12 @@ class WaveformImageJoyContour(WaveformImage): def save(self): """ Apply last 2D transforms and write all pixels to the file. """ - # middle line (0 for none) a = 1 for x in range(self.image_width): self.pixel[x, self.image_height/2] = tuple(map(lambda p: p+a, self.pixel[x, self.image_height/2])) - self.image = self.image.transpose(Image.FLIP_TOP_BOTTOM) +# self.image = self.image.transpose(Image.FLIP_TOP_BOTTOM) self.image.save(self.filename) diff --git a/timeside/grapher/waveform_joy.py b/timeside/grapher/waveform_joy.py index 2289a9f..31edf48 100644 --- a/timeside/grapher/waveform_joy.py +++ b/timeside/grapher/waveform_joy.py @@ -30,7 +30,7 @@ class WaveformJoyDiv(Processor): FFT_SIZE = 0x400 @interfacedoc - def __init__(self, width=1024, height=256, output=None, bg_color=(0,0,0), color_scheme='default'): + def __init__(self, width=1024, height=256, output=None, bg_color=(136,136,136), color_scheme='default'): self.width = width self.height = height self.bg_color = bg_color diff --git a/timeside/tools/waveform_batch.py b/timeside/tools/waveform_batch.py index 1827524..c5baaf5 100644 --- a/timeside/tools/waveform_batch.py +++ b/timeside/tools/waveform_batch.py @@ -39,13 +39,13 @@ class GrapherScheme: ]} # Width of the image - self.width = 1024 + self.width = 655 # Height of the image - self.height = 320 + self.height = 95 # Background color - self.bg_color = (25,25,25) + self.bg_color = (136,136,136) # Force computation. By default, the class doesn't overwrite existing image files. self.force = True @@ -97,7 +97,8 @@ class Media2Waveform(object): (decoder | analyzer | waveform).run() duration = analyzer.result() img_name = os.path.split(image)[1] - image = os.path.split(image)[0]+os.sep+os.path.splitext(img_name)[0]+'_'+str(int(duration))+os.path.splitext(img_name)[1] + image = os.path.split(image)[0]+os.sep+os.path.splitext(img_name)[0] + '_' +\ + '_'.join([str(self.width), str(self.height), str(int(duration))])+os.path.splitext(img_name)[1] waveform.graph.filename = image print 'Rendering ', source, ' to ', waveform.graph.filename, '...' print 'frames per pixel = ', waveform.graph.samples_per_pixel