blob: 2e29869f788efe46a3acd9e8ab4884bd8872ca64 [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
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400182#if 1
183/* Computes a rough approximation of log2(2^a + 2^b) */
184static opus_val16 logSum(opus_val16 a, opus_val16 b)
185{
186 opus_val16 max;
187 opus_val32 diff;
188 opus_val16 frac;
189 static const opus_val16 diff_table[17] = {
190 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
191 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
192 QCONST16(0.0028123f, DB_SHIFT)
193 };
194 int low;
195 if (a>b)
196 {
197 max = a;
198 diff = SUB32(EXTEND32(a),EXTEND32(b));
199 } else {
200 max = b;
201 diff = SUB32(EXTEND32(b),EXTEND32(a));
202 }
203 if (diff >= QCONST16(8.f, DB_SHIFT))
204 return max;
205#ifdef FIXED_POINT
206 low = SHR32(diff, DB_SHIFT-1);
207 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
208#else
209 low = floor(2*diff);
210 frac = 2*diff - low;
211#endif
212 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
213}
214#else
215opus_val16 logSum(opus_val16 a, opus_val16 b)
216{
217 return log2(pow(4, a)+ pow(4, b))/2;
218}
219#endif
220
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400221void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
222 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
223)
224{
225 int c;
226 int i;
227 /* FIXME: pass LM properly */
228 int LM=3;
229 int pos[8] = {0};
230 int upsample;
231 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400232 opus_val16 maskLogE[3][21];
233 VARDECL(opus_val32, in);
234 VARDECL(opus_val16, x);
235 VARDECL(opus_val32, out);
236 SAVE_STACK;
237 ALLOC(in, len+overlap, opus_val32);
238 ALLOC(x, len, opus_val16);
239 ALLOC(freq, len, opus_val32);
240
241 channel_pos(channels, pos);
242
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400243 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400244 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400245 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400246
247 upsample = resampling_factor(rate);
248 for (c=0;c<channels;c++)
249 {
250 OPUS_COPY(in, mem+c*overlap, overlap);
251 (*copy_channel_in)(x, 1, pcm, channels, c, len);
252 /* FIXME: Handle upsampling properly wrt len */
253 preemphasis(x, in+overlap, len, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
254 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
255 if (upsample != 1)
256 {
257 int bound = len/upsample;
258 for (i=0;i<bound;i++)
259 freq[i] *= upsample;
260 for (;i<len;i++)
261 freq[i] = 0;
262 }
263
264 compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400265 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400266 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
267 for (i=1;i<21;i++)
268 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
269 for (i=19;i>=0;i--)
270 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400271 if (pos[c]==1)
272 {
273 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400274 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400275 } else if (pos[c]==3)
276 {
277 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400278 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400279 } else if (pos[c]==2)
280 {
281 for (i=0;i<21;i++)
282 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400283 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
284 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400285 }
286 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400287#if 0
288 for (i=0;i<21;i++)
289 printf("%f ", bandLogE[21*c+i]);
290//#else
291 float sum=0;
292 for (i=0;i<21;i++)
293 sum += bandLogE[21*c+i];
294 printf("%f ", sum/21);
295#endif
296 OPUS_COPY(mem+c*overlap, in+len, overlap);
297 }
298 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400299 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400300 for (c=0;c<3;c++)
301 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400302 maskLogE[c][i] += QCONST16(.5f, DB_SHIFT)*log2(2.f/(channels-1));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400303#if 0
304 for (c=0;c<3;c++)
305 {
306 for (i=0;i<21;i++)
307 printf("%f ", maskLogE[c][i]);
308 }
309#endif
310 for (c=0;c<channels;c++)
311 {
312 opus_val16 *mask;
313 if (pos[c]!=0)
314 {
315 mask = &maskLogE[pos[c]-1][0];
316 for (i=0;i<21;i++)
317 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
318 } else {
319 for (i=0;i<21;i++)
320 bandLogE[21*c+i] = 0;
321 }
322#if 0
323 for (i=0;i<21;i++)
324 printf("%f ", bandLogE[21*c+i]);
325 printf("\n");
326#endif
327#if 0
328 float sum=0;
329 for (i=0;i<21;i++)
330 sum += bandLogE[21*c+i];
331 printf("%f ", sum/21);
332 printf("\n");
333#endif
334 }
335 RESTORE_STACK;
336}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500337
338opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
339{
340 int coupled_size;
341 int mono_size;
342
343 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
344 coupled_size = opus_encoder_get_size(2);
345 mono_size = opus_encoder_get_size(1);
346 return align(sizeof(OpusMSEncoder))
347 + nb_coupled_streams * align(coupled_size)
348 + (nb_streams-nb_coupled_streams) * align(mono_size);
349}
350
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400351opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
352{
353 int nb_streams;
354 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400355 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400356
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400357 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400358 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400359 if (channels==1)
360 {
361 nb_streams=1;
362 nb_coupled_streams=0;
363 } else if (channels==2)
364 {
365 nb_streams=1;
366 nb_coupled_streams=1;
367 } else
368 return 0;
369 } else if (mapping_family==1 && channels<=8 && channels>=1)
370 {
371 nb_streams=vorbis_mappings[channels-1].nb_streams;
372 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
373 } else if (mapping_family==255)
374 {
375 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400376 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400377 } else
378 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400379 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
380 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400381 {
382 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
383 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400384 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400385}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500386
387
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400388static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500389 OpusMSEncoder *st,
390 opus_int32 Fs,
391 int channels,
392 int streams,
393 int coupled_streams,
394 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400395 int application,
396 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500397)
398{
399 int coupled_size;
400 int mono_size;
401 int i, ret;
402 char *ptr;
403
404 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
405 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
406 return OPUS_BAD_ARG;
407
408 st->layout.nb_channels = channels;
409 st->layout.nb_streams = streams;
410 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400411 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
412 OPUS_CLEAR(&st->analysis,1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400413 if (!surround)
414 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500415 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500416 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500417 for (i=0;i<st->layout.nb_channels;i++)
418 st->layout.mapping[i] = mapping[i];
419 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
420 return OPUS_BAD_ARG;
421 ptr = (char*)st + align(sizeof(OpusMSEncoder));
422 coupled_size = opus_encoder_get_size(2);
423 mono_size = opus_encoder_get_size(1);
424
425 for (i=0;i<st->layout.nb_coupled_streams;i++)
426 {
427 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400428 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400429 if (i==st->lfe_stream)
430 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500431 ptr += align(coupled_size);
432 }
433 for (;i<st->layout.nb_streams;i++)
434 {
435 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400436 if (i==st->lfe_stream)
437 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500438 if(ret!=OPUS_OK)return ret;
439 ptr += align(mono_size);
440 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400441 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400442 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400443 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
444 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400445 }
446 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500447 return OPUS_OK;
448}
449
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400450int opus_multistream_encoder_init(
451 OpusMSEncoder *st,
452 opus_int32 Fs,
453 int channels,
454 int streams,
455 int coupled_streams,
456 const unsigned char *mapping,
457 int application
458)
459{
460 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
461}
462
463int opus_multistream_surround_encoder_init(
464 OpusMSEncoder *st,
465 opus_int32 Fs,
466 int channels,
467 int mapping_family,
468 int *streams,
469 int *coupled_streams,
470 unsigned char *mapping,
471 int application
472)
473{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400474 if ((channels>255) || (channels<1))
475 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400476 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400477 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400478 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400479 if (channels==1)
480 {
481 *streams=1;
482 *coupled_streams=0;
483 mapping[0]=0;
484 } else if (channels==2)
485 {
486 *streams=1;
487 *coupled_streams=1;
488 mapping[0]=0;
489 mapping[1]=1;
490 } else
491 return OPUS_UNIMPLEMENTED;
492 } else if (mapping_family==1 && channels<=8 && channels>=1)
493 {
494 int i;
495 *streams=vorbis_mappings[channels-1].nb_streams;
496 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
497 for (i=0;i<channels;i++)
498 mapping[i] = vorbis_mappings[channels-1].mapping[i];
499 if (channels>=6)
500 st->lfe_stream = *streams-1;
501 } else if (mapping_family==255)
502 {
503 int i;
504 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400505 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400506 for(i=0;i<channels;i++)
507 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400508 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400509 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400510 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400511 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400512}
513
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500514OpusMSEncoder *opus_multistream_encoder_create(
515 opus_int32 Fs,
516 int channels,
517 int streams,
518 int coupled_streams,
519 const unsigned char *mapping,
520 int application,
521 int *error
522)
523{
524 int ret;
525 OpusMSEncoder *st;
526 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
527 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
528 {
529 if (error)
530 *error = OPUS_BAD_ARG;
531 return NULL;
532 }
533 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
534 if (st==NULL)
535 {
536 if (error)
537 *error = OPUS_ALLOC_FAIL;
538 return NULL;
539 }
540 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
541 if (ret != OPUS_OK)
542 {
543 opus_free(st);
544 st = NULL;
545 }
546 if (error)
547 *error = ret;
548 return st;
549}
550
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400551OpusMSEncoder *opus_multistream_surround_encoder_create(
552 opus_int32 Fs,
553 int channels,
554 int mapping_family,
555 int *streams,
556 int *coupled_streams,
557 unsigned char *mapping,
558 int application,
559 int *error
560)
561{
562 int ret;
563 OpusMSEncoder *st;
564 if ((channels>255) || (channels<1))
565 {
566 if (error)
567 *error = OPUS_BAD_ARG;
568 return NULL;
569 }
570 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
571 if (st==NULL)
572 {
573 if (error)
574 *error = OPUS_ALLOC_FAIL;
575 return NULL;
576 }
577 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
578 if (ret != OPUS_OK)
579 {
580 opus_free(st);
581 st = NULL;
582 }
583 if (error)
584 *error = ret;
585 return st;
586}
587
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400588static void surround_rate_allocation(
589 OpusMSEncoder *st,
590 opus_int32 *rate,
591 int frame_size
592 )
593{
594 int i;
595 opus_int32 channel_rate;
596 opus_int32 Fs;
597 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400598 int stream_offset;
599 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400600 int coupled_ratio; /* Q8 */
601 int lfe_ratio; /* Q8 */
602
603 ptr = (char*)st + align(sizeof(OpusMSEncoder));
604 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
605
Jean-Marc Valin49587512013-07-07 02:50:18 -0400606 if (st->bitrate_bps > st->layout.nb_channels*40000)
607 stream_offset = 20000;
608 else
609 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400610 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
611 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400612 /* The LFE stream is an exception to the above and gets fewer bits. */
613 lfe_offset = 3500;
614 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
615 coupled_ratio = 512;
616 /* 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 -0400617 lfe_ratio = 32;
618
619 /* Compute bitrate allocation between streams */
620 if (st->bitrate_bps==OPUS_AUTO)
621 {
622 channel_rate = Fs+60*Fs/frame_size;
623 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
624 {
625 channel_rate = 300000;
626 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400627 int nb_lfe;
628 int nb_uncoupled;
629 int nb_coupled;
630 int total;
631 nb_lfe = (st->lfe_stream!=-1);
632 nb_coupled = st->layout.nb_coupled_streams;
633 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
634 total = (nb_uncoupled<<8) /* mono */
635 + coupled_ratio*nb_coupled /* stereo */
636 + nb_lfe*lfe_ratio;
637 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 -0400638 }
639#ifndef FIXED_POINT
640 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
641 {
642 opus_int32 bonus;
643 bonus = 60*(Fs/frame_size-50);
644 channel_rate += bonus;
645 }
646#endif
647
648 for (i=0;i<st->layout.nb_streams;i++)
649 {
650 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400651 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400652 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400653 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400654 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400655 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400656 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400657}
658
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500659/* Max size in case the encoder decides to return three frames */
660#define MS_FRAME_TMP (3*1275+7)
661static int opus_multistream_encode_native
662(
663 OpusMSEncoder *st,
664 opus_copy_channel_in_func copy_channel_in,
665 const void *pcm,
666 int frame_size,
667 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500668 opus_int32 max_data_bytes,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400669 int lsb_depth
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500670#ifndef FIXED_POINT
671 , downmix_func downmix
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500672 , const void *pcm_analysis
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500673#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500674)
675{
676 opus_int32 Fs;
677 int coupled_size;
678 int mono_size;
679 int s;
680 char *ptr;
681 int tot_size;
682 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400683 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500684 unsigned char tmp_data[MS_FRAME_TMP];
685 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500686 opus_int32 complexity;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400687#ifndef FIXED_POINT
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500688 AnalysisInfo analysis_info;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400689#endif
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500690 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400691 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400692 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400693 opus_val32 *mem = NULL;
694 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500695 ALLOC_STACK;
696
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400697 if (st->surround)
698 {
699 preemph_mem = ms_get_preemph_mem(st);
700 mem = ms_get_window_mem(st);
701 }
702
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500703 ptr = (char*)st + align(sizeof(OpusMSEncoder));
704 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500705 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
706 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500707
708 if (400*frame_size < Fs)
709 {
710 RESTORE_STACK;
711 return OPUS_BAD_ARG;
712 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500713#ifndef FIXED_POINT
714 analysis_info.valid = 0;
715 if (complexity >= 7 && Fs==48000)
Jean-Marc Valin74483662012-12-17 16:23:42 -0500716 {
Jean-Marc Valin74483662012-12-17 16:23:42 -0500717 opus_int32 delay_compensation;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500718 int channels;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500719
720 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
721 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
722 delay_compensation -= Fs/400;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500723
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500724 frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
725 frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
726 } else
727#endif
728 {
729 frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
730 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500731 /* Validate frame_size before using it to allocate stack space.
732 This mirrors the checks in opus_encode[_float](). */
733 if (400*frame_size != Fs && 200*frame_size != Fs &&
734 100*frame_size != Fs && 50*frame_size != Fs &&
735 25*frame_size != Fs && 50*frame_size != 3*Fs)
736 {
737 RESTORE_STACK;
738 return OPUS_BAD_ARG;
739 }
740 ALLOC(buf, 2*frame_size, opus_val16);
741 coupled_size = opus_encoder_get_size(2);
742 mono_size = opus_encoder_get_size(1);
743
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400744 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400745 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400746 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400747 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 -0400748 }
749
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500750 if (max_data_bytes < 4*st->layout.nb_streams-1)
751 {
752 RESTORE_STACK;
753 return OPUS_BUFFER_TOO_SMALL;
754 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500755
756 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400757 surround_rate_allocation(st, bitrates, frame_size);
758
Jean-Marc Valin74483662012-12-17 16:23:42 -0500759 ptr = (char*)st + align(sizeof(OpusMSEncoder));
760 for (s=0;s<st->layout.nb_streams;s++)
761 {
762 OpusEncoder *enc;
763 enc = (OpusEncoder*)ptr;
764 if (s < st->layout.nb_coupled_streams)
765 ptr += align(coupled_size);
766 else
767 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400768 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400769 if (st->surround)
770 {
771 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
772 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
773 if (s < st->layout.nb_coupled_streams)
774 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
775 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500776 }
777
778 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500779 /* Counting ToC */
780 tot_size = 0;
781 for (s=0;s<st->layout.nb_streams;s++)
782 {
783 OpusEncoder *enc;
784 int len;
785 int curr_max;
786
787 opus_repacketizer_init(&rp);
788 enc = (OpusEncoder*)ptr;
789 if (s < st->layout.nb_coupled_streams)
790 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400791 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500792 int left, right;
793 left = get_left_channel(&st->layout, s, -1);
794 right = get_right_channel(&st->layout, s, -1);
795 (*copy_channel_in)(buf, 2,
796 pcm, st->layout.nb_channels, left, frame_size);
797 (*copy_channel_in)(buf+1, 2,
798 pcm, st->layout.nb_channels, right, frame_size);
799 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400800 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400801 {
802 for (i=0;i<21;i++)
803 {
804 bandLogE[i] = bandSMR[21*left+i];
805 bandLogE[21+i] = bandSMR[21*right+i];
806 }
807 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500808 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400809 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500810 int chan = get_mono_channel(&st->layout, s, -1);
811 (*copy_channel_in)(buf, 1,
812 pcm, st->layout.nb_channels, chan, frame_size);
813 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400814 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400815 {
816 for (i=0;i<21;i++)
817 bandLogE[i] = bandSMR[21*chan+i];
818 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500819 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400820 if (st->surround)
821 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500822 /* number of bytes left (+Toc) */
823 curr_max = max_data_bytes - tot_size;
824 /* Reserve three bytes for the last stream and four for the others */
825 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
826 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500827 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
828#ifndef FIXED_POINT
829 , &analysis_info
830#endif
831 );
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500832 if (len<0)
833 {
834 RESTORE_STACK;
835 return len;
836 }
837 /* We need to use the repacketizer to add the self-delimiting lengths
838 while taking into account the fact that the encoder can now return
839 more than one frame at a time (e.g. 60 ms CELT-only) */
840 opus_repacketizer_cat(&rp, tmp_data, len);
841 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);
842 data += len;
843 tot_size += len;
844 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400845 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500846 RESTORE_STACK;
847 return tot_size;
848
849}
850
Pedro Becerra1af7f952013-07-11 00:00:47 -0400851#if !defined(DISABLE_FLOAT_API)
852static void opus_copy_channel_in_float(
853 opus_val16 *dst,
854 int dst_stride,
855 const void *src,
856 int src_stride,
857 int src_channel,
858 int frame_size
859)
860{
861 const float *float_src;
862 opus_int32 i;
863 float_src = (const float *)src;
864 for (i=0;i<frame_size;i++)
865#if defined(FIXED_POINT)
866 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
867#else
868 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
869#endif
870}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500871#endif
872
873static void opus_copy_channel_in_short(
874 opus_val16 *dst,
875 int dst_stride,
876 const void *src,
877 int src_stride,
878 int src_channel,
879 int frame_size
880)
881{
882 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700883 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500884 short_src = (const opus_int16 *)src;
885 for (i=0;i<frame_size;i++)
886#if defined(FIXED_POINT)
887 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
888#else
889 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
890#endif
891}
892
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400893
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500894#ifdef FIXED_POINT
895int opus_multistream_encode(
896 OpusMSEncoder *st,
897 const opus_val16 *pcm,
898 int frame_size,
899 unsigned char *data,
900 opus_int32 max_data_bytes
901)
902{
903 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400904 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500905}
906
907#ifndef DISABLE_FLOAT_API
908int opus_multistream_encode_float(
909 OpusMSEncoder *st,
910 const float *pcm,
911 int frame_size,
912 unsigned char *data,
913 opus_int32 max_data_bytes
914)
915{
916 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400917 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500918}
919#endif
920
921#else
922
923int opus_multistream_encode_float
924(
925 OpusMSEncoder *st,
926 const opus_val16 *pcm,
927 int frame_size,
928 unsigned char *data,
929 opus_int32 max_data_bytes
930)
931{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500932 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500933 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400934 pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500935}
936
937int opus_multistream_encode(
938 OpusMSEncoder *st,
939 const opus_int16 *pcm,
940 int frame_size,
941 unsigned char *data,
942 opus_int32 max_data_bytes
943)
944{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500945 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500946 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400947 pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500948}
949#endif
950
951int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
952{
953 va_list ap;
954 int coupled_size, mono_size;
955 char *ptr;
956 int ret = OPUS_OK;
957
958 va_start(ap, request);
959
960 coupled_size = opus_encoder_get_size(2);
961 mono_size = opus_encoder_get_size(1);
962 ptr = (char*)st + align(sizeof(OpusMSEncoder));
963 switch (request)
964 {
965 case OPUS_SET_BITRATE_REQUEST:
966 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500967 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700968 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
969 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500970 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700971 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500972 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500973 }
974 break;
975 case OPUS_GET_BITRATE_REQUEST:
976 {
977 int s;
978 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700979 if (!value)
980 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700981 goto bad_arg;
982 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500983 *value = 0;
984 for (s=0;s<st->layout.nb_streams;s++)
985 {
986 opus_int32 rate;
987 OpusEncoder *enc;
988 enc = (OpusEncoder*)ptr;
989 if (s < st->layout.nb_coupled_streams)
990 ptr += align(coupled_size);
991 else
992 ptr += align(mono_size);
993 opus_encoder_ctl(enc, request, &rate);
994 *value += rate;
995 }
996 }
997 break;
998 case OPUS_GET_LSB_DEPTH_REQUEST:
999 case OPUS_GET_VBR_REQUEST:
1000 case OPUS_GET_APPLICATION_REQUEST:
1001 case OPUS_GET_BANDWIDTH_REQUEST:
1002 case OPUS_GET_COMPLEXITY_REQUEST:
1003 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1004 case OPUS_GET_DTX_REQUEST:
1005 case OPUS_GET_VOICE_RATIO_REQUEST:
1006 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1007 case OPUS_GET_SIGNAL_REQUEST:
1008 case OPUS_GET_LOOKAHEAD_REQUEST:
1009 case OPUS_GET_SAMPLE_RATE_REQUEST:
1010 case OPUS_GET_INBAND_FEC_REQUEST:
1011 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1012 {
1013 OpusEncoder *enc;
1014 /* For int32* GET params, just query the first stream */
1015 opus_int32 *value = va_arg(ap, opus_int32*);
1016 enc = (OpusEncoder*)ptr;
1017 ret = opus_encoder_ctl(enc, request, value);
1018 }
1019 break;
1020 case OPUS_GET_FINAL_RANGE_REQUEST:
1021 {
1022 int s;
1023 opus_uint32 *value = va_arg(ap, opus_uint32*);
1024 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001025 if (!value)
1026 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001027 goto bad_arg;
1028 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001029 *value=0;
1030 for (s=0;s<st->layout.nb_streams;s++)
1031 {
1032 OpusEncoder *enc;
1033 enc = (OpusEncoder*)ptr;
1034 if (s < st->layout.nb_coupled_streams)
1035 ptr += align(coupled_size);
1036 else
1037 ptr += align(mono_size);
1038 ret = opus_encoder_ctl(enc, request, &tmp);
1039 if (ret != OPUS_OK) break;
1040 *value ^= tmp;
1041 }
1042 }
1043 break;
1044 case OPUS_SET_LSB_DEPTH_REQUEST:
1045 case OPUS_SET_COMPLEXITY_REQUEST:
1046 case OPUS_SET_VBR_REQUEST:
1047 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001048 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001049 case OPUS_SET_BANDWIDTH_REQUEST:
1050 case OPUS_SET_SIGNAL_REQUEST:
1051 case OPUS_SET_APPLICATION_REQUEST:
1052 case OPUS_SET_INBAND_FEC_REQUEST:
1053 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1054 case OPUS_SET_DTX_REQUEST:
1055 case OPUS_SET_FORCE_MODE_REQUEST:
1056 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1057 {
1058 int s;
1059 /* This works for int32 params */
1060 opus_int32 value = va_arg(ap, opus_int32);
1061 for (s=0;s<st->layout.nb_streams;s++)
1062 {
1063 OpusEncoder *enc;
1064
1065 enc = (OpusEncoder*)ptr;
1066 if (s < st->layout.nb_coupled_streams)
1067 ptr += align(coupled_size);
1068 else
1069 ptr += align(mono_size);
1070 ret = opus_encoder_ctl(enc, request, value);
1071 if (ret != OPUS_OK)
1072 break;
1073 }
1074 }
1075 break;
1076 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1077 {
1078 int s;
1079 opus_int32 stream_id;
1080 OpusEncoder **value;
1081 stream_id = va_arg(ap, opus_int32);
1082 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1083 ret = OPUS_BAD_ARG;
1084 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001085 if (!value)
1086 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001087 goto bad_arg;
1088 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001089 for (s=0;s<stream_id;s++)
1090 {
1091 if (s < st->layout.nb_coupled_streams)
1092 ptr += align(coupled_size);
1093 else
1094 ptr += align(mono_size);
1095 }
1096 *value = (OpusEncoder*)ptr;
1097 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001098 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001099 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001100 {
1101 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001102 st->variable_duration = value;
1103 }
1104 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001105 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001106 {
1107 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001108 if (!value)
1109 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001110 goto bad_arg;
1111 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001112 *value = st->variable_duration;
1113 }
1114 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001115 default:
1116 ret = OPUS_UNIMPLEMENTED;
1117 break;
1118 }
1119
1120 va_end(ap);
1121 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001122bad_arg:
1123 va_end(ap);
1124 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001125}
1126
1127void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1128{
1129 opus_free(st);
1130}