Brace a number of if statements instead of one-lining them.
[opus.git] / src / opus_multistream_decoder.c
1 /* Copyright (c) 2011 Xiph.Org Foundation
2    Written by Jean-Marc Valin */
3 /*
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions
6    are met:
7
8    - Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10
11    - Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in the
13    documentation and/or other materials provided with the distribution.
14
15    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "opus_multistream.h"
33 #include "opus.h"
34 #include "opus_private.h"
35 #include "stack_alloc.h"
36 #include <stdarg.h>
37 #include "float_cast.h"
38 #include "os_support.h"
39
40 struct OpusMSDecoder {
41    ChannelLayout layout;
42    /* Decoder states go here */
43 };
44
45
46
47
48 /* DECODER */
49
50 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
51 {
52    int coupled_size;
53    int mono_size;
54
55    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
56    coupled_size = opus_decoder_get_size(2);
57    mono_size = opus_decoder_get_size(1);
58    return align(sizeof(OpusMSDecoder))
59          + nb_coupled_streams * align(coupled_size)
60          + (nb_streams-nb_coupled_streams) * align(mono_size);
61 }
62
63 int opus_multistream_decoder_init(
64       OpusMSDecoder *st,
65       opus_int32 Fs,
66       int channels,
67       int streams,
68       int coupled_streams,
69       const unsigned char *mapping
70 )
71 {
72    int coupled_size;
73    int mono_size;
74    int i, ret;
75    char *ptr;
76
77    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
78        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
79       return OPUS_BAD_ARG;
80
81    st->layout.nb_channels = channels;
82    st->layout.nb_streams = streams;
83    st->layout.nb_coupled_streams = coupled_streams;
84
85    for (i=0;i<st->layout.nb_channels;i++)
86       st->layout.mapping[i] = mapping[i];
87    if (!validate_layout(&st->layout))
88       return OPUS_BAD_ARG;
89
90    ptr = (char*)st + align(sizeof(OpusMSDecoder));
91    coupled_size = opus_decoder_get_size(2);
92    mono_size = opus_decoder_get_size(1);
93
94    for (i=0;i<st->layout.nb_coupled_streams;i++)
95    {
96       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
97       if(ret!=OPUS_OK)return ret;
98       ptr += align(coupled_size);
99    }
100    for (;i<st->layout.nb_streams;i++)
101    {
102       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
103       if(ret!=OPUS_OK)return ret;
104       ptr += align(mono_size);
105    }
106    return OPUS_OK;
107 }
108
109
110 OpusMSDecoder *opus_multistream_decoder_create(
111       opus_int32 Fs,
112       int channels,
113       int streams,
114       int coupled_streams,
115       const unsigned char *mapping,
116       int *error
117 )
118 {
119    int ret;
120    OpusMSDecoder *st;
121    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
122        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
123    {
124       if (error)
125          *error = OPUS_BAD_ARG;
126       return NULL;
127    }
128    st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
129    if (st==NULL)
130    {
131       if (error)
132          *error = OPUS_ALLOC_FAIL;
133       return NULL;
134    }
135    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
136    if (error)
137       *error = ret;
138    if (ret != OPUS_OK)
139    {
140       opus_free(st);
141       st = NULL;
142    }
143    return st;
144 }
145
146 typedef void (*opus_copy_channel_out_func)(
147   void *dst,
148   int dst_stride,
149   int dst_channel,
150   const opus_val16 *src,
151   int src_stride,
152   int frame_size
153 );
154
155 static int opus_multistream_decode_native(
156       OpusMSDecoder *st,
157       const unsigned char *data,
158       opus_int32 len,
159       void *pcm,
160       opus_copy_channel_out_func copy_channel_out,
161       int frame_size,
162       int decode_fec,
163       int soft_clip
164 )
165 {
166    opus_int32 Fs;
167    int coupled_size;
168    int mono_size;
169    int s, c;
170    char *ptr;
171    int do_plc=0;
172    VARDECL(opus_val16, buf);
173    ALLOC_STACK;
174
175    /* Limit frame_size to avoid excessive stack allocations. */
176    opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
177    frame_size = IMIN(frame_size, Fs/25*3);
178    ALLOC(buf, 2*frame_size, opus_val16);
179    ptr = (char*)st + align(sizeof(OpusMSDecoder));
180    coupled_size = opus_decoder_get_size(2);
181    mono_size = opus_decoder_get_size(1);
182
183    if (len==0)
184       do_plc = 1;
185    if (len < 0)
186       return OPUS_BAD_ARG;
187    if (!do_plc && len < 2*st->layout.nb_streams-1)
188       return OPUS_INVALID_PACKET;
189    for (s=0;s<st->layout.nb_streams;s++)
190    {
191       OpusDecoder *dec;
192       int packet_offset, ret;
193
194       dec = (OpusDecoder*)ptr;
195       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
196
197       if (!do_plc && len<=0)
198       {
199          RESTORE_STACK;
200          return OPUS_INVALID_PACKET;
201       }
202       packet_offset = 0;
203       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
204       data += packet_offset;
205       len -= packet_offset;
206       if (ret > frame_size)
207       {
208          RESTORE_STACK;
209          return OPUS_BUFFER_TOO_SMALL;
210       }
211       if (s>0 && ret != frame_size)
212       {
213          RESTORE_STACK;
214          return OPUS_INVALID_PACKET;
215       }
216       if (ret <= 0)
217       {
218          RESTORE_STACK;
219          return ret;
220       }
221       frame_size = ret;
222       if (s < st->layout.nb_coupled_streams)
223       {
224          int chan, prev;
225          prev = -1;
226          /* Copy "left" audio to the channel(s) where it belongs */
227          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
228          {
229             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
230                buf, 2, frame_size);
231             prev = chan;
232          }
233          prev = -1;
234          /* Copy "right" audio to the channel(s) where it belongs */
235          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
236          {
237             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
238                buf+1, 2, frame_size);
239             prev = chan;
240          }
241       } else {
242          int chan, prev;
243          prev = -1;
244          /* Copy audio to the channel(s) where it belongs */
245          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
246          {
247             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
248                buf, 1, frame_size);
249             prev = chan;
250          }
251       }
252    }
253    /* Handle muted channels */
254    for (c=0;c<st->layout.nb_channels;c++)
255    {
256       if (st->layout.mapping[c] == 255)
257       {
258          (*copy_channel_out)(pcm, st->layout.nb_channels, c,
259             NULL, 0, frame_size);
260       }
261    }
262    RESTORE_STACK;
263    return frame_size;
264 }
265
266 #if !defined(DISABLE_FLOAT_API)
267 static void opus_copy_channel_out_float(
268   void *dst,
269   int dst_stride,
270   int dst_channel,
271   const opus_val16 *src,
272   int src_stride,
273   int frame_size
274 )
275 {
276    float *float_dst;
277    opus_int32 i;
278    float_dst = (float*)dst;
279    if (src != NULL)
280    {
281       for (i=0;i<frame_size;i++)
282 #if defined(FIXED_POINT)
283          float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
284 #else
285          float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
286 #endif
287    }
288    else
289    {
290       for (i=0;i<frame_size;i++)
291          float_dst[i*dst_stride+dst_channel] = 0;
292    }
293 }
294 #endif
295
296 static void opus_copy_channel_out_short(
297   void *dst,
298   int dst_stride,
299   int dst_channel,
300   const opus_val16 *src,
301   int src_stride,
302   int frame_size
303 )
304 {
305    opus_int16 *short_dst;
306    opus_int32 i;
307    short_dst = (opus_int16*)dst;
308    if (src != NULL)
309    {
310       for (i=0;i<frame_size;i++)
311 #if defined(FIXED_POINT)
312          short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
313 #else
314          short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
315 #endif
316    }
317    else
318    {
319       for (i=0;i<frame_size;i++)
320          short_dst[i*dst_stride+dst_channel] = 0;
321    }
322 }
323
324
325
326 #ifdef FIXED_POINT
327 int opus_multistream_decode(
328       OpusMSDecoder *st,
329       const unsigned char *data,
330       opus_int32 len,
331       opus_int16 *pcm,
332       int frame_size,
333       int decode_fec
334 )
335 {
336    return opus_multistream_decode_native(st, data, len,
337        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
338 }
339
340 #ifndef DISABLE_FLOAT_API
341 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
342       opus_int32 len, float *pcm, int frame_size, int decode_fec)
343 {
344    return opus_multistream_decode_native(st, data, len,
345        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
346 }
347 #endif
348
349 #else
350
351 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
352       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
353 {
354    return opus_multistream_decode_native(st, data, len,
355        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
356 }
357
358 int opus_multistream_decode_float(
359       OpusMSDecoder *st,
360       const unsigned char *data,
361       opus_int32 len,
362       float *pcm,
363       int frame_size,
364       int decode_fec
365 )
366 {
367    return opus_multistream_decode_native(st, data, len,
368        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
369 }
370 #endif
371
372 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
373 {
374    va_list ap;
375    int coupled_size, mono_size;
376    char *ptr;
377    int ret = OPUS_OK;
378
379    va_start(ap, request);
380
381    coupled_size = opus_decoder_get_size(2);
382    mono_size = opus_decoder_get_size(1);
383    ptr = (char*)st + align(sizeof(OpusMSDecoder));
384    switch (request)
385    {
386        case OPUS_GET_BANDWIDTH_REQUEST:
387        case OPUS_GET_SAMPLE_RATE_REQUEST:
388        case OPUS_GET_GAIN_REQUEST:
389        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
390        {
391           OpusDecoder *dec;
392           /* For int32* GET params, just query the first stream */
393           opus_int32 *value = va_arg(ap, opus_int32*);
394           dec = (OpusDecoder*)ptr;
395           ret = opus_decoder_ctl(dec, request, value);
396        }
397        break;
398        case OPUS_GET_FINAL_RANGE_REQUEST:
399        {
400           int s;
401           opus_uint32 *value = va_arg(ap, opus_uint32*);
402           opus_uint32 tmp;
403           if (!value) {
404              goto bad_arg;
405           }
406           *value = 0;
407           for (s=0;s<st->layout.nb_streams;s++)
408           {
409              OpusDecoder *dec;
410              dec = (OpusDecoder*)ptr;
411              if (s < st->layout.nb_coupled_streams)
412                 ptr += align(coupled_size);
413              else
414                 ptr += align(mono_size);
415              ret = opus_decoder_ctl(dec, request, &tmp);
416              if (ret != OPUS_OK) break;
417              *value ^= tmp;
418           }
419        }
420        break;
421        case OPUS_RESET_STATE:
422        {
423           int s;
424           for (s=0;s<st->layout.nb_streams;s++)
425           {
426              OpusDecoder *dec;
427
428              dec = (OpusDecoder*)ptr;
429              if (s < st->layout.nb_coupled_streams)
430                 ptr += align(coupled_size);
431              else
432                 ptr += align(mono_size);
433              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
434              if (ret != OPUS_OK)
435                 break;
436           }
437        }
438        break;
439        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
440        {
441           int s;
442           opus_int32 stream_id;
443           OpusDecoder **value;
444           stream_id = va_arg(ap, opus_int32);
445           if (stream_id<0 || stream_id >= st->layout.nb_streams)
446              ret = OPUS_BAD_ARG;
447           value = va_arg(ap, OpusDecoder**);
448           if (!value) {
449              goto bad_arg;
450           }
451           for (s=0;s<stream_id;s++)
452           {
453              if (s < st->layout.nb_coupled_streams)
454                 ptr += align(coupled_size);
455              else
456                 ptr += align(mono_size);
457           }
458           *value = (OpusDecoder*)ptr;
459        }
460        break;
461        case OPUS_SET_GAIN_REQUEST:
462        {
463           int s;
464           /* This works for int32 params */
465           opus_int32 value = va_arg(ap, opus_int32);
466           for (s=0;s<st->layout.nb_streams;s++)
467           {
468              OpusDecoder *dec;
469
470              dec = (OpusDecoder*)ptr;
471              if (s < st->layout.nb_coupled_streams)
472                 ptr += align(coupled_size);
473              else
474                 ptr += align(mono_size);
475              ret = opus_decoder_ctl(dec, request, value);
476              if (ret != OPUS_OK)
477                 break;
478           }
479        }
480        break;
481        default:
482           ret = OPUS_UNIMPLEMENTED;
483        break;
484    }
485
486    va_end(ap);
487    return ret;
488 bad_arg:
489    va_end(ap);
490    return OPUS_BAD_ARG;
491 }
492
493
494 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
495 {
496     opus_free(st);
497 }