1 #include "opus.h"
2
3 /********************************************************
4 Audio Tools, a module and set of tools for manipulating audio data
5 Copyright (C) 2007-2014 Brian Langenberger
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *******************************************************/
21
22 static PyObject*
23 OpusDecoder_new(PyTypeObject *type,
24 PyObject *args, PyObject *kwds)
25 {
26 decoders_OpusDecoder *self;
27
28 self = (decoders_OpusDecoder *)type->tp_alloc(type, 0);
29
OggFlacDecoder_new(PyTypeObject * type,PyObject * args,PyObject * kwds)30 return (PyObject *)self;
31 }
32
33 int
34 OpusDecoder_init(decoders_OpusDecoder *self,
35 PyObject *args, PyObject *kwds)
36 {
37 char *filename;
38 int error;
OggFlacDecoder_dealloc(decoders_OggFlacDecoder * self)39
40 self->opus_file = NULL;
41 self->audiotools_pcm = NULL;
42 self->channels = NULL;
43 self->closed = 0;
44
45 if (!PyArg_ParseTuple(args, "s", &filename))
46 return -1;
47
48 if ((self->opus_file = op_open_file(filename, &error)) == NULL) {
49 PyErr_SetString(PyExc_ValueError, "error opening Opus file");
50 return -1;
51 }
52
OggFlacDecoder_init(decoders_OggFlacDecoder * self,PyObject * args,PyObject * kwds)53 self->channel_count = op_channel_count(self->opus_file, -1);
54
55 if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL)
56 return -1;
57
58 self->channels = aa_int_new();
59
60 return 0;
61 }
62
63 void
64 OpusDecoders_dealloc(decoders_OpusDecoder *self)
65 {
66 if (self->opus_file != NULL)
67 op_free(self->opus_file);
68
69 Py_XDECREF(self->audiotools_pcm);
70
71 if (self->channels != NULL)
72 self->channels->del(self->channels);
73
74 Py_TYPE(self)->tp_free((PyObject*)self);
75 }
76
77 static PyObject*
78 OpusDecoder_sample_rate(decoders_OpusDecoder *self, void *closure)
79 {
80 /*always 48 kHz*/
81 const int sample_rate = 48000;
82
83 return Py_BuildValue("i", sample_rate);
84 }
85
86 static PyObject*
87 OpusDecoder_bits_per_sample(decoders_OpusDecoder *self, void *closure)
88 {
89 /*always 16 bps*/
90 const int bits_per_sample = 16;
91
92 return Py_BuildValue("i", bits_per_sample);
93 }
94
95 static PyObject*
96 OpusDecoder_channels(decoders_OpusDecoder *self, void *closure)
97 {
98 return Py_BuildValue("i", self->channel_count);
99 }
100
101 static PyObject*
102 OpusDecoder_channel_mask(decoders_OpusDecoder *self, void *closure)
103 {
104 /*use same channel mapping as Ogg Vorbis*/
105 int channel_mask;
106
107 enum {
108 fL = 0x1,
109 fR = 0x2,
110 fC = 0x4,
111 LFE = 0x8,
112 bL = 0x10,
113 bR = 0x20,
114 bC = 0x100,
115 sL = 0x200,
116 sR = 0x400
117 };
118
119 switch (self->channel_count) {
120 case 1:
121 /*fC*/
122 channel_mask = fC;
123 break;
124 case 2:
125 /*fL fR*/
126 channel_mask = fL | fR;
OggFlacDecoder_sample_rate(decoders_OggFlacDecoder * self,void * closure)127 break;
128 case 3:
129 /*fL fR fC*/
130 channel_mask = fL | fR | fC;
131 break;
OggFlacDecoder_bits_per_sample(decoders_OggFlacDecoder * self,void * closure)132 case 4:
133 /*fL fR bL bR*/
134 channel_mask = fL | fR | bL | bR;
135 break;
136 case 5:
OggFlacDecoder_channels(decoders_OggFlacDecoder * self,void * closure)137 /*fL fR fC bL bR*/
138 channel_mask = fL | fR | fC | bL | bR;
139 break;
140 case 6:
141 /*fL fR fC LFE bL bR*/
OggFlacDecoder_channel_mask(decoders_OggFlacDecoder * self,void * closure)142 channel_mask = fL | fR | fC | LFE | bL | bR;
143 break;
144 case 7:
145 /*fL fR fC LFE bC sL sR*/
146 channel_mask = fL | fR | fC | LFE | bC | sL | sR;
OggFlacDecoder_read(decoders_OggFlacDecoder * self,PyObject * args)147 break;
148 case 8:
149 /*fL fR fC LFE bL bR sL sR*/
150 channel_mask = fL | fR | fC | LFE | bL | bR | sL | sR;
151 break;
152 default:
153 /*undefined*/
154 channel_mask = 0x0;
155 break;
156 }
157
158 return Py_BuildValue("i", channel_mask);
159 }
160
161 /*assume at least 120ms across 8 channels, minimum*/
162 #define BUF_SIZE 5760 * 8
163
164 static PyObject*
165 OpusDecoder_read(decoders_OpusDecoder* self, PyObject *args)
166 {
167 static opus_int16 pcm[BUF_SIZE];
168 int pcm_frames_read;
169
170 if (self->closed) {
171 PyErr_SetString(PyExc_ValueError, "stream is closed");
172 return NULL;
173 }
174
175 if ((pcm_frames_read = op_read(self->opus_file,
176 pcm,
177 BUF_SIZE,
178 NULL)) >= 0) {
179 const int channel_count = op_head(self->opus_file, -1)->channel_count;
180 aa_int *channels = self->channels;
181 int c;
182 void (*a_int_swap)(a_int* a, a_int* b) = channels->_[0]->swap;
183
184 channels->reset(channels);
185
186 /*split buffer by channel*/
187 for (c = 0; c < channel_count; c++) {
188 a_int *channel = channels->append(channels);
189 int i;
190
191 channel->resize(channel, pcm_frames_read);
192 for (i = 0; i < pcm_frames_read; i++) {
193 a_append(channel, pcm[c + (i * channel_count)]);
194 }
195 }
196
197 /*reorder channels to .wav order if necessary*/
198 switch (channel_count) {
199 case 1:
200 case 2:
201 default:
202 /*no change*/
203 break;
204 case 3:
205 /*fL fC fR -> fL fR fC*/
206 a_int_swap(channels->_[1], channels->_[2]);
207 break;
208 case 4:
209 /*fL fR bL bR -> fL fR bL bR*/
210 /*no change*/
211 break;
212 case 5:
213 /*fL fC fR bL bR -> fL fR fC bL bR*/
214 a_int_swap(channels->_[1], channels->_[2]);
215 break;
216 case 6:
217 /*fL fC fR bL bR LFE -> fL fR fC bL bR LFE*/
218 a_int_swap(channels->_[1], channels->_[2]);
219
220 /*fL fR fC bL bR LFE -> fL fR fC LFE bR bL*/
221 a_int_swap(channels->_[3], channels->_[5]);
222
223 /*fL fR fC LFE bR bL -> fL fR fC LFE bL bR*/
224 a_int_swap(channels->_[4], channels->_[5]);
225 break;
226 case 7:
227 /*fL fC fR sL sR bC LFE -> fL fR fC sL sR bC LFE*/
228 a_int_swap(channels->_[1], channels->_[2]);
229
230 /*fL fR fC sL sR bC LFE -> fL fR fC LFE sR bC sL*/
231 a_int_swap(channels->_[3], channels->_[6]);
232
233 /*fL fR fC LFE sR bC sL -> fL fR fC LFE bC sR sL*/
234 a_int_swap(channels->_[4], channels->_[5]);
235
236 /*fL fR fC LFE bC sR sL -> fL fR fC LFE bC sL sR*/
237 a_int_swap(channels->_[5], channels->_[6]);
238 break;
239 case 8:
240 /*fL fC fR sL sR bL bR LFE -> fL fR fC sL sR bL bR LFE*/
241 a_int_swap(channels->_[1], channels->_[2]);
242
243 /*fL fR fC sL sR bL bR LFE -> fL fR fC LFE sR bL bR sL*/
244 a_int_swap(channels->_[3], channels->_[6]);
245
246 /*fL fR fC LFE sR bL bR sL -> fL fR fC LFE bL sR bR sL*/
247 a_int_swap(channels->_[4], channels->_[5]);
248
249 /*fL fR fC LFE bL sR bR sL -> fL fR fC LFE bL bR sR sL*/
250 a_int_swap(channels->_[5], channels->_[6]);
251
252 /*fL fR fC LFE bL bR sR sL -> fL fR fC LFE bL bR sL sR*/
253 a_int_swap(channels->_[6], channels->_[7]);
254 break;
255 }
256
257 /*return new FrameList object*/
258 return aa_int_to_FrameList(self->audiotools_pcm,
259 channels,
260 16);
261 } else {
262 /*some sort of read error occurred*/
263 PyErr_SetString(PyExc_ValueError, "error reading from file");
264 return NULL;
265 }
266 }
267
268 static PyObject*
269 OpusDecoder_close(decoders_OpusDecoder* self, PyObject *args)
270 {
271 self->closed = 1;
272 Py_INCREF(Py_None);
OggFlacDecoder_close(decoders_OggFlacDecoder * self,PyObject * args)273 return Py_None;
274 }
275
276 static PyObject*
277 OpusDecoder_enter(decoders_OpusDecoder* self, PyObject *args)
278 {
279 Py_INCREF(self);
280 return (PyObject *)self;
281 }
282
OggFlacDecoder_enter(decoders_OggFlacDecoder * self,PyObject * args)283 static PyObject*
284 OpusDecoder_exit(decoders_OpusDecoder* self, PyObject *args)
285 {
286 self->closed = 1;
287 Py_INCREF(Py_None);
288 return Py_None;
289 }
OggFlacDecoder_exit(decoders_OggFlacDecoder * self,PyObject * args)290