Adds 3rd clause to CELT license
[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    - Neither the name of Internet Society, IETF or IETF Trust, nor the
16    names of specific contributors, may be used to endorse or promote
17    products derived from this software without specific prior written
18    permission.
19
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "opus_multistream.h"
38 #include "opus.h"
39 #include "opus_private.h"
40 #include "stack_alloc.h"
41 #include <stdarg.h>
42 #include "float_cast.h"
43 #include "os_support.h"
44
45 typedef struct ChannelLayout {
46    int nb_channels;
47    int nb_streams;
48    int nb_coupled_streams;
49    unsigned char mapping[256];
50 } ChannelLayout;
51
52 struct OpusMSEncoder {
53    ChannelLayout layout;
54    int bitrate;
55    /* Encoder states go here */
56 };
57
58 struct OpusMSDecoder {
59    ChannelLayout layout;
60    /* Decoder states go here */
61 };
62
63
64 #ifdef FIXED_POINT
65 #define opus_encode_native opus_encode
66 #else
67 #define opus_encode_native opus_encode_float
68 #endif
69
70 static int validate_layout(const ChannelLayout *layout)
71 {
72    int i, max_channel;
73
74    max_channel = layout->nb_streams+layout->nb_coupled_streams;
75    if (max_channel>255)
76       return 0;
77    for (i=0;i<layout->nb_channels;i++)
78    {
79       if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
80          return 0;
81    }
82    return 1;
83 }
84
85
86 static int get_left_channel(const ChannelLayout *layout, int stream_id, int prev)
87 {
88    int i;
89    i = (prev<0) ? 0 : prev+1;
90    for (;i<layout->nb_channels;i++)
91    {
92       if (layout->mapping[i]==stream_id*2)
93          return i;
94    }
95    return -1;
96 }
97
98 static int get_right_channel(const ChannelLayout *layout, int stream_id, int prev)
99 {
100    int i;
101    i = (prev<0) ? 0 : prev+1;
102    for (;i<layout->nb_channels;i++)
103    {
104       if (layout->mapping[i]==stream_id*2+1)
105          return i;
106    }
107    return -1;
108 }
109
110 static int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev)
111 {
112    int i;
113    i = (prev<0) ? 0 : prev+1;
114    for (;i<layout->nb_channels;i++)
115    {
116       if (layout->mapping[i]==stream_id+layout->nb_coupled_streams)
117          return i;
118    }
119    return -1;
120 }
121
122 static int validate_encoder_layout(const ChannelLayout *layout)
123 {
124    int s;
125    for (s=0;s<layout->nb_streams;s++)
126    {
127       if (s < layout->nb_coupled_streams)
128       {
129          if (get_left_channel(layout, s, -1)==-1)
130             return 0;
131          if (get_right_channel(layout, s, -1)==-1)
132             return 0;
133       } else {
134          if (get_mono_channel(layout, s, -1)==-1)
135             return 0;
136       }
137    }
138    return 1;
139 }
140
141 opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
142 {
143    int coupled_size;
144    int mono_size;
145
146    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
147    coupled_size = opus_encoder_get_size(2);
148    mono_size = opus_encoder_get_size(1);
149    return align(sizeof(OpusMSEncoder))
150         + nb_coupled_streams * align(coupled_size)
151         + (nb_streams-nb_coupled_streams) * align(mono_size);
152 }
153
154
155
156 int opus_multistream_encoder_init(
157       OpusMSEncoder *st,
158       opus_int32 Fs,
159       int channels,
160       int streams,
161       int coupled_streams,
162       unsigned char *mapping,
163       int application
164 )
165 {
166    int coupled_size;
167    int mono_size;
168    int i;
169    char *ptr;
170
171    st->layout.nb_channels = channels;
172    st->layout.nb_streams = streams;
173    st->layout.nb_coupled_streams = coupled_streams;
174
175    for (i=0;i<st->layout.nb_channels;i++)
176       st->layout.mapping[i] = mapping[i];
177    if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
178       return OPUS_BAD_ARG;
179    ptr = (char*)st + align(sizeof(OpusMSEncoder));
180    coupled_size = opus_encoder_get_size(2);
181    mono_size = opus_encoder_get_size(1);
182
183    for (i=0;i<st->layout.nb_coupled_streams;i++)
184    {
185       opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
186       ptr += align(coupled_size);
187    }
188    for (;i<st->layout.nb_streams;i++)
189    {
190       opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
191       ptr += align(mono_size);
192    }
193    return OPUS_OK;
194 }
195
196 OpusMSEncoder *opus_multistream_encoder_create(
197       opus_int32 Fs,
198       int channels,
199       int streams,
200       int coupled_streams,
201       unsigned char *mapping,
202       int application,
203       int *error
204 )
205 {
206    int ret;
207    OpusMSEncoder *st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
208    if (st==NULL)
209    {
210       if (error)
211          *error = OPUS_ALLOC_FAIL;
212       return NULL;
213    }
214    ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
215    if (ret != OPUS_OK)
216    {
217       opus_free(st);
218       st = NULL;
219    }
220    if (error)
221       *error = ret;
222    return st;
223 }
224
225
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     int 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    /* Max size in case the encoder decides to return three frames */
245    unsigned char tmp_data[3*1275+7];
246    OpusRepacketizer rp;
247    ALLOC_STACK;
248
249    ALLOC(buf, 2*frame_size, opus_val16);
250    ptr = (char*)st + align(sizeof(OpusMSEncoder));
251    coupled_size = opus_encoder_get_size(2);
252    mono_size = opus_encoder_get_size(1);
253
254    if (max_data_bytes < 2*st->layout.nb_streams-1)
255    {
256       RESTORE_STACK;
257       return OPUS_BUFFER_TOO_SMALL;
258    }
259    /* Counting ToC */
260    tot_size = 0;
261    for (s=0;s<st->layout.nb_streams;s++)
262    {
263       OpusEncoder *enc;
264       int len;
265       int curr_max;
266
267       opus_repacketizer_init(&rp);
268       enc = (OpusEncoder*)ptr;
269       if (s < st->layout.nb_coupled_streams)
270       {
271          int left, right;
272          left = get_left_channel(&st->layout, s, -1);
273          right = get_right_channel(&st->layout, s, -1);
274          for (i=0;i<frame_size;i++)
275          {
276             buf[2*i] = pcm[st->layout.nb_channels*i+left];
277             buf[2*i+1] = pcm[st->layout.nb_channels*i+right];
278          }
279          ptr += align(coupled_size);
280       } else {
281          int chan = get_mono_channel(&st->layout, s, -1);
282          for (i=0;i<frame_size;i++)
283             buf[i] = pcm[st->layout.nb_channels*i+chan];
284          ptr += align(mono_size);
285       }
286       /* number of bytes left (+Toc) */
287       curr_max = max_data_bytes - tot_size;
288       /* Reserve one byte for the last stream and 2 for the others */
289       curr_max -= 2*(st->layout.nb_streams-s)-1;
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     int 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     int 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          opus_encoder_ctl(enc, request, value * (s < st->layout.nb_coupled_streams ? 2 : 1));
384       }
385    }
386    break;
387    case OPUS_GET_BITRATE_REQUEST:
388    {
389       int s;
390       opus_int32 *value = va_arg(ap, opus_int32*);
391       *value = 0;
392       for (s=0;s<st->layout.nb_streams;s++)
393       {
394          opus_int32 rate;
395          OpusEncoder *enc;
396          enc = (OpusEncoder*)ptr;
397          opus_encoder_ctl(enc, request, &rate);
398          *value += rate;
399       }
400    }
401    break;
402    case OPUS_GET_VBR_REQUEST:
403    case OPUS_GET_APPLICATION_REQUEST:
404    case OPUS_GET_BANDWIDTH_REQUEST:
405    case OPUS_GET_COMPLEXITY_REQUEST:
406    case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
407    case OPUS_GET_DTX_REQUEST:
408    case OPUS_GET_VOICE_RATIO_REQUEST:
409    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
410    case OPUS_GET_SIGNAL_REQUEST:
411    case OPUS_GET_LOOKAHEAD_REQUEST:
412    case OPUS_GET_INBAND_FEC_REQUEST:
413    {
414       OpusEncoder *enc;
415       /* For int32* GET params, just query the first stream */
416       opus_int32 *value = va_arg(ap, opus_int32*);
417       enc = (OpusEncoder*)ptr;
418       ret = opus_encoder_ctl(enc, request, value);
419    }
420    break;
421    case OPUS_GET_FINAL_RANGE_REQUEST:
422    {
423       int s;
424       opus_uint32 *value = va_arg(ap, opus_uint32*);
425       opus_uint32 tmp;
426       *value=0;
427       for (s=0;s<st->layout.nb_streams;s++)
428       {
429          OpusEncoder *enc;
430          enc = (OpusEncoder*)ptr;
431          if (s < st->layout.nb_coupled_streams)
432             ptr += align(coupled_size);
433          else
434             ptr += align(mono_size);
435          ret = opus_encoder_ctl(enc, request, &tmp);
436          if (ret != OPUS_OK) break;
437          *value ^= tmp;
438       }
439    }
440    break;
441    case OPUS_SET_COMPLEXITY_REQUEST:
442    case OPUS_SET_VBR_REQUEST:
443    case OPUS_SET_VBR_CONSTRAINT_REQUEST:
444    case OPUS_SET_BANDWIDTH_REQUEST:
445    case OPUS_SET_SIGNAL_REQUEST:
446    case OPUS_SET_APPLICATION_REQUEST:
447    case OPUS_SET_INBAND_FEC_REQUEST:
448    case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
449    case OPUS_SET_DTX_REQUEST:
450    case OPUS_SET_FORCE_MODE_REQUEST:
451    {
452       int s;
453       /* This works for int32 params */
454       opus_int32 value = va_arg(ap, opus_int32);
455       for (s=0;s<st->layout.nb_streams;s++)
456       {
457          OpusEncoder *enc;
458
459          enc = (OpusEncoder*)ptr;
460          if (s < st->layout.nb_coupled_streams)
461             ptr += align(coupled_size);
462          else
463             ptr += align(mono_size);
464          ret = opus_encoder_ctl(enc, request, value);
465          if (ret != OPUS_OK)
466             break;
467       }
468    }
469    break;
470    case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
471    {
472       int s;
473       opus_int32 stream_id;
474       OpusEncoder **value;
475       stream_id = va_arg(ap, opus_int32);
476       if (stream_id<0 || stream_id >= st->layout.nb_streams)
477          ret = OPUS_BAD_ARG;
478       value = va_arg(ap, OpusEncoder**);
479       for (s=0;s<stream_id;s++)
480       {
481          if (s < st->layout.nb_coupled_streams)
482             ptr += align(coupled_size);
483          else
484             ptr += align(mono_size);
485       }
486       *value = (OpusEncoder*)ptr;
487    }
488       break;
489    default:
490       ret = OPUS_UNIMPLEMENTED;
491       break;
492    }
493
494    va_end(ap);
495    return ret;
496 }
497
498 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
499 {
500     opus_free(st);
501 }
502
503
504 /* DECODER */
505
506 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
507 {
508    int coupled_size;
509    int mono_size;
510
511    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
512    coupled_size = opus_decoder_get_size(2);
513    mono_size = opus_decoder_get_size(1);
514    return align(sizeof(OpusMSDecoder))
515          + nb_coupled_streams * align(coupled_size)
516          + (nb_streams-nb_coupled_streams) * align(mono_size);
517 }
518
519 int opus_multistream_decoder_init(
520       OpusMSDecoder *st,
521       opus_int32 Fs,
522       int channels,
523       int streams,
524       int coupled_streams,
525       unsigned char *mapping
526 )
527 {
528    int coupled_size;
529    int mono_size;
530    int i, ret;
531    char *ptr;
532
533    st->layout.nb_channels = channels;
534    st->layout.nb_streams = streams;
535    st->layout.nb_coupled_streams = coupled_streams;
536
537    for (i=0;i<st->layout.nb_channels;i++)
538       st->layout.mapping[i] = mapping[i];
539    if (!validate_layout(&st->layout))
540       return OPUS_BAD_ARG;
541
542    ptr = (char*)st + align(sizeof(OpusMSDecoder));
543    coupled_size = opus_decoder_get_size(2);
544    mono_size = opus_decoder_get_size(1);
545
546    for (i=0;i<st->layout.nb_coupled_streams;i++)
547    {
548       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
549       if(ret!=OPUS_OK)return ret;
550       ptr += align(coupled_size);
551    }
552    for (;i<st->layout.nb_streams;i++)
553    {
554       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
555       if(ret!=OPUS_OK)return ret;
556       ptr += align(mono_size);
557    }
558    return OPUS_OK;
559 }
560
561
562 OpusMSDecoder *opus_multistream_decoder_create(
563       opus_int32 Fs,
564       int channels,
565       int streams,
566       int coupled_streams,
567       unsigned char *mapping,
568       int *error
569 )
570 {
571    int ret;
572    OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
573    if (st==NULL)
574    {
575       if (error)
576          *error = OPUS_ALLOC_FAIL;
577       return NULL;
578    }
579    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
580    if (error)
581       *error = ret;
582    if (ret != OPUS_OK)
583    {
584       opus_free(st);
585       st = NULL;
586    }
587    return st;
588
589
590 }
591
592 static int opus_multistream_decode_native(
593       OpusMSDecoder *st,
594       const unsigned char *data,
595       int len,
596       opus_val16 *pcm,
597       int frame_size,
598       int decode_fec
599 )
600 {
601    int coupled_size;
602    int mono_size;
603    int s, i, c;
604    char *ptr;
605    int do_plc=0;
606    VARDECL(opus_val16, buf);
607    ALLOC_STACK;
608
609    ALLOC(buf, 2*frame_size, opus_val16);
610    ptr = (char*)st + align(sizeof(OpusMSDecoder));
611    coupled_size = opus_decoder_get_size(2);
612    mono_size = opus_decoder_get_size(1);
613
614    if (len==0)
615       do_plc = 1;
616    if (len < 0)
617       return OPUS_BAD_ARG;
618    if (!do_plc && len < 2*st->layout.nb_streams-1)
619       return OPUS_INVALID_PACKET;
620    for (s=0;s<st->layout.nb_streams;s++)
621    {
622       OpusDecoder *dec;
623       int packet_offset, ret;
624
625       dec = (OpusDecoder*)ptr;
626       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
627
628       if (!do_plc && len<=0)
629       {
630          RESTORE_STACK;
631          return OPUS_INVALID_PACKET;
632       }
633       packet_offset = 0;
634       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset);
635       data += packet_offset;
636       len -= packet_offset;
637       if (ret > frame_size)
638       {
639          RESTORE_STACK;
640          return OPUS_BUFFER_TOO_SMALL;
641       }
642       if (s>0 && ret != frame_size)
643       {
644          RESTORE_STACK;
645          return OPUS_INVALID_PACKET;
646       }
647       if (ret <= 0)
648       {
649          RESTORE_STACK;
650          return ret;
651       }
652       frame_size = ret;
653       if (s < st->layout.nb_coupled_streams)
654       {
655          int chan, prev;
656          prev = -1;
657          /* Copy "left" audio to the channel(s) where it belongs */
658          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
659          {
660             for (i=0;i<frame_size;i++)
661                pcm[st->layout.nb_channels*i+chan] = buf[2*i];
662             prev = chan;
663          }
664          prev = -1;
665          /* Copy "right" audio to the channel(s) where it belongs */
666          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
667          {
668             for (i=0;i<frame_size;i++)
669                pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
670             prev = chan;
671          }
672       } else {
673          int chan, prev;
674          prev = -1;
675          /* Copy audio to the channel(s) where it belongs */
676          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
677          {
678             for (i=0;i<frame_size;i++)
679                pcm[st->layout.nb_channels*i+chan] = buf[i];
680             prev = chan;
681          }
682       }
683    }
684    /* Handle muted channels */
685    for (c=0;c<st->layout.nb_channels;c++)
686    {
687       if (st->layout.mapping[c] == 255)
688       {
689          for (i=0;i<frame_size;i++)
690             pcm[st->layout.nb_channels*i+c] = 0;
691       }
692    }
693    RESTORE_STACK;
694    return frame_size;
695 }
696
697 #ifdef FIXED_POINT
698 int opus_multistream_decode(
699       OpusMSDecoder *st,
700       const unsigned char *data,
701       int len,
702       opus_int16 *pcm,
703       int frame_size,
704       int decode_fec
705 )
706 {
707    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
708 }
709
710 #ifndef DISABLE_FLOAT_API
711 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
712       int len, float *pcm, int frame_size, int decode_fec)
713 {
714    VARDECL(opus_int16, out);
715    int ret, i;
716    ALLOC_STACK;
717
718    ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
719
720    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
721    if (ret > 0)
722    {
723       for (i=0;i<ret*st->layout.nb_channels;i++)
724          pcm[i] = (1./32768.)*(out[i]);
725    }
726    RESTORE_STACK;
727    return ret;
728 }
729 #endif
730
731 #else
732
733 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
734       int len, opus_int16 *pcm, int frame_size, int decode_fec)
735 {
736    VARDECL(float, out);
737    int ret, i;
738    ALLOC_STACK;
739
740    ALLOC(out, frame_size*st->layout.nb_channels, float);
741
742    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
743    if (ret > 0)
744    {
745       for (i=0;i<ret*st->layout.nb_channels;i++)
746          pcm[i] = FLOAT2INT16(out[i]);
747    }
748    RESTORE_STACK;
749    return ret;
750 }
751
752 int opus_multistream_decode_float(
753       OpusMSDecoder *st,
754       const unsigned char *data,
755       int len,
756       float *pcm,
757       int frame_size,
758       int decode_fec
759 )
760 {
761    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
762 }
763 #endif
764
765 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
766 {
767    va_list ap;
768    int coupled_size, mono_size;
769    char *ptr;
770    int ret = OPUS_OK;
771
772    va_start(ap, request);
773
774    coupled_size = opus_decoder_get_size(2);
775    mono_size = opus_decoder_get_size(1);
776    ptr = (char*)st + align(sizeof(OpusMSDecoder));
777    switch (request)
778    {
779        case OPUS_GET_BANDWIDTH_REQUEST:
780        {
781           OpusDecoder *dec;
782           /* For int32* GET params, just query the first stream */
783           opus_int32 *value = va_arg(ap, opus_int32*);
784           dec = (OpusDecoder*)ptr;
785           ret = opus_decoder_ctl(dec, request, value);
786        }
787        break;
788        case OPUS_GET_FINAL_RANGE_REQUEST:
789        {
790           int s;
791           opus_uint32 *value = va_arg(ap, opus_uint32*);
792           opus_uint32 tmp;
793           *value = 0;
794           for (s=0;s<st->layout.nb_streams;s++)
795           {
796              OpusDecoder *dec;
797              dec = (OpusDecoder*)ptr;
798              if (s < st->layout.nb_coupled_streams)
799                 ptr += align(coupled_size);
800              else
801                 ptr += align(mono_size);
802              ret = opus_decoder_ctl(dec, request, &tmp);
803              if (ret != OPUS_OK) break;
804              *value ^= tmp;
805           }
806        }
807        break;
808        case OPUS_RESET_STATE:
809        {
810           int s;
811           for (s=0;s<st->layout.nb_streams;s++)
812           {
813              OpusDecoder *dec;
814
815              dec = (OpusDecoder*)ptr;
816              if (s < st->layout.nb_coupled_streams)
817                 ptr += align(coupled_size);
818              else
819                 ptr += align(mono_size);
820              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
821              if (ret != OPUS_OK)
822                 break;
823           }
824        }
825        break;
826        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
827        {
828           int s;
829           opus_int32 stream_id;
830           OpusDecoder **value;
831           stream_id = va_arg(ap, opus_int32);
832           if (stream_id<0 || stream_id >= st->layout.nb_streams)
833              ret = OPUS_BAD_ARG;
834           value = va_arg(ap, OpusDecoder**);
835           for (s=0;s<stream_id;s++)
836           {
837              if (s < st->layout.nb_coupled_streams)
838                 ptr += align(coupled_size);
839              else
840                 ptr += align(mono_size);
841           }
842           *value = (OpusDecoder*)ptr;
843        }
844           break;
845        default:
846           ret = OPUS_UNIMPLEMENTED;
847        break;
848    }
849
850    va_end(ap);
851    return ret;
852 }
853
854
855 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
856 {
857     opus_free(st);
858 }