blob: 3065b6f77b0c5155ba35bb94712d81d5a69fddee [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;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400225 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400226 int pos[8] = {0};
227 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400228 int frame_size;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400229 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;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400235
236 upsample = resampling_factor(rate);
237 frame_size = len*upsample;
238
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400239 for (LM=0;LM<=celt_mode->maxLM;LM++)
240 if (celt_mode->shortMdctSize<<LM==frame_size)
241 break;
242
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400243 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400244 ALLOC(x, len, opus_val16);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400245 ALLOC(freq, frame_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400246
247 channel_pos(channels, pos);
248
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400249 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400250 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400251 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400252
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400253 for (c=0;c<channels;c++)
254 {
255 OPUS_COPY(in, mem+c*overlap, overlap);
256 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400257 preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400258 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
259 if (upsample != 1)
260 {
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400261 int bound = len;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400262 for (i=0;i<bound;i++)
263 freq[i] *= upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400264 for (;i<frame_size;i++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400265 freq[i] = 0;
266 }
267
268 compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400269 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400270 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
271 for (i=1;i<21;i++)
272 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
273 for (i=19;i>=0;i--)
274 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 -0400275 if (pos[c]==1)
276 {
277 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400278 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400279 } else if (pos[c]==3)
280 {
281 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400282 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400283 } else if (pos[c]==2)
284 {
285 for (i=0;i<21;i++)
286 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400287 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
288 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400289 }
290 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400291#if 0
292 for (i=0;i<21;i++)
293 printf("%f ", bandLogE[21*c+i]);
294//#else
295 float sum=0;
296 for (i=0;i<21;i++)
297 sum += bandLogE[21*c+i];
298 printf("%f ", sum/21);
299#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400300 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400301 }
302 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400303 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400304 for (c=0;c<3;c++)
305 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400306 maskLogE[c][i] += QCONST16(.5f, DB_SHIFT)*log2(2.f/(channels-1));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400307#if 0
308 for (c=0;c<3;c++)
309 {
310 for (i=0;i<21;i++)
311 printf("%f ", maskLogE[c][i]);
312 }
313#endif
314 for (c=0;c<channels;c++)
315 {
316 opus_val16 *mask;
317 if (pos[c]!=0)
318 {
319 mask = &maskLogE[pos[c]-1][0];
320 for (i=0;i<21;i++)
321 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
322 } else {
323 for (i=0;i<21;i++)
324 bandLogE[21*c+i] = 0;
325 }
326#if 0
327 for (i=0;i<21;i++)
328 printf("%f ", bandLogE[21*c+i]);
329 printf("\n");
330#endif
331#if 0
332 float sum=0;
333 for (i=0;i<21;i++)
334 sum += bandLogE[21*c+i];
335 printf("%f ", sum/21);
336 printf("\n");
337#endif
338 }
339 RESTORE_STACK;
340}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500341
342opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
343{
344 int coupled_size;
345 int mono_size;
346
347 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
348 coupled_size = opus_encoder_get_size(2);
349 mono_size = opus_encoder_get_size(1);
350 return align(sizeof(OpusMSEncoder))
351 + nb_coupled_streams * align(coupled_size)
352 + (nb_streams-nb_coupled_streams) * align(mono_size);
353}
354
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400355opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
356{
357 int nb_streams;
358 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400359 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400360
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400361 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400362 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400363 if (channels==1)
364 {
365 nb_streams=1;
366 nb_coupled_streams=0;
367 } else if (channels==2)
368 {
369 nb_streams=1;
370 nb_coupled_streams=1;
371 } else
372 return 0;
373 } else if (mapping_family==1 && channels<=8 && channels>=1)
374 {
375 nb_streams=vorbis_mappings[channels-1].nb_streams;
376 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
377 } else if (mapping_family==255)
378 {
379 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400380 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400381 } else
382 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400383 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
384 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400385 {
386 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
387 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400388 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400389}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500390
391
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400392static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500393 OpusMSEncoder *st,
394 opus_int32 Fs,
395 int channels,
396 int streams,
397 int coupled_streams,
398 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400399 int application,
400 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500401)
402{
403 int coupled_size;
404 int mono_size;
405 int i, ret;
406 char *ptr;
407
408 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
409 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
410 return OPUS_BAD_ARG;
411
412 st->layout.nb_channels = channels;
413 st->layout.nb_streams = streams;
414 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400415 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400416 if (!surround)
417 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500418 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500419 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500420 for (i=0;i<st->layout.nb_channels;i++)
421 st->layout.mapping[i] = mapping[i];
422 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
423 return OPUS_BAD_ARG;
424 ptr = (char*)st + align(sizeof(OpusMSEncoder));
425 coupled_size = opus_encoder_get_size(2);
426 mono_size = opus_encoder_get_size(1);
427
428 for (i=0;i<st->layout.nb_coupled_streams;i++)
429 {
430 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400431 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400432 if (i==st->lfe_stream)
433 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500434 ptr += align(coupled_size);
435 }
436 for (;i<st->layout.nb_streams;i++)
437 {
438 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400439 if (i==st->lfe_stream)
440 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500441 if(ret!=OPUS_OK)return ret;
442 ptr += align(mono_size);
443 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400444 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400445 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400446 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
447 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400448 }
449 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500450 return OPUS_OK;
451}
452
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400453int opus_multistream_encoder_init(
454 OpusMSEncoder *st,
455 opus_int32 Fs,
456 int channels,
457 int streams,
458 int coupled_streams,
459 const unsigned char *mapping,
460 int application
461)
462{
463 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
464}
465
466int opus_multistream_surround_encoder_init(
467 OpusMSEncoder *st,
468 opus_int32 Fs,
469 int channels,
470 int mapping_family,
471 int *streams,
472 int *coupled_streams,
473 unsigned char *mapping,
474 int application
475)
476{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400477 if ((channels>255) || (channels<1))
478 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400479 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400480 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400481 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400482 if (channels==1)
483 {
484 *streams=1;
485 *coupled_streams=0;
486 mapping[0]=0;
487 } else if (channels==2)
488 {
489 *streams=1;
490 *coupled_streams=1;
491 mapping[0]=0;
492 mapping[1]=1;
493 } else
494 return OPUS_UNIMPLEMENTED;
495 } else if (mapping_family==1 && channels<=8 && channels>=1)
496 {
497 int i;
498 *streams=vorbis_mappings[channels-1].nb_streams;
499 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
500 for (i=0;i<channels;i++)
501 mapping[i] = vorbis_mappings[channels-1].mapping[i];
502 if (channels>=6)
503 st->lfe_stream = *streams-1;
504 } else if (mapping_family==255)
505 {
506 int i;
507 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400508 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400509 for(i=0;i<channels;i++)
510 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400511 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400512 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400513 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400514 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400515}
516
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500517OpusMSEncoder *opus_multistream_encoder_create(
518 opus_int32 Fs,
519 int channels,
520 int streams,
521 int coupled_streams,
522 const unsigned char *mapping,
523 int application,
524 int *error
525)
526{
527 int ret;
528 OpusMSEncoder *st;
529 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
530 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
531 {
532 if (error)
533 *error = OPUS_BAD_ARG;
534 return NULL;
535 }
536 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
537 if (st==NULL)
538 {
539 if (error)
540 *error = OPUS_ALLOC_FAIL;
541 return NULL;
542 }
543 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
544 if (ret != OPUS_OK)
545 {
546 opus_free(st);
547 st = NULL;
548 }
549 if (error)
550 *error = ret;
551 return st;
552}
553
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400554OpusMSEncoder *opus_multistream_surround_encoder_create(
555 opus_int32 Fs,
556 int channels,
557 int mapping_family,
558 int *streams,
559 int *coupled_streams,
560 unsigned char *mapping,
561 int application,
562 int *error
563)
564{
565 int ret;
566 OpusMSEncoder *st;
567 if ((channels>255) || (channels<1))
568 {
569 if (error)
570 *error = OPUS_BAD_ARG;
571 return NULL;
572 }
573 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
574 if (st==NULL)
575 {
576 if (error)
577 *error = OPUS_ALLOC_FAIL;
578 return NULL;
579 }
580 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
581 if (ret != OPUS_OK)
582 {
583 opus_free(st);
584 st = NULL;
585 }
586 if (error)
587 *error = ret;
588 return st;
589}
590
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400591static void surround_rate_allocation(
592 OpusMSEncoder *st,
593 opus_int32 *rate,
594 int frame_size
595 )
596{
597 int i;
598 opus_int32 channel_rate;
599 opus_int32 Fs;
600 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400601 int stream_offset;
602 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400603 int coupled_ratio; /* Q8 */
604 int lfe_ratio; /* Q8 */
605
606 ptr = (char*)st + align(sizeof(OpusMSEncoder));
607 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
608
Jean-Marc Valin49587512013-07-07 02:50:18 -0400609 if (st->bitrate_bps > st->layout.nb_channels*40000)
610 stream_offset = 20000;
611 else
612 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400613 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
614 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400615 /* The LFE stream is an exception to the above and gets fewer bits. */
616 lfe_offset = 3500;
617 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
618 coupled_ratio = 512;
619 /* 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 -0400620 lfe_ratio = 32;
621
622 /* Compute bitrate allocation between streams */
623 if (st->bitrate_bps==OPUS_AUTO)
624 {
625 channel_rate = Fs+60*Fs/frame_size;
626 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
627 {
628 channel_rate = 300000;
629 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400630 int nb_lfe;
631 int nb_uncoupled;
632 int nb_coupled;
633 int total;
634 nb_lfe = (st->lfe_stream!=-1);
635 nb_coupled = st->layout.nb_coupled_streams;
636 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
637 total = (nb_uncoupled<<8) /* mono */
638 + coupled_ratio*nb_coupled /* stereo */
639 + nb_lfe*lfe_ratio;
640 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 -0400641 }
642#ifndef FIXED_POINT
643 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
644 {
645 opus_int32 bonus;
646 bonus = 60*(Fs/frame_size-50);
647 channel_rate += bonus;
648 }
649#endif
650
651 for (i=0;i<st->layout.nb_streams;i++)
652 {
653 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400654 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400655 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400656 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400657 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400658 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400659 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400660}
661
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500662/* Max size in case the encoder decides to return three frames */
663#define MS_FRAME_TMP (3*1275+7)
664static int opus_multistream_encode_native
665(
666 OpusMSEncoder *st,
667 opus_copy_channel_in_func copy_channel_in,
668 const void *pcm,
669 int frame_size,
670 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500671 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400672 int lsb_depth,
673 downmix_func downmix
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;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500687 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400688 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400689 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400690 opus_val32 *mem = NULL;
691 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500692 ALLOC_STACK;
693
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400694 if (st->surround)
695 {
696 preemph_mem = ms_get_preemph_mem(st);
697 mem = ms_get_window_mem(st);
698 }
699
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500700 ptr = (char*)st + align(sizeof(OpusMSEncoder));
701 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500702 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
703 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500704
705 if (400*frame_size < Fs)
706 {
707 RESTORE_STACK;
708 return OPUS_BAD_ARG;
709 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500710 /* Validate frame_size before using it to allocate stack space.
711 This mirrors the checks in opus_encode[_float](). */
712 if (400*frame_size != Fs && 200*frame_size != Fs &&
713 100*frame_size != Fs && 50*frame_size != Fs &&
714 25*frame_size != Fs && 50*frame_size != 3*Fs)
715 {
716 RESTORE_STACK;
717 return OPUS_BAD_ARG;
718 }
719 ALLOC(buf, 2*frame_size, opus_val16);
720 coupled_size = opus_encoder_get_size(2);
721 mono_size = opus_encoder_get_size(1);
722
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400723 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400724 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400725 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400726 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 -0400727 }
728
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500729 if (max_data_bytes < 4*st->layout.nb_streams-1)
730 {
731 RESTORE_STACK;
732 return OPUS_BUFFER_TOO_SMALL;
733 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500734
735 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400736 surround_rate_allocation(st, bitrates, frame_size);
737
Jean-Marc Valin74483662012-12-17 16:23:42 -0500738 ptr = (char*)st + align(sizeof(OpusMSEncoder));
739 for (s=0;s<st->layout.nb_streams;s++)
740 {
741 OpusEncoder *enc;
742 enc = (OpusEncoder*)ptr;
743 if (s < st->layout.nb_coupled_streams)
744 ptr += align(coupled_size);
745 else
746 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400747 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400748 if (st->surround)
749 {
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400750 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
751 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400752 {
753 /* To preserve the spatial image, force stereo CELT on coupled streams */
754 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400755 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400756 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400757 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500758 }
759
760 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500761 /* Counting ToC */
762 tot_size = 0;
763 for (s=0;s<st->layout.nb_streams;s++)
764 {
765 OpusEncoder *enc;
766 int len;
767 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400768 int c1, c2;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500769
770 opus_repacketizer_init(&rp);
771 enc = (OpusEncoder*)ptr;
772 if (s < st->layout.nb_coupled_streams)
773 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400774 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500775 int left, right;
776 left = get_left_channel(&st->layout, s, -1);
777 right = get_right_channel(&st->layout, s, -1);
778 (*copy_channel_in)(buf, 2,
779 pcm, st->layout.nb_channels, left, frame_size);
780 (*copy_channel_in)(buf+1, 2,
781 pcm, st->layout.nb_channels, right, frame_size);
782 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400783 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400784 {
785 for (i=0;i<21;i++)
786 {
787 bandLogE[i] = bandSMR[21*left+i];
788 bandLogE[21+i] = bandSMR[21*right+i];
789 }
790 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400791 c1 = left;
792 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500793 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400794 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500795 int chan = get_mono_channel(&st->layout, s, -1);
796 (*copy_channel_in)(buf, 1,
797 pcm, st->layout.nb_channels, chan, frame_size);
798 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400799 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400800 {
801 for (i=0;i<21;i++)
802 bandLogE[i] = bandSMR[21*chan+i];
803 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400804 c1 = chan;
805 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500806 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400807 if (st->surround)
808 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500809 /* number of bytes left (+Toc) */
810 curr_max = max_data_bytes - tot_size;
811 /* Reserve three bytes for the last stream and four for the others */
812 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
813 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400814 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 -0500815 if (len<0)
816 {
817 RESTORE_STACK;
818 return len;
819 }
820 /* We need to use the repacketizer to add the self-delimiting lengths
821 while taking into account the fact that the encoder can now return
822 more than one frame at a time (e.g. 60 ms CELT-only) */
823 opus_repacketizer_cat(&rp, tmp_data, len);
824 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);
825 data += len;
826 tot_size += len;
827 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400828 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500829 RESTORE_STACK;
830 return tot_size;
831
832}
833
Pedro Becerra1af7f952013-07-11 00:00:47 -0400834#if !defined(DISABLE_FLOAT_API)
835static void opus_copy_channel_in_float(
836 opus_val16 *dst,
837 int dst_stride,
838 const void *src,
839 int src_stride,
840 int src_channel,
841 int frame_size
842)
843{
844 const float *float_src;
845 opus_int32 i;
846 float_src = (const float *)src;
847 for (i=0;i<frame_size;i++)
848#if defined(FIXED_POINT)
849 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
850#else
851 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
852#endif
853}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500854#endif
855
856static void opus_copy_channel_in_short(
857 opus_val16 *dst,
858 int dst_stride,
859 const void *src,
860 int src_stride,
861 int src_channel,
862 int frame_size
863)
864{
865 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700866 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500867 short_src = (const opus_int16 *)src;
868 for (i=0;i<frame_size;i++)
869#if defined(FIXED_POINT)
870 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
871#else
872 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
873#endif
874}
875
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400876
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500877#ifdef FIXED_POINT
878int opus_multistream_encode(
879 OpusMSEncoder *st,
880 const opus_val16 *pcm,
881 int frame_size,
882 unsigned char *data,
883 opus_int32 max_data_bytes
884)
885{
886 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400887 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500888}
889
890#ifndef DISABLE_FLOAT_API
891int opus_multistream_encode_float(
892 OpusMSEncoder *st,
893 const float *pcm,
894 int frame_size,
895 unsigned char *data,
896 opus_int32 max_data_bytes
897)
898{
899 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400900 pcm, frame_size, data, max_data_bytes, 16, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500901}
902#endif
903
904#else
905
906int opus_multistream_encode_float
907(
908 OpusMSEncoder *st,
909 const opus_val16 *pcm,
910 int frame_size,
911 unsigned char *data,
912 opus_int32 max_data_bytes
913)
914{
915 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400916 pcm, frame_size, data, max_data_bytes, 24, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500917}
918
919int opus_multistream_encode(
920 OpusMSEncoder *st,
921 const opus_int16 *pcm,
922 int frame_size,
923 unsigned char *data,
924 opus_int32 max_data_bytes
925)
926{
927 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400928 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500929}
930#endif
931
932int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
933{
934 va_list ap;
935 int coupled_size, mono_size;
936 char *ptr;
937 int ret = OPUS_OK;
938
939 va_start(ap, request);
940
941 coupled_size = opus_encoder_get_size(2);
942 mono_size = opus_encoder_get_size(1);
943 ptr = (char*)st + align(sizeof(OpusMSEncoder));
944 switch (request)
945 {
946 case OPUS_SET_BITRATE_REQUEST:
947 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500948 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700949 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
950 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500951 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700952 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500953 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500954 }
955 break;
956 case OPUS_GET_BITRATE_REQUEST:
957 {
958 int s;
959 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700960 if (!value)
961 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700962 goto bad_arg;
963 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500964 *value = 0;
965 for (s=0;s<st->layout.nb_streams;s++)
966 {
967 opus_int32 rate;
968 OpusEncoder *enc;
969 enc = (OpusEncoder*)ptr;
970 if (s < st->layout.nb_coupled_streams)
971 ptr += align(coupled_size);
972 else
973 ptr += align(mono_size);
974 opus_encoder_ctl(enc, request, &rate);
975 *value += rate;
976 }
977 }
978 break;
979 case OPUS_GET_LSB_DEPTH_REQUEST:
980 case OPUS_GET_VBR_REQUEST:
981 case OPUS_GET_APPLICATION_REQUEST:
982 case OPUS_GET_BANDWIDTH_REQUEST:
983 case OPUS_GET_COMPLEXITY_REQUEST:
984 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
985 case OPUS_GET_DTX_REQUEST:
986 case OPUS_GET_VOICE_RATIO_REQUEST:
987 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
988 case OPUS_GET_SIGNAL_REQUEST:
989 case OPUS_GET_LOOKAHEAD_REQUEST:
990 case OPUS_GET_SAMPLE_RATE_REQUEST:
991 case OPUS_GET_INBAND_FEC_REQUEST:
992 case OPUS_GET_FORCE_CHANNELS_REQUEST:
993 {
994 OpusEncoder *enc;
995 /* For int32* GET params, just query the first stream */
996 opus_int32 *value = va_arg(ap, opus_int32*);
997 enc = (OpusEncoder*)ptr;
998 ret = opus_encoder_ctl(enc, request, value);
999 }
1000 break;
1001 case OPUS_GET_FINAL_RANGE_REQUEST:
1002 {
1003 int s;
1004 opus_uint32 *value = va_arg(ap, opus_uint32*);
1005 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001006 if (!value)
1007 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001008 goto bad_arg;
1009 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001010 *value=0;
1011 for (s=0;s<st->layout.nb_streams;s++)
1012 {
1013 OpusEncoder *enc;
1014 enc = (OpusEncoder*)ptr;
1015 if (s < st->layout.nb_coupled_streams)
1016 ptr += align(coupled_size);
1017 else
1018 ptr += align(mono_size);
1019 ret = opus_encoder_ctl(enc, request, &tmp);
1020 if (ret != OPUS_OK) break;
1021 *value ^= tmp;
1022 }
1023 }
1024 break;
1025 case OPUS_SET_LSB_DEPTH_REQUEST:
1026 case OPUS_SET_COMPLEXITY_REQUEST:
1027 case OPUS_SET_VBR_REQUEST:
1028 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001029 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001030 case OPUS_SET_BANDWIDTH_REQUEST:
1031 case OPUS_SET_SIGNAL_REQUEST:
1032 case OPUS_SET_APPLICATION_REQUEST:
1033 case OPUS_SET_INBAND_FEC_REQUEST:
1034 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1035 case OPUS_SET_DTX_REQUEST:
1036 case OPUS_SET_FORCE_MODE_REQUEST:
1037 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1038 {
1039 int s;
1040 /* This works for int32 params */
1041 opus_int32 value = va_arg(ap, opus_int32);
1042 for (s=0;s<st->layout.nb_streams;s++)
1043 {
1044 OpusEncoder *enc;
1045
1046 enc = (OpusEncoder*)ptr;
1047 if (s < st->layout.nb_coupled_streams)
1048 ptr += align(coupled_size);
1049 else
1050 ptr += align(mono_size);
1051 ret = opus_encoder_ctl(enc, request, value);
1052 if (ret != OPUS_OK)
1053 break;
1054 }
1055 }
1056 break;
1057 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1058 {
1059 int s;
1060 opus_int32 stream_id;
1061 OpusEncoder **value;
1062 stream_id = va_arg(ap, opus_int32);
1063 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1064 ret = OPUS_BAD_ARG;
1065 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001066 if (!value)
1067 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001068 goto bad_arg;
1069 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001070 for (s=0;s<stream_id;s++)
1071 {
1072 if (s < st->layout.nb_coupled_streams)
1073 ptr += align(coupled_size);
1074 else
1075 ptr += align(mono_size);
1076 }
1077 *value = (OpusEncoder*)ptr;
1078 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001079 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001080 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001081 {
1082 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001083 st->variable_duration = value;
1084 }
1085 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001086 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001087 {
1088 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001089 if (!value)
1090 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001091 goto bad_arg;
1092 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001093 *value = st->variable_duration;
1094 }
1095 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001096 default:
1097 ret = OPUS_UNIMPLEMENTED;
1098 break;
1099 }
1100
1101 va_end(ap);
1102 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001103bad_arg:
1104 va_end(ap);
1105 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001106}
1107
1108void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1109{
1110 opus_free(st);
1111}