blob: 32c6f0aa0f7717b51696ac57d02fcbaa69c3734d [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 Valin6fbfed62013-09-13 17:16:38 -0400750 opus_int32 equiv_rate;
751 equiv_rate = st->bitrate_bps;
752 if (frame_size*50 < Fs)
753 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
754 if (equiv_rate > 112000)
755 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
756 else if (equiv_rate > 76000)
757 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
758 else if (equiv_rate > 48000)
759 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
760 else
761 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400762 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400763 {
764 /* To preserve the spatial image, force stereo CELT on coupled streams */
765 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400766 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400767 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400768 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500769 }
770
771 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500772 /* Counting ToC */
773 tot_size = 0;
774 for (s=0;s<st->layout.nb_streams;s++)
775 {
776 OpusEncoder *enc;
777 int len;
778 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400779 int c1, c2;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500780
781 opus_repacketizer_init(&rp);
782 enc = (OpusEncoder*)ptr;
783 if (s < st->layout.nb_coupled_streams)
784 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400785 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500786 int left, right;
787 left = get_left_channel(&st->layout, s, -1);
788 right = get_right_channel(&st->layout, s, -1);
789 (*copy_channel_in)(buf, 2,
790 pcm, st->layout.nb_channels, left, frame_size);
791 (*copy_channel_in)(buf+1, 2,
792 pcm, st->layout.nb_channels, right, frame_size);
793 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400794 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400795 {
796 for (i=0;i<21;i++)
797 {
798 bandLogE[i] = bandSMR[21*left+i];
799 bandLogE[21+i] = bandSMR[21*right+i];
800 }
801 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400802 c1 = left;
803 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500804 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400805 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500806 int chan = get_mono_channel(&st->layout, s, -1);
807 (*copy_channel_in)(buf, 1,
808 pcm, st->layout.nb_channels, chan, frame_size);
809 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400810 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400811 {
812 for (i=0;i<21;i++)
813 bandLogE[i] = bandSMR[21*chan+i];
814 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400815 c1 = chan;
816 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500817 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400818 if (st->surround)
819 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500820 /* number of bytes left (+Toc) */
821 curr_max = max_data_bytes - tot_size;
822 /* Reserve three bytes for the last stream and four for the others */
823 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
824 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400825 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 -0500826 if (len<0)
827 {
828 RESTORE_STACK;
829 return len;
830 }
831 /* We need to use the repacketizer to add the self-delimiting lengths
832 while taking into account the fact that the encoder can now return
833 more than one frame at a time (e.g. 60 ms CELT-only) */
834 opus_repacketizer_cat(&rp, tmp_data, len);
835 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);
836 data += len;
837 tot_size += len;
838 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400839 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500840 RESTORE_STACK;
841 return tot_size;
842
843}
844
Pedro Becerra1af7f952013-07-11 00:00:47 -0400845#if !defined(DISABLE_FLOAT_API)
846static void opus_copy_channel_in_float(
847 opus_val16 *dst,
848 int dst_stride,
849 const void *src,
850 int src_stride,
851 int src_channel,
852 int frame_size
853)
854{
855 const float *float_src;
856 opus_int32 i;
857 float_src = (const float *)src;
858 for (i=0;i<frame_size;i++)
859#if defined(FIXED_POINT)
860 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
861#else
862 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
863#endif
864}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500865#endif
866
867static void opus_copy_channel_in_short(
868 opus_val16 *dst,
869 int dst_stride,
870 const void *src,
871 int src_stride,
872 int src_channel,
873 int frame_size
874)
875{
876 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700877 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500878 short_src = (const opus_int16 *)src;
879 for (i=0;i<frame_size;i++)
880#if defined(FIXED_POINT)
881 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
882#else
883 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
884#endif
885}
886
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400887
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500888#ifdef FIXED_POINT
889int opus_multistream_encode(
890 OpusMSEncoder *st,
891 const opus_val16 *pcm,
892 int frame_size,
893 unsigned char *data,
894 opus_int32 max_data_bytes
895)
896{
897 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400898 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500899}
900
901#ifndef DISABLE_FLOAT_API
902int opus_multistream_encode_float(
903 OpusMSEncoder *st,
904 const float *pcm,
905 int frame_size,
906 unsigned char *data,
907 opus_int32 max_data_bytes
908)
909{
910 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400911 pcm, frame_size, data, max_data_bytes, 16, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500912}
913#endif
914
915#else
916
917int opus_multistream_encode_float
918(
919 OpusMSEncoder *st,
920 const opus_val16 *pcm,
921 int frame_size,
922 unsigned char *data,
923 opus_int32 max_data_bytes
924)
925{
926 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400927 pcm, frame_size, data, max_data_bytes, 24, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500928}
929
930int opus_multistream_encode(
931 OpusMSEncoder *st,
932 const opus_int16 *pcm,
933 int frame_size,
934 unsigned char *data,
935 opus_int32 max_data_bytes
936)
937{
938 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400939 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500940}
941#endif
942
943int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
944{
945 va_list ap;
946 int coupled_size, mono_size;
947 char *ptr;
948 int ret = OPUS_OK;
949
950 va_start(ap, request);
951
952 coupled_size = opus_encoder_get_size(2);
953 mono_size = opus_encoder_get_size(1);
954 ptr = (char*)st + align(sizeof(OpusMSEncoder));
955 switch (request)
956 {
957 case OPUS_SET_BITRATE_REQUEST:
958 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500959 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700960 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
961 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500962 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700963 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500964 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500965 }
966 break;
967 case OPUS_GET_BITRATE_REQUEST:
968 {
969 int s;
970 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700971 if (!value)
972 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700973 goto bad_arg;
974 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500975 *value = 0;
976 for (s=0;s<st->layout.nb_streams;s++)
977 {
978 opus_int32 rate;
979 OpusEncoder *enc;
980 enc = (OpusEncoder*)ptr;
981 if (s < st->layout.nb_coupled_streams)
982 ptr += align(coupled_size);
983 else
984 ptr += align(mono_size);
985 opus_encoder_ctl(enc, request, &rate);
986 *value += rate;
987 }
988 }
989 break;
990 case OPUS_GET_LSB_DEPTH_REQUEST:
991 case OPUS_GET_VBR_REQUEST:
992 case OPUS_GET_APPLICATION_REQUEST:
993 case OPUS_GET_BANDWIDTH_REQUEST:
994 case OPUS_GET_COMPLEXITY_REQUEST:
995 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
996 case OPUS_GET_DTX_REQUEST:
997 case OPUS_GET_VOICE_RATIO_REQUEST:
998 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
999 case OPUS_GET_SIGNAL_REQUEST:
1000 case OPUS_GET_LOOKAHEAD_REQUEST:
1001 case OPUS_GET_SAMPLE_RATE_REQUEST:
1002 case OPUS_GET_INBAND_FEC_REQUEST:
1003 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1004 {
1005 OpusEncoder *enc;
1006 /* For int32* GET params, just query the first stream */
1007 opus_int32 *value = va_arg(ap, opus_int32*);
1008 enc = (OpusEncoder*)ptr;
1009 ret = opus_encoder_ctl(enc, request, value);
1010 }
1011 break;
1012 case OPUS_GET_FINAL_RANGE_REQUEST:
1013 {
1014 int s;
1015 opus_uint32 *value = va_arg(ap, opus_uint32*);
1016 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001017 if (!value)
1018 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001019 goto bad_arg;
1020 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001021 *value=0;
1022 for (s=0;s<st->layout.nb_streams;s++)
1023 {
1024 OpusEncoder *enc;
1025 enc = (OpusEncoder*)ptr;
1026 if (s < st->layout.nb_coupled_streams)
1027 ptr += align(coupled_size);
1028 else
1029 ptr += align(mono_size);
1030 ret = opus_encoder_ctl(enc, request, &tmp);
1031 if (ret != OPUS_OK) break;
1032 *value ^= tmp;
1033 }
1034 }
1035 break;
1036 case OPUS_SET_LSB_DEPTH_REQUEST:
1037 case OPUS_SET_COMPLEXITY_REQUEST:
1038 case OPUS_SET_VBR_REQUEST:
1039 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001040 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001041 case OPUS_SET_BANDWIDTH_REQUEST:
1042 case OPUS_SET_SIGNAL_REQUEST:
1043 case OPUS_SET_APPLICATION_REQUEST:
1044 case OPUS_SET_INBAND_FEC_REQUEST:
1045 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1046 case OPUS_SET_DTX_REQUEST:
1047 case OPUS_SET_FORCE_MODE_REQUEST:
1048 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1049 {
1050 int s;
1051 /* This works for int32 params */
1052 opus_int32 value = va_arg(ap, opus_int32);
1053 for (s=0;s<st->layout.nb_streams;s++)
1054 {
1055 OpusEncoder *enc;
1056
1057 enc = (OpusEncoder*)ptr;
1058 if (s < st->layout.nb_coupled_streams)
1059 ptr += align(coupled_size);
1060 else
1061 ptr += align(mono_size);
1062 ret = opus_encoder_ctl(enc, request, value);
1063 if (ret != OPUS_OK)
1064 break;
1065 }
1066 }
1067 break;
1068 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1069 {
1070 int s;
1071 opus_int32 stream_id;
1072 OpusEncoder **value;
1073 stream_id = va_arg(ap, opus_int32);
1074 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1075 ret = OPUS_BAD_ARG;
1076 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001077 if (!value)
1078 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001079 goto bad_arg;
1080 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001081 for (s=0;s<stream_id;s++)
1082 {
1083 if (s < st->layout.nb_coupled_streams)
1084 ptr += align(coupled_size);
1085 else
1086 ptr += align(mono_size);
1087 }
1088 *value = (OpusEncoder*)ptr;
1089 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001090 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001091 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001092 {
1093 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001094 st->variable_duration = value;
1095 }
1096 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001097 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001098 {
1099 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001100 if (!value)
1101 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001102 goto bad_arg;
1103 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001104 *value = st->variable_duration;
1105 }
1106 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001107 default:
1108 ret = OPUS_UNIMPLEMENTED;
1109 break;
1110 }
1111
1112 va_end(ap);
1113 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001114bad_arg:
1115 va_end(ap);
1116 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001117}
1118
1119void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1120{
1121 opus_free(st);
1122}