##// END OF EJS Templates
implemented support for multiple channels in Audio
Erik Tollerud -
Show More
@@ -14,7 +14,7 b' class Audio(DisplayObject):'
14 When this object is returned by an input cell or passed to the
14 When this object is returned by an input cell or passed to the
15 display function, it will result in Audio controls being displayed
15 display function, it will result in Audio controls being displayed
16 in the frontend (only works in the notebook).
16 in the frontend (only works in the notebook).
17
17
18 Parameters
18 Parameters
19 ----------
19 ----------
20 data : numpy array, list, unicode, str or bytes
20 data : numpy array, list, unicode, str or bytes
@@ -23,19 +23,19 b' class Audio(DisplayObject):'
23 * List of float or integer representing the waveform (mono)
23 * List of float or integer representing the waveform (mono)
24 * String containing the filename
24 * String containing the filename
25 * Bytestring containing raw PCM data or
25 * Bytestring containing raw PCM data or
26 * URL pointing to a file on the web.
26 * URL pointing to a file on the web.
27
27
28 If the array option is used the waveform will be normalized.
28 If the array option is used the waveform will be normalized.
29
29
30 If a filename or url is used the format support will be browser
30 If a filename or url is used the format support will be browser
31 dependent.
31 dependent.
32 url : unicode
32 url : unicode
33 A URL to download the data from.
33 A URL to download the data from.
34 filename : unicode
34 filename : unicode
35 Path to a local file to load the data from.
35 Path to a local file to load the data from.
36 embed : boolean
36 embed : boolean
37 Should the image data be embedded using a data URI (True) or should
37 Should the image data be embedded using a data URI (True) or should
38 the original source be referenced. Set this to True if you want the
38 the original source be referenced. Set this to True if you want the
39 audio to playable later with no internet connection in the notebook.
39 audio to playable later with no internet connection in the notebook.
40
40
41 Default is `True`, unless the keyword argument `url` is set, then
41 Default is `True`, unless the keyword argument `url` is set, then
@@ -75,17 +75,17 b' class Audio(DisplayObject):'
75 raise ValueError("No image data found. Expecting filename, url, or data.")
75 raise ValueError("No image data found. Expecting filename, url, or data.")
76 if embed is False and url is None:
76 if embed is False and url is None:
77 raise ValueError("No url found. Expecting url when embed=False")
77 raise ValueError("No url found. Expecting url when embed=False")
78
78
79 if url is not None and embed is not True:
79 if url is not None and embed is not True:
80 self.embed = False
80 self.embed = False
81 else:
81 else:
82 self.embed = True
82 self.embed = True
83 self.autoplay = autoplay
83 self.autoplay = autoplay
84 super(Audio, self).__init__(data=data, url=url, filename=filename)
84 super(Audio, self).__init__(data=data, url=url, filename=filename)
85
85
86 if self.data is not None and not isinstance(self.data, bytes):
86 if self.data is not None and not isinstance(self.data, bytes):
87 self.data = self._make_wav(data,rate)
87 self.data = self._make_wav(data,rate)
88
88
89 def reload(self):
89 def reload(self):
90 """Reload the raw data from file or URL."""
90 """Reload the raw data from file or URL."""
91 import mimetypes
91 import mimetypes
@@ -98,32 +98,55 b' class Audio(DisplayObject):'
98 self.mimetype = mimetypes.guess_type(self.url)[0]
98 self.mimetype = mimetypes.guess_type(self.url)[0]
99 else:
99 else:
100 self.mimetype = "audio/wav"
100 self.mimetype = "audio/wav"
101
101
102 def _make_wav(self, data, rate):
102 def _make_wav(self, data, rate):
103 """ Transform a numpy array to a PCM bytestring """
103 """ Transform a numpy array to a PCM bytestring """
104 import struct
104 import struct
105 from io import BytesIO
105 from io import BytesIO
106 import wave
106 import wave
107
107 try:
108 try:
108 import numpy as np
109 import numpy as np
109 data = np.array(data,dtype=float)
110
110 if len(data.shape) > 1:
111 data = np.array(data, dtype=float)
111 raise ValueError("encoding of stereo PCM signals are unsupported")
112 if len(data.shape) == 1:
113 nchan = 1
114 elif len(data.shape) == 2:
115 # In wave files,channels are interleaved. E.g.,
116 # "L1R1L2R2..." for stereo. See
117 # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
118 # for channel ordering
119 nchan = data.shape[0]
120 data = data.T.ravel()
121 else:
122 raise ValueError('Array audio input must be a 1D or 2D array')
112 scaled = np.int16(data/np.max(np.abs(data))*32767).tolist()
123 scaled = np.int16(data/np.max(np.abs(data))*32767).tolist()
113 except ImportError:
124 except ImportError:
125 # check that it is a "1D" list
126 idata = iter(data) # fails if not an iterable
127 try:
128 iter(idata.next())
129 raise TypeError('Only lists of mono audio are '
130 'supported if numpy is not installed')
131 except TypeError:
132 # this means it's not a nested list, which is what we want
133 pass
114 maxabsvalue = float(max([abs(x) for x in data]))
134 maxabsvalue = float(max([abs(x) for x in data]))
115 scaled = [int(x/maxabsvalue*32767) for x in data]
135 scaled = [int(x/maxabsvalue*32767) for x in data]
136 nchan = 1
137
116 fp = BytesIO()
138 fp = BytesIO()
117 waveobj = wave.open(fp,mode='wb')
139 waveobj = wave.open(fp,mode='wb')
118 waveobj.setnchannels(1)
140 waveobj.setnchannels(nchan)
119 waveobj.setframerate(rate)
141 waveobj.setframerate(rate)
120 waveobj.setsampwidth(2)
142 waveobj.setsampwidth(2)
121 waveobj.setcomptype('NONE','NONE')
143 waveobj.setcomptype('NONE','NONE')
122 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
144 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
123 val = fp.getvalue()
145 val = fp.getvalue()
124 waveobj.close()
146 waveobj.close()
125 return val
147
126
148 return val
149
127 def _data_and_metadata(self):
150 def _data_and_metadata(self):
128 """shortcut for returning metadata with url information, if defined"""
151 """shortcut for returning metadata with url information, if defined"""
129 md = {}
152 md = {}
@@ -133,7 +156,7 b' class Audio(DisplayObject):'
133 return self.data, md
156 return self.data, md
134 else:
157 else:
135 return self.data
158 return self.data
136
159
137 def _repr_html_(self):
160 def _repr_html_(self):
138 src = """
161 src = """
139 <audio controls="controls" {autoplay}>
162 <audio controls="controls" {autoplay}>
General Comments 0
You need to be logged in to leave comments. Login now