Initial surround code with new API
[opus.git] / src / opus_multistream_encoder.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 #include "analysis.h"
40
41 struct OpusMSEncoder {
42    TonalityAnalysisState analysis;
43    ChannelLayout layout;
44    int lfe_stream;
45    int variable_duration;
46    opus_int32 bitrate_bps;
47    opus_val32 subframe_mem[3];
48    /* Encoder states go here */
49 };
50
51
52 static int validate_encoder_layout(const ChannelLayout *layout)
53 {
54    int s;
55    for (s=0;s<layout->nb_streams;s++)
56    {
57       if (s < layout->nb_coupled_streams)
58       {
59          if (get_left_channel(layout, s, -1)==-1)
60             return 0;
61          if (get_right_channel(layout, s, -1)==-1)
62             return 0;
63       } else {
64          if (get_mono_channel(layout, s, -1)==-1)
65             return 0;
66       }
67    }
68    return 1;
69 }
70
71
72 opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
73 {
74    int coupled_size;
75    int mono_size;
76
77    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
78    coupled_size = opus_encoder_get_size(2);
79    mono_size = opus_encoder_get_size(1);
80    return align(sizeof(OpusMSEncoder))
81         + nb_coupled_streams * align(coupled_size)
82         + (nb_streams-nb_coupled_streams) * align(mono_size);
83 }
84
85 opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
86 {
87    int nb_streams;
88    int nb_coupled_streams;
89
90    if (channels==1 && mapping_family<=1)
91    {
92       nb_streams = 1;
93       nb_coupled_streams=0;
94    } else if (channels==2 && mapping_family<=1)
95    {
96       nb_streams = 1;
97       nb_coupled_streams=1;
98    } else if (channels==6 && mapping_family==1)
99    {
100       nb_streams = 4;
101       nb_coupled_streams=2;
102    } else
103       return 0;
104    return opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
105 }
106
107
108 static int opus_multistream_encoder_init_impl(
109       OpusMSEncoder *st,
110       opus_int32 Fs,
111       int channels,
112       int streams,
113       int coupled_streams,
114       const unsigned char *mapping,
115       int application,
116       int surround
117 )
118 {
119    int coupled_size;
120    int mono_size;
121    int i, ret;
122    char *ptr;
123
124    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
125        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
126       return OPUS_BAD_ARG;
127
128    st->layout.nb_channels = channels;
129    st->layout.nb_streams = streams;
130    st->layout.nb_coupled_streams = coupled_streams;
131    st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
132    OPUS_CLEAR(&st->analysis,1);
133    if (!surround)
134       st->lfe_stream = -1;
135    st->bitrate_bps = OPUS_AUTO;
136    st->variable_duration = OPUS_FRAMESIZE_ARG;
137    for (i=0;i<st->layout.nb_channels;i++)
138       st->layout.mapping[i] = mapping[i];
139    if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
140       return OPUS_BAD_ARG;
141    ptr = (char*)st + align(sizeof(OpusMSEncoder));
142    coupled_size = opus_encoder_get_size(2);
143    mono_size = opus_encoder_get_size(1);
144
145    for (i=0;i<st->layout.nb_coupled_streams;i++)
146    {
147       ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
148       if (i==st->lfe_stream)
149          opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
150       if(ret!=OPUS_OK)return ret;
151       ptr += align(coupled_size);
152    }
153    for (;i<st->layout.nb_streams;i++)
154    {
155       ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
156       if (i==st->lfe_stream)
157          opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
158       if(ret!=OPUS_OK)return ret;
159       ptr += align(mono_size);
160    }
161    return OPUS_OK;
162 }
163
164 int opus_multistream_encoder_init(
165       OpusMSEncoder *st,
166       opus_int32 Fs,
167       int channels,
168       int streams,
169       int coupled_streams,
170       const unsigned char *mapping,
171       int application
172 )
173 {
174    return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
175 }
176
177 int opus_multistream_surround_encoder_init(
178       OpusMSEncoder *st,
179       opus_int32 Fs,
180       int channels,
181       int mapping_family,
182       int *streams,
183       int *coupled_streams,
184       unsigned char *mapping,
185       int application
186 )
187 {
188    st->lfe_stream = -1;
189    if (channels==1 && mapping_family<=1)
190    {
191       *streams=1;
192       *coupled_streams=0;
193       mapping[0]=0;
194    } else if (channels==2 && mapping_family<=1)
195    {
196       *streams=1;
197       *coupled_streams=1;
198       mapping[0]=0;
199       mapping[1]=1;
200    } else if (channels==6 && mapping_family==1)
201    {
202       *streams=4;
203       *coupled_streams=2;
204       mapping[0]=0;
205       mapping[1]=4;
206       mapping[2]=1;
207       mapping[3]=2;
208       mapping[4]=3;
209       mapping[5]=5;
210       st->lfe_stream = 3;
211    } else
212       return OPUS_BAD_ARG;
213    opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams, mapping, application, 1);
214    return OPUS_OK;
215 }
216
217 OpusMSEncoder *opus_multistream_encoder_create(
218       opus_int32 Fs,
219       int channels,
220       int streams,
221       int coupled_streams,
222       const unsigned char *mapping,
223       int application,
224       int *error
225 )
226 {
227    int ret;
228    OpusMSEncoder *st;
229    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
230        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
231    {
232       if (error)
233          *error = OPUS_BAD_ARG;
234       return NULL;
235    }
236    st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
237    if (st==NULL)
238    {
239       if (error)
240          *error = OPUS_ALLOC_FAIL;
241       return NULL;
242    }
243    ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
244    if (ret != OPUS_OK)
245    {
246       opus_free(st);
247       st = NULL;
248    }
249    if (error)
250       *error = ret;
251    return st;
252 }
253
254 OpusMSEncoder *opus_multistream_surround_encoder_create(
255       opus_int32 Fs,
256       int channels,
257       int mapping_family,
258       int *streams,
259       int *coupled_streams,
260       unsigned char *mapping,
261       int application,
262       int *error
263 )
264 {
265    int ret;
266    OpusMSEncoder *st;
267    if ((channels>255) || (channels<1))
268    {
269       if (error)
270          *error = OPUS_BAD_ARG;
271       return NULL;
272    }
273    st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
274    if (st==NULL)
275    {
276       if (error)
277          *error = OPUS_ALLOC_FAIL;
278       return NULL;
279    }
280    ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
281    if (ret != OPUS_OK)
282    {
283       opus_free(st);
284       st = NULL;
285    }
286    if (error)
287       *error = ret;
288    return st;
289 }
290
291 typedef void (*opus_copy_channel_in_func)(
292   opus_val16 *dst,
293   int dst_stride,
294   const void *src,
295   int src_stride,
296   int src_channel,
297   int frame_size
298 );
299
300 static void surround_rate_allocation(
301       OpusMSEncoder *st,
302       opus_int32 *rate,
303       int frame_size
304       )
305 {
306    int i;
307    opus_int32 channel_rate;
308    opus_int32 Fs;
309    char *ptr;
310    int coupled_ratio; /* Q8 */
311    int lfe_ratio;     /* Q8 */
312
313    ptr = (char*)st + align(sizeof(OpusMSEncoder));
314    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
315
316    /* Should depend on the bitrate, for now we assume coupled streams get 60% more bits than mono */
317    coupled_ratio = 410;
318    /* Should depend on the bitrate, for now we assume LFE gets 1/12 the bits of mono */
319    lfe_ratio = 32;
320
321    /* Compute bitrate allocation between streams */
322    if (st->bitrate_bps==OPUS_AUTO)
323    {
324       channel_rate = Fs+60*Fs/frame_size;
325    } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
326    {
327       channel_rate = 300000;
328    } else {
329       int total = ((st->layout.nb_streams-st->layout.nb_coupled_streams-(st->lfe_stream!=-1))<<8) /* mono */
330             + coupled_ratio*st->layout.nb_coupled_streams /* stereo */
331             + (st->lfe_stream!=-1)*lfe_ratio;
332       channel_rate = 256*st->bitrate_bps/total;
333    }
334 #ifndef FIXED_POINT
335    if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
336    {
337       opus_int32 bonus;
338       bonus = 60*(Fs/frame_size-50);
339       channel_rate += bonus;
340    }
341 #endif
342
343    for (i=0;i<st->layout.nb_streams;i++)
344    {
345       if (i<st->layout.nb_coupled_streams)
346          rate[i] = channel_rate*coupled_ratio>>8;
347       else if (i!=st->lfe_stream)
348          rate[i] = channel_rate;
349       else
350          rate[i] = channel_rate*lfe_ratio>>8;
351    }
352
353
354 }
355
356 /* Max size in case the encoder decides to return three frames */
357 #define MS_FRAME_TMP (3*1275+7)
358 static int opus_multistream_encode_native
359 (
360     OpusMSEncoder *st,
361     opus_copy_channel_in_func copy_channel_in,
362     const void *pcm,
363     int frame_size,
364     unsigned char *data,
365     opus_int32 max_data_bytes,
366     int lsb_depth
367 #ifndef FIXED_POINT
368     , downmix_func downmix
369     , const void *pcm_analysis
370 #endif
371 )
372 {
373    opus_int32 Fs;
374    int coupled_size;
375    int mono_size;
376    int s;
377    char *ptr;
378    int tot_size;
379    VARDECL(opus_val16, buf);
380    unsigned char tmp_data[MS_FRAME_TMP];
381    OpusRepacketizer rp;
382    opus_int32 complexity;
383    AnalysisInfo analysis_info;
384    const CELTMode *celt_mode;
385    opus_int32 bitrates[256];
386    ALLOC_STACK;
387
388    ptr = (char*)st + align(sizeof(OpusMSEncoder));
389    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
390    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
391    opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
392
393    if (400*frame_size < Fs)
394    {
395       RESTORE_STACK;
396       return OPUS_BAD_ARG;
397    }
398 #ifndef FIXED_POINT
399    analysis_info.valid = 0;
400    if (complexity >= 7 && Fs==48000)
401    {
402       opus_int32 delay_compensation;
403       int channels;
404
405       channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
406       opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
407       delay_compensation -= Fs/400;
408
409       frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
410             frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
411    } else
412 #endif
413    {
414       frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
415    }
416    /* Validate frame_size before using it to allocate stack space.
417       This mirrors the checks in opus_encode[_float](). */
418    if (400*frame_size != Fs && 200*frame_size != Fs &&
419        100*frame_size != Fs &&  50*frame_size != Fs &&
420         25*frame_size != Fs &&  50*frame_size != 3*Fs)
421    {
422       RESTORE_STACK;
423       return OPUS_BAD_ARG;
424    }
425    ALLOC(buf, 2*frame_size, opus_val16);
426    coupled_size = opus_encoder_get_size(2);
427    mono_size = opus_encoder_get_size(1);
428
429    if (max_data_bytes < 4*st->layout.nb_streams-1)
430    {
431       RESTORE_STACK;
432       return OPUS_BUFFER_TOO_SMALL;
433    }
434
435    /* Compute bitrate allocation between streams (this could be a lot better) */
436    surround_rate_allocation(st, bitrates, frame_size);
437
438    ptr = (char*)st + align(sizeof(OpusMSEncoder));
439    for (s=0;s<st->layout.nb_streams;s++)
440    {
441       OpusEncoder *enc;
442       enc = (OpusEncoder*)ptr;
443       if (s < st->layout.nb_coupled_streams)
444          ptr += align(coupled_size);
445       else
446          ptr += align(mono_size);
447       opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
448    }
449
450    ptr = (char*)st + align(sizeof(OpusMSEncoder));
451    /* Counting ToC */
452    tot_size = 0;
453    for (s=0;s<st->layout.nb_streams;s++)
454    {
455       OpusEncoder *enc;
456       int len;
457       int curr_max;
458
459       opus_repacketizer_init(&rp);
460       enc = (OpusEncoder*)ptr;
461       if (s < st->layout.nb_coupled_streams)
462       {
463          int left, right;
464          left = get_left_channel(&st->layout, s, -1);
465          right = get_right_channel(&st->layout, s, -1);
466          (*copy_channel_in)(buf, 2,
467             pcm, st->layout.nb_channels, left, frame_size);
468          (*copy_channel_in)(buf+1, 2,
469             pcm, st->layout.nb_channels, right, frame_size);
470          ptr += align(coupled_size);
471       } else {
472          int chan = get_mono_channel(&st->layout, s, -1);
473          (*copy_channel_in)(buf, 1,
474             pcm, st->layout.nb_channels, chan, frame_size);
475          ptr += align(mono_size);
476       }
477       /* number of bytes left (+Toc) */
478       curr_max = max_data_bytes - tot_size;
479       /* Reserve three bytes for the last stream and four for the others */
480       curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
481       curr_max = IMIN(curr_max,MS_FRAME_TMP);
482       len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
483 #ifndef FIXED_POINT
484             , &analysis_info
485 #endif
486             );
487       if (len<0)
488       {
489          RESTORE_STACK;
490          return len;
491       }
492       /* We need to use the repacketizer to add the self-delimiting lengths
493          while taking into account the fact that the encoder can now return
494          more than one frame at a time (e.g. 60 ms CELT-only) */
495       opus_repacketizer_cat(&rp, tmp_data, len);
496       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);
497       data += len;
498       tot_size += len;
499    }
500    RESTORE_STACK;
501    return tot_size;
502
503 }
504
505 #if !defined(DISABLE_FLOAT_API)
506 static void opus_copy_channel_in_float(
507   opus_val16 *dst,
508   int dst_stride,
509   const void *src,
510   int src_stride,
511   int src_channel,
512   int frame_size
513 )
514 {
515    const float *float_src;
516    opus_int32 i;
517    float_src = (const float *)src;
518    for (i=0;i<frame_size;i++)
519 #if defined(FIXED_POINT)
520       dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
521 #else
522       dst[i*dst_stride] = float_src[i*src_stride+src_channel];
523 #endif
524 }
525 #endif
526
527 static void opus_copy_channel_in_short(
528   opus_val16 *dst,
529   int dst_stride,
530   const void *src,
531   int src_stride,
532   int src_channel,
533   int frame_size
534 )
535 {
536    const opus_int16 *short_src;
537    opus_int32 i;
538    short_src = (const opus_int16 *)src;
539    for (i=0;i<frame_size;i++)
540 #if defined(FIXED_POINT)
541       dst[i*dst_stride] = short_src[i*src_stride+src_channel];
542 #else
543       dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
544 #endif
545 }
546
547 #ifdef FIXED_POINT
548 int opus_multistream_encode(
549     OpusMSEncoder *st,
550     const opus_val16 *pcm,
551     int frame_size,
552     unsigned char *data,
553     opus_int32 max_data_bytes
554 )
555 {
556    return opus_multistream_encode_native(st, opus_copy_channel_in_short,
557       pcm, frame_size, data, max_data_bytes, 16);
558 }
559
560 #ifndef DISABLE_FLOAT_API
561 int opus_multistream_encode_float(
562     OpusMSEncoder *st,
563     const float *pcm,
564     int frame_size,
565     unsigned char *data,
566     opus_int32 max_data_bytes
567 )
568 {
569    return opus_multistream_encode_native(st, opus_copy_channel_in_float,
570       pcm, frame_size, data, max_data_bytes, 16);
571 }
572 #endif
573
574 #else
575
576 int opus_multistream_encode_float
577 (
578     OpusMSEncoder *st,
579     const opus_val16 *pcm,
580     int frame_size,
581     unsigned char *data,
582     opus_int32 max_data_bytes
583 )
584 {
585    int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
586    return opus_multistream_encode_native(st, opus_copy_channel_in_float,
587       pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset);
588 }
589
590 int opus_multistream_encode(
591     OpusMSEncoder *st,
592     const opus_int16 *pcm,
593     int frame_size,
594     unsigned char *data,
595     opus_int32 max_data_bytes
596 )
597 {
598    int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
599    return opus_multistream_encode_native(st, opus_copy_channel_in_short,
600       pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset);
601 }
602 #endif
603
604 int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
605 {
606    va_list ap;
607    int coupled_size, mono_size;
608    char *ptr;
609    int ret = OPUS_OK;
610
611    va_start(ap, request);
612
613    coupled_size = opus_encoder_get_size(2);
614    mono_size = opus_encoder_get_size(1);
615    ptr = (char*)st + align(sizeof(OpusMSEncoder));
616    switch (request)
617    {
618    case OPUS_SET_BITRATE_REQUEST:
619    {
620       opus_int32 value = va_arg(ap, opus_int32);
621       if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
622          goto bad_arg;
623       st->bitrate_bps = value;
624    }
625    break;
626    case OPUS_GET_BITRATE_REQUEST:
627    {
628       int s;
629       opus_int32 *value = va_arg(ap, opus_int32*);
630       *value = 0;
631       for (s=0;s<st->layout.nb_streams;s++)
632       {
633          opus_int32 rate;
634          OpusEncoder *enc;
635          enc = (OpusEncoder*)ptr;
636          if (s < st->layout.nb_coupled_streams)
637             ptr += align(coupled_size);
638          else
639             ptr += align(mono_size);
640          opus_encoder_ctl(enc, request, &rate);
641          *value += rate;
642       }
643    }
644    break;
645    case OPUS_GET_LSB_DEPTH_REQUEST:
646    case OPUS_GET_VBR_REQUEST:
647    case OPUS_GET_APPLICATION_REQUEST:
648    case OPUS_GET_BANDWIDTH_REQUEST:
649    case OPUS_GET_COMPLEXITY_REQUEST:
650    case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
651    case OPUS_GET_DTX_REQUEST:
652    case OPUS_GET_VOICE_RATIO_REQUEST:
653    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
654    case OPUS_GET_SIGNAL_REQUEST:
655    case OPUS_GET_LOOKAHEAD_REQUEST:
656    case OPUS_GET_SAMPLE_RATE_REQUEST:
657    case OPUS_GET_INBAND_FEC_REQUEST:
658    case OPUS_GET_FORCE_CHANNELS_REQUEST:
659    {
660       OpusEncoder *enc;
661       /* For int32* GET params, just query the first stream */
662       opus_int32 *value = va_arg(ap, opus_int32*);
663       enc = (OpusEncoder*)ptr;
664       ret = opus_encoder_ctl(enc, request, value);
665    }
666    break;
667    case OPUS_GET_FINAL_RANGE_REQUEST:
668    {
669       int s;
670       opus_uint32 *value = va_arg(ap, opus_uint32*);
671       opus_uint32 tmp;
672       *value=0;
673       for (s=0;s<st->layout.nb_streams;s++)
674       {
675          OpusEncoder *enc;
676          enc = (OpusEncoder*)ptr;
677          if (s < st->layout.nb_coupled_streams)
678             ptr += align(coupled_size);
679          else
680             ptr += align(mono_size);
681          ret = opus_encoder_ctl(enc, request, &tmp);
682          if (ret != OPUS_OK) break;
683          *value ^= tmp;
684       }
685    }
686    break;
687    case OPUS_SET_LSB_DEPTH_REQUEST:
688    case OPUS_SET_COMPLEXITY_REQUEST:
689    case OPUS_SET_VBR_REQUEST:
690    case OPUS_SET_VBR_CONSTRAINT_REQUEST:
691    case OPUS_SET_BANDWIDTH_REQUEST:
692    case OPUS_SET_SIGNAL_REQUEST:
693    case OPUS_SET_APPLICATION_REQUEST:
694    case OPUS_SET_INBAND_FEC_REQUEST:
695    case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
696    case OPUS_SET_DTX_REQUEST:
697    case OPUS_SET_FORCE_MODE_REQUEST:
698    case OPUS_SET_FORCE_CHANNELS_REQUEST:
699    {
700       int s;
701       /* This works for int32 params */
702       opus_int32 value = va_arg(ap, opus_int32);
703       for (s=0;s<st->layout.nb_streams;s++)
704       {
705          OpusEncoder *enc;
706
707          enc = (OpusEncoder*)ptr;
708          if (s < st->layout.nb_coupled_streams)
709             ptr += align(coupled_size);
710          else
711             ptr += align(mono_size);
712          ret = opus_encoder_ctl(enc, request, value);
713          if (ret != OPUS_OK)
714             break;
715       }
716    }
717    break;
718    case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
719    {
720       int s;
721       opus_int32 stream_id;
722       OpusEncoder **value;
723       stream_id = va_arg(ap, opus_int32);
724       if (stream_id<0 || stream_id >= st->layout.nb_streams)
725          ret = OPUS_BAD_ARG;
726       value = va_arg(ap, OpusEncoder**);
727       for (s=0;s<stream_id;s++)
728       {
729          if (s < st->layout.nb_coupled_streams)
730             ptr += align(coupled_size);
731          else
732             ptr += align(mono_size);
733       }
734       *value = (OpusEncoder*)ptr;
735    }
736    break;
737    case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
738    {
739        opus_int32 value = va_arg(ap, opus_int32);
740        st->variable_duration = value;
741    }
742    break;
743    case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
744    {
745        opus_int32 *value = va_arg(ap, opus_int32*);
746        *value = st->variable_duration;
747    }
748    break;
749    default:
750       ret = OPUS_UNIMPLEMENTED;
751       break;
752    }
753
754    va_end(ap);
755    return ret;
756 bad_arg:
757    va_end(ap);
758    return OPUS_BAD_ARG;
759 }
760
761 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
762 {
763     opus_free(st);
764 }
765
766