Implements multi-stream encoder requests the best we can
[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,            /* Encoder state */
152       opus_int32 Fs,                     /* Sampling rate of input signal (Hz) */
153       int channels,               /* Number of channels (1/2) in input signal */
154       int streams,
155       int coupled_streams,
156       unsigned char *mapping,
157       int application             /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
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,                     /* Sampling rate of input signal (Hz) */
192       int channels,               /* Number of channels (1/2) in input signal */
193       int streams,
194       int coupled_streams,
195       unsigned char *mapping,
196       int application,            /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
197       int *error                  /* Error code */
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,            /* Encoder state */
226     const opus_val16 *pcm,      /* Input signal (interleaved if 2 channels). length is frame_size*channels */
227     int frame_size,             /* Number of samples per frame of input signal */
228     unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
229     int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
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,          /* Encoder state */
311     const float *pcm,           /* Input signal (interleaved if 2 channels). length is frame_size*channels */
312     int frame_size,             /* Number of samples per frame of input signal */
313     unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
314     int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
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,          /* Encoder state */
335     const opus_int16 *pcm,      /* Input signal (interleaved if 2 channels). length is frame_size*channels */
336     int frame_size,             /* Number of samples per frame of input signal */
337     unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
338     int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
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    default:
447       ret = OPUS_UNIMPLEMENTED;
448       break;
449    }
450
451    va_end(ap);
452    return ret;
453 }
454
455 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
456 {
457     opus_free(st);
458 }
459
460
461 /* DECODER */
462
463 int opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
464 {
465    int coupled_size;
466    int mono_size;
467
468    coupled_size = opus_decoder_get_size(2);
469    mono_size = opus_decoder_get_size(1);
470    return align(sizeof(OpusMSDecoder))
471          + nb_coupled_streams * align(coupled_size)
472          + (nb_streams-nb_coupled_streams) * align(mono_size);
473 }
474
475 int opus_multistream_decoder_init(
476       OpusMSDecoder *st,            /* Encoder state */
477       opus_int32 Fs,                     /* Sampling rate of input signal (Hz) */
478       int channels,               /* Number of channels (1/2) in input signal */
479       int streams,
480       int coupled_streams,
481       unsigned char *mapping
482 )
483 {
484    int coupled_size;
485    int mono_size;
486    int i;
487    char *ptr;
488
489    st->layout.nb_channels = channels;
490    st->layout.nb_streams = streams;
491    st->layout.nb_coupled_streams = coupled_streams;
492
493    for (i=0;i<st->layout.nb_channels;i++)
494       st->layout.mapping[i] = mapping[i];
495    if (!validate_layout(&st->layout))
496       return OPUS_BAD_ARG;
497
498    ptr = (char*)st + align(sizeof(OpusMSEncoder));
499    coupled_size = opus_decoder_get_size(2);
500    mono_size = opus_decoder_get_size(1);
501
502    for (i=0;i<st->layout.nb_coupled_streams;i++)
503    {
504       opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
505       ptr += align(coupled_size);
506    }
507    for (;i<st->layout.nb_streams;i++)
508    {
509       opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
510       ptr += align(mono_size);
511    }
512    return OPUS_OK;
513 }
514
515
516 OpusMSDecoder *opus_multistream_decoder_create(
517       opus_int32 Fs,                     /* Sampling rate of input signal (Hz) */
518       int channels,               /* Number of channels (1/2) in input signal */
519       int streams,
520       int coupled_streams,
521       unsigned char *mapping,
522       int *error                  /* Error code */
523 )
524 {
525    int ret;
526    OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
527    if (st==NULL)
528    {
529       if (error)
530          *error = OPUS_ALLOC_FAIL;
531       return NULL;
532    }
533    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
534    if (error)
535       *error = ret;
536    if (ret != OPUS_OK)
537    {
538       opus_free(st);
539       st = NULL;
540    }
541    return st;
542
543
544 }
545
546 static int opus_multistream_decode_native(
547       OpusMSDecoder *st,            /* Encoder state */
548       const unsigned char *data,
549       int len,
550       opus_val16 *pcm,
551       int frame_size,
552       int decode_fec
553 )
554 {
555    int coupled_size;
556    int mono_size;
557    int s, i, c;
558    char *ptr;
559    VARDECL(opus_val16, buf);
560    ALLOC_STACK;
561
562    ALLOC(buf, 2*frame_size, opus_val16);
563    ptr = (char*)st + align(sizeof(OpusMSEncoder));
564    coupled_size = opus_decoder_get_size(2);
565    mono_size = opus_decoder_get_size(1);
566
567    if (len < 2*st->layout.nb_streams-1)
568       return OPUS_BUFFER_TOO_SMALL;
569    for (s=0;s<st->layout.nb_streams;s++)
570    {
571       OpusDecoder *dec;
572       int packet_offset, ret;
573
574       dec = (OpusDecoder*)ptr;
575       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
576
577       if (len<=0)
578       {
579          RESTORE_STACK;
580          return OPUS_INVALID_PACKET;
581       }
582       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset);
583       data += packet_offset;
584       len -= packet_offset;
585       if (ret > frame_size)
586       {
587          RESTORE_STACK;
588          return OPUS_BUFFER_TOO_SMALL;
589       }
590       if (s>0 && ret != frame_size)
591       {
592          RESTORE_STACK;
593          return OPUS_INVALID_PACKET;
594       }
595       if (ret <= 0)
596       {
597          RESTORE_STACK;
598          return ret;
599       }
600       frame_size = ret;
601       if (s < st->layout.nb_coupled_streams)
602       {
603          int chan, prev;
604          prev = -1;
605          /* Copy "left" audio to the channel(s) where it belongs */
606          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
607          {
608             for (i=0;i<frame_size;i++)
609                pcm[st->layout.nb_channels*i+chan] = buf[2*i];
610             prev = chan;
611          }
612          prev = -1;
613          /* Copy "right" audio to the channel(s) where it belongs */
614          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
615          {
616             for (i=0;i<frame_size;i++)
617                pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
618             prev = chan;
619          }
620       } else {
621          int chan, prev;
622          prev = -1;
623          /* Copy audio to the channel(s) where it belongs */
624          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
625          {
626             for (i=0;i<frame_size;i++)
627                pcm[st->layout.nb_channels*i+chan] = buf[i];
628             prev = chan;
629          }
630       }
631    }
632    /* Handle muted channels */
633    for (c=0;c<st->layout.nb_channels;c++)
634    {
635       if (st->layout.mapping[c] == 255)
636       {
637          for (i=0;i<frame_size;i++)
638             pcm[st->layout.nb_channels*i+c] = 0;
639       }
640    }
641    RESTORE_STACK;
642    return frame_size;
643 }
644
645 #ifdef FIXED_POINT
646 int opus_multistream_decode(
647       OpusMSDecoder *st,            /* Encoder state */
648       const unsigned char *data,
649       int len,
650       opus_int16 *pcm,
651       int frame_size,
652       int decode_fec
653 )
654 {
655    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
656 }
657
658 #ifndef DISABLE_FLOAT_API
659 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
660       int len, float *pcm, int frame_size, int decode_fec)
661 {
662    VARDECL(opus_int16, out);
663    int ret, i;
664    ALLOC_STACK;
665
666    ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
667
668    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
669    if (ret > 0)
670    {
671       for (i=0;i<ret*st->layout.nb_channels;i++)
672          pcm[i] = (1./32768.)*(out[i]);
673    }
674    RESTORE_STACK;
675    return ret;
676 }
677 #endif
678
679 #else
680
681 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
682       int len, opus_int16 *pcm, int frame_size, int decode_fec)
683 {
684    VARDECL(float, out);
685    int ret, i;
686    ALLOC_STACK;
687
688    ALLOC(out, frame_size*st->layout.nb_channels, float);
689
690    ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
691    if (ret > 0)
692    {
693       for (i=0;i<ret*st->layout.nb_channels;i++)
694          pcm[i] = FLOAT2INT16(out[i]);
695    }
696    RESTORE_STACK;
697    return ret;
698 }
699
700 int opus_multistream_decode_float(
701       OpusMSDecoder *st,            /* Encoder state */
702       const unsigned char *data,
703       int len,
704       float *pcm,
705       int frame_size,
706       int decode_fec
707 )
708 {
709    return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
710 }
711 #endif
712
713 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
714 {
715    va_list ap;
716    int coupled_size, mono_size;
717    char *ptr;
718    int ret = OPUS_OK;
719
720    va_start(ap, request);
721
722    coupled_size = opus_decoder_get_size(2);
723    mono_size = opus_decoder_get_size(1);
724    ptr = (char*)st + align(sizeof(OpusMSDecoder));
725    switch (request)
726    {
727        case OPUS_GET_BANDWIDTH_REQUEST:
728        case OPUS_GET_FINAL_RANGE_REQUEST:
729        {
730           int s;
731           /* This only works for int32* params, but that's all we have right now */
732           opus_uint32 *value = va_arg(ap, opus_uint32*);
733           for (s=0;s<st->layout.nb_streams;s++)
734           {
735              OpusDecoder *dec;
736
737              dec = (OpusDecoder*)ptr;
738              if (s < st->layout.nb_coupled_streams)
739                 ptr += align(coupled_size);
740              else
741                 ptr += align(mono_size);
742              ret = opus_decoder_ctl(dec, request, value);
743              if (ret < 0)
744                 break;
745           }
746        }
747        break;
748        case OPUS_RESET_STATE:
749        {
750           int s;
751           /* This only works for int32* params, but that's all we have right now */
752           for (s=0;s<st->layout.nb_streams;s++)
753           {
754              OpusDecoder *dec;
755
756              dec = (OpusDecoder*)ptr;
757              if (s < st->layout.nb_coupled_streams)
758                 ptr += align(coupled_size);
759              else
760                 ptr += align(mono_size);
761              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
762              if (ret < 0)
763                 break;
764           }
765        }
766        break;
767        default:
768           ret = OPUS_UNIMPLEMENTED;
769        break;
770    }
771
772    va_end(ap);
773    return ret;
774 }
775
776
777 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
778 {
779     opus_free(st);
780 }