Opus_multistream API hardening.
[opus.git] / src / opus_multistream.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 typedef struct ChannelLayout {
41    int nb_channels;
42    int nb_streams;
43    int nb_coupled_streams;
44    unsigned char mapping[256];
45 } ChannelLayout;
46
47 struct OpusMSEncoder {
48    ChannelLayout layout;
49    int bitrate;
50    /* Encoder states go here */
51 };
52
53 struct OpusMSDecoder {
54    ChannelLayout layout;
55    /* Decoder states go here */
56 };
57
58
59 #ifdef FIXED_POINT
60 #define opus_encode_native opus_encode
61 #else
62 #define opus_encode_native opus_encode_float
63 #endif
64
65 static int validate_layout(const ChannelLayout *layout)
66 {
67    int i, max_channel;
68
69    max_channel = layout->nb_streams+layout->nb_coupled_streams;
70    if (max_channel>255)
71       return 0;
72    for (i=0;i<layout->nb_channels;i++)
73    {
74       if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
75          return 0;
76    }
77    return 1;
78 }
79
80
81 static int get_left_channel(const ChannelLayout *layout, int stream_id, int prev)
82 {
83    int i;
84    i = (prev<0) ? 0 : prev+1;
85    for (;i<layout->nb_channels;i++)
86    {
87       if (layout->mapping[i]==stream_id*2)
88          return i;
89    }
90    return -1;
91 }
92
93 static int get_right_channel(const ChannelLayout *layout, int stream_id, int prev)
94 {
95    int i;
96    i = (prev<0) ? 0 : prev+1;
97    for (;i<layout->nb_channels;i++)
98    {
99       if (layout->mapping[i]==stream_id*2+1)
100          return i;
101    }
102    return -1;
103 }
104
105 static int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev)
106 {
107    int i;
108    i = (prev<0) ? 0 : prev+1;
109    for (;i<layout->nb_channels;i++)
110    {
111       if (layout->mapping[i]==stream_id+layout->nb_coupled_streams)
112          return i;
113    }
114    return -1;
115 }
116
117 static int validate_encoder_layout(const ChannelLayout *layout)
118 {
119    int s;
120    for (s=0;s<layout->nb_streams;s++)
121    {
122       if (s < layout->nb_coupled_streams)
123       {
124          if (get_left_channel(layout, s, -1)==-1)
125             return 0;
126          if (get_right_channel(layout, s, -1)==-1)
127             return 0;
128       } else {
129          if (get_mono_channel(layout, s, -1)==-1)
130             return 0;
131       }
132    }
133    return 1;
134 }
135
136 opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
137 {
138    int coupled_size;
139    int mono_size;
140
141    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
142    coupled_size = opus_encoder_get_size(2);
143    mono_size = opus_encoder_get_size(1);
144    return align(sizeof(OpusMSEncoder))
145         + nb_coupled_streams * align(coupled_size)
146         + (nb_streams-nb_coupled_streams) * align(mono_size);
147 }
148
149
150
151 int opus_multistream_encoder_init(
152       OpusMSEncoder *st,
153       opus_int32 Fs,
154       int channels,
155       int streams,
156       int coupled_streams,
157       const unsigned char *mapping,
158       int application
159 )
160 {
161    int coupled_size;
162    int mono_size;
163    int i;
164    char *ptr;
165
166    if ((channels>255) || (coupled_streams>streams) ||
167        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
168       return OPUS_BAD_ARG;
169
170    st->layout.nb_channels = channels;
171    st->layout.nb_streams = streams;
172    st->layout.nb_coupled_streams = coupled_streams;
173
174    for (i=0;i<st->layout.nb_channels;i++)
175       st->layout.mapping[i] = mapping[i];
176    if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
177       return OPUS_BAD_ARG;
178    ptr = (char*)st + align(sizeof(OpusMSEncoder));
179    coupled_size = opus_encoder_get_size(2);
180    mono_size = opus_encoder_get_size(1);
181
182    for (i=0;i<st->layout.nb_coupled_streams;i++)
183    {
184       opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
185       ptr += align(coupled_size);
186    }
187    for (;i<st->layout.nb_streams;i++)
188    {
189       opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
190       ptr += align(mono_size);
191    }
192    return OPUS_OK;
193 }
194
195 OpusMSEncoder *opus_multistream_encoder_create(
196       opus_int32 Fs,
197       int channels,
198       int streams,
199       int coupled_streams,
200       const unsigned char *mapping,
201       int application,
202       int *error
203 )
204 {
205    int ret;
206    OpusMSEncoder *st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
207    if (st==NULL)
208    {
209       if (error)
210          *error = OPUS_ALLOC_FAIL;
211       return NULL;
212    }
213    ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
214    if (ret != OPUS_OK)
215    {
216       opus_free(st);
217       st = NULL;
218    }
219    if (error)
220       *error = ret;
221    return st;
222 }
223
224 /* Max size in case the encoder decides to return three frames */
225 #define MS_FRAME_TMP (3*1275+7)
226 #ifdef FIXED_POINT
227 int opus_multistream_encode(
228 #else
229 int opus_multistream_encode_float(
230 #endif
231     OpusMSEncoder *st,
232     const opus_val16 *pcm,
233     int frame_size,
234     unsigned char *data,
235     opus_int32 max_data_bytes
236 )
237 {
238    int coupled_size;
239    int mono_size;
240    int s, i;
241    char *ptr;
242    int tot_size;
243    VARDECL(opus_val16, buf);
244    unsigned char tmp_data[MS_FRAME_TMP];
245    OpusRepacketizer rp;
246    ALLOC_STACK;
247
248    ALLOC(buf, 2*frame_size, opus_val16);
249    ptr = (char*)st + align(sizeof(OpusMSEncoder));
250    coupled_size = opus_encoder_get_size(2);
251    mono_size = opus_encoder_get_size(1);
252
253    if (max_data_bytes < 4*st->layout.nb_streams-1)
254    {
255       RESTORE_STACK;
256       return OPUS_BUFFER_TOO_SMALL;
257    }
258    /* Counting ToC */
259    tot_size = 0;
260    for (s=0;s<st->layout.nb_streams;s++)
261    {
262       OpusEncoder *enc;
263       int len;
264       int curr_max;
265
266       opus_repacketizer_init(&rp);
267       enc = (OpusEncoder*)ptr;
268       if (s < st->layout.nb_coupled_streams)
269       {
270          int left, right;
271          left = get_left_channel(&st->layout, s, -1);
272          right = get_right_channel(&st->layout, s, -1);
273          for (i=0;i<frame_size;i++)
274          {
275             buf[2*i] = pcm[st->layout.nb_channels*i+left];
276             buf[2*i+1] = pcm[st->layout.nb_channels*i+right];
277          }
278          ptr += align(coupled_size);
279       } else {
280          int chan = get_mono_channel(&st->layout, s, -1);
281          for (i=0;i<frame_size;i++)
282             buf[i] = pcm[st->layout.nb_channels*i+chan];
283          ptr += align(mono_size);
284       }
285       /* number of bytes left (+Toc) */
286       curr_max = max_data_bytes - tot_size;
287       /* Reserve three bytes for the last stream and four for the others */
288       curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
289       curr_max = IMIN(curr_max,MS_FRAME_TMP);
290       len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max);
291       if (len<0)
292       {
293          RESTORE_STACK;
294          return len;
295       }
296       /* We need to use the repacketizer to add the self-delimiting lengths
297          while taking into account the fact that the encoder can now return
298          more than one frame at a time (e.g. 60 ms CELT-only) */
299       opus_repacketizer_cat(&rp, tmp_data, len);
300       len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1);
301       data += len;
302       tot_size += len;
303    }
304    RESTORE_STACK;
305    return tot_size;
306
307 }
308
309 #ifdef FIXED_POINT
310
311 #ifndef DISABLE_FLOAT_API
312 int opus_multistream_encode_float(
313     OpusMSEncoder *st,
314     const float *pcm,
315     int frame_size,
316     unsigned char *data,
317     opus_int32 max_data_bytes
318 )
319 {
320    int i, ret;
321    VARDECL(opus_int16, in);
322    ALLOC_STACK;
323
324    ALLOC(in, frame_size*st->layout.nb_channels, opus_int16);
325
326    for (i=0;i<frame_size*st->layout.nb_channels;i++)
327       in[i] = FLOAT2INT16(pcm[i]);
328    ret = opus_multistream_encode(st, in, frame_size, data, max_data_bytes);
329    RESTORE_STACK;
330    return ret;
331 }
332 #endif
333
334 #else
335
336 int opus_multistream_encode(
337     OpusMSEncoder *st,
338     const opus_int16 *pcm,
339     int frame_size,
340     unsigned char *data,
341     opus_int32 max_data_bytes
342 )
343 {
344    int i, ret;
345    VARDECL(float, in);
346    ALLOC_STACK;
347
348    ALLOC(in, frame_size*st->layout.nb_channels, float);
349
350    for (i=0;i<frame_size*st->layout.nb_channels;i++)
351       in[i] = (1./32768)*pcm[i];
352    ret = opus_multistream_encode_float(st, in, frame_size, data, max_data_bytes);
353    RESTORE_STACK;
354    return ret;
355 }
356
357 #endif
358
359 int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
360 {
361    va_list ap;
362    int coupled_size, mono_size;
363    char *ptr;
364    int ret = OPUS_OK;
365
366    va_start(ap, request);
367
368    coupled_size = opus_encoder_get_size(2);
369    mono_size = opus_encoder_get_size(1);
370    ptr = (char*)st + align(sizeof(OpusMSEncoder));
371    switch (request)
372    {
373    case OPUS_SET_BITRATE_REQUEST:
374    {
375       int chan, s;
376       opus_int32 value = va_arg(ap, opus_int32);
377       chan = st->layout.nb_streams + st->layout.nb_coupled_streams;
378       value /= chan;
379       for (s=0;s<st->layout.nb_streams;s++)
380       {
381          OpusEncoder *enc;
382          enc = (OpusEncoder*)ptr;
383          if (s < st->layout.nb_coupled_streams)
384             ptr += align(coupled_size);
385          else
386             ptr += align(mono_size);
387          opus_encoder_ctl(enc, request, value * (s < st->layout.nb_coupled_streams ? 2 : 1));
388       }
389    }
390    break;
391    case OPUS_GET_BITRATE_REQUEST:
392    {
393       int s;
394       opus_int32 *value = va_arg(ap, opus_int32*);
395       *value = 0;
396       for (s=0;s<st->layout.nb_streams;s++)
397       {
398          opus_int32 rate;
399          OpusEncoder *enc;
400          enc = (OpusEncoder*)ptr;
401          if (s < st->layout.nb_coupled_streams)
402             ptr += align(coupled_size);
403          else
404             ptr += align(mono_size);
405          opus_encoder_ctl(enc, request, &rate);
406          *value += rate;
407       }
408    }
409    break;
410    case OPUS_GET_VBR_REQUEST:
411    case OPUS_GET_APPLICATION_REQUEST:
412    case OPUS_GET_BANDWIDTH_REQUEST:
413    case OPUS_GET_COMPLEXITY_REQUEST:
414    case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
415    case OPUS_GET_DTX_REQUEST:
416    case OPUS_GET_VOICE_RATIO_REQUEST:
417    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
418    case OPUS_GET_SIGNAL_REQUEST:
419    case OPUS_GET_LOOKAHEAD_REQUEST:
420    case OPUS_GET_INBAND_FEC_REQUEST:
421    {
422       OpusEncoder *enc;
423       /* For int32* GET params, just query the first stream */
424       opus_int32 *value = va_arg(ap, opus_int32*);
425       enc = (OpusEncoder*)ptr;
426       ret = opus_encoder_ctl(enc, request, value);
427    }
428    break;
429    case OPUS_GET_FINAL_RANGE_REQUEST:
430    {
431       int s;
432       opus_uint32 *value = va_arg(ap, opus_uint32*);
433       opus_uint32 tmp;
434       *value=0;
435       for (s=0;s<st->layout.nb_streams;s++)
436       {
437          OpusEncoder *enc;
438          enc = (OpusEncoder*)ptr;
439          if (s < st->layout.nb_coupled_streams)
440             ptr += align(coupled_size);
441          else
442             ptr += align(mono_size);
443          ret = opus_encoder_ctl(enc, request, &tmp);
444          if (ret != OPUS_OK) break;
445          *value ^= tmp;
446       }
447    }
448    break;
449    case OPUS_SET_COMPLEXITY_REQUEST:
450    case OPUS_SET_VBR_REQUEST:
451    case OPUS_SET_VBR_CONSTRAINT_REQUEST:
452    case OPUS_SET_BANDWIDTH_REQUEST:
453    case OPUS_SET_SIGNAL_REQUEST:
454    case OPUS_SET_APPLICATION_REQUEST:
455    case OPUS_SET_INBAND_FEC_REQUEST:
456    case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
457    case OPUS_SET_DTX_REQUEST:
458    case OPUS_SET_FORCE_MODE_REQUEST:
459    {
460       int s;
461       /* This works for int32 params */
462       opus_int32 value = va_arg(ap, opus_int32);
463       for (s=0;s<st->layout.nb_streams;s++)
464       {
465          OpusEncoder *enc;
466
467          enc = (OpusEncoder*)ptr;
468          if (s < st->layout.nb_coupled_streams)
469             ptr += align(coupled_size);
470          else
471             ptr += align(mono_size);
472          ret = opus_encoder_ctl(enc, request, value);
473          if (ret != OPUS_OK)
474             break;
475       }
476    }
477    break;
478    case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
479    {
480       int s;
481       opus_int32 stream_id;
482       OpusEncoder **value;
483       stream_id = va_arg(ap, opus_int32);
484       if (stream_id<0 || stream_id >= st->layout.nb_streams)
485          ret = OPUS_BAD_ARG;
486       value = va_arg(ap, OpusEncoder**);
487       for (s=0;s<stream_id;s++)
488       {
489          if (s < st->layout.nb_coupled_streams)
490             ptr += align(coupled_size);
491          else
492             ptr += align(mono_size);
493       }
494       *value = (OpusEncoder*)ptr;
495    }
496       break;
497    default:
498       ret = OPUS_UNIMPLEMENTED;
499       break;
500    }
501
502    va_end(ap);
503    return ret;
504 }
505
506 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
507 {
508     opus_free(st);
509 }
510
511
512 /* DECODER */
513
514 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
515 {
516    int coupled_size;
517    int mono_size;
518
519    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
520    coupled_size = opus_decoder_get_size(2);
521    mono_size = opus_decoder_get_size(1);
522    return align(sizeof(OpusMSDecoder))
523          + nb_coupled_streams * align(coupled_size)
524          + (nb_streams-nb_coupled_streams) * align(mono_size);
525 }
526
527 int opus_multistream_decoder_init(
528       OpusMSDecoder *st,
529       opus_int32 Fs,
530       int channels,
531       int streams,
532       int coupled_streams,
533       const unsigned char *mapping
534 )
535 {
536    int coupled_size;
537    int mono_size;
538    int i, ret;
539    char *ptr;
540
541    if ((channels>255) || (coupled_streams>streams) ||
542        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
543       return OPUS_BAD_ARG;
544
545    st->layout.nb_channels = channels;
546    st->layout.nb_streams = streams;
547    st->layout.nb_coupled_streams = coupled_streams;
548
549    for (i=0;i<st->layout.nb_channels;i++)
550       st->layout.mapping[i] = mapping[i];
551    if (!validate_layout(&st->layout))
552       return OPUS_BAD_ARG;
553
554    ptr = (char*)st + align(sizeof(OpusMSDecoder));
555    coupled_size = opus_decoder_get_size(2);
556    mono_size = opus_decoder_get_size(1);
557
558    for (i=0;i<st->layout.nb_coupled_streams;i++)
559    {
560       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
561       if(ret!=OPUS_OK)return ret;
562       ptr += align(coupled_size);
563    }
564    for (;i<st->layout.nb_streams;i++)
565    {
566       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
567       if(ret!=OPUS_OK)return ret;
568       ptr += align(mono_size);
569    }
570    return OPUS_OK;
571 }
572
573
574 OpusMSDecoder *opus_multistream_decoder_create(
575       opus_int32 Fs,
576       int channels,
577       int streams,
578       int coupled_streams,
579       const unsigned char *mapping,
580       int *error
581 )
582 {
583    int ret;
584    OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
585    if (st==NULL)
586    {
587       if (error)
588          *error = OPUS_ALLOC_FAIL;
589       return NULL;
590    }
591    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
592    if (error)
593       *error = ret;
594    if (ret != OPUS_OK)
595    {
596       opus_free(st);
597       st = NULL;
598    }
599    return st;
600
601
602 }
603
604 static int opus_multistream_decode_native(
605       OpusMSDecoder *st,
606       const unsigned char *data,
607       opus_int32 len,
608       opus_val16 *pcm,
609       int frame_size,
610       int decode_fec
611 )
612 {
613    int coupled_size;
614    int mono_size;
615    int s, i, c;
616    char *ptr;
617    int do_plc=0;
618    VARDECL(opus_val16, buf);
619    ALLOC_STACK;
620
621    ALLOC(buf, 2*frame_size, opus_val16);
622    ptr = (char*)st + align(sizeof(OpusMSDecoder));
623    coupled_size = opus_decoder_get_size(2);
624    mono_size = opus_decoder_get_size(1);
625
626    if (len==0)
627       do_plc = 1;
628    if (len < 0)
629       return OPUS_BAD_ARG;
630    if (!do_plc && len < 2*st->layout.nb_streams-1)
631       return OPUS_INVALID_PACKET;
632    for (s=0;s<st->layout.nb_streams;s++)
633    {
634       OpusDecoder *dec;
635       int packet_offset, ret;
636
637       dec = (OpusDecoder*)ptr;
638       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
639
640       if (!do_plc && len<=0)
641       {
642          RESTORE_STACK;
643          return OPUS_INVALID_PACKET;
644       }
645       packet_offset = 0;
646       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset);
647       data += packet_offset;
648       len -= packet_offset;
649       if (ret > frame_size)
650       {
651          RESTORE_STACK;
652          return OPUS_BUFFER_TOO_SMALL;
653       }
654       if (s>0 && ret != frame_size)
655       {
656          RESTORE_STACK;
657          return OPUS_INVALID_PACKET;
658       }
659       if (ret <= 0)
660       {
661          RESTORE_STACK;
662          return ret;
663       }
664       frame_size = ret;
665       if (s < st->layout.nb_coupled_streams)
666       {
667          int chan, prev;
668          prev = -1;
669          /* Copy "left" audio to the channel(s) where it belongs */
670          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
671          {
672             for (i=0;i<frame_size;i++)
673                pcm[st->layout.nb_channels*i+chan] = buf[2*i];
674             prev = chan;
675          }
676          prev = -1;
677          /* Copy "right" audio to the channel(s) where it belongs */
678          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
679          {
680             for (i=0;i<frame_size;i++)
681                pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
682             prev = chan;
683          }
684       } else {
685          int chan, prev;
686          prev = -1;
687          /* Copy audio to the channel(s) where it belongs */
688          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
689          {
690             for (i=0;i<frame_size;i++)
691                pcm[st->layout.nb_channels*i+chan] = buf[i];
692             prev = chan;
693          }
694       }
695    }
696    /* Handle muted channels */
697    for (c=0;c<st->layout.nb_channels;c++)
698    {
699       if (st->layout.mapping[c] == 255)
700       {
701          for (i=0;i<frame_size;i++)
702             pcm[st->layout.nb_channels*i+c] = 0;
703       }
704    }
705    RESTORE_STACK;
706    return frame_size;
707 }
708
709 #ifdef FIXED_POINT
710 int opus_multistream_decode(
711       OpusMSDecoder *st,
712       const unsigned char *data,
713       opus_int32 len,
714       opus_int16 *pcm,
715       int frame_size,
716       int decode_fec
717 )
718 {
719    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
720 }
721
722 #ifndef DISABLE_FLOAT_API
723 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
724       opus_int32 len, float *pcm, int frame_size, int decode_fec)
725 {
726    VARDECL(opus_int16, out);
727    int ret, i;
728    ALLOC_STACK;
729
730    ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
731
732    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
733    if (ret > 0)
734    {
735       for (i=0;i<ret*st->layout.nb_channels;i++)
736          pcm[i] = (1./32768.)*(out[i]);
737    }
738    RESTORE_STACK;
739    return ret;
740 }
741 #endif
742
743 #else
744
745 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
746       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
747 {
748    VARDECL(float, out);
749    int ret, i;
750    ALLOC_STACK;
751
752    ALLOC(out, frame_size*st->layout.nb_channels, float);
753
754    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
755    if (ret > 0)
756    {
757       for (i=0;i<ret*st->layout.nb_channels;i++)
758          pcm[i] = FLOAT2INT16(out[i]);
759    }
760    RESTORE_STACK;
761    return ret;
762 }
763
764 int opus_multistream_decode_float(
765       OpusMSDecoder *st,
766       const unsigned char *data,
767       opus_int32 len,
768       float *pcm,
769       int frame_size,
770       int decode_fec
771 )
772 {
773    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
774 }
775 #endif
776
777 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
778 {
779    va_list ap;
780    int coupled_size, mono_size;
781    char *ptr;
782    int ret = OPUS_OK;
783
784    va_start(ap, request);
785
786    coupled_size = opus_decoder_get_size(2);
787    mono_size = opus_decoder_get_size(1);
788    ptr = (char*)st + align(sizeof(OpusMSDecoder));
789    switch (request)
790    {
791        case OPUS_GET_BANDWIDTH_REQUEST:
792        {
793           OpusDecoder *dec;
794           /* For int32* GET params, just query the first stream */
795           opus_int32 *value = va_arg(ap, opus_int32*);
796           dec = (OpusDecoder*)ptr;
797           ret = opus_decoder_ctl(dec, request, value);
798        }
799        break;
800        case OPUS_GET_FINAL_RANGE_REQUEST:
801        {
802           int s;
803           opus_uint32 *value = va_arg(ap, opus_uint32*);
804           opus_uint32 tmp;
805           *value = 0;
806           for (s=0;s<st->layout.nb_streams;s++)
807           {
808              OpusDecoder *dec;
809              dec = (OpusDecoder*)ptr;
810              if (s < st->layout.nb_coupled_streams)
811                 ptr += align(coupled_size);
812              else
813                 ptr += align(mono_size);
814              ret = opus_decoder_ctl(dec, request, &tmp);
815              if (ret != OPUS_OK) break;
816              *value ^= tmp;
817           }
818        }
819        break;
820        case OPUS_RESET_STATE:
821        {
822           int s;
823           for (s=0;s<st->layout.nb_streams;s++)
824           {
825              OpusDecoder *dec;
826
827              dec = (OpusDecoder*)ptr;
828              if (s < st->layout.nb_coupled_streams)
829                 ptr += align(coupled_size);
830              else
831                 ptr += align(mono_size);
832              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
833              if (ret != OPUS_OK)
834                 break;
835           }
836        }
837        break;
838        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
839        {
840           int s;
841           opus_int32 stream_id;
842           OpusDecoder **value;
843           stream_id = va_arg(ap, opus_int32);
844           if (stream_id<0 || stream_id >= st->layout.nb_streams)
845              ret = OPUS_BAD_ARG;
846           value = va_arg(ap, OpusDecoder**);
847           for (s=0;s<stream_id;s++)
848           {
849              if (s < st->layout.nb_coupled_streams)
850                 ptr += align(coupled_size);
851              else
852                 ptr += align(mono_size);
853           }
854           *value = (OpusDecoder*)ptr;
855        }
856        break;
857        case OPUS_SET_GAIN_REQUEST:
858        {
859           int s;
860           /* This works for int32 params */
861           opus_int32 value = va_arg(ap, opus_int32);
862           for (s=0;s<st->layout.nb_streams;s++)
863           {
864              OpusDecoder *dec;
865
866              dec = (OpusDecoder*)ptr;
867              if (s < st->layout.nb_coupled_streams)
868                 ptr += align(coupled_size);
869              else
870                 ptr += align(mono_size);
871              ret = opus_decoder_ctl(dec, request, value);
872              if (ret != OPUS_OK)
873                 break;
874           }
875        }
876        break;
877        default:
878           ret = OPUS_UNIMPLEMENTED;
879        break;
880    }
881
882    va_end(ap);
883    return ret;
884 }
885
886
887 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
888 {
889     opus_free(st);
890 }