]> git.parisson.com Git - timeside.git/commitdiff
timeside/api.py: rename nframes to blocksize, use totalframes for file duration
authorPaul Brossier <piem@piem.org>
Sun, 2 Sep 2012 23:13:53 +0000 (17:13 -0600)
committerPaul Brossier <piem@piem.org>
Sun, 2 Sep 2012 23:13:53 +0000 (17:13 -0600)
tests/testdecoding.py
timeside/api.py
timeside/core.py
timeside/decoder/core.py

index 3589f410efeeb65922df564b2c798bac4a366400..020519777ae7f240af84d44e3cfe5d7c30b4f39c 100644 (file)
@@ -7,7 +7,7 @@ class TestDecoding(TestCase):
     "Test the low level streaming features"
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = None, None, None
+        self.samplerate, self.channels, self.blocksize = None, None, None
    
     def testWav(self):
         "Test wav decoding"
@@ -28,7 +28,7 @@ class TestDecoding(TestCase):
     def tearDown(self):
         decoder = FileDecoder(self.source)
 
-        decoder.setup(samplerate = self.samplerate, channels = self.channels, nframes = self.nframes)
+        decoder.setup(samplerate = self.samplerate, channels = self.channels, blocksize = self.blocksize)
 
         totalframes = 0.
 
@@ -36,16 +36,16 @@ class TestDecoding(TestCase):
             frames, eod = decoder.process()
             totalframes += frames.shape[0]
             if eod or decoder.eod: break
-            self.assertEquals(frames.shape[0], decoder.output_nframes )
+            self.assertEquals(frames.shape[0], decoder.output_blocksize )
             self.assertEquals(frames.shape[1], decoder.channels() )
 
         ratio = decoder.output_samplerate / float(decoder.input_samplerate)
         if 0:
-            print "input / output_samplerate:",   decoder.input_samplerate, '/', decoder.output_samplerate,
-            print "ratio:",             ratio
-            print "input / output_channels:",   decoder.input_channels, decoder.output_channels
-            print "input_duration:",     decoder.input_duration
-            print "input_total_frames:", decoder.input_total_frames
+            print "input / output_samplerate:", decoder.input_samplerate, '/', decoder.output_samplerate,
+            print "ratio:", ratio
+            print "input / output_channels:", decoder.input_channels, decoder.output_channels
+            print "input_duration:", decoder.input_duration
+            print "input_totalframes:", decoder.input_totalframes
 
         # FIXME compute actual number of frames from file
         if ratio == 1:
@@ -59,37 +59,37 @@ class TestDecoding(TestCase):
 class TestDecodingStereo(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = None, 2, None
+        self.samplerate, self.channels, self.blocksize = None, 2, None
 
 class TestDecodingMonoUpsampling(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = 48000, None, None
+        self.samplerate, self.channels, self.blocksize = 48000, None, None
 
 class TestDecodingMonoDownsampling(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = 16000, None, None
+        self.samplerate, self.channels, self.blocksize = 16000, None, None
 
 class TestDecodingStereoDownsampling(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = 32000, 2, None
+        self.samplerate, self.channels, self.blocksize = 32000, 2, None
 
 class TestDecodingStereoUpsampling(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = 96000, 2, None
+        self.samplerate, self.channels, self.blocksize = 96000, 2, None
 
-class TestDecodingShortframes(TestDecoding):
+class TestDecodingShortBlock(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = None, None, 256
+        self.samplerate, self.channels, self.blocksize = None, None, 256
 
-class TestDecodingLongframes(TestDecoding):
+class TestDecodingLongBlock(TestDecoding):
 
     def setUp(self):
-        self.samplerate, self.channels, self.nframes = None, None, 1024*8*2
+        self.samplerate, self.channels, self.blocksize = None, None, 1024*8*2
 
 if __name__ == '__main__':
     unittest.main(testRunner=TestRunner())
index edd68b5b48c7ad044fbb7912afa64dc4d96f9d9b..509d6bea435c6a33f52f9ee4dcf51631482d2eea 100644 (file)
@@ -34,11 +34,11 @@ class IProcessor(Interface):
         # be raised by MetaProcessor if the id is malformed or not unique amongst
         # registered processors.
 
-    def setup(self, channels=None, samplerate=None, nframes=None):
+    def setup(self, channels=None, samplerate=None, blocksize=None):
         """Allocate internal resources and reset state, so that this processor is
         ready for a new run. 
         
-        The channels, samplerate and/or nframes arguments may be required by 
+        The channels, samplerate and/or blocksize arguments may be required by
         processors which accept input. An error will occur if any of
         these arguments is passed to an output-only processor such as a decoder.
         """
@@ -53,7 +53,7 @@ class IProcessor(Interface):
         """Samplerate of the data returned by process(). May be different from
         the samplerate passed to setup()"""
 
-    def nframes():
+    def blocksize():
         """The total number of frames that this processor can output, or None if
         the duration is unknown."""
 
@@ -147,7 +147,7 @@ class IGrapher(IProcessor):
     """Media item visualizer driver interface"""
 
     # implementation: graphers which need to know the total number of frames
-    # should raise an exception in setup() if the nframesĀ argument is None 
+    # should raise an exception in setup() if the totalframes argument is None
 
     def __init__(self, width, height):
         """Create a new grapher. width and height are generally
index f5b3c31810c566f1193a37301bff8863af46c73a..a617164da413be1dbee2af6c0b397ac695fe18d7 100644 (file)
@@ -23,7 +23,7 @@ from timeside.exceptions import Error, ApiError
 import re
 import numpy
 
-__all__ = ['Processor', 'MetaProcessor', 'implements', 'abstract', 
+__all__ = ['Processor', 'MetaProcessor', 'implements', 'abstract',
            'interfacedoc', 'processors', 'get_processor', 'ProcessPipe',
            'FixedSizeInputAdapter']
 
@@ -58,13 +58,13 @@ class Processor(Component):
     implements(IProcessor)
 
     @interfacedoc
-    def setup(self, channels=None, samplerate=None, nframes=None):
+    def setup(self, channels=None, samplerate=None, blocksize=None):
         self.input_channels   = channels
         self.input_samplerate = samplerate
-        self.input_nframes    = nframes
+        self.input_blocksize  = blocksize
 
-    # default channels(), samplerate() and nframes() implementations returns 
-    # the input characteristics, but processors may change this behaviour by 
+    # default channels(), samplerate() and blocksize() implementations returns
+    # the input characteristics, but processors may change this behaviour by
     # overloading those methods
     @interfacedoc
     def channels(self):
@@ -75,8 +75,8 @@ class Processor(Component):
         return self.input_samplerate
 
     @interfacedoc
-    def nframes(self):
-        return self.input_nframes
+    def blocksize(self):
+        return self.input_blocksize
 
     @interfacedoc
     def process(self, frames, eod):
@@ -98,7 +98,7 @@ class FixedSizeInputAdapter(object):
 
     def __init__(self, buffer_size, channels, pad=False):
         """Construct a new adapter: buffer_size is the desired buffer size in frames,
-        channels the number of channels, and pad indicates whether the last block should 
+        channels the number of channels, and pad indicates whether the last block should
         be padded with zeros."""
 
         self.buffer      = numpy.empty((buffer_size, channels))
@@ -106,21 +106,21 @@ class FixedSizeInputAdapter(object):
         self.len         = 0
         self.pad         = pad
 
-    def nframes(self, input_nframes):
+    def blocksize(self, input_blocksize):
         """Return the total number of frames that this adapter will output according to the
-        input_nframes argument"""
+        input_blocksize argument"""
 
-        nframes = input_nframes
+        blocksize = input_blocksize
         if self.pad:
-            mod = input_nframes % self.buffer_size
+            mod = input_blocksize % self.buffer_size
             if mod:
-                nframes += self.buffer_size - mod
+                blocksize += self.buffer_size - mod
 
-        return nframes                
+        return blocksize
 
 
     def process(self, frames, eod):
-        """Returns an iterator over tuples of the form (buffer, eod) where buffer is a 
+        """Returns an iterator over tuples of the form (buffer, eod) where buffer is a
         fixed-sized block of data, and eod indicates whether this is the last block.
         In case padding is deactivated the last block may be smaller than the buffer size.
         """
@@ -155,17 +155,16 @@ class FixedSizeInputAdapter(object):
 
             yield block, True
             self.len = 0
-                            
+
 def processors(interface=IProcessor, recurse=True):
     """Returns the processors implementing a given interface and, if recurse,
     any of the descendants of this interface."""
     return implementations(interface, recurse)
-    
 
 def get_processor(processor_id):
     """Return a processor by its id"""
     if not _processors.has_key(processor_id):
-        raise Error("No processor registered with id: '%s'" 
+        raise Error("No processor registered with id: '%s'"
               % processor_id)
 
     return _processors[processor_id]
@@ -194,7 +193,7 @@ class ProcessPipe(object):
             for item in other:
                 self |= item
 
-        return self            
+        return self
 
     def run(self):
         """Setup/reset all processors in cascade and stream audio data along
@@ -207,7 +206,7 @@ class ProcessPipe(object):
         source.setup()
         last = source
         for item in items:
-            item.setup(last.channels(), last.samplerate(), last.nframes())
+            item.setup(last.channels(), last.samplerate(), last.blocksize())
             last = item
 
         # now stream audio data along the pipe
@@ -217,5 +216,4 @@ class ProcessPipe(object):
             for item in items:
                 frames, eod = item.process(frames, eod)
 
-        return self                
-       
+        return self
index 5fee050442b82960423e0d545611b8ffe089d227..75f584fd4c6866a94e99b16ac4aa8c7dbcf41429 100644 (file)
@@ -38,7 +38,7 @@ class FileDecoder(Processor):
     implements(IDecoder)
 
     mimetype = ''
-    output_nframes    = 8*1024
+    output_blocksize  = 8*1024
     output_samplerate = 44100
     output_channels   = 1
 
@@ -65,9 +65,9 @@ class FileDecoder(Processor):
         else:
             self.uri = uri
 
-    def setup(self, channels = None, samplerate = None, nframes = None):
+    def setup(self, channels = None, samplerate = None, blocksize = None):
         # the output data format we want
-        if nframes:    self.output_nframes    = nframes
+        if blocksize:  self.output_blocksize  = blocksize
         if samplerate: self.output_samplerate = int(samplerate)
         if channels:   self.output_channels   = int(channels)
         uri = self.uri
@@ -175,7 +175,7 @@ class FileDecoder(Processor):
             self.input_samplerate = caps[0]["rate"]
             self.input_channels = caps[0]["channels"]
             self.input_duration = length / 1.e9
-            self.input_total_frames = int(self.input_duration * self.input_samplerate)
+            self.input_totalframes = int(self.input_duration * self.input_samplerate)
             if "x-raw-float" in caps.to_string():
                 self.input_width = caps[0]["width"]
             else:
@@ -206,9 +206,9 @@ class FileDecoder(Processor):
             self.last_buffer = new_array
         else:
             self.last_buffer = concatenate((self.last_buffer, new_array), axis=0)
-        while self.last_buffer.shape[0] >= self.output_nframes:
-            new_block = self.last_buffer[:self.output_nframes]
-            self.last_buffer = self.last_buffer[self.output_nframes:]
+        while self.last_buffer.shape[0] >= self.output_blocksize:
+            new_block = self.last_buffer[:self.output_blocksize]
+            self.last_buffer = self.last_buffer[self.output_blocksize:]
             #print 'queueing', new_block.shape, 'remaining', self.last_buffer.shape
             self.queue.put( [new_block, False ] )
 
@@ -229,8 +229,15 @@ class FileDecoder(Processor):
         return self.output_samplerate
 
     @interfacedoc
-    def nframes(self):
-        return self.input_total_frames
+    def blocksize(self):
+        return self.output_blocksize
+
+    def totalframes(self):
+        if self.input_samplerate == self.output_samplerate:
+            return self.input_totalframes
+        else:
+            ratio = self.input_totalframes / self.output_samplerate
+            return self.input_totalframes * ratio
 
     @interfacedoc
     def release(self):
@@ -242,7 +249,6 @@ class FileDecoder(Processor):
 
     ## IDecoder methods
 
-    @interfacedoc
     @interfacedoc
     def format(self):
         # TODO check
@@ -266,4 +272,8 @@ class FileDecoder(Processor):
         return self.tags
 
     def duration(self):
-        return self.duration
+        if self.input_samplerate == self.output_samplerate:
+            return self.input_duration
+        else:
+            ratio = self.input_totalframes / self.output_samplerate
+            return self.input_duration * ratio