blob: bc86489d2070cc10acc8bc53f752a0c9f0e69a51 [file] [log] [blame]
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001/* 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"
Jean-Marc Valin51f4a322013-02-20 04:08:04 -050039#include "analysis.h"
Jean-Marc Valin49587512013-07-07 02:50:18 -040040#include "mathops.h"
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040041#include "mdct.h"
42#include "modes.h"
43#include "bands.h"
44#include "quant_bands.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050045
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040046typedef 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
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040064typedef 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
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050073struct OpusMSEncoder {
Jean-Marc Valin51f4a322013-02-20 04:08:04 -050074 TonalityAnalysisState analysis;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050075 ChannelLayout layout;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040076 int lfe_stream;
Jean-Marc Valin74483662012-12-17 16:23:42 -050077 int variable_duration;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -040078 int surround;
Jean-Marc Valin74483662012-12-17 16:23:42 -050079 opus_int32 bitrate_bps;
80 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050081 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040082 /* then opus_val32 window_mem[channels*120]; */
83 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050084};
85
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040086static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
87{
88 int s;
89 char *ptr;
90 int coupled_size, mono_size;
91
92 coupled_size = opus_encoder_get_size(2);
93 mono_size = opus_encoder_get_size(1);
94 ptr = (char*)st + align(sizeof(OpusMSEncoder));
95 for (s=0;s<st->layout.nb_streams;s++)
96 {
97 if (s < st->layout.nb_coupled_streams)
98 ptr += align(coupled_size);
99 else
100 ptr += align(mono_size);
101 }
102 return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
103}
104
105static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
106{
107 int s;
108 char *ptr;
109 int coupled_size, mono_size;
110
111 coupled_size = opus_encoder_get_size(2);
112 mono_size = opus_encoder_get_size(1);
113 ptr = (char*)st + align(sizeof(OpusMSEncoder));
114 for (s=0;s<st->layout.nb_streams;s++)
115 {
116 if (s < st->layout.nb_coupled_streams)
117 ptr += align(coupled_size);
118 else
119 ptr += align(mono_size);
120 }
121 return (opus_val32*)ptr;
122}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500123
124static int validate_encoder_layout(const ChannelLayout *layout)
125{
126 int s;
127 for (s=0;s<layout->nb_streams;s++)
128 {
129 if (s < layout->nb_coupled_streams)
130 {
131 if (get_left_channel(layout, s, -1)==-1)
132 return 0;
133 if (get_right_channel(layout, s, -1)==-1)
134 return 0;
135 } else {
136 if (get_mono_channel(layout, s, -1)==-1)
137 return 0;
138 }
139 }
140 return 1;
141}
142
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400143static void channel_pos(int channels, int pos[8])
144{
145 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
146 if (channels==4)
147 {
148 pos[0]=1;
149 pos[1]=3;
150 pos[2]=1;
151 pos[3]=3;
152 } else if (channels==3||channels==5||channels==6)
153 {
154 pos[0]=1;
155 pos[1]=2;
156 pos[2]=3;
157 pos[3]=1;
158 pos[4]=3;
159 pos[5]=0;
160 } else if (channels==7)
161 {
162 pos[0]=1;
163 pos[1]=2;
164 pos[2]=3;
165 pos[3]=1;
166 pos[4]=3;
167 pos[5]=2;
168 pos[6]=0;
169 } else if (channels==8)
170 {
171 pos[0]=1;
172 pos[1]=2;
173 pos[2]=3;
174 pos[3]=1;
175 pos[4]=3;
176 pos[5]=1;
177 pos[6]=3;
178 pos[7]=0;
179 }
180}
181
182void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
183 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
184)
185{
186 int c;
187 int i;
188 /* FIXME: pass LM properly */
189 int LM=3;
190 int pos[8] = {0};
191 int upsample;
192 opus_val32 bandE[21];
193 opus_val32 maskE[3][21];
194 opus_val16 maskLogE[3][21];
195 VARDECL(opus_val32, in);
196 VARDECL(opus_val16, x);
197 VARDECL(opus_val32, out);
198 SAVE_STACK;
199 ALLOC(in, len+overlap, opus_val32);
200 ALLOC(x, len, opus_val16);
201 ALLOC(freq, len, opus_val32);
202
203 channel_pos(channels, pos);
204
205 for (c=0;c<2;c++)
206 for (i=0;i<21;i++)
207 maskE[c][i] = 0;
208
209 upsample = resampling_factor(rate);
210 for (c=0;c<channels;c++)
211 {
212 OPUS_COPY(in, mem+c*overlap, overlap);
213 (*copy_channel_in)(x, 1, pcm, channels, c, len);
214 /* FIXME: Handle upsampling properly wrt len */
215 preemphasis(x, in+overlap, len, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
216 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
217 if (upsample != 1)
218 {
219 int bound = len/upsample;
220 for (i=0;i<bound;i++)
221 freq[i] *= upsample;
222 for (;i<len;i++)
223 freq[i] = 0;
224 }
225
226 compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
227 /* FIXME: Figure out how to square bandE[] in fixed-point */
228 if (pos[c]==1)
229 {
230 for (i=0;i<21;i++)
231 maskE[0][i] += bandE[i]*bandE[i];
232 } else if (pos[c]==3)
233 {
234 for (i=0;i<21;i++)
235 maskE[1][i] += bandE[i]*bandE[i];
236 } else if (pos[c]==2)
237 {
238 for (i=0;i<21;i++)
239 {
240 maskE[0][i] += HALF32(bandE[i]*bandE[i]);
241 maskE[1][i] += HALF32(bandE[i]*bandE[i]);
242 }
243 }
244 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
245#if 0
246 for (i=0;i<21;i++)
247 printf("%f ", bandLogE[21*c+i]);
248//#else
249 float sum=0;
250 for (i=0;i<21;i++)
251 sum += bandLogE[21*c+i];
252 printf("%f ", sum/21);
253#endif
254 OPUS_COPY(mem+c*overlap, in+len, overlap);
255 }
256 for (i=0;i<21;i++)
257 maskE[2][i] = MIN32(maskE[0][i],maskE[1][i]);
258 for (c=0;c<3;c++)
259 for (i=0;i<21;i++)
260 maskE[c][i] = sqrt(maskE[c][i]*2/(channels-1));
261 /* Left mask */
262 amp2Log2(celt_mode, 21, 21, &maskE[0][0], &maskLogE[0][0], 1);
263 /* Right mask */
264 amp2Log2(celt_mode, 21, 21, &maskE[1][0], &maskLogE[2][0], 1);
265 /* Centre mask */
266 amp2Log2(celt_mode, 21, 21, &maskE[2][0], &maskLogE[1][0], 1);
267#if 0
268 for (c=0;c<3;c++)
269 {
270 for (i=0;i<21;i++)
271 printf("%f ", maskLogE[c][i]);
272 }
273#endif
274 for (c=0;c<channels;c++)
275 {
276 opus_val16 *mask;
277 if (pos[c]!=0)
278 {
279 mask = &maskLogE[pos[c]-1][0];
280 for (i=0;i<21;i++)
281 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
282 } else {
283 for (i=0;i<21;i++)
284 bandLogE[21*c+i] = 0;
285 }
286#if 0
287 for (i=0;i<21;i++)
288 printf("%f ", bandLogE[21*c+i]);
289 printf("\n");
290#endif
291#if 0
292 float sum=0;
293 for (i=0;i<21;i++)
294 sum += bandLogE[21*c+i];
295 printf("%f ", sum/21);
296 printf("\n");
297#endif
298 }
299 RESTORE_STACK;
300}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500301
302opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
303{
304 int coupled_size;
305 int mono_size;
306
307 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
308 coupled_size = opus_encoder_get_size(2);
309 mono_size = opus_encoder_get_size(1);
310 return align(sizeof(OpusMSEncoder))
311 + nb_coupled_streams * align(coupled_size)
312 + (nb_streams-nb_coupled_streams) * align(mono_size);
313}
314
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400315opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
316{
317 int nb_streams;
318 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400319 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400320
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400321 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400322 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400323 if (channels==1)
324 {
325 nb_streams=1;
326 nb_coupled_streams=0;
327 } else if (channels==2)
328 {
329 nb_streams=1;
330 nb_coupled_streams=1;
331 } else
332 return 0;
333 } else if (mapping_family==1 && channels<=8 && channels>=1)
334 {
335 nb_streams=vorbis_mappings[channels-1].nb_streams;
336 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
337 } else if (mapping_family==255)
338 {
339 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400340 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400341 } else
342 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400343 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
344 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400345 {
346 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
347 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400348 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400349}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500350
351
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400352static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500353 OpusMSEncoder *st,
354 opus_int32 Fs,
355 int channels,
356 int streams,
357 int coupled_streams,
358 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400359 int application,
360 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500361)
362{
363 int coupled_size;
364 int mono_size;
365 int i, ret;
366 char *ptr;
367
368 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
369 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
370 return OPUS_BAD_ARG;
371
372 st->layout.nb_channels = channels;
373 st->layout.nb_streams = streams;
374 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400375 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
376 OPUS_CLEAR(&st->analysis,1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400377 if (!surround)
378 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500379 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500380 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500381 for (i=0;i<st->layout.nb_channels;i++)
382 st->layout.mapping[i] = mapping[i];
383 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
384 return OPUS_BAD_ARG;
385 ptr = (char*)st + align(sizeof(OpusMSEncoder));
386 coupled_size = opus_encoder_get_size(2);
387 mono_size = opus_encoder_get_size(1);
388
389 for (i=0;i<st->layout.nb_coupled_streams;i++)
390 {
391 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400392 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400393 if (i==st->lfe_stream)
394 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500395 ptr += align(coupled_size);
396 }
397 for (;i<st->layout.nb_streams;i++)
398 {
399 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400400 if (i==st->lfe_stream)
401 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500402 if(ret!=OPUS_OK)return ret;
403 ptr += align(mono_size);
404 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400405 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400406 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400407 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
408 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400409 }
410 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500411 return OPUS_OK;
412}
413
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400414int opus_multistream_encoder_init(
415 OpusMSEncoder *st,
416 opus_int32 Fs,
417 int channels,
418 int streams,
419 int coupled_streams,
420 const unsigned char *mapping,
421 int application
422)
423{
424 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
425}
426
427int opus_multistream_surround_encoder_init(
428 OpusMSEncoder *st,
429 opus_int32 Fs,
430 int channels,
431 int mapping_family,
432 int *streams,
433 int *coupled_streams,
434 unsigned char *mapping,
435 int application
436)
437{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400438 if ((channels>255) || (channels<1))
439 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400440 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400441 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400442 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400443 if (channels==1)
444 {
445 *streams=1;
446 *coupled_streams=0;
447 mapping[0]=0;
448 } else if (channels==2)
449 {
450 *streams=1;
451 *coupled_streams=1;
452 mapping[0]=0;
453 mapping[1]=1;
454 } else
455 return OPUS_UNIMPLEMENTED;
456 } else if (mapping_family==1 && channels<=8 && channels>=1)
457 {
458 int i;
459 *streams=vorbis_mappings[channels-1].nb_streams;
460 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
461 for (i=0;i<channels;i++)
462 mapping[i] = vorbis_mappings[channels-1].mapping[i];
463 if (channels>=6)
464 st->lfe_stream = *streams-1;
465 } else if (mapping_family==255)
466 {
467 int i;
468 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400469 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400470 for(i=0;i<channels;i++)
471 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400472 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400473 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400474 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400475 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400476}
477
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500478OpusMSEncoder *opus_multistream_encoder_create(
479 opus_int32 Fs,
480 int channels,
481 int streams,
482 int coupled_streams,
483 const unsigned char *mapping,
484 int application,
485 int *error
486)
487{
488 int ret;
489 OpusMSEncoder *st;
490 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
491 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
492 {
493 if (error)
494 *error = OPUS_BAD_ARG;
495 return NULL;
496 }
497 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
498 if (st==NULL)
499 {
500 if (error)
501 *error = OPUS_ALLOC_FAIL;
502 return NULL;
503 }
504 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
505 if (ret != OPUS_OK)
506 {
507 opus_free(st);
508 st = NULL;
509 }
510 if (error)
511 *error = ret;
512 return st;
513}
514
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400515OpusMSEncoder *opus_multistream_surround_encoder_create(
516 opus_int32 Fs,
517 int channels,
518 int mapping_family,
519 int *streams,
520 int *coupled_streams,
521 unsigned char *mapping,
522 int application,
523 int *error
524)
525{
526 int ret;
527 OpusMSEncoder *st;
528 if ((channels>255) || (channels<1))
529 {
530 if (error)
531 *error = OPUS_BAD_ARG;
532 return NULL;
533 }
534 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
535 if (st==NULL)
536 {
537 if (error)
538 *error = OPUS_ALLOC_FAIL;
539 return NULL;
540 }
541 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
542 if (ret != OPUS_OK)
543 {
544 opus_free(st);
545 st = NULL;
546 }
547 if (error)
548 *error = ret;
549 return st;
550}
551
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400552static void surround_rate_allocation(
553 OpusMSEncoder *st,
554 opus_int32 *rate,
555 int frame_size
556 )
557{
558 int i;
559 opus_int32 channel_rate;
560 opus_int32 Fs;
561 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400562 int stream_offset;
563 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400564 int coupled_ratio; /* Q8 */
565 int lfe_ratio; /* Q8 */
566
567 ptr = (char*)st + align(sizeof(OpusMSEncoder));
568 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
569
Jean-Marc Valin49587512013-07-07 02:50:18 -0400570 if (st->bitrate_bps > st->layout.nb_channels*40000)
571 stream_offset = 20000;
572 else
573 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400574 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
575 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400576 /* The LFE stream is an exception to the above and gets fewer bits. */
577 lfe_offset = 3500;
578 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
579 coupled_ratio = 512;
580 /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400581 lfe_ratio = 32;
582
583 /* Compute bitrate allocation between streams */
584 if (st->bitrate_bps==OPUS_AUTO)
585 {
586 channel_rate = Fs+60*Fs/frame_size;
587 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
588 {
589 channel_rate = 300000;
590 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400591 int nb_lfe;
592 int nb_uncoupled;
593 int nb_coupled;
594 int total;
595 nb_lfe = (st->lfe_stream!=-1);
596 nb_coupled = st->layout.nb_coupled_streams;
597 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
598 total = (nb_uncoupled<<8) /* mono */
599 + coupled_ratio*nb_coupled /* stereo */
600 + nb_lfe*lfe_ratio;
601 channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400602 }
603#ifndef FIXED_POINT
604 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
605 {
606 opus_int32 bonus;
607 bonus = 60*(Fs/frame_size-50);
608 channel_rate += bonus;
609 }
610#endif
611
612 for (i=0;i<st->layout.nb_streams;i++)
613 {
614 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400615 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400616 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400617 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400618 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400619 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400620 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400621}
622
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500623/* Max size in case the encoder decides to return three frames */
624#define MS_FRAME_TMP (3*1275+7)
625static int opus_multistream_encode_native
626(
627 OpusMSEncoder *st,
628 opus_copy_channel_in_func copy_channel_in,
629 const void *pcm,
630 int frame_size,
631 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500632 opus_int32 max_data_bytes,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400633 int lsb_depth
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500634#ifndef FIXED_POINT
635 , downmix_func downmix
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500636 , const void *pcm_analysis
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500637#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500638)
639{
640 opus_int32 Fs;
641 int coupled_size;
642 int mono_size;
643 int s;
644 char *ptr;
645 int tot_size;
646 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400647 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500648 unsigned char tmp_data[MS_FRAME_TMP];
649 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500650 opus_int32 complexity;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400651#ifndef FIXED_POINT
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500652 AnalysisInfo analysis_info;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400653#endif
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500654 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400655 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400656 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400657 opus_val32 *mem = NULL;
658 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500659 ALLOC_STACK;
660
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400661 if (st->surround)
662 {
663 preemph_mem = ms_get_preemph_mem(st);
664 mem = ms_get_window_mem(st);
665 }
666
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500667 ptr = (char*)st + align(sizeof(OpusMSEncoder));
668 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500669 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
670 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500671
672 if (400*frame_size < Fs)
673 {
674 RESTORE_STACK;
675 return OPUS_BAD_ARG;
676 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500677#ifndef FIXED_POINT
678 analysis_info.valid = 0;
679 if (complexity >= 7 && Fs==48000)
Jean-Marc Valin74483662012-12-17 16:23:42 -0500680 {
Jean-Marc Valin74483662012-12-17 16:23:42 -0500681 opus_int32 delay_compensation;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500682 int channels;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500683
684 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
685 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
686 delay_compensation -= Fs/400;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500687
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500688 frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
689 frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
690 } else
691#endif
692 {
693 frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
694 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500695 /* Validate frame_size before using it to allocate stack space.
696 This mirrors the checks in opus_encode[_float](). */
697 if (400*frame_size != Fs && 200*frame_size != Fs &&
698 100*frame_size != Fs && 50*frame_size != Fs &&
699 25*frame_size != Fs && 50*frame_size != 3*Fs)
700 {
701 RESTORE_STACK;
702 return OPUS_BAD_ARG;
703 }
704 ALLOC(buf, 2*frame_size, opus_val16);
705 coupled_size = opus_encoder_get_size(2);
706 mono_size = opus_encoder_get_size(1);
707
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400708 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400709 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400710 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400711 surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400712 }
713
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500714 if (max_data_bytes < 4*st->layout.nb_streams-1)
715 {
716 RESTORE_STACK;
717 return OPUS_BUFFER_TOO_SMALL;
718 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500719
720 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400721 surround_rate_allocation(st, bitrates, frame_size);
722
Jean-Marc Valin74483662012-12-17 16:23:42 -0500723 ptr = (char*)st + align(sizeof(OpusMSEncoder));
724 for (s=0;s<st->layout.nb_streams;s++)
725 {
726 OpusEncoder *enc;
727 enc = (OpusEncoder*)ptr;
728 if (s < st->layout.nb_coupled_streams)
729 ptr += align(coupled_size);
730 else
731 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400732 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400733 if (st->surround)
734 {
735 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
736 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
737 if (s < st->layout.nb_coupled_streams)
738 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
739 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500740 }
741
742 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500743 /* Counting ToC */
744 tot_size = 0;
745 for (s=0;s<st->layout.nb_streams;s++)
746 {
747 OpusEncoder *enc;
748 int len;
749 int curr_max;
750
751 opus_repacketizer_init(&rp);
752 enc = (OpusEncoder*)ptr;
753 if (s < st->layout.nb_coupled_streams)
754 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400755 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500756 int left, right;
757 left = get_left_channel(&st->layout, s, -1);
758 right = get_right_channel(&st->layout, s, -1);
759 (*copy_channel_in)(buf, 2,
760 pcm, st->layout.nb_channels, left, frame_size);
761 (*copy_channel_in)(buf+1, 2,
762 pcm, st->layout.nb_channels, right, frame_size);
763 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400764 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400765 {
766 for (i=0;i<21;i++)
767 {
768 bandLogE[i] = bandSMR[21*left+i];
769 bandLogE[21+i] = bandSMR[21*right+i];
770 }
771 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500772 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400773 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500774 int chan = get_mono_channel(&st->layout, s, -1);
775 (*copy_channel_in)(buf, 1,
776 pcm, st->layout.nb_channels, chan, frame_size);
777 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400778 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400779 {
780 for (i=0;i<21;i++)
781 bandLogE[i] = bandSMR[21*chan+i];
782 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500783 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400784 if (st->surround)
785 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500786 /* number of bytes left (+Toc) */
787 curr_max = max_data_bytes - tot_size;
788 /* Reserve three bytes for the last stream and four for the others */
789 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
790 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500791 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
792#ifndef FIXED_POINT
793 , &analysis_info
794#endif
795 );
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500796 if (len<0)
797 {
798 RESTORE_STACK;
799 return len;
800 }
801 /* We need to use the repacketizer to add the self-delimiting lengths
802 while taking into account the fact that the encoder can now return
803 more than one frame at a time (e.g. 60 ms CELT-only) */
804 opus_repacketizer_cat(&rp, tmp_data, len);
805 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);
806 data += len;
807 tot_size += len;
808 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400809 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500810 RESTORE_STACK;
811 return tot_size;
812
813}
814
Pedro Becerra1af7f952013-07-11 00:00:47 -0400815#if !defined(DISABLE_FLOAT_API)
816static void opus_copy_channel_in_float(
817 opus_val16 *dst,
818 int dst_stride,
819 const void *src,
820 int src_stride,
821 int src_channel,
822 int frame_size
823)
824{
825 const float *float_src;
826 opus_int32 i;
827 float_src = (const float *)src;
828 for (i=0;i<frame_size;i++)
829#if defined(FIXED_POINT)
830 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
831#else
832 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
833#endif
834}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500835#endif
836
837static void opus_copy_channel_in_short(
838 opus_val16 *dst,
839 int dst_stride,
840 const void *src,
841 int src_stride,
842 int src_channel,
843 int frame_size
844)
845{
846 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700847 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500848 short_src = (const opus_int16 *)src;
849 for (i=0;i<frame_size;i++)
850#if defined(FIXED_POINT)
851 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
852#else
853 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
854#endif
855}
856
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400857
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500858#ifdef FIXED_POINT
859int opus_multistream_encode(
860 OpusMSEncoder *st,
861 const opus_val16 *pcm,
862 int frame_size,
863 unsigned char *data,
864 opus_int32 max_data_bytes
865)
866{
867 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400868 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500869}
870
871#ifndef DISABLE_FLOAT_API
872int opus_multistream_encode_float(
873 OpusMSEncoder *st,
874 const float *pcm,
875 int frame_size,
876 unsigned char *data,
877 opus_int32 max_data_bytes
878)
879{
880 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400881 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500882}
883#endif
884
885#else
886
887int opus_multistream_encode_float
888(
889 OpusMSEncoder *st,
890 const opus_val16 *pcm,
891 int frame_size,
892 unsigned char *data,
893 opus_int32 max_data_bytes
894)
895{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500896 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500897 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400898 pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500899}
900
901int opus_multistream_encode(
902 OpusMSEncoder *st,
903 const opus_int16 *pcm,
904 int frame_size,
905 unsigned char *data,
906 opus_int32 max_data_bytes
907)
908{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500909 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500910 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400911 pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500912}
913#endif
914
915int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
916{
917 va_list ap;
918 int coupled_size, mono_size;
919 char *ptr;
920 int ret = OPUS_OK;
921
922 va_start(ap, request);
923
924 coupled_size = opus_encoder_get_size(2);
925 mono_size = opus_encoder_get_size(1);
926 ptr = (char*)st + align(sizeof(OpusMSEncoder));
927 switch (request)
928 {
929 case OPUS_SET_BITRATE_REQUEST:
930 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500931 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700932 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
933 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500934 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700935 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500936 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500937 }
938 break;
939 case OPUS_GET_BITRATE_REQUEST:
940 {
941 int s;
942 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700943 if (!value)
944 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700945 goto bad_arg;
946 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500947 *value = 0;
948 for (s=0;s<st->layout.nb_streams;s++)
949 {
950 opus_int32 rate;
951 OpusEncoder *enc;
952 enc = (OpusEncoder*)ptr;
953 if (s < st->layout.nb_coupled_streams)
954 ptr += align(coupled_size);
955 else
956 ptr += align(mono_size);
957 opus_encoder_ctl(enc, request, &rate);
958 *value += rate;
959 }
960 }
961 break;
962 case OPUS_GET_LSB_DEPTH_REQUEST:
963 case OPUS_GET_VBR_REQUEST:
964 case OPUS_GET_APPLICATION_REQUEST:
965 case OPUS_GET_BANDWIDTH_REQUEST:
966 case OPUS_GET_COMPLEXITY_REQUEST:
967 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
968 case OPUS_GET_DTX_REQUEST:
969 case OPUS_GET_VOICE_RATIO_REQUEST:
970 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
971 case OPUS_GET_SIGNAL_REQUEST:
972 case OPUS_GET_LOOKAHEAD_REQUEST:
973 case OPUS_GET_SAMPLE_RATE_REQUEST:
974 case OPUS_GET_INBAND_FEC_REQUEST:
975 case OPUS_GET_FORCE_CHANNELS_REQUEST:
976 {
977 OpusEncoder *enc;
978 /* For int32* GET params, just query the first stream */
979 opus_int32 *value = va_arg(ap, opus_int32*);
980 enc = (OpusEncoder*)ptr;
981 ret = opus_encoder_ctl(enc, request, value);
982 }
983 break;
984 case OPUS_GET_FINAL_RANGE_REQUEST:
985 {
986 int s;
987 opus_uint32 *value = va_arg(ap, opus_uint32*);
988 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700989 if (!value)
990 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700991 goto bad_arg;
992 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500993 *value=0;
994 for (s=0;s<st->layout.nb_streams;s++)
995 {
996 OpusEncoder *enc;
997 enc = (OpusEncoder*)ptr;
998 if (s < st->layout.nb_coupled_streams)
999 ptr += align(coupled_size);
1000 else
1001 ptr += align(mono_size);
1002 ret = opus_encoder_ctl(enc, request, &tmp);
1003 if (ret != OPUS_OK) break;
1004 *value ^= tmp;
1005 }
1006 }
1007 break;
1008 case OPUS_SET_LSB_DEPTH_REQUEST:
1009 case OPUS_SET_COMPLEXITY_REQUEST:
1010 case OPUS_SET_VBR_REQUEST:
1011 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001012 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001013 case OPUS_SET_BANDWIDTH_REQUEST:
1014 case OPUS_SET_SIGNAL_REQUEST:
1015 case OPUS_SET_APPLICATION_REQUEST:
1016 case OPUS_SET_INBAND_FEC_REQUEST:
1017 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1018 case OPUS_SET_DTX_REQUEST:
1019 case OPUS_SET_FORCE_MODE_REQUEST:
1020 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1021 {
1022 int s;
1023 /* This works for int32 params */
1024 opus_int32 value = va_arg(ap, opus_int32);
1025 for (s=0;s<st->layout.nb_streams;s++)
1026 {
1027 OpusEncoder *enc;
1028
1029 enc = (OpusEncoder*)ptr;
1030 if (s < st->layout.nb_coupled_streams)
1031 ptr += align(coupled_size);
1032 else
1033 ptr += align(mono_size);
1034 ret = opus_encoder_ctl(enc, request, value);
1035 if (ret != OPUS_OK)
1036 break;
1037 }
1038 }
1039 break;
1040 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1041 {
1042 int s;
1043 opus_int32 stream_id;
1044 OpusEncoder **value;
1045 stream_id = va_arg(ap, opus_int32);
1046 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1047 ret = OPUS_BAD_ARG;
1048 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001049 if (!value)
1050 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001051 goto bad_arg;
1052 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001053 for (s=0;s<stream_id;s++)
1054 {
1055 if (s < st->layout.nb_coupled_streams)
1056 ptr += align(coupled_size);
1057 else
1058 ptr += align(mono_size);
1059 }
1060 *value = (OpusEncoder*)ptr;
1061 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001062 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001063 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001064 {
1065 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001066 st->variable_duration = value;
1067 }
1068 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001069 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001070 {
1071 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001072 if (!value)
1073 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001074 goto bad_arg;
1075 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001076 *value = st->variable_duration;
1077 }
1078 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001079 default:
1080 ret = OPUS_UNIMPLEMENTED;
1081 break;
1082 }
1083
1084 va_end(ap);
1085 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001086bad_arg:
1087 va_end(ap);
1088 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001089}
1090
1091void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1092{
1093 opus_free(st);
1094}