blob: aa48a61b08deaf63e03b5b18424eb97bee6c8f47 [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 Valin7c49ad02015-10-07 09:17:50 -040044#include "pitch.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050045
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040046typedef struct {
47 int nb_streams;
48 int nb_coupled_streams;
49 unsigned char mapping[8];
50} VorbisLayout;
51
52/* Index is nb_channel-1*/
53static const VorbisLayout vorbis_mappings[8] = {
54 {1, 0, {0}}, /* 1: mono */
55 {1, 1, {0, 1}}, /* 2: stereo */
56 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
57 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
58 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
59 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
60 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
61 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
62};
63
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040064static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
65{
66 int s;
67 char *ptr;
68 int coupled_size, mono_size;
69
70 coupled_size = opus_encoder_get_size(2);
71 mono_size = opus_encoder_get_size(1);
72 ptr = (char*)st + align(sizeof(OpusMSEncoder));
73 for (s=0;s<st->layout.nb_streams;s++)
74 {
75 if (s < st->layout.nb_coupled_streams)
76 ptr += align(coupled_size);
77 else
78 ptr += align(mono_size);
79 }
Mark Harris4feb0df2015-08-07 01:24:48 -070080 /* void* cast avoids clang -Wcast-align warning */
81 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040082}
83
84static opus_val32 *ms_get_window_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 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700100 /* void* cast avoids clang -Wcast-align warning */
101 return (opus_val32*)(void*)ptr;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400102}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500103
Drew Allen17e14fb2017-04-28 09:58:04 -0700104#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
105static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
106{
107 int order_plus_one;
108 int acn_channels;
109 int nondiegetic_channels;
110
Mark Harris697beca2018-05-27 17:47:28 -0700111 if (nb_channels < 1 || nb_channels > 227)
112 return 0;
113
Drew Allen17e14fb2017-04-28 09:58:04 -0700114 order_plus_one = isqrt32(nb_channels);
115 acn_channels = order_plus_one * order_plus_one;
116 nondiegetic_channels = nb_channels - acn_channels;
117
Mark Harris697beca2018-05-27 17:47:28 -0700118 if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
Drew Allen17e14fb2017-04-28 09:58:04 -0700119 return 0;
120
121 if (nb_streams)
122 *nb_streams = acn_channels + (nondiegetic_channels != 0);
123 if (nb_coupled_streams)
124 *nb_coupled_streams = nondiegetic_channels != 0;
125 return 1;
126}
127#endif
128
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500129static int validate_encoder_layout(const ChannelLayout *layout)
130{
131 int s;
132 for (s=0;s<layout->nb_streams;s++)
133 {
134 if (s < layout->nb_coupled_streams)
135 {
136 if (get_left_channel(layout, s, -1)==-1)
137 return 0;
138 if (get_right_channel(layout, s, -1)==-1)
139 return 0;
140 } else {
141 if (get_mono_channel(layout, s, -1)==-1)
142 return 0;
143 }
144 }
145 return 1;
146}
147
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400148static void channel_pos(int channels, int pos[8])
149{
150 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
151 if (channels==4)
152 {
153 pos[0]=1;
154 pos[1]=3;
155 pos[2]=1;
156 pos[3]=3;
157 } else if (channels==3||channels==5||channels==6)
158 {
159 pos[0]=1;
160 pos[1]=2;
161 pos[2]=3;
162 pos[3]=1;
163 pos[4]=3;
164 pos[5]=0;
165 } else if (channels==7)
166 {
167 pos[0]=1;
168 pos[1]=2;
169 pos[2]=3;
170 pos[3]=1;
171 pos[4]=3;
172 pos[5]=2;
173 pos[6]=0;
174 } else if (channels==8)
175 {
176 pos[0]=1;
177 pos[1]=2;
178 pos[2]=3;
179 pos[3]=1;
180 pos[4]=3;
181 pos[5]=1;
182 pos[6]=3;
183 pos[7]=0;
184 }
185}
186
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400187#if 1
188/* Computes a rough approximation of log2(2^a + 2^b) */
189static opus_val16 logSum(opus_val16 a, opus_val16 b)
190{
191 opus_val16 max;
192 opus_val32 diff;
193 opus_val16 frac;
194 static const opus_val16 diff_table[17] = {
195 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
196 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
197 QCONST16(0.0028123f, DB_SHIFT)
198 };
199 int low;
200 if (a>b)
201 {
202 max = a;
203 diff = SUB32(EXTEND32(a),EXTEND32(b));
204 } else {
205 max = b;
206 diff = SUB32(EXTEND32(b),EXTEND32(a));
207 }
Mark Harrisa6595e62015-10-07 09:21:23 -0400208 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400209 return max;
210#ifdef FIXED_POINT
211 low = SHR32(diff, DB_SHIFT-1);
212 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
213#else
Jean-Marc Valina71c9ad2013-11-13 12:07:01 -0500214 low = (int)floor(2*diff);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400215 frac = 2*diff - low;
216#endif
217 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
218}
219#else
220opus_val16 logSum(opus_val16 a, opus_val16 b)
221{
222 return log2(pow(4, a)+ pow(4, b))/2;
223}
224#endif
225
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400226void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500227 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400228)
229{
230 int c;
231 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400232 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400233 int pos[8] = {0};
234 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400235 int frame_size;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400236 int freq_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400237 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400238 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400239 opus_val16 maskLogE[3][21];
240 VARDECL(opus_val32, in);
241 VARDECL(opus_val16, x);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400242 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400243 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400244
245 upsample = resampling_factor(rate);
246 frame_size = len*upsample;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400247 freq_size = IMIN(960, frame_size);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400248
Michael Graczyk39256682016-05-02 21:42:18 -0700249 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400250 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400251 if (celt_mode->shortMdctSize<<LM==frame_size)
252 break;
253
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400254 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400255 ALLOC(x, len, opus_val16);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400256 ALLOC(freq, freq_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400257
258 channel_pos(channels, pos);
259
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400260 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400261 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400262 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400263
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400264 for (c=0;c<channels;c++)
265 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400266 int frame;
267 int nb_frames = frame_size/freq_size;
268 celt_assert(nb_frames*freq_size == frame_size);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400269 OPUS_COPY(in, mem+c*overlap, overlap);
Andrew Allen65f11d32017-12-04 15:32:18 -0800270 (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500271 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400272#ifndef FIXED_POINT
273 {
274 opus_val32 sum;
275 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
276 /* This should filter out both NaNs and ridiculous signals that could
277 cause NaNs further down. */
Jean-Marc Valin0d2ba552017-05-23 03:32:18 -0400278 if (!(sum < 1e18f) || celt_isnan(sum))
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400279 {
280 OPUS_CLEAR(in, frame_size+overlap);
281 preemph_mem[c] = 0;
282 }
283 }
284#endif
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400285 OPUS_CLEAR(bandE, 21);
286 for (frame=0;frame<nb_frames;frame++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400287 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400288 opus_val32 tmpE[21];
289 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
290 overlap, celt_mode->maxLM-LM, 1, arch);
291 if (upsample != 1)
292 {
293 int bound = freq_size/upsample;
294 for (i=0;i<bound;i++)
295 freq[i] *= upsample;
296 for (;i<freq_size;i++)
297 freq[i] = 0;
298 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400299
Linfeng Zhanga1ae8212016-09-07 15:29:03 -0700300 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400301 /* If we have multiple frames, take the max energy. */
302 for (i=0;i<21;i++)
303 bandE[i] = MAX32(bandE[i], tmpE[i]);
304 }
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400305 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400306 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
307 for (i=1;i<21;i++)
308 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
309 for (i=19;i>=0;i--)
310 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 -0400311 if (pos[c]==1)
312 {
313 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400314 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400315 } else if (pos[c]==3)
316 {
317 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400318 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400319 } else if (pos[c]==2)
320 {
321 for (i=0;i<21;i++)
322 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400323 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
324 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400325 }
326 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400327#if 0
328 for (i=0;i<21;i++)
329 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400330 float sum=0;
331 for (i=0;i<21;i++)
332 sum += bandLogE[21*c+i];
333 printf("%f ", sum/21);
334#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400335 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400336 }
337 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400338 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400339 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400340 for (c=0;c<3;c++)
341 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400342 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400343#if 0
344 for (c=0;c<3;c++)
345 {
346 for (i=0;i<21;i++)
347 printf("%f ", maskLogE[c][i]);
348 }
349#endif
350 for (c=0;c<channels;c++)
351 {
352 opus_val16 *mask;
353 if (pos[c]!=0)
354 {
355 mask = &maskLogE[pos[c]-1][0];
356 for (i=0;i<21;i++)
357 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
358 } else {
359 for (i=0;i<21;i++)
360 bandLogE[21*c+i] = 0;
361 }
362#if 0
363 for (i=0;i<21;i++)
364 printf("%f ", bandLogE[21*c+i]);
365 printf("\n");
366#endif
367#if 0
368 float sum=0;
369 for (i=0;i<21;i++)
370 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400371 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400372 printf("\n");
373#endif
374 }
375 RESTORE_STACK;
376}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500377
378opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
379{
380 int coupled_size;
381 int mono_size;
382
383 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
384 coupled_size = opus_encoder_get_size(2);
385 mono_size = opus_encoder_get_size(1);
386 return align(sizeof(OpusMSEncoder))
387 + nb_coupled_streams * align(coupled_size)
388 + (nb_streams-nb_coupled_streams) * align(mono_size);
389}
390
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400391opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
392{
393 int nb_streams;
394 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400395 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400396
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400397 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400398 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400399 if (channels==1)
400 {
401 nb_streams=1;
402 nb_coupled_streams=0;
403 } else if (channels==2)
404 {
405 nb_streams=1;
406 nb_coupled_streams=1;
407 } else
408 return 0;
409 } else if (mapping_family==1 && channels<=8 && channels>=1)
410 {
411 nb_streams=vorbis_mappings[channels-1].nb_streams;
412 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
413 } else if (mapping_family==255)
414 {
415 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400416 nb_coupled_streams=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700417#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
418 } else if (mapping_family==254)
419 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700420 if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
421 return 0;
Michael Graczyk39256682016-05-02 21:42:18 -0700422#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400423 } else
424 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400425 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
426 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400427 {
428 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
429 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400430 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400431}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500432
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400433static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500434 OpusMSEncoder *st,
435 opus_int32 Fs,
436 int channels,
437 int streams,
438 int coupled_streams,
439 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400440 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700441 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500442)
443{
444 int coupled_size;
445 int mono_size;
446 int i, ret;
447 char *ptr;
448
449 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800450 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500451 return OPUS_BAD_ARG;
452
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500453 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500454 st->layout.nb_channels = channels;
455 st->layout.nb_streams = streams;
456 st->layout.nb_coupled_streams = coupled_streams;
Michael Graczyk39256682016-05-02 21:42:18 -0700457 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400458 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500459 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400460 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500461 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500462 for (i=0;i<st->layout.nb_channels;i++)
463 st->layout.mapping[i] = mapping[i];
Drew Allen17e14fb2017-04-28 09:58:04 -0700464 if (!validate_layout(&st->layout))
465 return OPUS_BAD_ARG;
466 if (mapping_type == MAPPING_TYPE_SURROUND &&
467 !validate_encoder_layout(&st->layout))
468 return OPUS_BAD_ARG;
469#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
470 if (mapping_type == MAPPING_TYPE_AMBISONICS &&
471 !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
472 return OPUS_BAD_ARG;
473#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500474 ptr = (char*)st + align(sizeof(OpusMSEncoder));
475 coupled_size = opus_encoder_get_size(2);
476 mono_size = opus_encoder_get_size(1);
477
478 for (i=0;i<st->layout.nb_coupled_streams;i++)
479 {
480 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400481 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400482 if (i==st->lfe_stream)
483 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500484 ptr += align(coupled_size);
485 }
486 for (;i<st->layout.nb_streams;i++)
487 {
488 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400489 if (i==st->lfe_stream)
490 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500491 if(ret!=OPUS_OK)return ret;
492 ptr += align(mono_size);
493 }
Michael Graczyk39256682016-05-02 21:42:18 -0700494 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400495 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400496 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
497 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400498 }
Michael Graczyk39256682016-05-02 21:42:18 -0700499 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500500 return OPUS_OK;
501}
502
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400503int opus_multistream_encoder_init(
504 OpusMSEncoder *st,
505 opus_int32 Fs,
506 int channels,
507 int streams,
508 int coupled_streams,
509 const unsigned char *mapping,
510 int application
511)
512{
Michael Graczyk39256682016-05-02 21:42:18 -0700513 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
514 coupled_streams, mapping,
515 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400516}
517
518int opus_multistream_surround_encoder_init(
519 OpusMSEncoder *st,
520 opus_int32 Fs,
521 int channels,
522 int mapping_family,
523 int *streams,
524 int *coupled_streams,
525 unsigned char *mapping,
526 int application
527)
528{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700529 MappingType mapping_type;
530
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400531 if ((channels>255) || (channels<1))
532 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400533 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400534 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400535 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400536 if (channels==1)
537 {
538 *streams=1;
539 *coupled_streams=0;
540 mapping[0]=0;
541 } else if (channels==2)
542 {
543 *streams=1;
544 *coupled_streams=1;
545 mapping[0]=0;
546 mapping[1]=1;
547 } else
548 return OPUS_UNIMPLEMENTED;
549 } else if (mapping_family==1 && channels<=8 && channels>=1)
550 {
551 int i;
552 *streams=vorbis_mappings[channels-1].nb_streams;
553 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
554 for (i=0;i<channels;i++)
555 mapping[i] = vorbis_mappings[channels-1].mapping[i];
556 if (channels>=6)
557 st->lfe_stream = *streams-1;
558 } else if (mapping_family==255)
559 {
560 int i;
561 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400562 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400563 for(i=0;i<channels;i++)
564 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700565#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
566 } else if (mapping_family==254)
567 {
568 int i;
Drew Allen17e14fb2017-04-28 09:58:04 -0700569 if (!validate_ambisonics(channels, streams, coupled_streams))
570 return OPUS_BAD_ARG;
571 for(i = 0; i < (*streams - *coupled_streams); i++)
572 mapping[i] = i + (*coupled_streams * 2);
573 for(i = 0; i < *coupled_streams * 2; i++)
574 mapping[i + (*streams - *coupled_streams)] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700575#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400576 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400577 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700578
579 if (channels>2 && mapping_family==1) {
580 mapping_type = MAPPING_TYPE_SURROUND;
581#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
582 } else if (mapping_family==254)
583 {
584 mapping_type = MAPPING_TYPE_AMBISONICS;
585#endif
586 } else
587 {
588 mapping_type = MAPPING_TYPE_NONE;
589 }
590 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
591 *coupled_streams, mapping,
592 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400593}
594
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500595OpusMSEncoder *opus_multistream_encoder_create(
596 opus_int32 Fs,
597 int channels,
598 int streams,
599 int coupled_streams,
600 const unsigned char *mapping,
601 int application,
602 int *error
603)
604{
605 int ret;
606 OpusMSEncoder *st;
607 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800608 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500609 {
610 if (error)
611 *error = OPUS_BAD_ARG;
612 return NULL;
613 }
614 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
615 if (st==NULL)
616 {
617 if (error)
618 *error = OPUS_ALLOC_FAIL;
619 return NULL;
620 }
621 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
622 if (ret != OPUS_OK)
623 {
624 opus_free(st);
625 st = NULL;
626 }
627 if (error)
628 *error = ret;
629 return st;
630}
631
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400632OpusMSEncoder *opus_multistream_surround_encoder_create(
633 opus_int32 Fs,
634 int channels,
635 int mapping_family,
636 int *streams,
637 int *coupled_streams,
638 unsigned char *mapping,
639 int application,
640 int *error
641)
642{
643 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800644 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400645 OpusMSEncoder *st;
646 if ((channels>255) || (channels<1))
647 {
648 if (error)
649 *error = OPUS_BAD_ARG;
650 return NULL;
651 }
Mark Harris25b27a92014-11-27 08:48:09 -0800652 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
653 if (!size)
654 {
655 if (error)
656 *error = OPUS_UNIMPLEMENTED;
657 return NULL;
658 }
659 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400660 if (st==NULL)
661 {
662 if (error)
663 *error = OPUS_ALLOC_FAIL;
664 return NULL;
665 }
666 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
667 if (ret != OPUS_OK)
668 {
669 opus_free(st);
670 st = NULL;
671 }
672 if (error)
673 *error = ret;
674 return st;
675}
676
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700677static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400678 OpusMSEncoder *st,
679 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700680 int frame_size,
681 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400682 )
683{
684 int i;
685 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400686 int stream_offset;
687 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400688 int coupled_ratio; /* Q8 */
689 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400690 int nb_lfe;
691 int nb_uncoupled;
692 int nb_coupled;
693 int nb_normal;
694 opus_int32 channel_offset;
695 opus_int32 bitrate;
696 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400697
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400698 nb_lfe = (st->lfe_stream!=-1);
699 nb_coupled = st->layout.nb_coupled_streams;
700 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
701 nb_normal = 2*nb_coupled + nb_uncoupled;
702
703 /* Give each non-LFE channel enough bits per channel for coding band energy. */
704 channel_offset = 40*IMAX(50, Fs/frame_size);
705
706 if (st->bitrate_bps==OPUS_AUTO)
707 {
708 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
709 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
710 {
711 bitrate = nb_normal*300000 + nb_lfe*128000;
712 } else {
713 bitrate = st->bitrate_bps;
714 }
715
716 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
717 total rate for the non-energy part to avoid problems at really low rate. */
718 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
719
720 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400721 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400722 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
723 stream_offset = IMAX(0, IMIN(20000, stream_offset));
724
725 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400726 coupled_ratio = 512;
727 /* 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 -0400728 lfe_ratio = 32;
729
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400730 total = (nb_uncoupled<<8) /* mono */
731 + coupled_ratio*nb_coupled /* stereo */
732 + nb_lfe*lfe_ratio;
733 channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400734
735 for (i=0;i<st->layout.nb_streams;i++)
736 {
737 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400738 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400739 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400740 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400741 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400742 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700743 }
744}
745
746#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
747static void ambisonics_rate_allocation(
748 OpusMSEncoder *st,
749 opus_int32 *rate,
750 int frame_size,
751 opus_int32 Fs
752 )
753{
754 int i;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700755 int total_rate;
Drew Allen17e14fb2017-04-28 09:58:04 -0700756 int directional_rate;
757 int nondirectional_rate;
758 int leftover_bits;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700759
Drew Allen17e14fb2017-04-28 09:58:04 -0700760 /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
761 * as many bits as all other ambisonics channels.
762 */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700763 const int rate_ratio_num = 4;
764 const int rate_ratio_den = 3;
Drew Allen17e14fb2017-04-28 09:58:04 -0700765 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
766 const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
767 const int nb_directional_channels = st->layout.nb_streams - 1;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700768
769 if (st->bitrate_bps==OPUS_AUTO)
770 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700771 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
772 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700773 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
774 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700775 total_rate = nb_channels * 320000;
776 } else
777 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700778 total_rate = st->bitrate_bps;
779 }
780
Drew Allen17e14fb2017-04-28 09:58:04 -0700781 /* Let y be the directional rate, m be the num of nondirectional channels
782 * m = (s + 1)
783 * and let p, q be integers such that the nondirectional rate is
784 * m_rate = (p / q) * y
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700785 * Also let T be the total bitrate to allocate. Then
Drew Allen17e14fb2017-04-28 09:58:04 -0700786 * T = (n - m) * y + m * m_rate
787 * Solving for y,
788 * y = (q * T) / (m * (p - q) + n * q)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700789 */
Drew Allen17e14fb2017-04-28 09:58:04 -0700790 directional_rate =
791 total_rate * rate_ratio_den
792 / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
793 + nb_channels * rate_ratio_den);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700794
Drew Allen17e14fb2017-04-28 09:58:04 -0700795 /* Calculate the nondirectional rate.
796 * m_rate = y * (p / q)
797 */
798 nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
799
800 /* Calculate the leftover from truncation error.
801 * leftover = T - y * (n - m) - m_rate * m
802 * Place leftover bits in omnidirectional channel.
803 */
804 leftover_bits = total_rate
805 - directional_rate * nb_directional_channels
806 - nondirectional_rate * nb_nondirectional_channels;
807
808 /* Calculate rates for each channel */
809 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700810 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700811 if (i < st->layout.nb_coupled_streams)
812 {
813 rate[i] = nondirectional_rate * 2;
814 } else if (i == st->layout.nb_coupled_streams)
815 {
816 rate[i] = nondirectional_rate + leftover_bits;
817 } else
818 {
819 rate[i] = directional_rate;
820 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700821 }
822}
823#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
824
825static opus_int32 rate_allocation(
826 OpusMSEncoder *st,
827 opus_int32 *rate,
828 int frame_size
829 )
830{
831 int i;
832 opus_int32 rate_sum=0;
833 opus_int32 Fs;
834 char *ptr;
835
836 ptr = (char*)st + align(sizeof(OpusMSEncoder));
837 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
838
839#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
840 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
841 ambisonics_rate_allocation(st, rate, frame_size, Fs);
842 } else
843#endif
844 {
845 surround_rate_allocation(st, rate, frame_size, Fs);
846 }
847
848 for (i=0;i<st->layout.nb_streams;i++)
849 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400850 rate[i] = IMAX(rate[i], 500);
851 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400852 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400853 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400854}
855
Felicia Lim0962cbe2016-10-27 17:03:36 -0700856/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
857#define MS_FRAME_TMP (6*1275+12)
Andrew Allen65f11d32017-12-04 15:32:18 -0800858int opus_multistream_encode_native
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500859(
860 OpusMSEncoder *st,
861 opus_copy_channel_in_func copy_channel_in,
862 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400863 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500864 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500865 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400866 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500867 downmix_func downmix,
Andrew Allen65f11d32017-12-04 15:32:18 -0800868 int float_api,
869 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500870)
871{
872 opus_int32 Fs;
873 int coupled_size;
874 int mono_size;
875 int s;
876 char *ptr;
877 int tot_size;
878 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400879 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500880 unsigned char tmp_data[MS_FRAME_TMP];
881 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400882 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500883 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400884 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400885 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400886 opus_val32 *mem = NULL;
887 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400888 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400889 opus_int32 rate_sum;
890 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500891 ALLOC_STACK;
892
Michael Graczyk39256682016-05-02 21:42:18 -0700893 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400894 {
895 preemph_mem = ms_get_preemph_mem(st);
896 mem = ms_get_window_mem(st);
897 }
898
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500899 ptr = (char*)st + align(sizeof(OpusMSEncoder));
900 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400901 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500902 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500903
Mark Harrisd73c5a92016-11-05 22:01:52 -0700904 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
905 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500906 {
907 RESTORE_STACK;
908 return OPUS_BAD_ARG;
909 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400910
911 /* Smallest packet the encoder can produce. */
912 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700913 /* 100 ms needs an extra byte per stream for the ToC. */
914 if (Fs/frame_size == 10)
915 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400916 if (max_data_bytes < smallest_packet)
917 {
918 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400919 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400920 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500921 ALLOC(buf, 2*frame_size, opus_val16);
922 coupled_size = opus_encoder_get_size(2);
923 mono_size = opus_encoder_get_size(1);
924
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400925 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700926 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400927 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500928 surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400929 }
930
Jean-Marc Valin74483662012-12-17 16:23:42 -0500931 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700932 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400933
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400934 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400935 {
936 if (st->bitrate_bps == OPUS_AUTO)
937 {
938 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
939 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
940 {
941 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
942 3*st->bitrate_bps/(3*8*Fs/frame_size)));
943 }
944 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500945 ptr = (char*)st + align(sizeof(OpusMSEncoder));
946 for (s=0;s<st->layout.nb_streams;s++)
947 {
948 OpusEncoder *enc;
949 enc = (OpusEncoder*)ptr;
950 if (s < st->layout.nb_coupled_streams)
951 ptr += align(coupled_size);
952 else
953 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400954 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700955 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400956 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400957 opus_int32 equiv_rate;
958 equiv_rate = st->bitrate_bps;
959 if (frame_size*50 < Fs)
960 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500961 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400962 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500963 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400964 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500965 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400966 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
967 else
968 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400969 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400970 {
971 /* To preserve the spatial image, force stereo CELT on coupled streams */
972 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400973 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400974 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400975 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700976#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
977 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
978 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
979 }
980#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500981 }
982
983 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500984 /* Counting ToC */
985 tot_size = 0;
986 for (s=0;s<st->layout.nb_streams;s++)
987 {
988 OpusEncoder *enc;
989 int len;
990 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400991 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400992 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500993
994 opus_repacketizer_init(&rp);
995 enc = (OpusEncoder*)ptr;
996 if (s < st->layout.nb_coupled_streams)
997 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400998 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500999 int left, right;
1000 left = get_left_channel(&st->layout, s, -1);
1001 right = get_right_channel(&st->layout, s, -1);
1002 (*copy_channel_in)(buf, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -08001003 pcm, st->layout.nb_channels, left, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001004 (*copy_channel_in)(buf+1, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -08001005 pcm, st->layout.nb_channels, right, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001006 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001007 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001008 {
1009 for (i=0;i<21;i++)
1010 {
1011 bandLogE[i] = bandSMR[21*left+i];
1012 bandLogE[21+i] = bandSMR[21*right+i];
1013 }
1014 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001015 c1 = left;
1016 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001017 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001018 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001019 int chan = get_mono_channel(&st->layout, s, -1);
1020 (*copy_channel_in)(buf, 1,
Andrew Allen65f11d32017-12-04 15:32:18 -08001021 pcm, st->layout.nb_channels, chan, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001022 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001023 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001024 {
1025 for (i=0;i<21;i++)
1026 bandLogE[i] = bandSMR[21*chan+i];
1027 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001028 c1 = chan;
1029 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001030 }
Michael Graczyk39256682016-05-02 21:42:18 -07001031 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001032 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001033 /* number of bytes left (+Toc) */
1034 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001035 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001036 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001037 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001038 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001039 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001040 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001041 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001042 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001043 if (!vbr && s == st->layout.nb_streams-1)
1044 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001045 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001046 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001047 if (len<0)
1048 {
1049 RESTORE_STACK;
1050 return len;
1051 }
1052 /* We need to use the repacketizer to add the self-delimiting lengths
1053 while taking into account the fact that the encoder can now return
1054 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001055 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1056 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1057 with the encoder. */
1058 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001059 {
1060 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001061 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001062 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001063 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1064 data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001065 data += len;
1066 tot_size += len;
1067 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001068 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001069 RESTORE_STACK;
1070 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001071}
1072
Pedro Becerra1af7f952013-07-11 00:00:47 -04001073#if !defined(DISABLE_FLOAT_API)
1074static void opus_copy_channel_in_float(
1075 opus_val16 *dst,
1076 int dst_stride,
1077 const void *src,
1078 int src_stride,
1079 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001080 int frame_size,
1081 void *user_data
Pedro Becerra1af7f952013-07-11 00:00:47 -04001082)
1083{
1084 const float *float_src;
1085 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001086 (void)user_data;
Pedro Becerra1af7f952013-07-11 00:00:47 -04001087 float_src = (const float *)src;
1088 for (i=0;i<frame_size;i++)
1089#if defined(FIXED_POINT)
1090 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1091#else
1092 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1093#endif
1094}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001095#endif
1096
1097static void opus_copy_channel_in_short(
1098 opus_val16 *dst,
1099 int dst_stride,
1100 const void *src,
1101 int src_stride,
1102 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001103 int frame_size,
1104 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001105)
1106{
1107 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001108 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001109 (void)user_data;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001110 short_src = (const opus_int16 *)src;
1111 for (i=0;i<frame_size;i++)
1112#if defined(FIXED_POINT)
1113 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1114#else
1115 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1116#endif
1117}
1118
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001119
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001120#ifdef FIXED_POINT
1121int opus_multistream_encode(
1122 OpusMSEncoder *st,
1123 const opus_val16 *pcm,
1124 int frame_size,
1125 unsigned char *data,
1126 opus_int32 max_data_bytes
1127)
1128{
1129 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001130 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001131}
1132
1133#ifndef DISABLE_FLOAT_API
1134int opus_multistream_encode_float(
1135 OpusMSEncoder *st,
1136 const float *pcm,
1137 int frame_size,
1138 unsigned char *data,
1139 opus_int32 max_data_bytes
1140)
1141{
1142 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001143 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001144}
1145#endif
1146
1147#else
1148
1149int opus_multistream_encode_float
1150(
1151 OpusMSEncoder *st,
1152 const opus_val16 *pcm,
1153 int frame_size,
1154 unsigned char *data,
1155 opus_int32 max_data_bytes
1156)
1157{
1158 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001159 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001160}
1161
1162int opus_multistream_encode(
1163 OpusMSEncoder *st,
1164 const opus_int16 *pcm,
1165 int frame_size,
1166 unsigned char *data,
1167 opus_int32 max_data_bytes
1168)
1169{
1170 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001171 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001172}
1173#endif
1174
Andrew Allenf643c032017-11-07 13:26:23 -08001175int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
1176 va_list ap)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001177{
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001178 int coupled_size, mono_size;
1179 char *ptr;
1180 int ret = OPUS_OK;
1181
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001182 coupled_size = opus_encoder_get_size(2);
1183 mono_size = opus_encoder_get_size(1);
1184 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1185 switch (request)
1186 {
1187 case OPUS_SET_BITRATE_REQUEST:
1188 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001189 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001190 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001191 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001192 if (value <= 0)
1193 goto bad_arg;
1194 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001195 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001196 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001197 }
1198 break;
1199 case OPUS_GET_BITRATE_REQUEST:
1200 {
1201 int s;
1202 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001203 if (!value)
1204 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001205 goto bad_arg;
1206 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001207 *value = 0;
1208 for (s=0;s<st->layout.nb_streams;s++)
1209 {
1210 opus_int32 rate;
1211 OpusEncoder *enc;
1212 enc = (OpusEncoder*)ptr;
1213 if (s < st->layout.nb_coupled_streams)
1214 ptr += align(coupled_size);
1215 else
1216 ptr += align(mono_size);
1217 opus_encoder_ctl(enc, request, &rate);
1218 *value += rate;
1219 }
1220 }
1221 break;
1222 case OPUS_GET_LSB_DEPTH_REQUEST:
1223 case OPUS_GET_VBR_REQUEST:
1224 case OPUS_GET_APPLICATION_REQUEST:
1225 case OPUS_GET_BANDWIDTH_REQUEST:
1226 case OPUS_GET_COMPLEXITY_REQUEST:
1227 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1228 case OPUS_GET_DTX_REQUEST:
1229 case OPUS_GET_VOICE_RATIO_REQUEST:
1230 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1231 case OPUS_GET_SIGNAL_REQUEST:
1232 case OPUS_GET_LOOKAHEAD_REQUEST:
1233 case OPUS_GET_SAMPLE_RATE_REQUEST:
1234 case OPUS_GET_INBAND_FEC_REQUEST:
1235 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001236 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001237 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001238 {
1239 OpusEncoder *enc;
1240 /* For int32* GET params, just query the first stream */
1241 opus_int32 *value = va_arg(ap, opus_int32*);
1242 enc = (OpusEncoder*)ptr;
1243 ret = opus_encoder_ctl(enc, request, value);
1244 }
1245 break;
1246 case OPUS_GET_FINAL_RANGE_REQUEST:
1247 {
1248 int s;
1249 opus_uint32 *value = va_arg(ap, opus_uint32*);
1250 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001251 if (!value)
1252 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001253 goto bad_arg;
1254 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001255 *value=0;
1256 for (s=0;s<st->layout.nb_streams;s++)
1257 {
1258 OpusEncoder *enc;
1259 enc = (OpusEncoder*)ptr;
1260 if (s < st->layout.nb_coupled_streams)
1261 ptr += align(coupled_size);
1262 else
1263 ptr += align(mono_size);
1264 ret = opus_encoder_ctl(enc, request, &tmp);
1265 if (ret != OPUS_OK) break;
1266 *value ^= tmp;
1267 }
1268 }
1269 break;
1270 case OPUS_SET_LSB_DEPTH_REQUEST:
1271 case OPUS_SET_COMPLEXITY_REQUEST:
1272 case OPUS_SET_VBR_REQUEST:
1273 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001274 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001275 case OPUS_SET_BANDWIDTH_REQUEST:
1276 case OPUS_SET_SIGNAL_REQUEST:
1277 case OPUS_SET_APPLICATION_REQUEST:
1278 case OPUS_SET_INBAND_FEC_REQUEST:
1279 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1280 case OPUS_SET_DTX_REQUEST:
1281 case OPUS_SET_FORCE_MODE_REQUEST:
1282 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001283 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001284 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001285 {
1286 int s;
1287 /* This works for int32 params */
1288 opus_int32 value = va_arg(ap, opus_int32);
1289 for (s=0;s<st->layout.nb_streams;s++)
1290 {
1291 OpusEncoder *enc;
1292
1293 enc = (OpusEncoder*)ptr;
1294 if (s < st->layout.nb_coupled_streams)
1295 ptr += align(coupled_size);
1296 else
1297 ptr += align(mono_size);
1298 ret = opus_encoder_ctl(enc, request, value);
1299 if (ret != OPUS_OK)
1300 break;
1301 }
1302 }
1303 break;
1304 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1305 {
1306 int s;
1307 opus_int32 stream_id;
1308 OpusEncoder **value;
1309 stream_id = va_arg(ap, opus_int32);
1310 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1311 ret = OPUS_BAD_ARG;
1312 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001313 if (!value)
1314 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001315 goto bad_arg;
1316 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001317 for (s=0;s<stream_id;s++)
1318 {
1319 if (s < st->layout.nb_coupled_streams)
1320 ptr += align(coupled_size);
1321 else
1322 ptr += align(mono_size);
1323 }
1324 *value = (OpusEncoder*)ptr;
1325 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001326 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001327 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001328 {
1329 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001330 st->variable_duration = value;
1331 }
1332 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001333 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001334 {
1335 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001336 if (!value)
1337 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001338 goto bad_arg;
1339 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001340 *value = st->variable_duration;
1341 }
1342 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001343 case OPUS_RESET_STATE:
1344 {
1345 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001346 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001347 {
1348 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1349 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1350 }
1351 for (s=0;s<st->layout.nb_streams;s++)
1352 {
1353 OpusEncoder *enc;
1354 enc = (OpusEncoder*)ptr;
1355 if (s < st->layout.nb_coupled_streams)
1356 ptr += align(coupled_size);
1357 else
1358 ptr += align(mono_size);
1359 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1360 if (ret != OPUS_OK)
1361 break;
1362 }
1363 }
1364 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001365 default:
1366 ret = OPUS_UNIMPLEMENTED;
1367 break;
1368 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001369 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001370bad_arg:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001371 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001372}
1373
Andrew Allenf643c032017-11-07 13:26:23 -08001374int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1375{
1376 int ret;
1377 va_list ap;
1378 va_start(ap, request);
1379 ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
1380 va_end(ap);
1381 return ret;
1382}
1383
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001384void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1385{
1386 opus_free(st);
1387}