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