blob: 7cc3237ea80b2e8e0d5ec942ed50baa213b9b3e4 [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 Valinfdceae82013-08-30 21:58:02 -0400266 if (pos[c]==1)
267 {
268 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400269 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400270 } else if (pos[c]==3)
271 {
272 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400273 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400274 } else if (pos[c]==2)
275 {
276 for (i=0;i<21;i++)
277 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400278 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
279 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400280 }
281 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400282#if 0
283 for (i=0;i<21;i++)
284 printf("%f ", bandLogE[21*c+i]);
285//#else
286 float sum=0;
287 for (i=0;i<21;i++)
288 sum += bandLogE[21*c+i];
289 printf("%f ", sum/21);
290#endif
291 OPUS_COPY(mem+c*overlap, in+len, overlap);
292 }
293 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400294 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400295 for (c=0;c<3;c++)
296 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400297 maskLogE[c][i] += QCONST16(.5f, DB_SHIFT)*log2(2.f/(channels-1));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400298#if 0
299 for (c=0;c<3;c++)
300 {
301 for (i=0;i<21;i++)
302 printf("%f ", maskLogE[c][i]);
303 }
304#endif
305 for (c=0;c<channels;c++)
306 {
307 opus_val16 *mask;
308 if (pos[c]!=0)
309 {
310 mask = &maskLogE[pos[c]-1][0];
311 for (i=0;i<21;i++)
312 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
313 } else {
314 for (i=0;i<21;i++)
315 bandLogE[21*c+i] = 0;
316 }
317#if 0
318 for (i=0;i<21;i++)
319 printf("%f ", bandLogE[21*c+i]);
320 printf("\n");
321#endif
322#if 0
323 float sum=0;
324 for (i=0;i<21;i++)
325 sum += bandLogE[21*c+i];
326 printf("%f ", sum/21);
327 printf("\n");
328#endif
329 }
330 RESTORE_STACK;
331}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500332
333opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
334{
335 int coupled_size;
336 int mono_size;
337
338 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
339 coupled_size = opus_encoder_get_size(2);
340 mono_size = opus_encoder_get_size(1);
341 return align(sizeof(OpusMSEncoder))
342 + nb_coupled_streams * align(coupled_size)
343 + (nb_streams-nb_coupled_streams) * align(mono_size);
344}
345
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400346opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
347{
348 int nb_streams;
349 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400350 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400351
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400352 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400353 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400354 if (channels==1)
355 {
356 nb_streams=1;
357 nb_coupled_streams=0;
358 } else if (channels==2)
359 {
360 nb_streams=1;
361 nb_coupled_streams=1;
362 } else
363 return 0;
364 } else if (mapping_family==1 && channels<=8 && channels>=1)
365 {
366 nb_streams=vorbis_mappings[channels-1].nb_streams;
367 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
368 } else if (mapping_family==255)
369 {
370 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400371 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400372 } else
373 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400374 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
375 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400376 {
377 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
378 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400379 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400380}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500381
382
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400383static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500384 OpusMSEncoder *st,
385 opus_int32 Fs,
386 int channels,
387 int streams,
388 int coupled_streams,
389 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400390 int application,
391 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500392)
393{
394 int coupled_size;
395 int mono_size;
396 int i, ret;
397 char *ptr;
398
399 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
400 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
401 return OPUS_BAD_ARG;
402
403 st->layout.nb_channels = channels;
404 st->layout.nb_streams = streams;
405 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400406 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
407 OPUS_CLEAR(&st->analysis,1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400408 if (!surround)
409 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500410 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500411 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500412 for (i=0;i<st->layout.nb_channels;i++)
413 st->layout.mapping[i] = mapping[i];
414 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
415 return OPUS_BAD_ARG;
416 ptr = (char*)st + align(sizeof(OpusMSEncoder));
417 coupled_size = opus_encoder_get_size(2);
418 mono_size = opus_encoder_get_size(1);
419
420 for (i=0;i<st->layout.nb_coupled_streams;i++)
421 {
422 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400423 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400424 if (i==st->lfe_stream)
425 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500426 ptr += align(coupled_size);
427 }
428 for (;i<st->layout.nb_streams;i++)
429 {
430 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400431 if (i==st->lfe_stream)
432 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500433 if(ret!=OPUS_OK)return ret;
434 ptr += align(mono_size);
435 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400436 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400437 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400438 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
439 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400440 }
441 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500442 return OPUS_OK;
443}
444
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400445int opus_multistream_encoder_init(
446 OpusMSEncoder *st,
447 opus_int32 Fs,
448 int channels,
449 int streams,
450 int coupled_streams,
451 const unsigned char *mapping,
452 int application
453)
454{
455 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
456}
457
458int opus_multistream_surround_encoder_init(
459 OpusMSEncoder *st,
460 opus_int32 Fs,
461 int channels,
462 int mapping_family,
463 int *streams,
464 int *coupled_streams,
465 unsigned char *mapping,
466 int application
467)
468{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400469 if ((channels>255) || (channels<1))
470 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400471 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400472 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400473 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400474 if (channels==1)
475 {
476 *streams=1;
477 *coupled_streams=0;
478 mapping[0]=0;
479 } else if (channels==2)
480 {
481 *streams=1;
482 *coupled_streams=1;
483 mapping[0]=0;
484 mapping[1]=1;
485 } else
486 return OPUS_UNIMPLEMENTED;
487 } else if (mapping_family==1 && channels<=8 && channels>=1)
488 {
489 int i;
490 *streams=vorbis_mappings[channels-1].nb_streams;
491 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
492 for (i=0;i<channels;i++)
493 mapping[i] = vorbis_mappings[channels-1].mapping[i];
494 if (channels>=6)
495 st->lfe_stream = *streams-1;
496 } else if (mapping_family==255)
497 {
498 int i;
499 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400500 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400501 for(i=0;i<channels;i++)
502 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400503 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400504 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400505 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400506 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400507}
508
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500509OpusMSEncoder *opus_multistream_encoder_create(
510 opus_int32 Fs,
511 int channels,
512 int streams,
513 int coupled_streams,
514 const unsigned char *mapping,
515 int application,
516 int *error
517)
518{
519 int ret;
520 OpusMSEncoder *st;
521 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
522 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
523 {
524 if (error)
525 *error = OPUS_BAD_ARG;
526 return NULL;
527 }
528 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
529 if (st==NULL)
530 {
531 if (error)
532 *error = OPUS_ALLOC_FAIL;
533 return NULL;
534 }
535 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
536 if (ret != OPUS_OK)
537 {
538 opus_free(st);
539 st = NULL;
540 }
541 if (error)
542 *error = ret;
543 return st;
544}
545
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400546OpusMSEncoder *opus_multistream_surround_encoder_create(
547 opus_int32 Fs,
548 int channels,
549 int mapping_family,
550 int *streams,
551 int *coupled_streams,
552 unsigned char *mapping,
553 int application,
554 int *error
555)
556{
557 int ret;
558 OpusMSEncoder *st;
559 if ((channels>255) || (channels<1))
560 {
561 if (error)
562 *error = OPUS_BAD_ARG;
563 return NULL;
564 }
565 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
566 if (st==NULL)
567 {
568 if (error)
569 *error = OPUS_ALLOC_FAIL;
570 return NULL;
571 }
572 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
573 if (ret != OPUS_OK)
574 {
575 opus_free(st);
576 st = NULL;
577 }
578 if (error)
579 *error = ret;
580 return st;
581}
582
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400583static void surround_rate_allocation(
584 OpusMSEncoder *st,
585 opus_int32 *rate,
586 int frame_size
587 )
588{
589 int i;
590 opus_int32 channel_rate;
591 opus_int32 Fs;
592 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400593 int stream_offset;
594 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400595 int coupled_ratio; /* Q8 */
596 int lfe_ratio; /* Q8 */
597
598 ptr = (char*)st + align(sizeof(OpusMSEncoder));
599 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
600
Jean-Marc Valin49587512013-07-07 02:50:18 -0400601 if (st->bitrate_bps > st->layout.nb_channels*40000)
602 stream_offset = 20000;
603 else
604 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400605 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
606 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400607 /* The LFE stream is an exception to the above and gets fewer bits. */
608 lfe_offset = 3500;
609 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
610 coupled_ratio = 512;
611 /* 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 -0400612 lfe_ratio = 32;
613
614 /* Compute bitrate allocation between streams */
615 if (st->bitrate_bps==OPUS_AUTO)
616 {
617 channel_rate = Fs+60*Fs/frame_size;
618 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
619 {
620 channel_rate = 300000;
621 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400622 int nb_lfe;
623 int nb_uncoupled;
624 int nb_coupled;
625 int total;
626 nb_lfe = (st->lfe_stream!=-1);
627 nb_coupled = st->layout.nb_coupled_streams;
628 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
629 total = (nb_uncoupled<<8) /* mono */
630 + coupled_ratio*nb_coupled /* stereo */
631 + nb_lfe*lfe_ratio;
632 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 -0400633 }
634#ifndef FIXED_POINT
635 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
636 {
637 opus_int32 bonus;
638 bonus = 60*(Fs/frame_size-50);
639 channel_rate += bonus;
640 }
641#endif
642
643 for (i=0;i<st->layout.nb_streams;i++)
644 {
645 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400646 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400647 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400648 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400649 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400650 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400651 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400652}
653
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500654/* Max size in case the encoder decides to return three frames */
655#define MS_FRAME_TMP (3*1275+7)
656static int opus_multistream_encode_native
657(
658 OpusMSEncoder *st,
659 opus_copy_channel_in_func copy_channel_in,
660 const void *pcm,
661 int frame_size,
662 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500663 opus_int32 max_data_bytes,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400664 int lsb_depth
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500665#ifndef FIXED_POINT
666 , downmix_func downmix
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500667 , const void *pcm_analysis
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500668#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500669)
670{
671 opus_int32 Fs;
672 int coupled_size;
673 int mono_size;
674 int s;
675 char *ptr;
676 int tot_size;
677 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400678 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500679 unsigned char tmp_data[MS_FRAME_TMP];
680 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500681 opus_int32 complexity;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400682#ifndef FIXED_POINT
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500683 AnalysisInfo analysis_info;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400684#endif
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500685 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400686 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400687 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400688 opus_val32 *mem = NULL;
689 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500690 ALLOC_STACK;
691
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400692 if (st->surround)
693 {
694 preemph_mem = ms_get_preemph_mem(st);
695 mem = ms_get_window_mem(st);
696 }
697
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500698 ptr = (char*)st + align(sizeof(OpusMSEncoder));
699 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500700 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
701 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500702
703 if (400*frame_size < Fs)
704 {
705 RESTORE_STACK;
706 return OPUS_BAD_ARG;
707 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500708#ifndef FIXED_POINT
709 analysis_info.valid = 0;
710 if (complexity >= 7 && Fs==48000)
Jean-Marc Valin74483662012-12-17 16:23:42 -0500711 {
Jean-Marc Valin74483662012-12-17 16:23:42 -0500712 opus_int32 delay_compensation;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500713 int channels;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500714
715 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
716 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
717 delay_compensation -= Fs/400;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500718
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500719 frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
720 frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
721 } else
722#endif
723 {
724 frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
725 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500726 /* Validate frame_size before using it to allocate stack space.
727 This mirrors the checks in opus_encode[_float](). */
728 if (400*frame_size != Fs && 200*frame_size != Fs &&
729 100*frame_size != Fs && 50*frame_size != Fs &&
730 25*frame_size != Fs && 50*frame_size != 3*Fs)
731 {
732 RESTORE_STACK;
733 return OPUS_BAD_ARG;
734 }
735 ALLOC(buf, 2*frame_size, opus_val16);
736 coupled_size = opus_encoder_get_size(2);
737 mono_size = opus_encoder_get_size(1);
738
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400739 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400740 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400741 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400742 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 -0400743 }
744
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500745 if (max_data_bytes < 4*st->layout.nb_streams-1)
746 {
747 RESTORE_STACK;
748 return OPUS_BUFFER_TOO_SMALL;
749 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500750
751 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400752 surround_rate_allocation(st, bitrates, frame_size);
753
Jean-Marc Valin74483662012-12-17 16:23:42 -0500754 ptr = (char*)st + align(sizeof(OpusMSEncoder));
755 for (s=0;s<st->layout.nb_streams;s++)
756 {
757 OpusEncoder *enc;
758 enc = (OpusEncoder*)ptr;
759 if (s < st->layout.nb_coupled_streams)
760 ptr += align(coupled_size);
761 else
762 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400763 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400764 if (st->surround)
765 {
766 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
767 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
768 if (s < st->layout.nb_coupled_streams)
769 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
770 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500771 }
772
773 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500774 /* Counting ToC */
775 tot_size = 0;
776 for (s=0;s<st->layout.nb_streams;s++)
777 {
778 OpusEncoder *enc;
779 int len;
780 int curr_max;
781
782 opus_repacketizer_init(&rp);
783 enc = (OpusEncoder*)ptr;
784 if (s < st->layout.nb_coupled_streams)
785 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400786 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500787 int left, right;
788 left = get_left_channel(&st->layout, s, -1);
789 right = get_right_channel(&st->layout, s, -1);
790 (*copy_channel_in)(buf, 2,
791 pcm, st->layout.nb_channels, left, frame_size);
792 (*copy_channel_in)(buf+1, 2,
793 pcm, st->layout.nb_channels, right, frame_size);
794 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400795 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400796 {
797 for (i=0;i<21;i++)
798 {
799 bandLogE[i] = bandSMR[21*left+i];
800 bandLogE[21+i] = bandSMR[21*right+i];
801 }
802 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500803 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400804 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500805 int chan = get_mono_channel(&st->layout, s, -1);
806 (*copy_channel_in)(buf, 1,
807 pcm, st->layout.nb_channels, chan, frame_size);
808 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400809 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400810 {
811 for (i=0;i<21;i++)
812 bandLogE[i] = bandSMR[21*chan+i];
813 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500814 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400815 if (st->surround)
816 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500817 /* number of bytes left (+Toc) */
818 curr_max = max_data_bytes - tot_size;
819 /* Reserve three bytes for the last stream and four for the others */
820 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
821 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500822 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
823#ifndef FIXED_POINT
824 , &analysis_info
825#endif
826 );
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500827 if (len<0)
828 {
829 RESTORE_STACK;
830 return len;
831 }
832 /* We need to use the repacketizer to add the self-delimiting lengths
833 while taking into account the fact that the encoder can now return
834 more than one frame at a time (e.g. 60 ms CELT-only) */
835 opus_repacketizer_cat(&rp, tmp_data, len);
836 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);
837 data += len;
838 tot_size += len;
839 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400840 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500841 RESTORE_STACK;
842 return tot_size;
843
844}
845
Pedro Becerra1af7f952013-07-11 00:00:47 -0400846#if !defined(DISABLE_FLOAT_API)
847static void opus_copy_channel_in_float(
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 float *float_src;
857 opus_int32 i;
858 float_src = (const float *)src;
859 for (i=0;i<frame_size;i++)
860#if defined(FIXED_POINT)
861 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
862#else
863 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
864#endif
865}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500866#endif
867
868static void opus_copy_channel_in_short(
869 opus_val16 *dst,
870 int dst_stride,
871 const void *src,
872 int src_stride,
873 int src_channel,
874 int frame_size
875)
876{
877 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700878 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500879 short_src = (const opus_int16 *)src;
880 for (i=0;i<frame_size;i++)
881#if defined(FIXED_POINT)
882 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
883#else
884 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
885#endif
886}
887
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400888
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500889#ifdef FIXED_POINT
890int opus_multistream_encode(
891 OpusMSEncoder *st,
892 const opus_val16 *pcm,
893 int frame_size,
894 unsigned char *data,
895 opus_int32 max_data_bytes
896)
897{
898 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400899 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500900}
901
902#ifndef DISABLE_FLOAT_API
903int opus_multistream_encode_float(
904 OpusMSEncoder *st,
905 const float *pcm,
906 int frame_size,
907 unsigned char *data,
908 opus_int32 max_data_bytes
909)
910{
911 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400912 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500913}
914#endif
915
916#else
917
918int opus_multistream_encode_float
919(
920 OpusMSEncoder *st,
921 const opus_val16 *pcm,
922 int frame_size,
923 unsigned char *data,
924 opus_int32 max_data_bytes
925)
926{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500927 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500928 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400929 pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500930}
931
932int opus_multistream_encode(
933 OpusMSEncoder *st,
934 const opus_int16 *pcm,
935 int frame_size,
936 unsigned char *data,
937 opus_int32 max_data_bytes
938)
939{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500940 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500941 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400942 pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500943}
944#endif
945
946int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
947{
948 va_list ap;
949 int coupled_size, mono_size;
950 char *ptr;
951 int ret = OPUS_OK;
952
953 va_start(ap, request);
954
955 coupled_size = opus_encoder_get_size(2);
956 mono_size = opus_encoder_get_size(1);
957 ptr = (char*)st + align(sizeof(OpusMSEncoder));
958 switch (request)
959 {
960 case OPUS_SET_BITRATE_REQUEST:
961 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500962 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700963 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
964 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500965 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700966 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500967 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500968 }
969 break;
970 case OPUS_GET_BITRATE_REQUEST:
971 {
972 int s;
973 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700974 if (!value)
975 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700976 goto bad_arg;
977 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500978 *value = 0;
979 for (s=0;s<st->layout.nb_streams;s++)
980 {
981 opus_int32 rate;
982 OpusEncoder *enc;
983 enc = (OpusEncoder*)ptr;
984 if (s < st->layout.nb_coupled_streams)
985 ptr += align(coupled_size);
986 else
987 ptr += align(mono_size);
988 opus_encoder_ctl(enc, request, &rate);
989 *value += rate;
990 }
991 }
992 break;
993 case OPUS_GET_LSB_DEPTH_REQUEST:
994 case OPUS_GET_VBR_REQUEST:
995 case OPUS_GET_APPLICATION_REQUEST:
996 case OPUS_GET_BANDWIDTH_REQUEST:
997 case OPUS_GET_COMPLEXITY_REQUEST:
998 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
999 case OPUS_GET_DTX_REQUEST:
1000 case OPUS_GET_VOICE_RATIO_REQUEST:
1001 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1002 case OPUS_GET_SIGNAL_REQUEST:
1003 case OPUS_GET_LOOKAHEAD_REQUEST:
1004 case OPUS_GET_SAMPLE_RATE_REQUEST:
1005 case OPUS_GET_INBAND_FEC_REQUEST:
1006 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1007 {
1008 OpusEncoder *enc;
1009 /* For int32* GET params, just query the first stream */
1010 opus_int32 *value = va_arg(ap, opus_int32*);
1011 enc = (OpusEncoder*)ptr;
1012 ret = opus_encoder_ctl(enc, request, value);
1013 }
1014 break;
1015 case OPUS_GET_FINAL_RANGE_REQUEST:
1016 {
1017 int s;
1018 opus_uint32 *value = va_arg(ap, opus_uint32*);
1019 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001020 if (!value)
1021 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001022 goto bad_arg;
1023 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001024 *value=0;
1025 for (s=0;s<st->layout.nb_streams;s++)
1026 {
1027 OpusEncoder *enc;
1028 enc = (OpusEncoder*)ptr;
1029 if (s < st->layout.nb_coupled_streams)
1030 ptr += align(coupled_size);
1031 else
1032 ptr += align(mono_size);
1033 ret = opus_encoder_ctl(enc, request, &tmp);
1034 if (ret != OPUS_OK) break;
1035 *value ^= tmp;
1036 }
1037 }
1038 break;
1039 case OPUS_SET_LSB_DEPTH_REQUEST:
1040 case OPUS_SET_COMPLEXITY_REQUEST:
1041 case OPUS_SET_VBR_REQUEST:
1042 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001043 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001044 case OPUS_SET_BANDWIDTH_REQUEST:
1045 case OPUS_SET_SIGNAL_REQUEST:
1046 case OPUS_SET_APPLICATION_REQUEST:
1047 case OPUS_SET_INBAND_FEC_REQUEST:
1048 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1049 case OPUS_SET_DTX_REQUEST:
1050 case OPUS_SET_FORCE_MODE_REQUEST:
1051 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1052 {
1053 int s;
1054 /* This works for int32 params */
1055 opus_int32 value = va_arg(ap, opus_int32);
1056 for (s=0;s<st->layout.nb_streams;s++)
1057 {
1058 OpusEncoder *enc;
1059
1060 enc = (OpusEncoder*)ptr;
1061 if (s < st->layout.nb_coupled_streams)
1062 ptr += align(coupled_size);
1063 else
1064 ptr += align(mono_size);
1065 ret = opus_encoder_ctl(enc, request, value);
1066 if (ret != OPUS_OK)
1067 break;
1068 }
1069 }
1070 break;
1071 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1072 {
1073 int s;
1074 opus_int32 stream_id;
1075 OpusEncoder **value;
1076 stream_id = va_arg(ap, opus_int32);
1077 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1078 ret = OPUS_BAD_ARG;
1079 value = va_arg(ap, OpusEncoder**);
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 Valinae0e2ca2012-11-07 19:57:33 -05001084 for (s=0;s<stream_id;s++)
1085 {
1086 if (s < st->layout.nb_coupled_streams)
1087 ptr += align(coupled_size);
1088 else
1089 ptr += align(mono_size);
1090 }
1091 *value = (OpusEncoder*)ptr;
1092 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001093 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001094 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001095 {
1096 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001097 st->variable_duration = value;
1098 }
1099 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001100 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001101 {
1102 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001103 if (!value)
1104 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001105 goto bad_arg;
1106 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001107 *value = st->variable_duration;
1108 }
1109 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001110 default:
1111 ret = OPUS_UNIMPLEMENTED;
1112 break;
1113 }
1114
1115 va_end(ap);
1116 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001117bad_arg:
1118 va_end(ap);
1119 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001120}
1121
1122void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1123{
1124 opus_free(st);
1125}