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