+++ /dev/null
-# -*- coding: utf-8 -*-
-from timeside.analysis.api import *
-from timeside.analysis.core import *
-from timeside.analysis.channels import *
-from timeside.analysis.format import *
-from timeside.analysis.encoding import *
-from timeside.analysis.resolution import *
-from timeside.analysis.samplerate import *
-from timeside.analysis.duration import *
-from timeside.analysis.max_level import *
-from timeside.analysis.mean_level import *
-from timeside.analysis.dc import *
-
-
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.core import *
-
-class IMediaItemAnalyzer(Interface):
- """Media item analyzer driver interface"""
-
- def get_id():
- """Return a short id alphanumeric, lower-case string."""
-
- def get_name():
- """Return the analysis name, such as "Mean Level", "Max level",
- "Total length, etc..
- """
-
- def get_unit():
- """Return the unit of the data such as "dB", "seconds", etc...
- """
-
- def render(media_item, options=None):
- """Return the result data of the process"""
-
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class ChannelAnalyser(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "nb_channels"
-
- def get_name(self):
- return "Channels"
-
- def get_unit(self):
- return ""
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- if self.channels == 1:
- return 'mono'
- if self.channels == 2:
- return 'stereo'
- else:
- return self.channels
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Authors:
-# Bram de Jong <bram.dejong at domain.com where domain in gmail>
-# Guillaume Pellerin <yomguy at parisson.com>
-
-from timeside.core import *
-import optparse, math, sys
-import numpy
-import scikits.audiolab as audiolab
-
-class AudioProcessor(Component):
-
- def __init__(self):
- self.fft_size = 2048
- self.window_function = numpy.ones
- self.window = self.window_function(self.fft_size)
- self.spectrum_range = None
- self.lower = 100
- self.higher = 22050
- self.lower_log = math.log10(self.lower)
- self.higher_log = math.log10(self.higher)
- self.clip = lambda val, low, high: min(high, max(low, val))
-
- def pre_process(self, media_item):
- wav_file = media_item.file.path
- self.audio_file = audiolab.sndfile(wav_file, 'read')
- self.frames = self.audio_file.get_nframes()
- self.samplerate = self.audio_file.get_samplerate()
- self.channels = self.audio_file.get_channels()
- self.format = self.audio_file.get_file_format()
- self.encoding = self.audio_file.get_encoding()
-
- def get_samples(self):
- samples = self.audio_file.read_frames(self.frames)
- return samples
-
- def get_mono_samples(self):
- # convert to mono by selecting left channel only
- samples = self.get_samples()
- if self.channels > 1:
- return samples[:,0]
- else:
- return samples
-
- def read(self, start, size, resize_if_less=False):
- """ read size samples starting at start, if resize_if_less is True and less than size
- samples are read, resize the array to size and fill with zeros """
-
- # number of zeros to add to start and end of the buffer
- add_to_start = 0
- add_to_end = 0
-
- if start < 0:
- # the first FFT window starts centered around zero
- if size + start <= 0:
- if resize_if_less:
- return numpy.zeros(size)
- else:
- return numpy.array([])
- else:
- self.audio_file.seek(0)
-
- add_to_start = -start # remember: start is negative!
- to_read = size + start
-
- if to_read > self.frames:
- add_to_end = to_read - self.frames
- to_read = self.frames
- else:
- self.audio_file.seek(start)
-
- to_read = size
- if start + to_read >= self.frames:
- to_read = self.frames - start
- add_to_end = size - to_read
-
- try:
- samples = self.audio_file.read_frames(to_read)
- except IOError:
- # this can happen for wave files with broken headers...
- if resize_if_less:
- return numpy.zeros(size)
- else:
- return numpy.zeros(2)
-
- # convert to mono by selecting left channel only
- if self.channels > 1:
- samples = samples[:,0]
-
- if resize_if_less and (add_to_start > 0 or add_to_end > 0):
- if add_to_start > 0:
- samples = numpy.concatenate((numpy.zeros(add_to_start), samples), axis=1)
-
- if add_to_end > 0:
- samples = numpy.resize(samples, size)
- samples[size - add_to_end:] = 0
-
- return samples
-
-
- def spectral_centroid(self, seek_point, spec_range=120.0):
- """ starting at seek_point read fft_size samples, and calculate the spectral centroid """
-
- samples = self.read(seek_point - self.fft_size/2, self.fft_size, True)
-
- samples *= self.window
- fft = numpy.fft.fft(samples)
- spectrum = numpy.abs(fft[:fft.shape[0] / 2 + 1]) / float(self.fft_size) # normalized abs(FFT) between 0 and 1
- length = numpy.float64(spectrum.shape[0])
-
- # scale the db spectrum from [- spec_range db ... 0 db] > [0..1]
- db_spectrum = ((20*(numpy.log10(spectrum + 1e-30))).clip(-spec_range, 0.0) + spec_range)/spec_range
-
- energy = spectrum.sum()
- spectral_centroid = 0
-
- if energy > 1e-20:
- # calculate the spectral centroid
-
- if self.spectrum_range == None:
- self.spectrum_range = numpy.arange(length)
-
- spectral_centroid = (spectrum * self.spectrum_range).sum() / (energy * (length - 1)) * self.samplerate * 0.5
-
- # clip > log10 > scale between 0 and 1
- spectral_centroid = (math.log10(self.clip(spectral_centroid, self.lower, self.higher)) - self.lower_log) / (self.higher_log - self.lower_log)
-
- return (spectral_centroid, db_spectrum)
-
-
- def peaks(self, start_seek, end_seek):
- """ read all samples between start_seek and end_seek, then find the minimum and maximum peak
- in that range. Returns that pair in the order they were found. So if min was found first,
- it returns (min, max) else the other way around. """
-
- # larger blocksizes are faster but take more mem...
- # Aha, Watson, a clue, a tradeof!
- block_size = 4096
-
- max_index = -1
- max_value = -1
- min_index = -1
- min_value = 1
-
- if end_seek > self.frames:
- end_seek = self.frames
-
- if block_size > end_seek - start_seek:
- block_size = end_seek - start_seek
-
- if block_size <= 1:
- samples = self.read(start_seek, 1)
- return samples[0], samples[0]
- elif block_size == 2:
- samples = self.read(start_seek, True)
- return samples[0], samples[1]
-
- for i in range(start_seek, end_seek, block_size):
- samples = self.read(i, block_size)
-
- local_max_index = numpy.argmax(samples)
- local_max_value = samples[local_max_index]
-
- if local_max_value > max_value:
- max_value = local_max_value
- max_index = local_max_index
-
- local_min_index = numpy.argmin(samples)
- local_min_value = samples[local_min_index]
-
- if local_min_value < min_value:
- min_value = local_min_value
- min_index = local_min_index
-
- if min_index < max_index:
- return (min_value, max_value)
- else:
- return (max_value, min_value)
-
-
-
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class MeanDCShiftAnalyser(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "dc"
-
- def get_name(self):
- return "Mean DC shift"
-
- def get_unit(self):
- return "%"
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- samples = self.get_mono_samples()
- return numpy.round(100*numpy.mean(samples),4)
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-import datetime
-
-class DurationAnalyzer(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "duration"
-
- def get_name(self):
- return "Duration"
-
- def get_unit(self):
- return "h:m:s"
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- media_time = numpy.round(float(self.frames)/float(self.samplerate),0)
- return datetime.timedelta(0,media_time)
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class EncodingAnalyser(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "encoding"
-
- def get_name(self):
- return "Encoding format"
-
- def get_unit(self):
- return ""
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- return self.encoding
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class FormatAnalyser(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "format"
-
- def get_name(self):
- return "File format"
-
- def get_unit(self):
- return ""
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- return self.format
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class MaxLevelAnalyzer(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "max_level"
-
- def get_name(self):
- return "Maximum peak level"
-
- def get_unit(self):
- return "dB"
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- samples = self.get_samples()
- return numpy.round(20*numpy.log10(numpy.max(samples)),2)
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class MeanLevelAnalyser(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "mean_level"
-
- def get_name(self):
- return "Mean RMS level"
-
- def get_unit(self):
- return "dB"
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- samples = self.get_mono_samples()
- return numpy.round(20*numpy.log10(numpy.mean(numpy.sqrt(numpy.square(samples)))),2)
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class ResolutionAnalyser(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "resolution"
-
- def get_name(self):
- return "Resolution"
-
- def get_unit(self):
- return "bits"
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- if '8' in self.encoding:
- return 8
- if '16' in self.encoding:
- return 16
- if '24' in self.encoding:
- return 24
- if '32' in self.encoding:
- return 32
- else:
- return ''
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.analysis.core import *
-from timeside.analysis.api import IMediaItemAnalyzer
-import numpy
-
-class SampleRateAnalyzer(AudioProcessor):
- """Media item analyzer driver interface"""
-
- implements(IMediaItemAnalyzer)
-
- def get_id(self):
- return "samplerate"
-
- def get_name(self):
- return "Samplerate"
-
- def get_unit(self):
- return "Hz"
-
- def render(self, media_item, options=None):
- self.pre_process(media_item)
- return self.samplerate
+++ /dev/null
-# -*- coding: utf-8 -*-
-
-from timeside.analysis.vamp.core import *
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
-
-# 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 <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-from timeside.core import *
-from tempfile import NamedTemporaryFile
-from timeside.analysis.api import IMediaItemAnalyzer
-import os
-import random
-import subprocess
-import signal
-import time
-
-class VampCoreAnalyzer:
- """Parent class for Vamp plugin drivers"""
-
- def __init__(self):
- self.vamp_path = '/usr/lib/vamp/'
- # needs vamp-examples package
- self.host = 'vamp-simple-host'
- self.buffer_size = 0xFFFF
-
- def get_id(self):
- return "vamp_plugins"
-
- def get_name(self):
- return "Vamp plugins"
-
- def get_unit(self):
- return ""
-
- def get_plugins_list(self):
- if os.path.exists(self.vamp_path):
- args = ' --list-outputs'
- command = self.host + args
- #tmp_file = NamedTemporaryFile()
- data = self.core_process(command, self.buffer_size)
- text = ''
- plugins = []
- for chunk in data:
- text = text + chunk
- lines = text.split('\n')
- for line in lines:
- if line != '':
- struct = line.split(':')
- struct = struct[1:]
- plugins.append(struct)
- return plugins
- else:
- return []
-
- def get_wav_path(self, media_item):
- return settings.MEDIA_ROOT + '/' + media_item.file
- #return media_item
-
- def render(self, plugin, media_item):
- self.wavFile = self.get_wav_path(media_item)
- args = ' -s ' + ':'.join(plugin) + ' ' + str(self.wavFile)
- command = command = self.host + args
- data = self.core_process(command, self.buffer_size)
- string = ''
- values = {}
- for chunk in data:
- string = string + chunk
- lines = string.split('\n')
- for line in lines:
- if line != '':
- struct = line.split(':')
- values[struct[0]] = struct[1]
- return values
-
- def core_process(self, command, buffer_size):
- """Encode and stream audio data through a generator"""
-
- __chunk = 0
-
- try:
- proc = subprocess.Popen(command,
- shell = True,
- bufsize = buffer_size,
- stdin = subprocess.PIPE,
- stdout = subprocess.PIPE,
- close_fds = True)
- except:
- raise VampProcessError('Command failure:', command, proc)
-
- # Core processing
- while True:
- __chunk = proc.stdout.read(buffer_size)
- status = proc.poll()
- if status != None and status != 0:
- raise VampProcessError('Command failure:', command, proc)
- if len(__chunk) == 0:
- break
- yield __chunk
-
-
-class VampProcessError(TimeSideError):
-
- def __init__(self, message, command, subprocess):
- self.message = message
- self.command = str(command)
- self.subprocess = subprocess
-
- def __str__(self):
- if self.subprocess.stderr != None:
- error = self.subprocess.stderr.read()
- else:
- error = ''
- return "%s ; command: %s; error: %s" % (self.message,
- self.command,
- error)
--- /dev/null
+# -*- coding: utf-8 -*-
+from timeside.analysis.api import *
+from timeside.analysis.core import *
+from timeside.analysis.channels import *
+from timeside.analysis.format import *
+from timeside.analysis.encoding import *
+from timeside.analysis.resolution import *
+from timeside.analysis.samplerate import *
+from timeside.analysis.duration import *
+from timeside.analysis.max_level import *
+from timeside.analysis.mean_level import *
+from timeside.analysis.dc import *
+
+
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.core import *
+
+class IMediaItemAnalyzer(Interface):
+ """Media item analyzer driver interface"""
+
+ def get_id():
+ """Return a short id alphanumeric, lower-case string."""
+
+ def get_name():
+ """Return the analysis name, such as "Mean Level", "Max level",
+ "Total length, etc..
+ """
+
+ def get_unit():
+ """Return the unit of the data such as "dB", "seconds", etc...
+ """
+
+ def render(media_item, options=None):
+ """Return the result data of the process"""
+
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class ChannelAnalyser(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "nb_channels"
+
+ def get_name(self):
+ return "Channels"
+
+ def get_unit(self):
+ return ""
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ if self.channels == 1:
+ return 'mono'
+ if self.channels == 2:
+ return 'stereo'
+ else:
+ return self.channels
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Authors:
+# Bram de Jong <bram.dejong at domain.com where domain in gmail>
+# Guillaume Pellerin <yomguy at parisson.com>
+
+from timeside.core import *
+import optparse, math, sys
+import numpy
+import scikits.audiolab as audiolab
+
+class AudioProcessor(Component):
+
+ def __init__(self):
+ self.fft_size = 2048
+ self.window_function = numpy.ones
+ self.window = self.window_function(self.fft_size)
+ self.spectrum_range = None
+ self.lower = 100
+ self.higher = 22050
+ self.lower_log = math.log10(self.lower)
+ self.higher_log = math.log10(self.higher)
+ self.clip = lambda val, low, high: min(high, max(low, val))
+
+ def pre_process(self, media_item):
+ wav_file = media_item.file.path
+ self.audio_file = audiolab.sndfile(wav_file, 'read')
+ self.frames = self.audio_file.get_nframes()
+ self.samplerate = self.audio_file.get_samplerate()
+ self.channels = self.audio_file.get_channels()
+ self.format = self.audio_file.get_file_format()
+ self.encoding = self.audio_file.get_encoding()
+
+ def get_samples(self):
+ samples = self.audio_file.read_frames(self.frames)
+ return samples
+
+ def get_mono_samples(self):
+ # convert to mono by selecting left channel only
+ samples = self.get_samples()
+ if self.channels > 1:
+ return samples[:,0]
+ else:
+ return samples
+
+ def read(self, start, size, resize_if_less=False):
+ """ read size samples starting at start, if resize_if_less is True and less than size
+ samples are read, resize the array to size and fill with zeros """
+
+ # number of zeros to add to start and end of the buffer
+ add_to_start = 0
+ add_to_end = 0
+
+ if start < 0:
+ # the first FFT window starts centered around zero
+ if size + start <= 0:
+ if resize_if_less:
+ return numpy.zeros(size)
+ else:
+ return numpy.array([])
+ else:
+ self.audio_file.seek(0)
+
+ add_to_start = -start # remember: start is negative!
+ to_read = size + start
+
+ if to_read > self.frames:
+ add_to_end = to_read - self.frames
+ to_read = self.frames
+ else:
+ self.audio_file.seek(start)
+
+ to_read = size
+ if start + to_read >= self.frames:
+ to_read = self.frames - start
+ add_to_end = size - to_read
+
+ try:
+ samples = self.audio_file.read_frames(to_read)
+ except IOError:
+ # this can happen for wave files with broken headers...
+ if resize_if_less:
+ return numpy.zeros(size)
+ else:
+ return numpy.zeros(2)
+
+ # convert to mono by selecting left channel only
+ if self.channels > 1:
+ samples = samples[:,0]
+
+ if resize_if_less and (add_to_start > 0 or add_to_end > 0):
+ if add_to_start > 0:
+ samples = numpy.concatenate((numpy.zeros(add_to_start), samples), axis=1)
+
+ if add_to_end > 0:
+ samples = numpy.resize(samples, size)
+ samples[size - add_to_end:] = 0
+
+ return samples
+
+
+ def spectral_centroid(self, seek_point, spec_range=120.0):
+ """ starting at seek_point read fft_size samples, and calculate the spectral centroid """
+
+ samples = self.read(seek_point - self.fft_size/2, self.fft_size, True)
+
+ samples *= self.window
+ fft = numpy.fft.fft(samples)
+ spectrum = numpy.abs(fft[:fft.shape[0] / 2 + 1]) / float(self.fft_size) # normalized abs(FFT) between 0 and 1
+ length = numpy.float64(spectrum.shape[0])
+
+ # scale the db spectrum from [- spec_range db ... 0 db] > [0..1]
+ db_spectrum = ((20*(numpy.log10(spectrum + 1e-30))).clip(-spec_range, 0.0) + spec_range)/spec_range
+
+ energy = spectrum.sum()
+ spectral_centroid = 0
+
+ if energy > 1e-20:
+ # calculate the spectral centroid
+
+ if self.spectrum_range == None:
+ self.spectrum_range = numpy.arange(length)
+
+ spectral_centroid = (spectrum * self.spectrum_range).sum() / (energy * (length - 1)) * self.samplerate * 0.5
+
+ # clip > log10 > scale between 0 and 1
+ spectral_centroid = (math.log10(self.clip(spectral_centroid, self.lower, self.higher)) - self.lower_log) / (self.higher_log - self.lower_log)
+
+ return (spectral_centroid, db_spectrum)
+
+
+ def peaks(self, start_seek, end_seek):
+ """ read all samples between start_seek and end_seek, then find the minimum and maximum peak
+ in that range. Returns that pair in the order they were found. So if min was found first,
+ it returns (min, max) else the other way around. """
+
+ # larger blocksizes are faster but take more mem...
+ # Aha, Watson, a clue, a tradeof!
+ block_size = 4096
+
+ max_index = -1
+ max_value = -1
+ min_index = -1
+ min_value = 1
+
+ if end_seek > self.frames:
+ end_seek = self.frames
+
+ if block_size > end_seek - start_seek:
+ block_size = end_seek - start_seek
+
+ if block_size <= 1:
+ samples = self.read(start_seek, 1)
+ return samples[0], samples[0]
+ elif block_size == 2:
+ samples = self.read(start_seek, True)
+ return samples[0], samples[1]
+
+ for i in range(start_seek, end_seek, block_size):
+ samples = self.read(i, block_size)
+
+ local_max_index = numpy.argmax(samples)
+ local_max_value = samples[local_max_index]
+
+ if local_max_value > max_value:
+ max_value = local_max_value
+ max_index = local_max_index
+
+ local_min_index = numpy.argmin(samples)
+ local_min_value = samples[local_min_index]
+
+ if local_min_value < min_value:
+ min_value = local_min_value
+ min_index = local_min_index
+
+ if min_index < max_index:
+ return (min_value, max_value)
+ else:
+ return (max_value, min_value)
+
+
+
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class MeanDCShiftAnalyser(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "dc"
+
+ def get_name(self):
+ return "Mean DC shift"
+
+ def get_unit(self):
+ return "%"
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ samples = self.get_mono_samples()
+ return numpy.round(100*numpy.mean(samples),4)
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+import datetime
+
+class DurationAnalyzer(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "duration"
+
+ def get_name(self):
+ return "Duration"
+
+ def get_unit(self):
+ return "h:m:s"
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ media_time = numpy.round(float(self.frames)/float(self.samplerate),0)
+ return datetime.timedelta(0,media_time)
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class EncodingAnalyser(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "encoding"
+
+ def get_name(self):
+ return "Encoding format"
+
+ def get_unit(self):
+ return ""
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ return self.encoding
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class FormatAnalyser(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "format"
+
+ def get_name(self):
+ return "File format"
+
+ def get_unit(self):
+ return ""
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ return self.format
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class MaxLevelAnalyzer(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "max_level"
+
+ def get_name(self):
+ return "Maximum peak level"
+
+ def get_unit(self):
+ return "dB"
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ samples = self.get_samples()
+ return numpy.round(20*numpy.log10(numpy.max(samples)),2)
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class MeanLevelAnalyser(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "mean_level"
+
+ def get_name(self):
+ return "Mean RMS level"
+
+ def get_unit(self):
+ return "dB"
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ samples = self.get_mono_samples()
+ return numpy.round(20*numpy.log10(numpy.mean(numpy.sqrt(numpy.square(samples)))),2)
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class ResolutionAnalyser(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "resolution"
+
+ def get_name(self):
+ return "Resolution"
+
+ def get_unit(self):
+ return "bits"
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ if '8' in self.encoding:
+ return 8
+ if '16' in self.encoding:
+ return 16
+ if '24' in self.encoding:
+ return 24
+ if '32' in self.encoding:
+ return 32
+ else:
+ return ''
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.analysis.core import *
+from timeside.analysis.api import IMediaItemAnalyzer
+import numpy
+
+class SampleRateAnalyzer(AudioProcessor):
+ """Media item analyzer driver interface"""
+
+ implements(IMediaItemAnalyzer)
+
+ def get_id(self):
+ return "samplerate"
+
+ def get_name(self):
+ return "Samplerate"
+
+ def get_unit(self):
+ return "Hz"
+
+ def render(self, media_item, options=None):
+ self.pre_process(media_item)
+ return self.samplerate
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from timeside.analysis.vamp.core import *
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from timeside.core import *
+from tempfile import NamedTemporaryFile
+from timeside.analysis.api import IMediaItemAnalyzer
+import os
+import random
+import subprocess
+import signal
+import time
+
+class VampCoreAnalyzer:
+ """Parent class for Vamp plugin drivers"""
+
+ def __init__(self):
+ self.vamp_path = '/usr/lib/vamp/'
+ # needs vamp-examples package
+ self.host = 'vamp-simple-host'
+ self.buffer_size = 0xFFFF
+
+ def get_id(self):
+ return "vamp_plugins"
+
+ def get_name(self):
+ return "Vamp plugins"
+
+ def get_unit(self):
+ return ""
+
+ def get_plugins_list(self):
+ if os.path.exists(self.vamp_path):
+ args = ' --list-outputs'
+ command = self.host + args
+ #tmp_file = NamedTemporaryFile()
+ data = self.core_process(command, self.buffer_size)
+ text = ''
+ plugins = []
+ for chunk in data:
+ text = text + chunk
+ lines = text.split('\n')
+ for line in lines:
+ if line != '':
+ struct = line.split(':')
+ struct = struct[1:]
+ plugins.append(struct)
+ return plugins
+ else:
+ return []
+
+ def get_wav_path(self, media_item):
+ return settings.MEDIA_ROOT + '/' + media_item.file
+ #return media_item
+
+ def render(self, plugin, media_item):
+ self.wavFile = self.get_wav_path(media_item)
+ args = ' -s ' + ':'.join(plugin) + ' ' + str(self.wavFile)
+ command = command = self.host + args
+ data = self.core_process(command, self.buffer_size)
+ string = ''
+ values = {}
+ for chunk in data:
+ string = string + chunk
+ lines = string.split('\n')
+ for line in lines:
+ if line != '':
+ struct = line.split(':')
+ values[struct[0]] = struct[1]
+ return values
+
+ def core_process(self, command, buffer_size):
+ """Encode and stream audio data through a generator"""
+
+ __chunk = 0
+
+ try:
+ proc = subprocess.Popen(command,
+ shell = True,
+ bufsize = buffer_size,
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ close_fds = True)
+ except:
+ raise VampProcessError('Command failure:', command, proc)
+
+ # Core processing
+ while True:
+ __chunk = proc.stdout.read(buffer_size)
+ status = proc.poll()
+ if status != None and status != 0:
+ raise VampProcessError('Command failure:', command, proc)
+ if len(__chunk) == 0:
+ break
+ yield __chunk
+
+
+class VampProcessError(TimeSideError):
+
+ def __init__(self, message, command, subprocess):
+ self.message = message
+ self.command = str(command)
+ self.subprocess = subprocess
+
+ def __str__(self):
+ if self.subprocess.stderr != None:
+ error = self.subprocess.stderr.read()
+ else:
+ error = ''
+ return "%s ; command: %s; error: %s" % (self.message,
+ self.command,
+ error)