changeset 153:39559566226b

Add _FileAudioSource class
author Amine Sehili <amine.sehili@gmail.com>
date Sun, 24 Feb 2019 15:21:19 +0100
parents 71181bbe312a
children dde6da718b42
files auditok/io.py
diffstat 1 files changed, 51 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/auditok/io.py	Sat Feb 23 21:08:01 2019 +0100
+++ b/auditok/io.py	Sun Feb 24 15:21:19 2019 +0100
@@ -23,12 +23,12 @@
         from_file
         player_for
 """
-from abc import ABCMeta, abstractmethod
 import os
 import sys
 import wave
 import audioop
 from array import array
+from functools import partial
 
 if sys.version_info >= (3, 0):
     PYTHON_3 = True
@@ -203,7 +203,7 @@
     return _array_to_bytes(buffer[use_channel::channels])
 
 
-class AudioSource():
+class AudioSource:
     """ 
     Base class for audio source objects.
 
@@ -223,12 +223,17 @@
             Number of channels of audio stream.
     """
 
-    def __init__(self, sampling_rate=DEFAULT_SAMPLE_RATE,
-                 sample_width=DEFAULT_SAMPLE_WIDTH,
-                 channels=DEFAULT_NB_CHANNELS):
+    def __init__(
+        self,
+        sampling_rate=DEFAULT_SAMPLE_RATE,
+        sample_width=DEFAULT_SAMPLE_WIDTH,
+        channels=DEFAULT_NB_CHANNELS,
+    ):
 
         if not sample_width in (1, 2, 4):
-            raise AudioParameterError("Sample width must be one of: 1, 2 or 4 (bytes)")
+            raise AudioParameterError(
+                "Sample width must be one of: 1, 2 or 4 (bytes)"
+            )
 
         self._sampling_rate = sampling_rate
         self._sample_width = sample_width
@@ -309,13 +314,14 @@
         return self.channels
 
 
-class Rewindable():
+class Rewindable:
     """
     Base class for rewindable audio streams.
     Subclasses should implement methods to return to the beginning of an
     audio stream as well as method to move to an absolute audio position
     expressed in time or in number of samples. 
     """
+
     @property
     def rewindable(self):
         return True
@@ -324,7 +330,6 @@
         """ Go back to the beginning of audio stream """
         raise NotImplementedError
 
-
     def get_position(self):
         """ Return the total number of already read samples """
         raise NotImplementedError
@@ -343,7 +348,6 @@
         """
         raise NotImplementedError
 
-
     def set_time_position(self, time_position):
         """ Move to an absolute position expressed in seconds
 
@@ -449,6 +453,44 @@
         self.set_position(position)
 
 
+class _FileAudioSource(AudioSource):
+    def __init__(self, sampling_rate, sample_width, channels, use_channel):
+        AudioSource.__init__(self, sampling_rate, sample_width, channels)
+        self._audio_stream = None
+        if channels > 1:
+            self._extract_selected_channel = partial(
+                _extract_selected_channel,
+                channels=channels,
+                sample_width=sample_width,
+                use_channel=use_channel,
+            )
+        else:
+            self._extract_selected_channel = lambda x: x
+
+    def __del__(self):
+        if self.is_open():
+            self.close()
+
+    def is_open(self):
+        return self._audio_stream is not None
+
+    def close(self):
+        if self._audio_stream is not None:
+            self._audio_stream.close()
+            self._audio_stream = None
+
+    def _read_from_stream(self, size):
+        raise NotImplementedError
+
+    def read(self, size):
+        if not self.is_open():
+            raise AudioIOError("Audio stream is not open")
+        data = self._read_from_stream(size)
+        if data:
+            return self._extract_selected_channel(data)
+        return None
+
+
 class WaveAudioSource(AudioSource):
     """
     A class for an `AudioSource` that reads data from a wave file.