da498dd6e0aa49a9a7d372c89808fcca3b0ea6db
[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 <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include "float_cast.h"
41 #include "os_support.h"
42
43 typedef struct ChannelLayout {
44    int nb_channels;
45    int nb_streams;
46    int nb_coupled_streams;
47    unsigned char mapping[256];
48 } ChannelLayout;
49
50 struct OpusMSEncoder {
51    ChannelLayout layout;
52    int bitrate;
53    /* Encoder states go here */
54 };
55
56 struct OpusMSDecoder {
57    ChannelLayout layout;
58    /* Decoder states go here */
59 };
60
61
62 #ifdef FIXED_POINT
63 #define opus_encode_native opus_encode
64 #else
65 #define opus_encode_native opus_encode_float
66 #endif
67
68 static int validate_layout(const ChannelLayout *layout)
69 {
70    int i, max_channel;
71
72    max_channel = layout->nb_streams+layout->nb_coupled_streams;
73    if (max_channel>255)
74       return 0;
75    for (i=0;i<layout->nb_channels;i++)
76    {
77       if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
78          return 0;
79    }
80    return 1;
81 }
82
83
84 static int get_left_channel(const ChannelLayout *layout, int stream_id, int prev)
85 {
86    int i;
87    i = (prev<0) ? 0 : prev+1;
88    for (;i<layout->nb_channels;i++)
89    {
90       if (layout->mapping[i]==stream_id*2)
91          return i;
92    }
93    return -1;
94 }
95
96 static int get_right_channel(const ChannelLayout *layout, int stream_id, int prev)
97 {
98    int i;
99    i = (prev<0) ? 0 : prev+1;
100    for (;i<layout->nb_channels;i++)
101    {
102       if (layout->mapping[i]==stream_id*2+1)
103          return i;
104    }
105    return -1;
106 }
107
108 static int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev)
109 {
110    int i;
111    i = (prev<0) ? 0 : prev+1;
112    for (;i<layout->nb_channels;i++)
113    {
114       if (layout->mapping[i]==2*layout->nb_coupled_streams+stream_id)
115          return i;
116    }
117    return -1;
118 }
119
120 static int validate_encoder_layout(const ChannelLayout *layout)
121 {
122    int s;
123    for (s=0;s<layout->nb_streams;s++)
124    {
125       if (s < layout->nb_coupled_streams)
126       {
127          if (get_left_channel(layout, s, -1)==-1)
128             return 0;
129          if (get_right_channel(layout, s, -1)==-1)
130             return 0;
131       } else {
132          if (get_mono_channel(layout, s, -1)==-1)
133             return 0;
134       }
135    }
136    return 1;
137 }
138
139 int opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
140 {
141         int coupled_size;
142         int mono_size;
143
144         coupled_size = opus_encoder_get_size(2);
145         mono_size = opus_encoder_get_size(1);
146         return align(sizeof(OpusMSEncoder))
147                         + nb_coupled_streams * align(coupled_size)
148                 + (nb_streams-nb_coupled_streams) * align(mono_size);
149 }
150
151
152
153 int opus_multistream_encoder_init(
154       OpusMSEncoder *st,            /* Encoder state */
155       int Fs,                     /* Sampling rate of input signal (Hz) */
156       int channels,               /* Number of channels (1/2) in input signal */
157       int streams,
158       int coupled_streams,
159       unsigned char *mapping,
160       int application             /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
161 )
162 {
163    int coupled_size;
164    int mono_size;
165    int i;
166    char *ptr;
167
168    st->layout.nb_channels = channels;
169    st->layout.nb_streams = streams;
170    st->layout.nb_coupled_streams = coupled_streams;
171
172    for (i=0;i<st->layout.nb_channels;i++)
173       st->layout.mapping[i] = mapping[i];
174    if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
175       return OPUS_BAD_ARG;
176    ptr = (char*)st + align(sizeof(OpusMSEncoder));
177    coupled_size = opus_encoder_get_size(2);
178    mono_size = opus_encoder_get_size(1);
179
180    for (i=0;i<st->layout.nb_coupled_streams;i++)
181    {
182       opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
183       ptr += align(coupled_size);
184    }
185    for (;i<st->layout.nb_streams;i++)
186    {
187       opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
188       ptr += align(mono_size);
189    }
190    return OPUS_OK;
191 }
192
193 OpusMSEncoder *opus_multistream_encoder_create(
194       int Fs,                     /* Sampling rate of input signal (Hz) */
195       int channels,               /* Number of channels (1/2) in input signal */
196       int streams,
197       int coupled_streams,
198       unsigned char *mapping,
199       int application,            /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
200       int *error                  /* Error code */
201 )
202 {
203    int ret;
204    OpusMSEncoder *st = opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
205    if (st==NULL)
206    {
207       if (error)
208          *error = OPUS_ALLOC_FAIL;
209       return NULL;
210    }
211    ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
212    if (ret != OPUS_OK)
213    {
214       opus_free(st);
215       st = NULL;
216    }
217    if (error)
218       *error = ret;
219    return st;
220 }
221
222
223 #ifdef FIXED_POINT
224 int opus_multistream_encode(
225 #else
226 int opus_multistream_encode_float(
227 #endif
228     OpusMSEncoder *st,            /* Encoder state */
229     const opus_val16 *pcm,      /* Input signal (interleaved if 2 channels). length is frame_size*channels */
230     int frame_size,             /* Number of samples per frame of input signal */
231     unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
232     int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
233 )
234 {
235    int coupled_size;
236    int mono_size;
237    int s, i;
238    char *ptr;
239    int tot_size;
240    VARDECL(opus_val16, buf);
241    unsigned char tmp_data[1276];
242    ALLOC_STACK;
243
244    ALLOC(buf, 2*frame_size, opus_val16);
245    ptr = (char*)st + align(sizeof(OpusMSEncoder));
246    coupled_size = opus_encoder_get_size(2);
247    mono_size = opus_encoder_get_size(1);
248
249    if (max_data_bytes < 2*st->layout.nb_streams-1)
250    {
251       RESTORE_STACK;
252       return OPUS_BUFFER_TOO_SMALL;
253    }
254    /* Counting ToC */
255    tot_size = 0;
256    for (s=0;s<st->layout.nb_streams;s++)
257    {
258       OpusEncoder *enc;
259       int len;
260       int curr_max;
261
262       enc = (OpusEncoder*)ptr;
263       if (s < st->layout.nb_coupled_streams)
264       {
265          int left, right;
266          left = get_left_channel(&st->layout, s, -1);
267          right = get_right_channel(&st->layout, s, -1);
268          for (i=0;i<frame_size;i++)
269          {
270             buf[2*i] = pcm[st->layout.nb_channels*i+left];
271             buf[2*i+1] = pcm[st->layout.nb_channels*i+right];
272          }
273          ptr += align(coupled_size);
274       } else {
275          int chan = get_mono_channel(&st->layout, s, -1);
276          for (i=0;i<frame_size;i++)
277             buf[i] = pcm[st->layout.nb_channels*i+chan];
278          ptr += align(mono_size);
279       }
280       /* number of bytes left (+Toc) */
281       curr_max = max_data_bytes - tot_size;
282       /* Reserve one byte for the last stream and 2 for the others */
283       curr_max -= 2*(st->layout.nb_streams-s)-1;
284       len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max);
285       if (len<0)
286       {
287          RESTORE_STACK;
288          return len;
289       }
290       /* ToC first */
291       *data++ = tmp_data[0];
292       if (s != st->layout.nb_streams-1)
293       {
294          int tmp = encode_size(len-1, data);
295          data += tmp;
296          tot_size += tmp;
297       }
298       /* IMPORTANT: Here we assume that the encoder only returned one frame */
299       tot_size += len;
300       memcpy(data, &tmp_data[1], len-1);
301    }
302    RESTORE_STACK;
303    return tot_size;
304
305 }
306
307 #ifdef FIXED_POINT
308
309 #ifndef DISABLE_FLOAT_API
310 int opus_multistream_encode_float(
311     OpusMSEncoder *st,          /* Encoder state */
312     const float *pcm,           /* Input signal (interleaved if 2 channels). length is frame_size*channels */
313     int frame_size,             /* Number of samples per frame of input signal */
314     unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
315     int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
316 )
317 {
318    int i, ret;
319    VARDECL(opus_int16, in);
320    ALLOC_STACK;
321
322    ALLOC(in, frame_size*st->layout.nb_channels, opus_int16);
323
324    for (i=0;i<frame_size*st->layout.nb_channels;i++)
325       in[i] = FLOAT2INT16(pcm[i]);
326    ret = opus_multistream_encode(st, in, frame_size, data, max_data_bytes);
327    RESTORE_STACK;
328    return ret;
329 }
330 #endif
331
332 #else
333
334 int opus_multistream_encode(
335     OpusMSEncoder *st,          /* Encoder state */
336     const opus_int16 *pcm,      /* Input signal (interleaved if 2 channels). length is frame_size*channels */
337     int frame_size,             /* Number of samples per frame of input signal */
338     unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
339     int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
340 )
341 {
342    int i, ret;
343    VARDECL(float, in);
344    ALLOC_STACK;
345
346    ALLOC(in, frame_size*st->layout.nb_channels, float);
347
348    for (i=0;i<frame_size*st->layout.nb_channels;i++)
349       in[i] = (1./32768)*pcm[i];
350    ret = opus_multistream_encode_float(st, in, frame_size, data, max_data_bytes);
351    RESTORE_STACK;
352    return ret;
353 }
354
355 #endif
356
357 int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
358 {
359    va_list ap;
360    int coupled_size, mono_size;
361    char *ptr;
362    int ret = OPUS_OK;
363
364    va_start(ap, request);
365
366    coupled_size = opus_encoder_get_size(2);
367    mono_size = opus_encoder_get_size(1);
368    ptr = (char*)st + align(sizeof(OpusMSEncoder));
369    switch (request)
370    {
371    case OPUS_SET_BITRATE_REQUEST:
372    {
373       int chan, s;
374       opus_uint32 value = va_arg(ap, opus_uint32);
375       chan = st->layout.nb_streams + st->layout.nb_coupled_streams;
376       value /= chan;
377       for (s=0;s<st->layout.nb_streams;s++)
378       {
379          OpusEncoder *enc;
380          enc = (OpusEncoder*)ptr;
381          opus_encoder_ctl(enc, request, value * (s < st->layout.nb_coupled_streams ? 2 : 1));
382       }
383    }
384    break;
385    /* FIXME: Add missing ones */
386    case OPUS_GET_BITRATE_REQUEST:
387    case OPUS_GET_VBR_REQUEST:
388    case OPUS_GET_APPLICATION_REQUEST:
389    case OPUS_GET_BANDWIDTH_REQUEST:
390    case OPUS_GET_COMPLEXITY_REQUEST:
391    case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
392    case OPUS_GET_DTX_REQUEST:
393    case OPUS_GET_VOICE_RATIO_REQUEST:
394    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
395    case OPUS_GET_SIGNAL_REQUEST:
396    case OPUS_GET_LOOKAHEAD_REQUEST:
397    {
398       int s;
399       /* This works for int32* params */
400       opus_uint32 *value = va_arg(ap, opus_uint32*);
401       for (s=0;s<st->layout.nb_streams;s++)
402       {
403          OpusEncoder *enc;
404
405          enc = (OpusEncoder*)ptr;
406          if (s < st->layout.nb_coupled_streams)
407             ptr += align(coupled_size);
408          else
409             ptr += align(mono_size);
410          ret = opus_encoder_ctl(enc, request, value);
411          if (ret < 0)
412             break;
413       }
414    }
415    break;
416    default:
417    {
418       int s;
419       /* This works for int32 params */
420       opus_uint32 value = va_arg(ap, opus_uint32);
421       for (s=0;s<st->layout.nb_streams;s++)
422       {
423          OpusEncoder *enc;
424
425          enc = (OpusEncoder*)ptr;
426          if (s < st->layout.nb_coupled_streams)
427             ptr += align(coupled_size);
428          else
429             ptr += align(mono_size);
430          ret = opus_encoder_ctl(enc, request, value);
431          if (ret < 0)
432             break;
433       }
434    }
435    break;
436    }
437
438    va_end(ap);
439    return ret;
440 }
441
442 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
443 {
444     opus_free(st);
445 }
446
447
448 /* DECODER */
449
450 int opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
451 {
452    int coupled_size;
453    int mono_size;
454
455    coupled_size = opus_decoder_get_size(2);
456    mono_size = opus_decoder_get_size(1);
457    return align(sizeof(OpusMSDecoder))
458          + nb_coupled_streams * align(coupled_size)
459          + (nb_streams-nb_coupled_streams) * align(mono_size);
460 }
461
462 int opus_multistream_decoder_init(
463       OpusMSDecoder *st,            /* Encoder state */
464       int Fs,                     /* Sampling rate of input signal (Hz) */
465       int channels,               /* Number of channels (1/2) in input signal */
466       int streams,
467       int coupled_streams,
468       unsigned char *mapping
469 )
470 {
471    int coupled_size;
472    int mono_size;
473    int i;
474    char *ptr;
475
476    st->layout.nb_channels = channels;
477    st->layout.nb_streams = streams;
478    st->layout.nb_coupled_streams = coupled_streams;
479
480    for (i=0;i<st->layout.nb_channels;i++)
481       st->layout.mapping[i] = mapping[i];
482    if (!validate_layout(&st->layout))
483       return OPUS_BAD_ARG;
484
485    ptr = (char*)st + align(sizeof(OpusMSEncoder));
486    coupled_size = opus_decoder_get_size(2);
487    mono_size = opus_decoder_get_size(1);
488
489    for (i=0;i<st->layout.nb_coupled_streams;i++)
490    {
491       opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
492       ptr += align(coupled_size);
493    }
494    for (;i<st->layout.nb_streams;i++)
495    {
496       opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
497       ptr += align(mono_size);
498    }
499    return OPUS_OK;
500 }
501
502
503 OpusMSDecoder *opus_multistream_decoder_create(
504       int Fs,                     /* Sampling rate of input signal (Hz) */
505       int channels,               /* Number of channels (1/2) in input signal */
506       int streams,
507       int coupled_streams,
508       unsigned char *mapping,
509       int *error                  /* Error code */
510 )
511 {
512    int ret;
513    OpusMSDecoder *st = opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
514    if (st==NULL)
515    {
516       if (error)
517          *error = OPUS_ALLOC_FAIL;
518       return NULL;
519    }
520    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
521    if (error)
522       *error = ret;
523    if (ret != OPUS_OK)
524    {
525       opus_free(st);
526       st = NULL;
527    }
528    return st;
529
530
531 }
532
533 static int opus_multistream_decode_native(
534       OpusMSDecoder *st,            /* Encoder state */
535       const unsigned char *data,
536       int len,
537       opus_val16 *pcm,
538       int frame_size,
539       int decode_fec
540 )
541 {
542    int coupled_size;
543    int mono_size;
544    int s, i, c;
545    char *ptr;
546    VARDECL(opus_val16, buf);
547    ALLOC_STACK;
548
549    ALLOC(buf, 2*frame_size, opus_val16);
550    ptr = (char*)st + align(sizeof(OpusMSEncoder));
551    coupled_size = opus_decoder_get_size(2);
552    mono_size = opus_decoder_get_size(1);
553
554    if (len < 2*st->layout.nb_streams-1)
555       return OPUS_BUFFER_TOO_SMALL;
556    for (s=0;s<st->layout.nb_streams;s++)
557    {
558       OpusDecoder *dec;
559       int packet_offset, ret;
560
561       dec = (OpusDecoder*)ptr;
562       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
563
564       if (len<=0)
565       {
566          RESTORE_STACK;
567          return OPUS_CORRUPTED_DATA;
568       }
569       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, 1, &packet_offset);
570       data += packet_offset;
571       len -= packet_offset;
572       if (ret > frame_size)
573       {
574          RESTORE_STACK;
575          return OPUS_BUFFER_TOO_SMALL;
576       }
577       if (s>0 && ret != frame_size)
578       {
579          RESTORE_STACK;
580          return OPUS_CORRUPTED_DATA;
581       }
582       if (ret <= 0)
583       {
584          RESTORE_STACK;
585          return ret;
586       }
587       frame_size = ret;
588       if (s < st->layout.nb_coupled_streams)
589       {
590          int chan, prev;
591          prev = -1;
592          /* Copy "left" audio to the channel(s) where it belongs */
593          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
594          {
595             for (i=0;i<frame_size;i++)
596                pcm[st->layout.nb_channels*i+chan] = buf[2*i];
597             prev = chan;
598          }
599          prev = -1;
600          /* Copy "right" audio to the channel(s) where it belongs */
601          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
602          {
603             for (i=0;i<frame_size;i++)
604                pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
605             prev = chan;
606          }
607       } else {
608          int chan, prev;
609          prev = -1;
610          /* Copy audio to the channel(s) where it belongs */
611          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
612          {
613             for (i=0;i<frame_size;i++)
614                pcm[st->layout.nb_channels*i+chan] = buf[i];
615             prev = chan;
616          }
617       }
618    }
619    /* Handle muted channels */
620    for (c=0;c<st->layout.nb_channels;c++)
621    {
622       if (st->layout.mapping[c] == 255)
623       {
624          for (i=0;i<frame_size;i++)
625             pcm[st->layout.nb_channels*i+c] = 0;
626       }
627    }
628    RESTORE_STACK;
629    return frame_size;
630 }
631
632 #ifdef FIXED_POINT
633 int opus_multistream_decode(
634       OpusMSDecoder *st,            /* Encoder state */
635       const unsigned char *data,
636       int len,
637       opus_int16 *pcm,
638       int frame_size,
639       int decode_fec
640 )
641 {
642    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
643 }
644
645 #ifndef DISABLE_FLOAT_API
646 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
647       int len, float *pcm, int frame_size, int decode_fec)
648 {
649    VARDECL(opus_int16, out);
650    int ret, i;
651    ALLOC_STACK;
652
653    ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
654
655    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
656    if (ret > 0)
657    {
658       for (i=0;i<ret*st->layout.nb_channels;i++)
659          pcm[i] = (1./32768.)*(out[i]);
660    }
661    RESTORE_STACK;
662    return ret;
663 }
664 #endif
665
666 #else
667
668 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
669       int len, opus_int16 *pcm, int frame_size, int decode_fec)
670 {
671    VARDECL(float, out);
672    int ret, i;
673    ALLOC_STACK;
674
675    ALLOC(out, frame_size*st->layout.nb_channels, float);
676
677    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
678    if (ret > 0)
679    {
680       for (i=0;i<ret*st->layout.nb_channels;i++)
681          pcm[i] = FLOAT2INT16(out[i]);
682    }
683    RESTORE_STACK;
684    return ret;
685 }
686
687 int opus_multistream_decode_float(
688       OpusMSDecoder *st,            /* Encoder state */
689       const unsigned char *data,
690       int len,
691       float *pcm,
692       int frame_size,
693       int decode_fec
694 )
695 {
696    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
697 }
698 #endif
699
700 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
701 {
702    va_list ap;
703    int coupled_size, mono_size;
704    char *ptr;
705    int ret = OPUS_OK;
706
707    va_start(ap, request);
708
709    coupled_size = opus_decoder_get_size(2);
710    mono_size = opus_decoder_get_size(1);
711    ptr = (char*)st + align(sizeof(OpusMSDecoder));
712    switch (request)
713    {
714        default:
715        {
716           int s;
717           /* This only works for int32* params, but that's all we have right now */
718           opus_uint32 *value = va_arg(ap, opus_uint32*);
719           for (s=0;s<st->layout.nb_streams;s++)
720           {
721              OpusDecoder *enc;
722
723              enc = (OpusDecoder*)ptr;
724              if (s < st->layout.nb_coupled_streams)
725                 ptr += align(coupled_size);
726              else
727                 ptr += align(mono_size);
728              ret = opus_decoder_ctl(enc, request, value);
729              if (ret < 0)
730                 break;
731           }
732        }
733        break;
734    }
735
736    va_end(ap);
737    return ret;
738 }
739
740
741 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
742 {
743     opus_free(st);
744 }