Additional multistream tests and reject channels<1 in MS API.
[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) || (channels<1) || (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.f/32768.f)*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_LSB_DEPTH_REQUEST:
411    case OPUS_GET_VBR_REQUEST:
412    case OPUS_GET_APPLICATION_REQUEST:
413    case OPUS_GET_BANDWIDTH_REQUEST:
414    case OPUS_GET_COMPLEXITY_REQUEST:
415    case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
416    case OPUS_GET_DTX_REQUEST:
417    case OPUS_GET_VOICE_RATIO_REQUEST:
418    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
419    case OPUS_GET_SIGNAL_REQUEST:
420    case OPUS_GET_LOOKAHEAD_REQUEST:
421    case OPUS_GET_INBAND_FEC_REQUEST:
422    {
423       OpusEncoder *enc;
424       /* For int32* GET params, just query the first stream */
425       opus_int32 *value = va_arg(ap, opus_int32*);
426       enc = (OpusEncoder*)ptr;
427       ret = opus_encoder_ctl(enc, request, value);
428    }
429    break;
430    case OPUS_GET_FINAL_RANGE_REQUEST:
431    {
432       int s;
433       opus_uint32 *value = va_arg(ap, opus_uint32*);
434       opus_uint32 tmp;
435       *value=0;
436       for (s=0;s<st->layout.nb_streams;s++)
437       {
438          OpusEncoder *enc;
439          enc = (OpusEncoder*)ptr;
440          if (s < st->layout.nb_coupled_streams)
441             ptr += align(coupled_size);
442          else
443             ptr += align(mono_size);
444          ret = opus_encoder_ctl(enc, request, &tmp);
445          if (ret != OPUS_OK) break;
446          *value ^= tmp;
447       }
448    }
449    break;
450    case OPUS_SET_LSB_DEPTH_REQUEST:
451    case OPUS_SET_COMPLEXITY_REQUEST:
452    case OPUS_SET_VBR_REQUEST:
453    case OPUS_SET_VBR_CONSTRAINT_REQUEST:
454    case OPUS_SET_BANDWIDTH_REQUEST:
455    case OPUS_SET_SIGNAL_REQUEST:
456    case OPUS_SET_APPLICATION_REQUEST:
457    case OPUS_SET_INBAND_FEC_REQUEST:
458    case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
459    case OPUS_SET_DTX_REQUEST:
460    case OPUS_SET_FORCE_MODE_REQUEST:
461    {
462       int s;
463       /* This works for int32 params */
464       opus_int32 value = va_arg(ap, opus_int32);
465       for (s=0;s<st->layout.nb_streams;s++)
466       {
467          OpusEncoder *enc;
468
469          enc = (OpusEncoder*)ptr;
470          if (s < st->layout.nb_coupled_streams)
471             ptr += align(coupled_size);
472          else
473             ptr += align(mono_size);
474          ret = opus_encoder_ctl(enc, request, value);
475          if (ret != OPUS_OK)
476             break;
477       }
478    }
479    break;
480    case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
481    {
482       int s;
483       opus_int32 stream_id;
484       OpusEncoder **value;
485       stream_id = va_arg(ap, opus_int32);
486       if (stream_id<0 || stream_id >= st->layout.nb_streams)
487          ret = OPUS_BAD_ARG;
488       value = va_arg(ap, OpusEncoder**);
489       for (s=0;s<stream_id;s++)
490       {
491          if (s < st->layout.nb_coupled_streams)
492             ptr += align(coupled_size);
493          else
494             ptr += align(mono_size);
495       }
496       *value = (OpusEncoder*)ptr;
497    }
498       break;
499    default:
500       ret = OPUS_UNIMPLEMENTED;
501       break;
502    }
503
504    va_end(ap);
505    return ret;
506 }
507
508 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
509 {
510     opus_free(st);
511 }
512
513
514 /* DECODER */
515
516 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
517 {
518    int coupled_size;
519    int mono_size;
520
521    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
522    coupled_size = opus_decoder_get_size(2);
523    mono_size = opus_decoder_get_size(1);
524    return align(sizeof(OpusMSDecoder))
525          + nb_coupled_streams * align(coupled_size)
526          + (nb_streams-nb_coupled_streams) * align(mono_size);
527 }
528
529 int opus_multistream_decoder_init(
530       OpusMSDecoder *st,
531       opus_int32 Fs,
532       int channels,
533       int streams,
534       int coupled_streams,
535       const unsigned char *mapping
536 )
537 {
538    int coupled_size;
539    int mono_size;
540    int i, ret;
541    char *ptr;
542
543    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
544        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
545       return OPUS_BAD_ARG;
546
547    st->layout.nb_channels = channels;
548    st->layout.nb_streams = streams;
549    st->layout.nb_coupled_streams = coupled_streams;
550
551    for (i=0;i<st->layout.nb_channels;i++)
552       st->layout.mapping[i] = mapping[i];
553    if (!validate_layout(&st->layout))
554       return OPUS_BAD_ARG;
555
556    ptr = (char*)st + align(sizeof(OpusMSDecoder));
557    coupled_size = opus_decoder_get_size(2);
558    mono_size = opus_decoder_get_size(1);
559
560    for (i=0;i<st->layout.nb_coupled_streams;i++)
561    {
562       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
563       if(ret!=OPUS_OK)return ret;
564       ptr += align(coupled_size);
565    }
566    for (;i<st->layout.nb_streams;i++)
567    {
568       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
569       if(ret!=OPUS_OK)return ret;
570       ptr += align(mono_size);
571    }
572    return OPUS_OK;
573 }
574
575
576 OpusMSDecoder *opus_multistream_decoder_create(
577       opus_int32 Fs,
578       int channels,
579       int streams,
580       int coupled_streams,
581       const unsigned char *mapping,
582       int *error
583 )
584 {
585    int ret;
586    OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
587    if (st==NULL)
588    {
589       if (error)
590          *error = OPUS_ALLOC_FAIL;
591       return NULL;
592    }
593    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
594    if (error)
595       *error = ret;
596    if (ret != OPUS_OK)
597    {
598       opus_free(st);
599       st = NULL;
600    }
601    return st;
602
603
604 }
605
606 static int opus_multistream_decode_native(
607       OpusMSDecoder *st,
608       const unsigned char *data,
609       opus_int32 len,
610       opus_val16 *pcm,
611       int frame_size,
612       int decode_fec
613 )
614 {
615    int coupled_size;
616    int mono_size;
617    int s, i, c;
618    char *ptr;
619    int do_plc=0;
620    VARDECL(opus_val16, buf);
621    ALLOC_STACK;
622
623    ALLOC(buf, 2*frame_size, opus_val16);
624    ptr = (char*)st + align(sizeof(OpusMSDecoder));
625    coupled_size = opus_decoder_get_size(2);
626    mono_size = opus_decoder_get_size(1);
627
628    if (len==0)
629       do_plc = 1;
630    if (len < 0)
631       return OPUS_BAD_ARG;
632    if (!do_plc && len < 2*st->layout.nb_streams-1)
633       return OPUS_INVALID_PACKET;
634    for (s=0;s<st->layout.nb_streams;s++)
635    {
636       OpusDecoder *dec;
637       int packet_offset, ret;
638
639       dec = (OpusDecoder*)ptr;
640       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
641
642       if (!do_plc && len<=0)
643       {
644          RESTORE_STACK;
645          return OPUS_INVALID_PACKET;
646       }
647       packet_offset = 0;
648       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset);
649       data += packet_offset;
650       len -= packet_offset;
651       if (ret > frame_size)
652       {
653          RESTORE_STACK;
654          return OPUS_BUFFER_TOO_SMALL;
655       }
656       if (s>0 && ret != frame_size)
657       {
658          RESTORE_STACK;
659          return OPUS_INVALID_PACKET;
660       }
661       if (ret <= 0)
662       {
663          RESTORE_STACK;
664          return ret;
665       }
666       frame_size = ret;
667       if (s < st->layout.nb_coupled_streams)
668       {
669          int chan, prev;
670          prev = -1;
671          /* Copy "left" audio to the channel(s) where it belongs */
672          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
673          {
674             for (i=0;i<frame_size;i++)
675                pcm[st->layout.nb_channels*i+chan] = buf[2*i];
676             prev = chan;
677          }
678          prev = -1;
679          /* Copy "right" audio to the channel(s) where it belongs */
680          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
681          {
682             for (i=0;i<frame_size;i++)
683                pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
684             prev = chan;
685          }
686       } else {
687          int chan, prev;
688          prev = -1;
689          /* Copy audio to the channel(s) where it belongs */
690          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
691          {
692             for (i=0;i<frame_size;i++)
693                pcm[st->layout.nb_channels*i+chan] = buf[i];
694             prev = chan;
695          }
696       }
697    }
698    /* Handle muted channels */
699    for (c=0;c<st->layout.nb_channels;c++)
700    {
701       if (st->layout.mapping[c] == 255)
702       {
703          for (i=0;i<frame_size;i++)
704             pcm[st->layout.nb_channels*i+c] = 0;
705       }
706    }
707    RESTORE_STACK;
708    return frame_size;
709 }
710
711 #ifdef FIXED_POINT
712 int opus_multistream_decode(
713       OpusMSDecoder *st,
714       const unsigned char *data,
715       opus_int32 len,
716       opus_int16 *pcm,
717       int frame_size,
718       int decode_fec
719 )
720 {
721    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
722 }
723
724 #ifndef DISABLE_FLOAT_API
725 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
726       opus_int32 len, float *pcm, int frame_size, int decode_fec)
727 {
728    VARDECL(opus_int16, out);
729    int ret, i;
730    ALLOC_STACK;
731
732    ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
733
734    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
735    if (ret > 0)
736    {
737       for (i=0;i<ret*st->layout.nb_channels;i++)
738          pcm[i] = (1.f/32768.f)*(out[i]);
739    }
740    RESTORE_STACK;
741    return ret;
742 }
743 #endif
744
745 #else
746
747 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
748       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
749 {
750    VARDECL(float, out);
751    int ret, i;
752    ALLOC_STACK;
753
754    ALLOC(out, frame_size*st->layout.nb_channels, float);
755
756    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
757    if (ret > 0)
758    {
759       for (i=0;i<ret*st->layout.nb_channels;i++)
760          pcm[i] = FLOAT2INT16(out[i]);
761    }
762    RESTORE_STACK;
763    return ret;
764 }
765
766 int opus_multistream_decode_float(
767       OpusMSDecoder *st,
768       const unsigned char *data,
769       opus_int32 len,
770       float *pcm,
771       int frame_size,
772       int decode_fec
773 )
774 {
775    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
776 }
777 #endif
778
779 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
780 {
781    va_list ap;
782    int coupled_size, mono_size;
783    char *ptr;
784    int ret = OPUS_OK;
785
786    va_start(ap, request);
787
788    coupled_size = opus_decoder_get_size(2);
789    mono_size = opus_decoder_get_size(1);
790    ptr = (char*)st + align(sizeof(OpusMSDecoder));
791    switch (request)
792    {
793        case OPUS_GET_BANDWIDTH_REQUEST:
794        {
795           OpusDecoder *dec;
796           /* For int32* GET params, just query the first stream */
797           opus_int32 *value = va_arg(ap, opus_int32*);
798           dec = (OpusDecoder*)ptr;
799           ret = opus_decoder_ctl(dec, request, value);
800        }
801        break;
802        case OPUS_GET_FINAL_RANGE_REQUEST:
803        {
804           int s;
805           opus_uint32 *value = va_arg(ap, opus_uint32*);
806           opus_uint32 tmp;
807           *value = 0;
808           for (s=0;s<st->layout.nb_streams;s++)
809           {
810              OpusDecoder *dec;
811              dec = (OpusDecoder*)ptr;
812              if (s < st->layout.nb_coupled_streams)
813                 ptr += align(coupled_size);
814              else
815                 ptr += align(mono_size);
816              ret = opus_decoder_ctl(dec, request, &tmp);
817              if (ret != OPUS_OK) break;
818              *value ^= tmp;
819           }
820        }
821        break;
822        case OPUS_RESET_STATE:
823        {
824           int s;
825           for (s=0;s<st->layout.nb_streams;s++)
826           {
827              OpusDecoder *dec;
828
829              dec = (OpusDecoder*)ptr;
830              if (s < st->layout.nb_coupled_streams)
831                 ptr += align(coupled_size);
832              else
833                 ptr += align(mono_size);
834              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
835              if (ret != OPUS_OK)
836                 break;
837           }
838        }
839        break;
840        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
841        {
842           int s;
843           opus_int32 stream_id;
844           OpusDecoder **value;
845           stream_id = va_arg(ap, opus_int32);
846           if (stream_id<0 || stream_id >= st->layout.nb_streams)
847              ret = OPUS_BAD_ARG;
848           value = va_arg(ap, OpusDecoder**);
849           for (s=0;s<stream_id;s++)
850           {
851              if (s < st->layout.nb_coupled_streams)
852                 ptr += align(coupled_size);
853              else
854                 ptr += align(mono_size);
855           }
856           *value = (OpusDecoder*)ptr;
857        }
858        break;
859        case OPUS_SET_GAIN_REQUEST:
860        {
861           int s;
862           /* This works for int32 params */
863           opus_int32 value = va_arg(ap, opus_int32);
864           for (s=0;s<st->layout.nb_streams;s++)
865           {
866              OpusDecoder *dec;
867
868              dec = (OpusDecoder*)ptr;
869              if (s < st->layout.nb_coupled_streams)
870                 ptr += align(coupled_size);
871              else
872                 ptr += align(mono_size);
873              ret = opus_decoder_ctl(dec, request, value);
874              if (ret != OPUS_OK)
875                 break;
876           }
877        }
878        break;
879        default:
880           ret = OPUS_UNIMPLEMENTED;
881        break;
882    }
883
884    va_end(ap);
885    return ret;
886 }
887
888
889 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
890 {
891     opus_free(st);
892 }