blob: 9e857735736fbf3eee06ce839e2f6847cc83f548 [file] [log] [blame]
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001/* 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 "mathops.h"
40#include "mdct.h"
41#include "modes.h"
42#include "bands.h"
43#include "quant_bands.h"
flimc91ee5b2016-01-26 14:33:44 +010044#include "pitch.h"
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080045
46typedef struct {
47 int nb_streams;
48 int nb_coupled_streams;
49 unsigned char mapping[8];
50} VorbisLayout;
51
52/* Index is nb_channel-1*/
53static const VorbisLayout vorbis_mappings[8] = {
54 {1, 0, {0}}, /* 1: mono */
55 {1, 1, {0, 1}}, /* 2: stereo */
56 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
57 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
58 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
59 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
60 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
61 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
62};
63
64typedef void (*opus_copy_channel_in_func)(
65 opus_val16 *dst,
66 int dst_stride,
67 const void *src,
68 int src_stride,
69 int src_channel,
70 int frame_size
71);
72
73struct OpusMSEncoder {
74 ChannelLayout layout;
flimc91ee5b2016-01-26 14:33:44 +010075 int arch;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080076 int lfe_stream;
77 int application;
78 int variable_duration;
79 int surround;
80 opus_int32 bitrate_bps;
81 float subframe_mem[3];
82 /* Encoder states go here */
83 /* then opus_val32 window_mem[channels*120]; */
84 /* then opus_val32 preemph_mem[channels]; */
85};
86
87static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
88{
89 int s;
90 char *ptr;
91 int coupled_size, mono_size;
92
93 coupled_size = opus_encoder_get_size(2);
94 mono_size = opus_encoder_get_size(1);
95 ptr = (char*)st + align(sizeof(OpusMSEncoder));
96 for (s=0;s<st->layout.nb_streams;s++)
97 {
98 if (s < st->layout.nb_coupled_streams)
99 ptr += align(coupled_size);
100 else
101 ptr += align(mono_size);
102 }
flimc91ee5b2016-01-26 14:33:44 +0100103 /* void* cast avoids clang -Wcast-align warning */
104 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800105}
106
107static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
108{
109 int s;
110 char *ptr;
111 int coupled_size, mono_size;
112
113 coupled_size = opus_encoder_get_size(2);
114 mono_size = opus_encoder_get_size(1);
115 ptr = (char*)st + align(sizeof(OpusMSEncoder));
116 for (s=0;s<st->layout.nb_streams;s++)
117 {
118 if (s < st->layout.nb_coupled_streams)
119 ptr += align(coupled_size);
120 else
121 ptr += align(mono_size);
122 }
flimc91ee5b2016-01-26 14:33:44 +0100123 /* void* cast avoids clang -Wcast-align warning */
124 return (opus_val32*)(void*)ptr;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800125}
126
127static int validate_encoder_layout(const ChannelLayout *layout)
128{
129 int s;
130 for (s=0;s<layout->nb_streams;s++)
131 {
132 if (s < layout->nb_coupled_streams)
133 {
134 if (get_left_channel(layout, s, -1)==-1)
135 return 0;
136 if (get_right_channel(layout, s, -1)==-1)
137 return 0;
138 } else {
139 if (get_mono_channel(layout, s, -1)==-1)
140 return 0;
141 }
142 }
143 return 1;
144}
145
146static void channel_pos(int channels, int pos[8])
147{
148 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
149 if (channels==4)
150 {
151 pos[0]=1;
152 pos[1]=3;
153 pos[2]=1;
154 pos[3]=3;
155 } else if (channels==3||channels==5||channels==6)
156 {
157 pos[0]=1;
158 pos[1]=2;
159 pos[2]=3;
160 pos[3]=1;
161 pos[4]=3;
162 pos[5]=0;
163 } else if (channels==7)
164 {
165 pos[0]=1;
166 pos[1]=2;
167 pos[2]=3;
168 pos[3]=1;
169 pos[4]=3;
170 pos[5]=2;
171 pos[6]=0;
172 } else if (channels==8)
173 {
174 pos[0]=1;
175 pos[1]=2;
176 pos[2]=3;
177 pos[3]=1;
178 pos[4]=3;
179 pos[5]=1;
180 pos[6]=3;
181 pos[7]=0;
182 }
183}
184
185#if 1
186/* Computes a rough approximation of log2(2^a + 2^b) */
187static opus_val16 logSum(opus_val16 a, opus_val16 b)
188{
189 opus_val16 max;
190 opus_val32 diff;
191 opus_val16 frac;
192 static const opus_val16 diff_table[17] = {
193 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
194 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
195 QCONST16(0.0028123f, DB_SHIFT)
196 };
197 int low;
198 if (a>b)
199 {
200 max = a;
201 diff = SUB32(EXTEND32(a),EXTEND32(b));
202 } else {
203 max = b;
204 diff = SUB32(EXTEND32(b),EXTEND32(a));
205 }
flimc91ee5b2016-01-26 14:33:44 +0100206 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800207 return max;
208#ifdef FIXED_POINT
209 low = SHR32(diff, DB_SHIFT-1);
210 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
211#else
212 low = (int)floor(2*diff);
213 frac = 2*diff - low;
214#endif
215 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
216}
217#else
218opus_val16 logSum(opus_val16 a, opus_val16 b)
219{
220 return log2(pow(4, a)+ pow(4, b))/2;
221}
222#endif
223
224void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
flimc91ee5b2016-01-26 14:33:44 +0100225 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800226)
227{
228 int c;
229 int i;
230 int LM;
231 int pos[8] = {0};
232 int upsample;
233 int frame_size;
234 opus_val16 channel_offset;
235 opus_val32 bandE[21];
236 opus_val16 maskLogE[3][21];
237 VARDECL(opus_val32, in);
238 VARDECL(opus_val16, x);
239 VARDECL(opus_val32, freq);
240 SAVE_STACK;
241
242 upsample = resampling_factor(rate);
243 frame_size = len*upsample;
244
245 for (LM=0;LM<celt_mode->maxLM;LM++)
246 if (celt_mode->shortMdctSize<<LM==frame_size)
247 break;
248
249 ALLOC(in, frame_size+overlap, opus_val32);
250 ALLOC(x, len, opus_val16);
251 ALLOC(freq, frame_size, opus_val32);
252
253 channel_pos(channels, pos);
254
255 for (c=0;c<3;c++)
256 for (i=0;i<21;i++)
257 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
258
259 for (c=0;c<channels;c++)
260 {
261 OPUS_COPY(in, mem+c*overlap, overlap);
262 (*copy_channel_in)(x, 1, pcm, channels, c, len);
263 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
flimc91ee5b2016-01-26 14:33:44 +0100264#ifndef FIXED_POINT
265 {
266 opus_val32 sum;
267 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
268 /* This should filter out both NaNs and ridiculous signals that could
269 cause NaNs further down. */
270 if (!(sum < 1e9f) || celt_isnan(sum))
271 {
272 OPUS_CLEAR(in, frame_size+overlap);
273 preemph_mem[c] = 0;
274 }
275 }
276#endif
277 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window,
278 overlap, celt_mode->maxLM-LM, 1, arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800279 if (upsample != 1)
280 {
281 int bound = len;
282 for (i=0;i<bound;i++)
283 freq[i] *= upsample;
284 for (;i<frame_size;i++)
285 freq[i] = 0;
286 }
287
flimc91ee5b2016-01-26 14:33:44 +0100288 compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800289 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
290 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
291 for (i=1;i<21;i++)
292 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
293 for (i=19;i>=0;i--)
294 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
295 if (pos[c]==1)
296 {
297 for (i=0;i<21;i++)
298 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
299 } else if (pos[c]==3)
300 {
301 for (i=0;i<21;i++)
302 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
303 } else if (pos[c]==2)
304 {
305 for (i=0;i<21;i++)
306 {
307 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
308 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
309 }
310 }
311#if 0
312 for (i=0;i<21;i++)
313 printf("%f ", bandLogE[21*c+i]);
314 float sum=0;
315 for (i=0;i<21;i++)
316 sum += bandLogE[21*c+i];
317 printf("%f ", sum/21);
318#endif
319 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
320 }
321 for (i=0;i<21;i++)
322 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
323 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
324 for (c=0;c<3;c++)
325 for (i=0;i<21;i++)
326 maskLogE[c][i] += channel_offset;
327#if 0
328 for (c=0;c<3;c++)
329 {
330 for (i=0;i<21;i++)
331 printf("%f ", maskLogE[c][i]);
332 }
333#endif
334 for (c=0;c<channels;c++)
335 {
336 opus_val16 *mask;
337 if (pos[c]!=0)
338 {
339 mask = &maskLogE[pos[c]-1][0];
340 for (i=0;i<21;i++)
341 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
342 } else {
343 for (i=0;i<21;i++)
344 bandLogE[21*c+i] = 0;
345 }
346#if 0
347 for (i=0;i<21;i++)
348 printf("%f ", bandLogE[21*c+i]);
349 printf("\n");
350#endif
351#if 0
352 float sum=0;
353 for (i=0;i<21;i++)
354 sum += bandLogE[21*c+i];
355 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
356 printf("\n");
357#endif
358 }
359 RESTORE_STACK;
360}
361
362opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
363{
364 int coupled_size;
365 int mono_size;
366
367 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
368 coupled_size = opus_encoder_get_size(2);
369 mono_size = opus_encoder_get_size(1);
370 return align(sizeof(OpusMSEncoder))
371 + nb_coupled_streams * align(coupled_size)
372 + (nb_streams-nb_coupled_streams) * align(mono_size);
373}
374
375opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
376{
377 int nb_streams;
378 int nb_coupled_streams;
379 opus_int32 size;
380
381 if (mapping_family==0)
382 {
383 if (channels==1)
384 {
385 nb_streams=1;
386 nb_coupled_streams=0;
387 } else if (channels==2)
388 {
389 nb_streams=1;
390 nb_coupled_streams=1;
391 } else
392 return 0;
393 } else if (mapping_family==1 && channels<=8 && channels>=1)
394 {
395 nb_streams=vorbis_mappings[channels-1].nb_streams;
396 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
397 } else if (mapping_family==255)
398 {
399 nb_streams=channels;
400 nb_coupled_streams=0;
401 } else
402 return 0;
403 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
404 if (channels>2)
405 {
406 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
407 }
408 return size;
409}
410
411
412static int opus_multistream_encoder_init_impl(
413 OpusMSEncoder *st,
414 opus_int32 Fs,
415 int channels,
416 int streams,
417 int coupled_streams,
418 const unsigned char *mapping,
419 int application,
420 int surround
421)
422{
423 int coupled_size;
424 int mono_size;
425 int i, ret;
426 char *ptr;
427
428 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
flimc91ee5b2016-01-26 14:33:44 +0100429 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800430 return OPUS_BAD_ARG;
431
flimc91ee5b2016-01-26 14:33:44 +0100432 st->arch = opus_select_arch();
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800433 st->layout.nb_channels = channels;
434 st->layout.nb_streams = streams;
435 st->layout.nb_coupled_streams = coupled_streams;
436 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
437 if (!surround)
438 st->lfe_stream = -1;
439 st->bitrate_bps = OPUS_AUTO;
440 st->application = application;
441 st->variable_duration = OPUS_FRAMESIZE_ARG;
442 for (i=0;i<st->layout.nb_channels;i++)
443 st->layout.mapping[i] = mapping[i];
444 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
445 return OPUS_BAD_ARG;
446 ptr = (char*)st + align(sizeof(OpusMSEncoder));
447 coupled_size = opus_encoder_get_size(2);
448 mono_size = opus_encoder_get_size(1);
449
450 for (i=0;i<st->layout.nb_coupled_streams;i++)
451 {
452 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
453 if(ret!=OPUS_OK)return ret;
454 if (i==st->lfe_stream)
455 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
456 ptr += align(coupled_size);
457 }
458 for (;i<st->layout.nb_streams;i++)
459 {
460 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
461 if (i==st->lfe_stream)
462 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
463 if(ret!=OPUS_OK)return ret;
464 ptr += align(mono_size);
465 }
466 if (surround)
467 {
468 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
469 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
470 }
471 st->surround = surround;
472 return OPUS_OK;
473}
474
475int opus_multistream_encoder_init(
476 OpusMSEncoder *st,
477 opus_int32 Fs,
478 int channels,
479 int streams,
480 int coupled_streams,
481 const unsigned char *mapping,
482 int application
483)
484{
485 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
486}
487
488int opus_multistream_surround_encoder_init(
489 OpusMSEncoder *st,
490 opus_int32 Fs,
491 int channels,
492 int mapping_family,
493 int *streams,
494 int *coupled_streams,
495 unsigned char *mapping,
496 int application
497)
498{
499 if ((channels>255) || (channels<1))
500 return OPUS_BAD_ARG;
501 st->lfe_stream = -1;
502 if (mapping_family==0)
503 {
504 if (channels==1)
505 {
506 *streams=1;
507 *coupled_streams=0;
508 mapping[0]=0;
509 } else if (channels==2)
510 {
511 *streams=1;
512 *coupled_streams=1;
513 mapping[0]=0;
514 mapping[1]=1;
515 } else
516 return OPUS_UNIMPLEMENTED;
517 } else if (mapping_family==1 && channels<=8 && channels>=1)
518 {
519 int i;
520 *streams=vorbis_mappings[channels-1].nb_streams;
521 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
522 for (i=0;i<channels;i++)
523 mapping[i] = vorbis_mappings[channels-1].mapping[i];
524 if (channels>=6)
525 st->lfe_stream = *streams-1;
526 } else if (mapping_family==255)
527 {
528 int i;
529 *streams=channels;
530 *coupled_streams=0;
531 for(i=0;i<channels;i++)
532 mapping[i] = i;
533 } else
534 return OPUS_UNIMPLEMENTED;
535 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
536 mapping, application, channels>2&&mapping_family==1);
537}
538
539OpusMSEncoder *opus_multistream_encoder_create(
540 opus_int32 Fs,
541 int channels,
542 int streams,
543 int coupled_streams,
544 const unsigned char *mapping,
545 int application,
546 int *error
547)
548{
549 int ret;
550 OpusMSEncoder *st;
551 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
flimc91ee5b2016-01-26 14:33:44 +0100552 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800553 {
554 if (error)
555 *error = OPUS_BAD_ARG;
556 return NULL;
557 }
558 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
559 if (st==NULL)
560 {
561 if (error)
562 *error = OPUS_ALLOC_FAIL;
563 return NULL;
564 }
565 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
566 if (ret != OPUS_OK)
567 {
568 opus_free(st);
569 st = NULL;
570 }
571 if (error)
572 *error = ret;
573 return st;
574}
575
576OpusMSEncoder *opus_multistream_surround_encoder_create(
577 opus_int32 Fs,
578 int channels,
579 int mapping_family,
580 int *streams,
581 int *coupled_streams,
582 unsigned char *mapping,
583 int application,
584 int *error
585)
586{
587 int ret;
flimc91ee5b2016-01-26 14:33:44 +0100588 opus_int32 size;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800589 OpusMSEncoder *st;
590 if ((channels>255) || (channels<1))
591 {
592 if (error)
593 *error = OPUS_BAD_ARG;
594 return NULL;
595 }
flimc91ee5b2016-01-26 14:33:44 +0100596 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
597 if (!size)
598 {
599 if (error)
600 *error = OPUS_UNIMPLEMENTED;
601 return NULL;
602 }
603 st = (OpusMSEncoder *)opus_alloc(size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800604 if (st==NULL)
605 {
606 if (error)
607 *error = OPUS_ALLOC_FAIL;
608 return NULL;
609 }
610 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
611 if (ret != OPUS_OK)
612 {
613 opus_free(st);
614 st = NULL;
615 }
616 if (error)
617 *error = ret;
618 return st;
619}
620
flimc91ee5b2016-01-26 14:33:44 +0100621static opus_int32 surround_rate_allocation(
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800622 OpusMSEncoder *st,
623 opus_int32 *rate,
624 int frame_size
625 )
626{
627 int i;
628 opus_int32 channel_rate;
629 opus_int32 Fs;
630 char *ptr;
631 int stream_offset;
632 int lfe_offset;
633 int coupled_ratio; /* Q8 */
634 int lfe_ratio; /* Q8 */
flimc91ee5b2016-01-26 14:33:44 +0100635 opus_int32 rate_sum=0;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800636
637 ptr = (char*)st + align(sizeof(OpusMSEncoder));
638 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
639
640 if (st->bitrate_bps > st->layout.nb_channels*40000)
641 stream_offset = 20000;
642 else
643 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
644 stream_offset += 60*(Fs/frame_size-50);
645 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
646 This models the main saving of coupled channels over uncoupled. */
647 /* The LFE stream is an exception to the above and gets fewer bits. */
648 lfe_offset = 3500 + 60*(Fs/frame_size-50);
649 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
650 coupled_ratio = 512;
651 /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
652 lfe_ratio = 32;
653
654 /* Compute bitrate allocation between streams */
655 if (st->bitrate_bps==OPUS_AUTO)
656 {
657 channel_rate = Fs+60*Fs/frame_size;
658 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
659 {
660 channel_rate = 300000;
661 } else {
662 int nb_lfe;
663 int nb_uncoupled;
664 int nb_coupled;
665 int total;
666 nb_lfe = (st->lfe_stream!=-1);
667 nb_coupled = st->layout.nb_coupled_streams;
668 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
669 total = (nb_uncoupled<<8) /* mono */
670 + coupled_ratio*nb_coupled /* stereo */
671 + nb_lfe*lfe_ratio;
672 channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
673 }
674#ifndef FIXED_POINT
675 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
676 {
677 opus_int32 bonus;
678 bonus = 60*(Fs/frame_size-50);
679 channel_rate += bonus;
680 }
681#endif
682
683 for (i=0;i<st->layout.nb_streams;i++)
684 {
685 if (i<st->layout.nb_coupled_streams)
686 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
687 else if (i!=st->lfe_stream)
688 rate[i] = stream_offset+channel_rate;
689 else
690 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
flimc91ee5b2016-01-26 14:33:44 +0100691 rate[i] = IMAX(rate[i], 500);
692 rate_sum += rate[i];
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800693 }
flimc91ee5b2016-01-26 14:33:44 +0100694 return rate_sum;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800695}
696
697/* Max size in case the encoder decides to return three frames */
698#define MS_FRAME_TMP (3*1275+7)
699static int opus_multistream_encode_native
700(
701 OpusMSEncoder *st,
702 opus_copy_channel_in_func copy_channel_in,
703 const void *pcm,
704 int analysis_frame_size,
705 unsigned char *data,
706 opus_int32 max_data_bytes,
707 int lsb_depth,
flimc91ee5b2016-01-26 14:33:44 +0100708 downmix_func downmix,
709 int float_api
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800710)
711{
712 opus_int32 Fs;
713 int coupled_size;
714 int mono_size;
715 int s;
716 char *ptr;
717 int tot_size;
718 VARDECL(opus_val16, buf);
719 VARDECL(opus_val16, bandSMR);
720 unsigned char tmp_data[MS_FRAME_TMP];
721 OpusRepacketizer rp;
722 opus_int32 vbr;
723 const CELTMode *celt_mode;
724 opus_int32 bitrates[256];
725 opus_val16 bandLogE[42];
726 opus_val32 *mem = NULL;
727 opus_val32 *preemph_mem=NULL;
728 int frame_size;
flimc91ee5b2016-01-26 14:33:44 +0100729 opus_int32 rate_sum;
730 opus_int32 smallest_packet;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800731 ALLOC_STACK;
732
733 if (st->surround)
734 {
735 preemph_mem = ms_get_preemph_mem(st);
736 mem = ms_get_window_mem(st);
737 }
738
739 ptr = (char*)st + align(sizeof(OpusMSEncoder));
740 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
741 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
742 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
743
744 {
745 opus_int32 delay_compensation;
746 int channels;
747
748 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
749 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
750 delay_compensation -= Fs/400;
751 frame_size = compute_frame_size(pcm, analysis_frame_size,
752 st->variable_duration, channels, Fs, st->bitrate_bps,
753 delay_compensation, downmix
754#ifndef DISABLE_FLOAT_API
755 , st->subframe_mem
756#endif
757 );
758 }
759
760 if (400*frame_size < Fs)
761 {
762 RESTORE_STACK;
763 return OPUS_BAD_ARG;
764 }
765 /* Validate frame_size before using it to allocate stack space.
766 This mirrors the checks in opus_encode[_float](). */
767 if (400*frame_size != Fs && 200*frame_size != Fs &&
768 100*frame_size != Fs && 50*frame_size != Fs &&
769 25*frame_size != Fs && 50*frame_size != 3*Fs)
770 {
771 RESTORE_STACK;
772 return OPUS_BAD_ARG;
773 }
flimc91ee5b2016-01-26 14:33:44 +0100774
775 /* Smallest packet the encoder can produce. */
776 smallest_packet = st->layout.nb_streams*2-1;
777 if (max_data_bytes < smallest_packet)
778 {
779 RESTORE_STACK;
780 return OPUS_BUFFER_TOO_SMALL;
781 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800782 ALLOC(buf, 2*frame_size, opus_val16);
783 coupled_size = opus_encoder_get_size(2);
784 mono_size = opus_encoder_get_size(1);
785
786 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
787 if (st->surround)
788 {
flimc91ee5b2016-01-26 14:33:44 +0100789 surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800790 }
791
792 /* Compute bitrate allocation between streams (this could be a lot better) */
flimc91ee5b2016-01-26 14:33:44 +0100793 rate_sum = surround_rate_allocation(st, bitrates, frame_size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800794
795 if (!vbr)
flimc91ee5b2016-01-26 14:33:44 +0100796 {
797 if (st->bitrate_bps == OPUS_AUTO)
798 {
799 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
800 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
801 {
802 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
803 3*st->bitrate_bps/(3*8*Fs/frame_size)));
804 }
805 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800806 ptr = (char*)st + align(sizeof(OpusMSEncoder));
807 for (s=0;s<st->layout.nb_streams;s++)
808 {
809 OpusEncoder *enc;
810 enc = (OpusEncoder*)ptr;
811 if (s < st->layout.nb_coupled_streams)
812 ptr += align(coupled_size);
813 else
814 ptr += align(mono_size);
815 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
816 if (st->surround)
817 {
818 opus_int32 equiv_rate;
819 equiv_rate = st->bitrate_bps;
820 if (frame_size*50 < Fs)
821 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
822 if (equiv_rate > 10000*st->layout.nb_channels)
823 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
824 else if (equiv_rate > 7000*st->layout.nb_channels)
825 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
826 else if (equiv_rate > 5000*st->layout.nb_channels)
827 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
828 else
829 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
830 if (s < st->layout.nb_coupled_streams)
831 {
832 /* To preserve the spatial image, force stereo CELT on coupled streams */
833 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
834 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
835 }
836 }
837 }
838
839 ptr = (char*)st + align(sizeof(OpusMSEncoder));
840 /* Counting ToC */
841 tot_size = 0;
842 for (s=0;s<st->layout.nb_streams;s++)
843 {
844 OpusEncoder *enc;
845 int len;
846 int curr_max;
847 int c1, c2;
848
849 opus_repacketizer_init(&rp);
850 enc = (OpusEncoder*)ptr;
851 if (s < st->layout.nb_coupled_streams)
852 {
853 int i;
854 int left, right;
855 left = get_left_channel(&st->layout, s, -1);
856 right = get_right_channel(&st->layout, s, -1);
857 (*copy_channel_in)(buf, 2,
858 pcm, st->layout.nb_channels, left, frame_size);
859 (*copy_channel_in)(buf+1, 2,
860 pcm, st->layout.nb_channels, right, frame_size);
861 ptr += align(coupled_size);
862 if (st->surround)
863 {
864 for (i=0;i<21;i++)
865 {
866 bandLogE[i] = bandSMR[21*left+i];
867 bandLogE[21+i] = bandSMR[21*right+i];
868 }
869 }
870 c1 = left;
871 c2 = right;
872 } else {
873 int i;
874 int chan = get_mono_channel(&st->layout, s, -1);
875 (*copy_channel_in)(buf, 1,
876 pcm, st->layout.nb_channels, chan, frame_size);
877 ptr += align(mono_size);
878 if (st->surround)
879 {
880 for (i=0;i<21;i++)
881 bandLogE[i] = bandSMR[21*chan+i];
882 }
883 c1 = chan;
884 c2 = -1;
885 }
886 if (st->surround)
887 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
888 /* number of bytes left (+Toc) */
889 curr_max = max_data_bytes - tot_size;
flimc91ee5b2016-01-26 14:33:44 +0100890 /* Reserve one byte for the last stream and two for the others */
891 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800892 curr_max = IMIN(curr_max,MS_FRAME_TMP);
flimc91ee5b2016-01-26 14:33:44 +0100893 /* Repacketizer will add one or two bytes for self-delimited frames */
894 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800895 if (!vbr && s == st->layout.nb_streams-1)
896 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
897 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
flimc91ee5b2016-01-26 14:33:44 +0100898 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800899 if (len<0)
900 {
901 RESTORE_STACK;
902 return len;
903 }
904 /* We need to use the repacketizer to add the self-delimiting lengths
905 while taking into account the fact that the encoder can now return
906 more than one frame at a time (e.g. 60 ms CELT-only) */
907 opus_repacketizer_cat(&rp, tmp_data, len);
908 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
909 data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
910 data += len;
911 tot_size += len;
912 }
913 /*printf("\n");*/
914 RESTORE_STACK;
915 return tot_size;
916}
917
918#if !defined(DISABLE_FLOAT_API)
919static void opus_copy_channel_in_float(
920 opus_val16 *dst,
921 int dst_stride,
922 const void *src,
923 int src_stride,
924 int src_channel,
925 int frame_size
926)
927{
928 const float *float_src;
929 opus_int32 i;
930 float_src = (const float *)src;
931 for (i=0;i<frame_size;i++)
932#if defined(FIXED_POINT)
933 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
934#else
935 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
936#endif
937}
938#endif
939
940static void opus_copy_channel_in_short(
941 opus_val16 *dst,
942 int dst_stride,
943 const void *src,
944 int src_stride,
945 int src_channel,
946 int frame_size
947)
948{
949 const opus_int16 *short_src;
950 opus_int32 i;
951 short_src = (const opus_int16 *)src;
952 for (i=0;i<frame_size;i++)
953#if defined(FIXED_POINT)
954 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
955#else
956 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
957#endif
958}
959
960
961#ifdef FIXED_POINT
962int opus_multistream_encode(
963 OpusMSEncoder *st,
964 const opus_val16 *pcm,
965 int frame_size,
966 unsigned char *data,
967 opus_int32 max_data_bytes
968)
969{
970 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
flimc91ee5b2016-01-26 14:33:44 +0100971 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800972}
973
974#ifndef DISABLE_FLOAT_API
975int opus_multistream_encode_float(
976 OpusMSEncoder *st,
977 const float *pcm,
978 int frame_size,
979 unsigned char *data,
980 opus_int32 max_data_bytes
981)
982{
983 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
flimc91ee5b2016-01-26 14:33:44 +0100984 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800985}
986#endif
987
988#else
989
990int opus_multistream_encode_float
991(
992 OpusMSEncoder *st,
993 const opus_val16 *pcm,
994 int frame_size,
995 unsigned char *data,
996 opus_int32 max_data_bytes
997)
998{
999 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
flimc91ee5b2016-01-26 14:33:44 +01001000 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001001}
1002
1003int opus_multistream_encode(
1004 OpusMSEncoder *st,
1005 const opus_int16 *pcm,
1006 int frame_size,
1007 unsigned char *data,
1008 opus_int32 max_data_bytes
1009)
1010{
1011 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
flimc91ee5b2016-01-26 14:33:44 +01001012 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001013}
1014#endif
1015
1016int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1017{
1018 va_list ap;
1019 int coupled_size, mono_size;
1020 char *ptr;
1021 int ret = OPUS_OK;
1022
1023 va_start(ap, request);
1024
1025 coupled_size = opus_encoder_get_size(2);
1026 mono_size = opus_encoder_get_size(1);
1027 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1028 switch (request)
1029 {
1030 case OPUS_SET_BITRATE_REQUEST:
1031 {
1032 opus_int32 value = va_arg(ap, opus_int32);
1033 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
1034 {
1035 goto bad_arg;
1036 }
1037 st->bitrate_bps = value;
1038 }
1039 break;
1040 case OPUS_GET_BITRATE_REQUEST:
1041 {
1042 int s;
1043 opus_int32 *value = va_arg(ap, opus_int32*);
1044 if (!value)
1045 {
1046 goto bad_arg;
1047 }
1048 *value = 0;
1049 for (s=0;s<st->layout.nb_streams;s++)
1050 {
1051 opus_int32 rate;
1052 OpusEncoder *enc;
1053 enc = (OpusEncoder*)ptr;
1054 if (s < st->layout.nb_coupled_streams)
1055 ptr += align(coupled_size);
1056 else
1057 ptr += align(mono_size);
1058 opus_encoder_ctl(enc, request, &rate);
1059 *value += rate;
1060 }
1061 }
1062 break;
1063 case OPUS_GET_LSB_DEPTH_REQUEST:
1064 case OPUS_GET_VBR_REQUEST:
1065 case OPUS_GET_APPLICATION_REQUEST:
1066 case OPUS_GET_BANDWIDTH_REQUEST:
1067 case OPUS_GET_COMPLEXITY_REQUEST:
1068 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1069 case OPUS_GET_DTX_REQUEST:
1070 case OPUS_GET_VOICE_RATIO_REQUEST:
1071 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1072 case OPUS_GET_SIGNAL_REQUEST:
1073 case OPUS_GET_LOOKAHEAD_REQUEST:
1074 case OPUS_GET_SAMPLE_RATE_REQUEST:
1075 case OPUS_GET_INBAND_FEC_REQUEST:
1076 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1077 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
1078 {
1079 OpusEncoder *enc;
1080 /* For int32* GET params, just query the first stream */
1081 opus_int32 *value = va_arg(ap, opus_int32*);
1082 enc = (OpusEncoder*)ptr;
1083 ret = opus_encoder_ctl(enc, request, value);
1084 }
1085 break;
1086 case OPUS_GET_FINAL_RANGE_REQUEST:
1087 {
1088 int s;
1089 opus_uint32 *value = va_arg(ap, opus_uint32*);
1090 opus_uint32 tmp;
1091 if (!value)
1092 {
1093 goto bad_arg;
1094 }
1095 *value=0;
1096 for (s=0;s<st->layout.nb_streams;s++)
1097 {
1098 OpusEncoder *enc;
1099 enc = (OpusEncoder*)ptr;
1100 if (s < st->layout.nb_coupled_streams)
1101 ptr += align(coupled_size);
1102 else
1103 ptr += align(mono_size);
1104 ret = opus_encoder_ctl(enc, request, &tmp);
1105 if (ret != OPUS_OK) break;
1106 *value ^= tmp;
1107 }
1108 }
1109 break;
1110 case OPUS_SET_LSB_DEPTH_REQUEST:
1111 case OPUS_SET_COMPLEXITY_REQUEST:
1112 case OPUS_SET_VBR_REQUEST:
1113 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
1114 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
1115 case OPUS_SET_BANDWIDTH_REQUEST:
1116 case OPUS_SET_SIGNAL_REQUEST:
1117 case OPUS_SET_APPLICATION_REQUEST:
1118 case OPUS_SET_INBAND_FEC_REQUEST:
1119 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1120 case OPUS_SET_DTX_REQUEST:
1121 case OPUS_SET_FORCE_MODE_REQUEST:
1122 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1123 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
1124 {
1125 int s;
1126 /* This works for int32 params */
1127 opus_int32 value = va_arg(ap, opus_int32);
1128 for (s=0;s<st->layout.nb_streams;s++)
1129 {
1130 OpusEncoder *enc;
1131
1132 enc = (OpusEncoder*)ptr;
1133 if (s < st->layout.nb_coupled_streams)
1134 ptr += align(coupled_size);
1135 else
1136 ptr += align(mono_size);
1137 ret = opus_encoder_ctl(enc, request, value);
1138 if (ret != OPUS_OK)
1139 break;
1140 }
1141 }
1142 break;
1143 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1144 {
1145 int s;
1146 opus_int32 stream_id;
1147 OpusEncoder **value;
1148 stream_id = va_arg(ap, opus_int32);
1149 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1150 ret = OPUS_BAD_ARG;
1151 value = va_arg(ap, OpusEncoder**);
1152 if (!value)
1153 {
1154 goto bad_arg;
1155 }
1156 for (s=0;s<stream_id;s++)
1157 {
1158 if (s < st->layout.nb_coupled_streams)
1159 ptr += align(coupled_size);
1160 else
1161 ptr += align(mono_size);
1162 }
1163 *value = (OpusEncoder*)ptr;
1164 }
1165 break;
1166 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
1167 {
1168 opus_int32 value = va_arg(ap, opus_int32);
1169 st->variable_duration = value;
1170 }
1171 break;
1172 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
1173 {
1174 opus_int32 *value = va_arg(ap, opus_int32*);
1175 if (!value)
1176 {
1177 goto bad_arg;
1178 }
1179 *value = st->variable_duration;
1180 }
1181 break;
1182 case OPUS_RESET_STATE:
1183 {
1184 int s;
1185 st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
1186 if (st->surround)
1187 {
1188 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1189 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1190 }
1191 for (s=0;s<st->layout.nb_streams;s++)
1192 {
1193 OpusEncoder *enc;
1194 enc = (OpusEncoder*)ptr;
1195 if (s < st->layout.nb_coupled_streams)
1196 ptr += align(coupled_size);
1197 else
1198 ptr += align(mono_size);
1199 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1200 if (ret != OPUS_OK)
1201 break;
1202 }
1203 }
1204 break;
1205 default:
1206 ret = OPUS_UNIMPLEMENTED;
1207 break;
1208 }
1209
1210 va_end(ap);
1211 return ret;
1212bad_arg:
1213 va_end(ap);
1214 return OPUS_BAD_ARG;
1215}
1216
1217void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1218{
1219 opus_free(st);
1220}