Show More
@@ -14,7 +14,7 b' class Audio(DisplayObject):' | |||
|
14 | 14 | When this object is returned by an input cell or passed to the |
|
15 | 15 | display function, it will result in Audio controls being displayed |
|
16 | 16 | in the frontend (only works in the notebook). |
|
17 | ||
|
17 | ||
|
18 | 18 | Parameters |
|
19 | 19 | ---------- |
|
20 | 20 | data : numpy array, list, unicode, str or bytes |
@@ -23,19 +23,19 b' class Audio(DisplayObject):' | |||
|
23 | 23 | * List of float or integer representing the waveform (mono) |
|
24 | 24 | * String containing the filename |
|
25 | 25 | * Bytestring containing raw PCM data or |
|
26 |
* URL pointing to a file on the web. |
|
|
27 | ||
|
26 | * URL pointing to a file on the web. | |
|
27 | ||
|
28 | 28 | If the array option is used the waveform will be normalized. |
|
29 | ||
|
30 |
If a filename or url is used the format support will be browser |
|
|
31 |
dependent. |
|
|
29 | ||
|
30 | If a filename or url is used the format support will be browser | |
|
31 | dependent. | |
|
32 | 32 | url : unicode |
|
33 | 33 | A URL to download the data from. |
|
34 | 34 | filename : unicode |
|
35 | 35 | Path to a local file to load the data from. |
|
36 | 36 | embed : boolean |
|
37 | 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 | 39 | audio to playable later with no internet connection in the notebook. |
|
40 | 40 | |
|
41 | 41 | Default is `True`, unless the keyword argument `url` is set, then |
@@ -75,17 +75,17 b' class Audio(DisplayObject):' | |||
|
75 | 75 | raise ValueError("No image data found. Expecting filename, url, or data.") |
|
76 | 76 | if embed is False and url is None: |
|
77 | 77 | raise ValueError("No url found. Expecting url when embed=False") |
|
78 | ||
|
78 | ||
|
79 | 79 | if url is not None and embed is not True: |
|
80 | 80 | self.embed = False |
|
81 | 81 | else: |
|
82 | 82 | self.embed = True |
|
83 | 83 | self.autoplay = autoplay |
|
84 | 84 | super(Audio, self).__init__(data=data, url=url, filename=filename) |
|
85 | ||
|
85 | ||
|
86 | 86 | if self.data is not None and not isinstance(self.data, bytes): |
|
87 | 87 | self.data = self._make_wav(data,rate) |
|
88 | ||
|
88 | ||
|
89 | 89 | def reload(self): |
|
90 | 90 | """Reload the raw data from file or URL.""" |
|
91 | 91 | import mimetypes |
@@ -98,32 +98,55 b' class Audio(DisplayObject):' | |||
|
98 | 98 | self.mimetype = mimetypes.guess_type(self.url)[0] |
|
99 | 99 | else: |
|
100 | 100 | self.mimetype = "audio/wav" |
|
101 | ||
|
101 | ||
|
102 | 102 | def _make_wav(self, data, rate): |
|
103 | 103 | """ Transform a numpy array to a PCM bytestring """ |
|
104 | 104 | import struct |
|
105 | 105 | from io import BytesIO |
|
106 | 106 | import wave |
|
107 | ||
|
107 | 108 | try: |
|
108 | 109 | import numpy as np |
|
109 | data = np.array(data,dtype=float) | |
|
110 | if len(data.shape) > 1: | |
|
111 | raise ValueError("encoding of stereo PCM signals are unsupported") | |
|
110 | ||
|
111 | data = np.array(data, dtype=float) | |
|
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 | 123 | scaled = np.int16(data/np.max(np.abs(data))*32767).tolist() |
|
113 | 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 | 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 | 138 | fp = BytesIO() |
|
117 | 139 | waveobj = wave.open(fp,mode='wb') |
|
118 |
waveobj.setnchannels( |
|
|
140 | waveobj.setnchannels(nchan) | |
|
119 | 141 | waveobj.setframerate(rate) |
|
120 | 142 | waveobj.setsampwidth(2) |
|
121 | 143 | waveobj.setcomptype('NONE','NONE') |
|
122 | 144 | waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled])) |
|
123 | 145 | val = fp.getvalue() |
|
124 | 146 | waveobj.close() |
|
125 | return val | |
|
126 | ||
|
147 | ||
|
148 | return val | |
|
149 | ||
|
127 | 150 | def _data_and_metadata(self): |
|
128 | 151 | """shortcut for returning metadata with url information, if defined""" |
|
129 | 152 | md = {} |
@@ -133,7 +156,7 b' class Audio(DisplayObject):' | |||
|
133 | 156 | return self.data, md |
|
134 | 157 | else: |
|
135 | 158 | return self.data |
|
136 | ||
|
159 | ||
|
137 | 160 | def _repr_html_(self): |
|
138 | 161 | src = """ |
|
139 | 162 | <audio controls="controls" {autoplay}> |
General Comments 0
You need to be logged in to leave comments.
Login now