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