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