blob: 31447bf9c19383890e96baaca2eac4c1a20e53a6 [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 Valinb90e63b2013-09-16 13:08:52 -040075 int application;
Jean-Marc Valin74483662012-12-17 16:23:42 -050076 int variable_duration;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -040077 int surround;
Jean-Marc Valin74483662012-12-17 16:23:42 -050078 opus_int32 bitrate_bps;
79 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050080 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040081 /* then opus_val32 window_mem[channels*120]; */
82 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050083};
84
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040085static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
86{
87 int s;
88 char *ptr;
89 int coupled_size, mono_size;
90
91 coupled_size = opus_encoder_get_size(2);
92 mono_size = opus_encoder_get_size(1);
93 ptr = (char*)st + align(sizeof(OpusMSEncoder));
94 for (s=0;s<st->layout.nb_streams;s++)
95 {
96 if (s < st->layout.nb_coupled_streams)
97 ptr += align(coupled_size);
98 else
99 ptr += align(mono_size);
100 }
101 return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
102}
103
104static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
105{
106 int s;
107 char *ptr;
108 int coupled_size, mono_size;
109
110 coupled_size = opus_encoder_get_size(2);
111 mono_size = opus_encoder_get_size(1);
112 ptr = (char*)st + align(sizeof(OpusMSEncoder));
113 for (s=0;s<st->layout.nb_streams;s++)
114 {
115 if (s < st->layout.nb_coupled_streams)
116 ptr += align(coupled_size);
117 else
118 ptr += align(mono_size);
119 }
120 return (opus_val32*)ptr;
121}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500122
123static int validate_encoder_layout(const ChannelLayout *layout)
124{
125 int s;
126 for (s=0;s<layout->nb_streams;s++)
127 {
128 if (s < layout->nb_coupled_streams)
129 {
130 if (get_left_channel(layout, s, -1)==-1)
131 return 0;
132 if (get_right_channel(layout, s, -1)==-1)
133 return 0;
134 } else {
135 if (get_mono_channel(layout, s, -1)==-1)
136 return 0;
137 }
138 }
139 return 1;
140}
141
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400142static void channel_pos(int channels, int pos[8])
143{
144 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
145 if (channels==4)
146 {
147 pos[0]=1;
148 pos[1]=3;
149 pos[2]=1;
150 pos[3]=3;
151 } else if (channels==3||channels==5||channels==6)
152 {
153 pos[0]=1;
154 pos[1]=2;
155 pos[2]=3;
156 pos[3]=1;
157 pos[4]=3;
158 pos[5]=0;
159 } else if (channels==7)
160 {
161 pos[0]=1;
162 pos[1]=2;
163 pos[2]=3;
164 pos[3]=1;
165 pos[4]=3;
166 pos[5]=2;
167 pos[6]=0;
168 } else if (channels==8)
169 {
170 pos[0]=1;
171 pos[1]=2;
172 pos[2]=3;
173 pos[3]=1;
174 pos[4]=3;
175 pos[5]=1;
176 pos[6]=3;
177 pos[7]=0;
178 }
179}
180
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400181#if 1
182/* Computes a rough approximation of log2(2^a + 2^b) */
183static opus_val16 logSum(opus_val16 a, opus_val16 b)
184{
185 opus_val16 max;
186 opus_val32 diff;
187 opus_val16 frac;
188 static const opus_val16 diff_table[17] = {
189 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
190 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
191 QCONST16(0.0028123f, DB_SHIFT)
192 };
193 int low;
194 if (a>b)
195 {
196 max = a;
197 diff = SUB32(EXTEND32(a),EXTEND32(b));
198 } else {
199 max = b;
200 diff = SUB32(EXTEND32(b),EXTEND32(a));
201 }
202 if (diff >= QCONST16(8.f, DB_SHIFT))
203 return max;
204#ifdef FIXED_POINT
205 low = SHR32(diff, DB_SHIFT-1);
206 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
207#else
208 low = floor(2*diff);
209 frac = 2*diff - low;
210#endif
211 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
212}
213#else
214opus_val16 logSum(opus_val16 a, opus_val16 b)
215{
216 return log2(pow(4, a)+ pow(4, b))/2;
217}
218#endif
219
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400220void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
221 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
222)
223{
224 int c;
225 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400226 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400227 int pos[8] = {0};
228 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400229 int frame_size;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400230 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400231 opus_val16 maskLogE[3][21];
232 VARDECL(opus_val32, in);
233 VARDECL(opus_val16, x);
234 VARDECL(opus_val32, out);
235 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400236
237 upsample = resampling_factor(rate);
238 frame_size = len*upsample;
239
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400240 for (LM=0;LM<=celt_mode->maxLM;LM++)
241 if (celt_mode->shortMdctSize<<LM==frame_size)
242 break;
243
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400244 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400245 ALLOC(x, len, opus_val16);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400246 ALLOC(freq, frame_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400247
248 channel_pos(channels, pos);
249
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400250 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400251 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400252 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400253
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400254 for (c=0;c<channels;c++)
255 {
256 OPUS_COPY(in, mem+c*overlap, overlap);
257 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400258 preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400259 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
260 if (upsample != 1)
261 {
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400262 int bound = len;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400263 for (i=0;i<bound;i++)
264 freq[i] *= upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400265 for (;i<frame_size;i++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400266 freq[i] = 0;
267 }
268
269 compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400270 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400271 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
272 for (i=1;i<21;i++)
273 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
274 for (i=19;i>=0;i--)
275 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 -0400276 if (pos[c]==1)
277 {
278 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400279 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400280 } else if (pos[c]==3)
281 {
282 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400283 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400284 } else if (pos[c]==2)
285 {
286 for (i=0;i<21;i++)
287 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400288 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
289 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400290 }
291 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400292#if 0
293 for (i=0;i<21;i++)
294 printf("%f ", bandLogE[21*c+i]);
295//#else
296 float sum=0;
297 for (i=0;i<21;i++)
298 sum += bandLogE[21*c+i];
299 printf("%f ", sum/21);
300#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400301 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400302 }
303 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400304 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400305 for (c=0;c<3;c++)
306 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400307 maskLogE[c][i] += QCONST16(.5f, DB_SHIFT)*log2(2.f/(channels-1));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400308#if 0
309 for (c=0;c<3;c++)
310 {
311 for (i=0;i<21;i++)
312 printf("%f ", maskLogE[c][i]);
313 }
314#endif
315 for (c=0;c<channels;c++)
316 {
317 opus_val16 *mask;
318 if (pos[c]!=0)
319 {
320 mask = &maskLogE[pos[c]-1][0];
321 for (i=0;i<21;i++)
322 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
323 } else {
324 for (i=0;i<21;i++)
325 bandLogE[21*c+i] = 0;
326 }
327#if 0
328 for (i=0;i<21;i++)
329 printf("%f ", bandLogE[21*c+i]);
330 printf("\n");
331#endif
332#if 0
333 float sum=0;
334 for (i=0;i<21;i++)
335 sum += bandLogE[21*c+i];
336 printf("%f ", sum/21);
337 printf("\n");
338#endif
339 }
340 RESTORE_STACK;
341}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500342
343opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
344{
345 int coupled_size;
346 int mono_size;
347
348 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
349 coupled_size = opus_encoder_get_size(2);
350 mono_size = opus_encoder_get_size(1);
351 return align(sizeof(OpusMSEncoder))
352 + nb_coupled_streams * align(coupled_size)
353 + (nb_streams-nb_coupled_streams) * align(mono_size);
354}
355
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400356opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
357{
358 int nb_streams;
359 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400360 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400361
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400362 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400363 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400364 if (channels==1)
365 {
366 nb_streams=1;
367 nb_coupled_streams=0;
368 } else if (channels==2)
369 {
370 nb_streams=1;
371 nb_coupled_streams=1;
372 } else
373 return 0;
374 } else if (mapping_family==1 && channels<=8 && channels>=1)
375 {
376 nb_streams=vorbis_mappings[channels-1].nb_streams;
377 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
378 } else if (mapping_family==255)
379 {
380 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400381 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400382 } else
383 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400384 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
385 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400386 {
387 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
388 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400389 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400390}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500391
392
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400393static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500394 OpusMSEncoder *st,
395 opus_int32 Fs,
396 int channels,
397 int streams,
398 int coupled_streams,
399 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400400 int application,
401 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500402)
403{
404 int coupled_size;
405 int mono_size;
406 int i, ret;
407 char *ptr;
408
409 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
410 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
411 return OPUS_BAD_ARG;
412
413 st->layout.nb_channels = channels;
414 st->layout.nb_streams = streams;
415 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400416 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400417 if (!surround)
418 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500419 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400420 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500421 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500422 for (i=0;i<st->layout.nb_channels;i++)
423 st->layout.mapping[i] = mapping[i];
424 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
425 return OPUS_BAD_ARG;
426 ptr = (char*)st + align(sizeof(OpusMSEncoder));
427 coupled_size = opus_encoder_get_size(2);
428 mono_size = opus_encoder_get_size(1);
429
430 for (i=0;i<st->layout.nb_coupled_streams;i++)
431 {
432 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400433 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400434 if (i==st->lfe_stream)
435 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500436 ptr += align(coupled_size);
437 }
438 for (;i<st->layout.nb_streams;i++)
439 {
440 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400441 if (i==st->lfe_stream)
442 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500443 if(ret!=OPUS_OK)return ret;
444 ptr += align(mono_size);
445 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400446 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400447 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400448 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
449 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400450 }
451 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500452 return OPUS_OK;
453}
454
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400455int opus_multistream_encoder_init(
456 OpusMSEncoder *st,
457 opus_int32 Fs,
458 int channels,
459 int streams,
460 int coupled_streams,
461 const unsigned char *mapping,
462 int application
463)
464{
465 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
466}
467
468int opus_multistream_surround_encoder_init(
469 OpusMSEncoder *st,
470 opus_int32 Fs,
471 int channels,
472 int mapping_family,
473 int *streams,
474 int *coupled_streams,
475 unsigned char *mapping,
476 int application
477)
478{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400479 if ((channels>255) || (channels<1))
480 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400481 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400482 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400483 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400484 if (channels==1)
485 {
486 *streams=1;
487 *coupled_streams=0;
488 mapping[0]=0;
489 } else if (channels==2)
490 {
491 *streams=1;
492 *coupled_streams=1;
493 mapping[0]=0;
494 mapping[1]=1;
495 } else
496 return OPUS_UNIMPLEMENTED;
497 } else if (mapping_family==1 && channels<=8 && channels>=1)
498 {
499 int i;
500 *streams=vorbis_mappings[channels-1].nb_streams;
501 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
502 for (i=0;i<channels;i++)
503 mapping[i] = vorbis_mappings[channels-1].mapping[i];
504 if (channels>=6)
505 st->lfe_stream = *streams-1;
506 } else if (mapping_family==255)
507 {
508 int i;
509 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400510 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400511 for(i=0;i<channels;i++)
512 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400513 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400514 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400515 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400516 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400517}
518
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500519OpusMSEncoder *opus_multistream_encoder_create(
520 opus_int32 Fs,
521 int channels,
522 int streams,
523 int coupled_streams,
524 const unsigned char *mapping,
525 int application,
526 int *error
527)
528{
529 int ret;
530 OpusMSEncoder *st;
531 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
532 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
533 {
534 if (error)
535 *error = OPUS_BAD_ARG;
536 return NULL;
537 }
538 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
539 if (st==NULL)
540 {
541 if (error)
542 *error = OPUS_ALLOC_FAIL;
543 return NULL;
544 }
545 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
546 if (ret != OPUS_OK)
547 {
548 opus_free(st);
549 st = NULL;
550 }
551 if (error)
552 *error = ret;
553 return st;
554}
555
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400556OpusMSEncoder *opus_multistream_surround_encoder_create(
557 opus_int32 Fs,
558 int channels,
559 int mapping_family,
560 int *streams,
561 int *coupled_streams,
562 unsigned char *mapping,
563 int application,
564 int *error
565)
566{
567 int ret;
568 OpusMSEncoder *st;
569 if ((channels>255) || (channels<1))
570 {
571 if (error)
572 *error = OPUS_BAD_ARG;
573 return NULL;
574 }
575 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
576 if (st==NULL)
577 {
578 if (error)
579 *error = OPUS_ALLOC_FAIL;
580 return NULL;
581 }
582 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
583 if (ret != OPUS_OK)
584 {
585 opus_free(st);
586 st = NULL;
587 }
588 if (error)
589 *error = ret;
590 return st;
591}
592
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400593static void surround_rate_allocation(
594 OpusMSEncoder *st,
595 opus_int32 *rate,
596 int frame_size
597 )
598{
599 int i;
600 opus_int32 channel_rate;
601 opus_int32 Fs;
602 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400603 int stream_offset;
604 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400605 int coupled_ratio; /* Q8 */
606 int lfe_ratio; /* Q8 */
607
608 ptr = (char*)st + align(sizeof(OpusMSEncoder));
609 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
610
Jean-Marc Valin49587512013-07-07 02:50:18 -0400611 if (st->bitrate_bps > st->layout.nb_channels*40000)
612 stream_offset = 20000;
613 else
614 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400615 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
616 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400617 /* The LFE stream is an exception to the above and gets fewer bits. */
618 lfe_offset = 3500;
619 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
620 coupled_ratio = 512;
621 /* 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 -0400622 lfe_ratio = 32;
623
624 /* Compute bitrate allocation between streams */
625 if (st->bitrate_bps==OPUS_AUTO)
626 {
627 channel_rate = Fs+60*Fs/frame_size;
628 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
629 {
630 channel_rate = 300000;
631 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400632 int nb_lfe;
633 int nb_uncoupled;
634 int nb_coupled;
635 int total;
636 nb_lfe = (st->lfe_stream!=-1);
637 nb_coupled = st->layout.nb_coupled_streams;
638 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
639 total = (nb_uncoupled<<8) /* mono */
640 + coupled_ratio*nb_coupled /* stereo */
641 + nb_lfe*lfe_ratio;
642 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 -0400643 }
644#ifndef FIXED_POINT
645 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
646 {
647 opus_int32 bonus;
648 bonus = 60*(Fs/frame_size-50);
649 channel_rate += bonus;
650 }
651#endif
652
653 for (i=0;i<st->layout.nb_streams;i++)
654 {
655 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400656 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400657 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400658 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400659 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400660 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400661 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400662}
663
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500664/* Max size in case the encoder decides to return three frames */
665#define MS_FRAME_TMP (3*1275+7)
666static int opus_multistream_encode_native
667(
668 OpusMSEncoder *st,
669 opus_copy_channel_in_func copy_channel_in,
670 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400671 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500672 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500673 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400674 int lsb_depth,
675 downmix_func downmix
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500676)
677{
678 opus_int32 Fs;
679 int coupled_size;
680 int mono_size;
681 int s;
682 char *ptr;
683 int tot_size;
684 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400685 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500686 unsigned char tmp_data[MS_FRAME_TMP];
687 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500688 opus_int32 complexity;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500689 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400690 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400691 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400692 opus_val32 *mem = NULL;
693 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400694 int frame_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500695 ALLOC_STACK;
696
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400697 if (st->surround)
698 {
699 preemph_mem = ms_get_preemph_mem(st);
700 mem = ms_get_window_mem(st);
701 }
702
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500703 ptr = (char*)st + align(sizeof(OpusMSEncoder));
704 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500705 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
706 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500707
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400708 {
709 opus_int32 delay_compensation;
710 int channels;
711
712 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
713 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
714 delay_compensation -= Fs/400;
715 frame_size = compute_frame_size(pcm, analysis_frame_size,
716 st->variable_duration, channels, Fs, st->bitrate_bps,
717 delay_compensation, downmix, st->subframe_mem);
718 }
719
Jean-Marc Valin74483662012-12-17 16:23:42 -0500720 if (400*frame_size < Fs)
721 {
722 RESTORE_STACK;
723 return OPUS_BAD_ARG;
724 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500725 /* Validate frame_size before using it to allocate stack space.
726 This mirrors the checks in opus_encode[_float](). */
727 if (400*frame_size != Fs && 200*frame_size != Fs &&
728 100*frame_size != Fs && 50*frame_size != Fs &&
729 25*frame_size != Fs && 50*frame_size != 3*Fs)
730 {
731 RESTORE_STACK;
732 return OPUS_BAD_ARG;
733 }
734 ALLOC(buf, 2*frame_size, opus_val16);
735 coupled_size = opus_encoder_get_size(2);
736 mono_size = opus_encoder_get_size(1);
737
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400738 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400739 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400740 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400741 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 -0400742 }
743
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500744 if (max_data_bytes < 4*st->layout.nb_streams-1)
745 {
746 RESTORE_STACK;
747 return OPUS_BUFFER_TOO_SMALL;
748 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500749
750 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400751 surround_rate_allocation(st, bitrates, frame_size);
752
Jean-Marc Valin74483662012-12-17 16:23:42 -0500753 ptr = (char*)st + align(sizeof(OpusMSEncoder));
754 for (s=0;s<st->layout.nb_streams;s++)
755 {
756 OpusEncoder *enc;
757 enc = (OpusEncoder*)ptr;
758 if (s < st->layout.nb_coupled_streams)
759 ptr += align(coupled_size);
760 else
761 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400762 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400763 if (st->surround)
764 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400765 opus_int32 equiv_rate;
766 equiv_rate = st->bitrate_bps;
767 if (frame_size*50 < Fs)
768 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
769 if (equiv_rate > 112000)
770 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
771 else if (equiv_rate > 76000)
772 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
773 else if (equiv_rate > 48000)
774 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
775 else
776 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400777 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400778 {
779 /* To preserve the spatial image, force stereo CELT on coupled streams */
780 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400781 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400782 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400783 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500784 }
785
786 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500787 /* Counting ToC */
788 tot_size = 0;
789 for (s=0;s<st->layout.nb_streams;s++)
790 {
791 OpusEncoder *enc;
792 int len;
793 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400794 int c1, c2;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500795
796 opus_repacketizer_init(&rp);
797 enc = (OpusEncoder*)ptr;
798 if (s < st->layout.nb_coupled_streams)
799 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400800 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500801 int left, right;
802 left = get_left_channel(&st->layout, s, -1);
803 right = get_right_channel(&st->layout, s, -1);
804 (*copy_channel_in)(buf, 2,
805 pcm, st->layout.nb_channels, left, frame_size);
806 (*copy_channel_in)(buf+1, 2,
807 pcm, st->layout.nb_channels, right, frame_size);
808 ptr += align(coupled_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 {
813 bandLogE[i] = bandSMR[21*left+i];
814 bandLogE[21+i] = bandSMR[21*right+i];
815 }
816 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400817 c1 = left;
818 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500819 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400820 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500821 int chan = get_mono_channel(&st->layout, s, -1);
822 (*copy_channel_in)(buf, 1,
823 pcm, st->layout.nb_channels, chan, frame_size);
824 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400825 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400826 {
827 for (i=0;i<21;i++)
828 bandLogE[i] = bandSMR[21*chan+i];
829 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400830 c1 = chan;
831 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500832 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400833 if (st->surround)
834 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500835 /* number of bytes left (+Toc) */
836 curr_max = max_data_bytes - tot_size;
837 /* Reserve three bytes for the last stream and four for the others */
838 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
839 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400840 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
841 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500842 if (len<0)
843 {
844 RESTORE_STACK;
845 return len;
846 }
847 /* We need to use the repacketizer to add the self-delimiting lengths
848 while taking into account the fact that the encoder can now return
849 more than one frame at a time (e.g. 60 ms CELT-only) */
850 opus_repacketizer_cat(&rp, tmp_data, len);
851 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);
852 data += len;
853 tot_size += len;
854 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400855 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500856 RESTORE_STACK;
857 return tot_size;
858
859}
860
Pedro Becerra1af7f952013-07-11 00:00:47 -0400861#if !defined(DISABLE_FLOAT_API)
862static void opus_copy_channel_in_float(
863 opus_val16 *dst,
864 int dst_stride,
865 const void *src,
866 int src_stride,
867 int src_channel,
868 int frame_size
869)
870{
871 const float *float_src;
872 opus_int32 i;
873 float_src = (const float *)src;
874 for (i=0;i<frame_size;i++)
875#if defined(FIXED_POINT)
876 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
877#else
878 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
879#endif
880}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500881#endif
882
883static void opus_copy_channel_in_short(
884 opus_val16 *dst,
885 int dst_stride,
886 const void *src,
887 int src_stride,
888 int src_channel,
889 int frame_size
890)
891{
892 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700893 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500894 short_src = (const opus_int16 *)src;
895 for (i=0;i<frame_size;i++)
896#if defined(FIXED_POINT)
897 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
898#else
899 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
900#endif
901}
902
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400903
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500904#ifdef FIXED_POINT
905int opus_multistream_encode(
906 OpusMSEncoder *st,
907 const opus_val16 *pcm,
908 int frame_size,
909 unsigned char *data,
910 opus_int32 max_data_bytes
911)
912{
913 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400914 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500915}
916
917#ifndef DISABLE_FLOAT_API
918int opus_multistream_encode_float(
919 OpusMSEncoder *st,
920 const float *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, 16, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500928}
929#endif
930
931#else
932
933int opus_multistream_encode_float
934(
935 OpusMSEncoder *st,
936 const opus_val16 *pcm,
937 int frame_size,
938 unsigned char *data,
939 opus_int32 max_data_bytes
940)
941{
942 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400943 pcm, frame_size, data, max_data_bytes, 24, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500944}
945
946int opus_multistream_encode(
947 OpusMSEncoder *st,
948 const opus_int16 *pcm,
949 int frame_size,
950 unsigned char *data,
951 opus_int32 max_data_bytes
952)
953{
954 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400955 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500956}
957#endif
958
959int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
960{
961 va_list ap;
962 int coupled_size, mono_size;
963 char *ptr;
964 int ret = OPUS_OK;
965
966 va_start(ap, request);
967
968 coupled_size = opus_encoder_get_size(2);
969 mono_size = opus_encoder_get_size(1);
970 ptr = (char*)st + align(sizeof(OpusMSEncoder));
971 switch (request)
972 {
973 case OPUS_SET_BITRATE_REQUEST:
974 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500975 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700976 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
977 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500978 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700979 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500980 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500981 }
982 break;
983 case OPUS_GET_BITRATE_REQUEST:
984 {
985 int s;
986 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700987 if (!value)
988 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700989 goto bad_arg;
990 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500991 *value = 0;
992 for (s=0;s<st->layout.nb_streams;s++)
993 {
994 opus_int32 rate;
995 OpusEncoder *enc;
996 enc = (OpusEncoder*)ptr;
997 if (s < st->layout.nb_coupled_streams)
998 ptr += align(coupled_size);
999 else
1000 ptr += align(mono_size);
1001 opus_encoder_ctl(enc, request, &rate);
1002 *value += rate;
1003 }
1004 }
1005 break;
1006 case OPUS_GET_LSB_DEPTH_REQUEST:
1007 case OPUS_GET_VBR_REQUEST:
1008 case OPUS_GET_APPLICATION_REQUEST:
1009 case OPUS_GET_BANDWIDTH_REQUEST:
1010 case OPUS_GET_COMPLEXITY_REQUEST:
1011 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1012 case OPUS_GET_DTX_REQUEST:
1013 case OPUS_GET_VOICE_RATIO_REQUEST:
1014 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1015 case OPUS_GET_SIGNAL_REQUEST:
1016 case OPUS_GET_LOOKAHEAD_REQUEST:
1017 case OPUS_GET_SAMPLE_RATE_REQUEST:
1018 case OPUS_GET_INBAND_FEC_REQUEST:
1019 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1020 {
1021 OpusEncoder *enc;
1022 /* For int32* GET params, just query the first stream */
1023 opus_int32 *value = va_arg(ap, opus_int32*);
1024 enc = (OpusEncoder*)ptr;
1025 ret = opus_encoder_ctl(enc, request, value);
1026 }
1027 break;
1028 case OPUS_GET_FINAL_RANGE_REQUEST:
1029 {
1030 int s;
1031 opus_uint32 *value = va_arg(ap, opus_uint32*);
1032 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001033 if (!value)
1034 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001035 goto bad_arg;
1036 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001037 *value=0;
1038 for (s=0;s<st->layout.nb_streams;s++)
1039 {
1040 OpusEncoder *enc;
1041 enc = (OpusEncoder*)ptr;
1042 if (s < st->layout.nb_coupled_streams)
1043 ptr += align(coupled_size);
1044 else
1045 ptr += align(mono_size);
1046 ret = opus_encoder_ctl(enc, request, &tmp);
1047 if (ret != OPUS_OK) break;
1048 *value ^= tmp;
1049 }
1050 }
1051 break;
1052 case OPUS_SET_LSB_DEPTH_REQUEST:
1053 case OPUS_SET_COMPLEXITY_REQUEST:
1054 case OPUS_SET_VBR_REQUEST:
1055 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001056 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001057 case OPUS_SET_BANDWIDTH_REQUEST:
1058 case OPUS_SET_SIGNAL_REQUEST:
1059 case OPUS_SET_APPLICATION_REQUEST:
1060 case OPUS_SET_INBAND_FEC_REQUEST:
1061 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1062 case OPUS_SET_DTX_REQUEST:
1063 case OPUS_SET_FORCE_MODE_REQUEST:
1064 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1065 {
1066 int s;
1067 /* This works for int32 params */
1068 opus_int32 value = va_arg(ap, opus_int32);
1069 for (s=0;s<st->layout.nb_streams;s++)
1070 {
1071 OpusEncoder *enc;
1072
1073 enc = (OpusEncoder*)ptr;
1074 if (s < st->layout.nb_coupled_streams)
1075 ptr += align(coupled_size);
1076 else
1077 ptr += align(mono_size);
1078 ret = opus_encoder_ctl(enc, request, value);
1079 if (ret != OPUS_OK)
1080 break;
1081 }
1082 }
1083 break;
1084 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1085 {
1086 int s;
1087 opus_int32 stream_id;
1088 OpusEncoder **value;
1089 stream_id = va_arg(ap, opus_int32);
1090 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1091 ret = OPUS_BAD_ARG;
1092 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001093 if (!value)
1094 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001095 goto bad_arg;
1096 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001097 for (s=0;s<stream_id;s++)
1098 {
1099 if (s < st->layout.nb_coupled_streams)
1100 ptr += align(coupled_size);
1101 else
1102 ptr += align(mono_size);
1103 }
1104 *value = (OpusEncoder*)ptr;
1105 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001106 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001107 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001108 {
1109 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001110 st->variable_duration = value;
1111 }
1112 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001113 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001114 {
1115 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001116 if (!value)
1117 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001118 goto bad_arg;
1119 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001120 *value = st->variable_duration;
1121 }
1122 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001123 default:
1124 ret = OPUS_UNIMPLEMENTED;
1125 break;
1126 }
1127
1128 va_end(ap);
1129 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001130bad_arg:
1131 va_end(ap);
1132 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001133}
1134
1135void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1136{
1137 opus_free(st);
1138}