blob: 91ce2cdc7742906c56e3111c1fb86e14cf64363d [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 Valin49587512013-07-07 02:50:18 -040039#include "mathops.h"
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040040#include "mdct.h"
41#include "modes.h"
42#include "bands.h"
43#include "quant_bands.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050044
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040045typedef struct {
46 int nb_streams;
47 int nb_coupled_streams;
48 unsigned char mapping[8];
49} VorbisLayout;
50
51/* Index is nb_channel-1*/
52static const VorbisLayout vorbis_mappings[8] = {
53 {1, 0, {0}}, /* 1: mono */
54 {1, 1, {0, 1}}, /* 2: stereo */
55 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
56 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
57 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
58 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
59 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
60 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
61};
62
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040063typedef void (*opus_copy_channel_in_func)(
64 opus_val16 *dst,
65 int dst_stride,
66 const void *src,
67 int src_stride,
68 int src_channel,
69 int frame_size
70);
71
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050072struct OpusMSEncoder {
73 ChannelLayout layout;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040074 int lfe_stream;
Jean-Marc Valin74483662012-12-17 16:23:42 -050075 int variable_duration;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -040076 int surround;
Jean-Marc Valin74483662012-12-17 16:23:42 -050077 opus_int32 bitrate_bps;
78 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050079 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040080 /* then opus_val32 window_mem[channels*120]; */
81 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050082};
83
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040084static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
85{
86 int s;
87 char *ptr;
88 int coupled_size, mono_size;
89
90 coupled_size = opus_encoder_get_size(2);
91 mono_size = opus_encoder_get_size(1);
92 ptr = (char*)st + align(sizeof(OpusMSEncoder));
93 for (s=0;s<st->layout.nb_streams;s++)
94 {
95 if (s < st->layout.nb_coupled_streams)
96 ptr += align(coupled_size);
97 else
98 ptr += align(mono_size);
99 }
100 return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
101}
102
103static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
104{
105 int s;
106 char *ptr;
107 int coupled_size, mono_size;
108
109 coupled_size = opus_encoder_get_size(2);
110 mono_size = opus_encoder_get_size(1);
111 ptr = (char*)st + align(sizeof(OpusMSEncoder));
112 for (s=0;s<st->layout.nb_streams;s++)
113 {
114 if (s < st->layout.nb_coupled_streams)
115 ptr += align(coupled_size);
116 else
117 ptr += align(mono_size);
118 }
119 return (opus_val32*)ptr;
120}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500121
122static int validate_encoder_layout(const ChannelLayout *layout)
123{
124 int s;
125 for (s=0;s<layout->nb_streams;s++)
126 {
127 if (s < layout->nb_coupled_streams)
128 {
129 if (get_left_channel(layout, s, -1)==-1)
130 return 0;
131 if (get_right_channel(layout, s, -1)==-1)
132 return 0;
133 } else {
134 if (get_mono_channel(layout, s, -1)==-1)
135 return 0;
136 }
137 }
138 return 1;
139}
140
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400141static void channel_pos(int channels, int pos[8])
142{
143 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
144 if (channels==4)
145 {
146 pos[0]=1;
147 pos[1]=3;
148 pos[2]=1;
149 pos[3]=3;
150 } else if (channels==3||channels==5||channels==6)
151 {
152 pos[0]=1;
153 pos[1]=2;
154 pos[2]=3;
155 pos[3]=1;
156 pos[4]=3;
157 pos[5]=0;
158 } else if (channels==7)
159 {
160 pos[0]=1;
161 pos[1]=2;
162 pos[2]=3;
163 pos[3]=1;
164 pos[4]=3;
165 pos[5]=2;
166 pos[6]=0;
167 } else if (channels==8)
168 {
169 pos[0]=1;
170 pos[1]=2;
171 pos[2]=3;
172 pos[3]=1;
173 pos[4]=3;
174 pos[5]=1;
175 pos[6]=3;
176 pos[7]=0;
177 }
178}
179
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400180#if 1
181/* Computes a rough approximation of log2(2^a + 2^b) */
182static opus_val16 logSum(opus_val16 a, opus_val16 b)
183{
184 opus_val16 max;
185 opus_val32 diff;
186 opus_val16 frac;
187 static const opus_val16 diff_table[17] = {
188 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
189 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
190 QCONST16(0.0028123f, DB_SHIFT)
191 };
192 int low;
193 if (a>b)
194 {
195 max = a;
196 diff = SUB32(EXTEND32(a),EXTEND32(b));
197 } else {
198 max = b;
199 diff = SUB32(EXTEND32(b),EXTEND32(a));
200 }
201 if (diff >= QCONST16(8.f, DB_SHIFT))
202 return max;
203#ifdef FIXED_POINT
204 low = SHR32(diff, DB_SHIFT-1);
205 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
206#else
207 low = floor(2*diff);
208 frac = 2*diff - low;
209#endif
210 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
211}
212#else
213opus_val16 logSum(opus_val16 a, opus_val16 b)
214{
215 return log2(pow(4, a)+ pow(4, b))/2;
216}
217#endif
218
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400219void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
220 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
221)
222{
223 int c;
224 int i;
225 /* FIXME: pass LM properly */
226 int LM=3;
227 int pos[8] = {0};
228 int upsample;
229 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400230 opus_val16 maskLogE[3][21];
231 VARDECL(opus_val32, in);
232 VARDECL(opus_val16, x);
233 VARDECL(opus_val32, out);
234 SAVE_STACK;
235 ALLOC(in, len+overlap, opus_val32);
236 ALLOC(x, len, opus_val16);
237 ALLOC(freq, len, opus_val32);
238
239 channel_pos(channels, pos);
240
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400241 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400242 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400243 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400244
245 upsample = resampling_factor(rate);
246 for (c=0;c<channels;c++)
247 {
248 OPUS_COPY(in, mem+c*overlap, overlap);
249 (*copy_channel_in)(x, 1, pcm, channels, c, len);
250 /* FIXME: Handle upsampling properly wrt len */
251 preemphasis(x, in+overlap, len, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
252 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
253 if (upsample != 1)
254 {
255 int bound = len/upsample;
256 for (i=0;i<bound;i++)
257 freq[i] *= upsample;
258 for (;i<len;i++)
259 freq[i] = 0;
260 }
261
262 compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400263 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400264 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
265 for (i=1;i<21;i++)
266 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
267 for (i=19;i>=0;i--)
268 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 -0400269 if (pos[c]==1)
270 {
271 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400272 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400273 } else if (pos[c]==3)
274 {
275 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400276 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400277 } else if (pos[c]==2)
278 {
279 for (i=0;i<21;i++)
280 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400281 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
282 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400283 }
284 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400285#if 0
286 for (i=0;i<21;i++)
287 printf("%f ", bandLogE[21*c+i]);
288//#else
289 float sum=0;
290 for (i=0;i<21;i++)
291 sum += bandLogE[21*c+i];
292 printf("%f ", sum/21);
293#endif
294 OPUS_COPY(mem+c*overlap, in+len, overlap);
295 }
296 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400297 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400298 for (c=0;c<3;c++)
299 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400300 maskLogE[c][i] += QCONST16(.5f, DB_SHIFT)*log2(2.f/(channels-1));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400301#if 0
302 for (c=0;c<3;c++)
303 {
304 for (i=0;i<21;i++)
305 printf("%f ", maskLogE[c][i]);
306 }
307#endif
308 for (c=0;c<channels;c++)
309 {
310 opus_val16 *mask;
311 if (pos[c]!=0)
312 {
313 mask = &maskLogE[pos[c]-1][0];
314 for (i=0;i<21;i++)
315 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
316 } else {
317 for (i=0;i<21;i++)
318 bandLogE[21*c+i] = 0;
319 }
320#if 0
321 for (i=0;i<21;i++)
322 printf("%f ", bandLogE[21*c+i]);
323 printf("\n");
324#endif
325#if 0
326 float sum=0;
327 for (i=0;i<21;i++)
328 sum += bandLogE[21*c+i];
329 printf("%f ", sum/21);
330 printf("\n");
331#endif
332 }
333 RESTORE_STACK;
334}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500335
336opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
337{
338 int coupled_size;
339 int mono_size;
340
341 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
342 coupled_size = opus_encoder_get_size(2);
343 mono_size = opus_encoder_get_size(1);
344 return align(sizeof(OpusMSEncoder))
345 + nb_coupled_streams * align(coupled_size)
346 + (nb_streams-nb_coupled_streams) * align(mono_size);
347}
348
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400349opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
350{
351 int nb_streams;
352 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400353 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400354
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400355 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400356 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400357 if (channels==1)
358 {
359 nb_streams=1;
360 nb_coupled_streams=0;
361 } else if (channels==2)
362 {
363 nb_streams=1;
364 nb_coupled_streams=1;
365 } else
366 return 0;
367 } else if (mapping_family==1 && channels<=8 && channels>=1)
368 {
369 nb_streams=vorbis_mappings[channels-1].nb_streams;
370 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
371 } else if (mapping_family==255)
372 {
373 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400374 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400375 } else
376 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400377 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
378 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400379 {
380 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
381 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400382 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400383}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500384
385
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400386static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500387 OpusMSEncoder *st,
388 opus_int32 Fs,
389 int channels,
390 int streams,
391 int coupled_streams,
392 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400393 int application,
394 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500395)
396{
397 int coupled_size;
398 int mono_size;
399 int i, ret;
400 char *ptr;
401
402 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
403 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
404 return OPUS_BAD_ARG;
405
406 st->layout.nb_channels = channels;
407 st->layout.nb_streams = streams;
408 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400409 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400410 if (!surround)
411 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500412 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500413 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500414 for (i=0;i<st->layout.nb_channels;i++)
415 st->layout.mapping[i] = mapping[i];
416 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
417 return OPUS_BAD_ARG;
418 ptr = (char*)st + align(sizeof(OpusMSEncoder));
419 coupled_size = opus_encoder_get_size(2);
420 mono_size = opus_encoder_get_size(1);
421
422 for (i=0;i<st->layout.nb_coupled_streams;i++)
423 {
424 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400425 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400426 if (i==st->lfe_stream)
427 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500428 ptr += align(coupled_size);
429 }
430 for (;i<st->layout.nb_streams;i++)
431 {
432 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400433 if (i==st->lfe_stream)
434 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500435 if(ret!=OPUS_OK)return ret;
436 ptr += align(mono_size);
437 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400438 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400439 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400440 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
441 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400442 }
443 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500444 return OPUS_OK;
445}
446
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400447int opus_multistream_encoder_init(
448 OpusMSEncoder *st,
449 opus_int32 Fs,
450 int channels,
451 int streams,
452 int coupled_streams,
453 const unsigned char *mapping,
454 int application
455)
456{
457 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
458}
459
460int opus_multistream_surround_encoder_init(
461 OpusMSEncoder *st,
462 opus_int32 Fs,
463 int channels,
464 int mapping_family,
465 int *streams,
466 int *coupled_streams,
467 unsigned char *mapping,
468 int application
469)
470{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400471 if ((channels>255) || (channels<1))
472 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400473 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400474 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400475 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400476 if (channels==1)
477 {
478 *streams=1;
479 *coupled_streams=0;
480 mapping[0]=0;
481 } else if (channels==2)
482 {
483 *streams=1;
484 *coupled_streams=1;
485 mapping[0]=0;
486 mapping[1]=1;
487 } else
488 return OPUS_UNIMPLEMENTED;
489 } else if (mapping_family==1 && channels<=8 && channels>=1)
490 {
491 int i;
492 *streams=vorbis_mappings[channels-1].nb_streams;
493 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
494 for (i=0;i<channels;i++)
495 mapping[i] = vorbis_mappings[channels-1].mapping[i];
496 if (channels>=6)
497 st->lfe_stream = *streams-1;
498 } else if (mapping_family==255)
499 {
500 int i;
501 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400502 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400503 for(i=0;i<channels;i++)
504 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400505 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400506 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400507 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400508 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400509}
510
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500511OpusMSEncoder *opus_multistream_encoder_create(
512 opus_int32 Fs,
513 int channels,
514 int streams,
515 int coupled_streams,
516 const unsigned char *mapping,
517 int application,
518 int *error
519)
520{
521 int ret;
522 OpusMSEncoder *st;
523 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
524 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
525 {
526 if (error)
527 *error = OPUS_BAD_ARG;
528 return NULL;
529 }
530 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
531 if (st==NULL)
532 {
533 if (error)
534 *error = OPUS_ALLOC_FAIL;
535 return NULL;
536 }
537 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
538 if (ret != OPUS_OK)
539 {
540 opus_free(st);
541 st = NULL;
542 }
543 if (error)
544 *error = ret;
545 return st;
546}
547
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400548OpusMSEncoder *opus_multistream_surround_encoder_create(
549 opus_int32 Fs,
550 int channels,
551 int mapping_family,
552 int *streams,
553 int *coupled_streams,
554 unsigned char *mapping,
555 int application,
556 int *error
557)
558{
559 int ret;
560 OpusMSEncoder *st;
561 if ((channels>255) || (channels<1))
562 {
563 if (error)
564 *error = OPUS_BAD_ARG;
565 return NULL;
566 }
567 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
568 if (st==NULL)
569 {
570 if (error)
571 *error = OPUS_ALLOC_FAIL;
572 return NULL;
573 }
574 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
575 if (ret != OPUS_OK)
576 {
577 opus_free(st);
578 st = NULL;
579 }
580 if (error)
581 *error = ret;
582 return st;
583}
584
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400585static void surround_rate_allocation(
586 OpusMSEncoder *st,
587 opus_int32 *rate,
588 int frame_size
589 )
590{
591 int i;
592 opus_int32 channel_rate;
593 opus_int32 Fs;
594 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400595 int stream_offset;
596 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400597 int coupled_ratio; /* Q8 */
598 int lfe_ratio; /* Q8 */
599
600 ptr = (char*)st + align(sizeof(OpusMSEncoder));
601 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
602
Jean-Marc Valin49587512013-07-07 02:50:18 -0400603 if (st->bitrate_bps > st->layout.nb_channels*40000)
604 stream_offset = 20000;
605 else
606 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400607 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
608 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400609 /* The LFE stream is an exception to the above and gets fewer bits. */
610 lfe_offset = 3500;
611 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
612 coupled_ratio = 512;
613 /* 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 -0400614 lfe_ratio = 32;
615
616 /* Compute bitrate allocation between streams */
617 if (st->bitrate_bps==OPUS_AUTO)
618 {
619 channel_rate = Fs+60*Fs/frame_size;
620 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
621 {
622 channel_rate = 300000;
623 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400624 int nb_lfe;
625 int nb_uncoupled;
626 int nb_coupled;
627 int total;
628 nb_lfe = (st->lfe_stream!=-1);
629 nb_coupled = st->layout.nb_coupled_streams;
630 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
631 total = (nb_uncoupled<<8) /* mono */
632 + coupled_ratio*nb_coupled /* stereo */
633 + nb_lfe*lfe_ratio;
634 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 -0400635 }
636#ifndef FIXED_POINT
637 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
638 {
639 opus_int32 bonus;
640 bonus = 60*(Fs/frame_size-50);
641 channel_rate += bonus;
642 }
643#endif
644
645 for (i=0;i<st->layout.nb_streams;i++)
646 {
647 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400648 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400649 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400650 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400651 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400652 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400653 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400654}
655
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500656/* Max size in case the encoder decides to return three frames */
657#define MS_FRAME_TMP (3*1275+7)
658static int opus_multistream_encode_native
659(
660 OpusMSEncoder *st,
661 opus_copy_channel_in_func copy_channel_in,
662 const void *pcm,
663 int frame_size,
664 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500665 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400666 int lsb_depth,
667 downmix_func downmix
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500668)
669{
670 opus_int32 Fs;
671 int coupled_size;
672 int mono_size;
673 int s;
674 char *ptr;
675 int tot_size;
676 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400677 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500678 unsigned char tmp_data[MS_FRAME_TMP];
679 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500680 opus_int32 complexity;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500681 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400682 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400683 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400684 opus_val32 *mem = NULL;
685 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500686 ALLOC_STACK;
687
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400688 if (st->surround)
689 {
690 preemph_mem = ms_get_preemph_mem(st);
691 mem = ms_get_window_mem(st);
692 }
693
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500694 ptr = (char*)st + align(sizeof(OpusMSEncoder));
695 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500696 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
697 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500698
699 if (400*frame_size < Fs)
700 {
701 RESTORE_STACK;
702 return OPUS_BAD_ARG;
703 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500704 /* Validate frame_size before using it to allocate stack space.
705 This mirrors the checks in opus_encode[_float](). */
706 if (400*frame_size != Fs && 200*frame_size != Fs &&
707 100*frame_size != Fs && 50*frame_size != Fs &&
708 25*frame_size != Fs && 50*frame_size != 3*Fs)
709 {
710 RESTORE_STACK;
711 return OPUS_BAD_ARG;
712 }
713 ALLOC(buf, 2*frame_size, opus_val16);
714 coupled_size = opus_encoder_get_size(2);
715 mono_size = opus_encoder_get_size(1);
716
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400717 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400718 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400719 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400720 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 -0400721 }
722
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500723 if (max_data_bytes < 4*st->layout.nb_streams-1)
724 {
725 RESTORE_STACK;
726 return OPUS_BUFFER_TOO_SMALL;
727 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500728
729 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400730 surround_rate_allocation(st, bitrates, frame_size);
731
Jean-Marc Valin74483662012-12-17 16:23:42 -0500732 ptr = (char*)st + align(sizeof(OpusMSEncoder));
733 for (s=0;s<st->layout.nb_streams;s++)
734 {
735 OpusEncoder *enc;
736 enc = (OpusEncoder*)ptr;
737 if (s < st->layout.nb_coupled_streams)
738 ptr += align(coupled_size);
739 else
740 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400741 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400742 if (st->surround)
743 {
744 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
745 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
746 if (s < st->layout.nb_coupled_streams)
747 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
748 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500749 }
750
751 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500752 /* Counting ToC */
753 tot_size = 0;
754 for (s=0;s<st->layout.nb_streams;s++)
755 {
756 OpusEncoder *enc;
757 int len;
758 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400759 int c1, c2;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500760
761 opus_repacketizer_init(&rp);
762 enc = (OpusEncoder*)ptr;
763 if (s < st->layout.nb_coupled_streams)
764 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400765 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500766 int left, right;
767 left = get_left_channel(&st->layout, s, -1);
768 right = get_right_channel(&st->layout, s, -1);
769 (*copy_channel_in)(buf, 2,
770 pcm, st->layout.nb_channels, left, frame_size);
771 (*copy_channel_in)(buf+1, 2,
772 pcm, st->layout.nb_channels, right, frame_size);
773 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400774 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400775 {
776 for (i=0;i<21;i++)
777 {
778 bandLogE[i] = bandSMR[21*left+i];
779 bandLogE[21+i] = bandSMR[21*right+i];
780 }
781 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400782 c1 = left;
783 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500784 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400785 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500786 int chan = get_mono_channel(&st->layout, s, -1);
787 (*copy_channel_in)(buf, 1,
788 pcm, st->layout.nb_channels, chan, frame_size);
789 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400790 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400791 {
792 for (i=0;i<21;i++)
793 bandLogE[i] = bandSMR[21*chan+i];
794 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400795 c1 = chan;
796 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500797 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400798 if (st->surround)
799 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500800 /* number of bytes left (+Toc) */
801 curr_max = max_data_bytes - tot_size;
802 /* Reserve three bytes for the last stream and four for the others */
803 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
804 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400805 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, pcm, c1, c2, st->layout.nb_channels, downmix);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500806 if (len<0)
807 {
808 RESTORE_STACK;
809 return len;
810 }
811 /* We need to use the repacketizer to add the self-delimiting lengths
812 while taking into account the fact that the encoder can now return
813 more than one frame at a time (e.g. 60 ms CELT-only) */
814 opus_repacketizer_cat(&rp, tmp_data, len);
815 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);
816 data += len;
817 tot_size += len;
818 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400819 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500820 RESTORE_STACK;
821 return tot_size;
822
823}
824
Pedro Becerra1af7f952013-07-11 00:00:47 -0400825#if !defined(DISABLE_FLOAT_API)
826static void opus_copy_channel_in_float(
827 opus_val16 *dst,
828 int dst_stride,
829 const void *src,
830 int src_stride,
831 int src_channel,
832 int frame_size
833)
834{
835 const float *float_src;
836 opus_int32 i;
837 float_src = (const float *)src;
838 for (i=0;i<frame_size;i++)
839#if defined(FIXED_POINT)
840 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
841#else
842 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
843#endif
844}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500845#endif
846
847static void opus_copy_channel_in_short(
848 opus_val16 *dst,
849 int dst_stride,
850 const void *src,
851 int src_stride,
852 int src_channel,
853 int frame_size
854)
855{
856 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700857 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500858 short_src = (const opus_int16 *)src;
859 for (i=0;i<frame_size;i++)
860#if defined(FIXED_POINT)
861 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
862#else
863 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
864#endif
865}
866
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400867
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500868#ifdef FIXED_POINT
869int opus_multistream_encode(
870 OpusMSEncoder *st,
871 const opus_val16 *pcm,
872 int frame_size,
873 unsigned char *data,
874 opus_int32 max_data_bytes
875)
876{
877 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400878 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500879}
880
881#ifndef DISABLE_FLOAT_API
882int opus_multistream_encode_float(
883 OpusMSEncoder *st,
884 const float *pcm,
885 int frame_size,
886 unsigned char *data,
887 opus_int32 max_data_bytes
888)
889{
890 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400891 pcm, frame_size, data, max_data_bytes, 16, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500892}
893#endif
894
895#else
896
897int opus_multistream_encode_float
898(
899 OpusMSEncoder *st,
900 const opus_val16 *pcm,
901 int frame_size,
902 unsigned char *data,
903 opus_int32 max_data_bytes
904)
905{
906 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400907 pcm, frame_size, data, max_data_bytes, 24, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500908}
909
910int opus_multistream_encode(
911 OpusMSEncoder *st,
912 const opus_int16 *pcm,
913 int frame_size,
914 unsigned char *data,
915 opus_int32 max_data_bytes
916)
917{
918 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400919 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500920}
921#endif
922
923int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
924{
925 va_list ap;
926 int coupled_size, mono_size;
927 char *ptr;
928 int ret = OPUS_OK;
929
930 va_start(ap, request);
931
932 coupled_size = opus_encoder_get_size(2);
933 mono_size = opus_encoder_get_size(1);
934 ptr = (char*)st + align(sizeof(OpusMSEncoder));
935 switch (request)
936 {
937 case OPUS_SET_BITRATE_REQUEST:
938 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500939 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700940 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
941 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500942 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700943 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500944 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500945 }
946 break;
947 case OPUS_GET_BITRATE_REQUEST:
948 {
949 int s;
950 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700951 if (!value)
952 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700953 goto bad_arg;
954 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500955 *value = 0;
956 for (s=0;s<st->layout.nb_streams;s++)
957 {
958 opus_int32 rate;
959 OpusEncoder *enc;
960 enc = (OpusEncoder*)ptr;
961 if (s < st->layout.nb_coupled_streams)
962 ptr += align(coupled_size);
963 else
964 ptr += align(mono_size);
965 opus_encoder_ctl(enc, request, &rate);
966 *value += rate;
967 }
968 }
969 break;
970 case OPUS_GET_LSB_DEPTH_REQUEST:
971 case OPUS_GET_VBR_REQUEST:
972 case OPUS_GET_APPLICATION_REQUEST:
973 case OPUS_GET_BANDWIDTH_REQUEST:
974 case OPUS_GET_COMPLEXITY_REQUEST:
975 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
976 case OPUS_GET_DTX_REQUEST:
977 case OPUS_GET_VOICE_RATIO_REQUEST:
978 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
979 case OPUS_GET_SIGNAL_REQUEST:
980 case OPUS_GET_LOOKAHEAD_REQUEST:
981 case OPUS_GET_SAMPLE_RATE_REQUEST:
982 case OPUS_GET_INBAND_FEC_REQUEST:
983 case OPUS_GET_FORCE_CHANNELS_REQUEST:
984 {
985 OpusEncoder *enc;
986 /* For int32* GET params, just query the first stream */
987 opus_int32 *value = va_arg(ap, opus_int32*);
988 enc = (OpusEncoder*)ptr;
989 ret = opus_encoder_ctl(enc, request, value);
990 }
991 break;
992 case OPUS_GET_FINAL_RANGE_REQUEST:
993 {
994 int s;
995 opus_uint32 *value = va_arg(ap, opus_uint32*);
996 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700997 if (!value)
998 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700999 goto bad_arg;
1000 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001001 *value=0;
1002 for (s=0;s<st->layout.nb_streams;s++)
1003 {
1004 OpusEncoder *enc;
1005 enc = (OpusEncoder*)ptr;
1006 if (s < st->layout.nb_coupled_streams)
1007 ptr += align(coupled_size);
1008 else
1009 ptr += align(mono_size);
1010 ret = opus_encoder_ctl(enc, request, &tmp);
1011 if (ret != OPUS_OK) break;
1012 *value ^= tmp;
1013 }
1014 }
1015 break;
1016 case OPUS_SET_LSB_DEPTH_REQUEST:
1017 case OPUS_SET_COMPLEXITY_REQUEST:
1018 case OPUS_SET_VBR_REQUEST:
1019 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001020 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001021 case OPUS_SET_BANDWIDTH_REQUEST:
1022 case OPUS_SET_SIGNAL_REQUEST:
1023 case OPUS_SET_APPLICATION_REQUEST:
1024 case OPUS_SET_INBAND_FEC_REQUEST:
1025 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1026 case OPUS_SET_DTX_REQUEST:
1027 case OPUS_SET_FORCE_MODE_REQUEST:
1028 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1029 {
1030 int s;
1031 /* This works for int32 params */
1032 opus_int32 value = va_arg(ap, opus_int32);
1033 for (s=0;s<st->layout.nb_streams;s++)
1034 {
1035 OpusEncoder *enc;
1036
1037 enc = (OpusEncoder*)ptr;
1038 if (s < st->layout.nb_coupled_streams)
1039 ptr += align(coupled_size);
1040 else
1041 ptr += align(mono_size);
1042 ret = opus_encoder_ctl(enc, request, value);
1043 if (ret != OPUS_OK)
1044 break;
1045 }
1046 }
1047 break;
1048 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1049 {
1050 int s;
1051 opus_int32 stream_id;
1052 OpusEncoder **value;
1053 stream_id = va_arg(ap, opus_int32);
1054 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1055 ret = OPUS_BAD_ARG;
1056 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001057 if (!value)
1058 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001059 goto bad_arg;
1060 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001061 for (s=0;s<stream_id;s++)
1062 {
1063 if (s < st->layout.nb_coupled_streams)
1064 ptr += align(coupled_size);
1065 else
1066 ptr += align(mono_size);
1067 }
1068 *value = (OpusEncoder*)ptr;
1069 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001070 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001071 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001072 {
1073 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001074 st->variable_duration = value;
1075 }
1076 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001077 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001078 {
1079 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001080 if (!value)
1081 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001082 goto bad_arg;
1083 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001084 *value = st->variable_duration;
1085 }
1086 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001087 default:
1088 ret = OPUS_UNIMPLEMENTED;
1089 break;
1090 }
1091
1092 va_end(ap);
1093 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001094bad_arg:
1095 va_end(ap);
1096 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001097}
1098
1099void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1100{
1101 opus_free(st);
1102}