blob: 6cc1f43225a3a6d7a838f201b18bf7ef5fbc38c3 [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 -0700104static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
105{
106 int order_plus_one;
107 int acn_channels;
108 int nondiegetic_channels;
109
Mark Harris697beca2018-05-27 17:47:28 -0700110 if (nb_channels < 1 || nb_channels > 227)
111 return 0;
112
Drew Allen17e14fb2017-04-28 09:58:04 -0700113 order_plus_one = isqrt32(nb_channels);
114 acn_channels = order_plus_one * order_plus_one;
115 nondiegetic_channels = nb_channels - acn_channels;
116
Mark Harris697beca2018-05-27 17:47:28 -0700117 if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
Drew Allen17e14fb2017-04-28 09:58:04 -0700118 return 0;
119
120 if (nb_streams)
121 *nb_streams = acn_channels + (nondiegetic_channels != 0);
122 if (nb_coupled_streams)
123 *nb_coupled_streams = nondiegetic_channels != 0;
124 return 1;
125}
Drew Allen17e14fb2017-04-28 09:58:04 -0700126
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500127static int validate_encoder_layout(const ChannelLayout *layout)
128{
129 int s;
130 for (s=0;s<layout->nb_streams;s++)
131 {
132 if (s < layout->nb_coupled_streams)
133 {
134 if (get_left_channel(layout, s, -1)==-1)
135 return 0;
136 if (get_right_channel(layout, s, -1)==-1)
137 return 0;
138 } else {
139 if (get_mono_channel(layout, s, -1)==-1)
140 return 0;
141 }
142 }
143 return 1;
144}
145
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400146static void channel_pos(int channels, int pos[8])
147{
148 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
149 if (channels==4)
150 {
151 pos[0]=1;
152 pos[1]=3;
153 pos[2]=1;
154 pos[3]=3;
155 } else if (channels==3||channels==5||channels==6)
156 {
157 pos[0]=1;
158 pos[1]=2;
159 pos[2]=3;
160 pos[3]=1;
161 pos[4]=3;
162 pos[5]=0;
163 } else if (channels==7)
164 {
165 pos[0]=1;
166 pos[1]=2;
167 pos[2]=3;
168 pos[3]=1;
169 pos[4]=3;
170 pos[5]=2;
171 pos[6]=0;
172 } else if (channels==8)
173 {
174 pos[0]=1;
175 pos[1]=2;
176 pos[2]=3;
177 pos[3]=1;
178 pos[4]=3;
179 pos[5]=1;
180 pos[6]=3;
181 pos[7]=0;
182 }
183}
184
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400185#if 1
186/* Computes a rough approximation of log2(2^a + 2^b) */
187static opus_val16 logSum(opus_val16 a, opus_val16 b)
188{
189 opus_val16 max;
190 opus_val32 diff;
191 opus_val16 frac;
192 static const opus_val16 diff_table[17] = {
193 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
194 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
195 QCONST16(0.0028123f, DB_SHIFT)
196 };
197 int low;
198 if (a>b)
199 {
200 max = a;
201 diff = SUB32(EXTEND32(a),EXTEND32(b));
202 } else {
203 max = b;
204 diff = SUB32(EXTEND32(b),EXTEND32(a));
205 }
Mark Harrisa6595e62015-10-07 09:21:23 -0400206 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400207 return max;
208#ifdef FIXED_POINT
209 low = SHR32(diff, DB_SHIFT-1);
210 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
211#else
Jean-Marc Valina71c9ad2013-11-13 12:07:01 -0500212 low = (int)floor(2*diff);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400213 frac = 2*diff - low;
214#endif
215 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
216}
217#else
218opus_val16 logSum(opus_val16 a, opus_val16 b)
219{
220 return log2(pow(4, a)+ pow(4, b))/2;
221}
222#endif
223
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400224void 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 -0500225 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 -0400226)
227{
228 int c;
229 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400230 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400231 int pos[8] = {0};
232 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400233 int frame_size;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400234 int freq_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400235 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400236 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400237 opus_val16 maskLogE[3][21];
238 VARDECL(opus_val32, in);
239 VARDECL(opus_val16, x);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400240 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400241 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400242
243 upsample = resampling_factor(rate);
244 frame_size = len*upsample;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400245 freq_size = IMIN(960, frame_size);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400246
Michael Graczyk39256682016-05-02 21:42:18 -0700247 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400248 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400249 if (celt_mode->shortMdctSize<<LM==frame_size)
250 break;
251
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400252 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400253 ALLOC(x, len, opus_val16);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400254 ALLOC(freq, freq_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400255
256 channel_pos(channels, pos);
257
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400258 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400259 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400260 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400261
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400262 for (c=0;c<channels;c++)
263 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400264 int frame;
265 int nb_frames = frame_size/freq_size;
266 celt_assert(nb_frames*freq_size == frame_size);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400267 OPUS_COPY(in, mem+c*overlap, overlap);
Andrew Allen65f11d32017-12-04 15:32:18 -0800268 (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500269 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400270#ifndef FIXED_POINT
271 {
272 opus_val32 sum;
273 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
274 /* This should filter out both NaNs and ridiculous signals that could
275 cause NaNs further down. */
Jean-Marc Valin0d2ba552017-05-23 03:32:18 -0400276 if (!(sum < 1e18f) || celt_isnan(sum))
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400277 {
278 OPUS_CLEAR(in, frame_size+overlap);
279 preemph_mem[c] = 0;
280 }
281 }
282#endif
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400283 OPUS_CLEAR(bandE, 21);
284 for (frame=0;frame<nb_frames;frame++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400285 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400286 opus_val32 tmpE[21];
287 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
288 overlap, celt_mode->maxLM-LM, 1, arch);
289 if (upsample != 1)
290 {
291 int bound = freq_size/upsample;
292 for (i=0;i<bound;i++)
293 freq[i] *= upsample;
294 for (;i<freq_size;i++)
295 freq[i] = 0;
296 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400297
Linfeng Zhanga1ae8212016-09-07 15:29:03 -0700298 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400299 /* If we have multiple frames, take the max energy. */
300 for (i=0;i<21;i++)
301 bandE[i] = MAX32(bandE[i], tmpE[i]);
302 }
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400303 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400304 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
305 for (i=1;i<21;i++)
306 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
307 for (i=19;i>=0;i--)
308 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 -0400309 if (pos[c]==1)
310 {
311 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400312 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400313 } else if (pos[c]==3)
314 {
315 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400316 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400317 } else if (pos[c]==2)
318 {
319 for (i=0;i<21;i++)
320 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400321 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
322 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400323 }
324 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400325#if 0
326 for (i=0;i<21;i++)
327 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400328 float sum=0;
329 for (i=0;i<21;i++)
330 sum += bandLogE[21*c+i];
331 printf("%f ", sum/21);
332#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400333 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400334 }
335 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400336 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400337 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400338 for (c=0;c<3;c++)
339 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400340 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400341#if 0
342 for (c=0;c<3;c++)
343 {
344 for (i=0;i<21;i++)
345 printf("%f ", maskLogE[c][i]);
346 }
347#endif
348 for (c=0;c<channels;c++)
349 {
350 opus_val16 *mask;
351 if (pos[c]!=0)
352 {
353 mask = &maskLogE[pos[c]-1][0];
354 for (i=0;i<21;i++)
355 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
356 } else {
357 for (i=0;i<21;i++)
358 bandLogE[21*c+i] = 0;
359 }
360#if 0
361 for (i=0;i<21;i++)
362 printf("%f ", bandLogE[21*c+i]);
363 printf("\n");
364#endif
365#if 0
366 float sum=0;
367 for (i=0;i<21;i++)
368 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400369 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400370 printf("\n");
371#endif
372 }
373 RESTORE_STACK;
374}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500375
376opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
377{
378 int coupled_size;
379 int mono_size;
380
381 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
382 coupled_size = opus_encoder_get_size(2);
383 mono_size = opus_encoder_get_size(1);
384 return align(sizeof(OpusMSEncoder))
385 + nb_coupled_streams * align(coupled_size)
386 + (nb_streams-nb_coupled_streams) * align(mono_size);
387}
388
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400389opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
390{
391 int nb_streams;
392 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400393 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400394
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400395 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400396 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400397 if (channels==1)
398 {
399 nb_streams=1;
400 nb_coupled_streams=0;
401 } else if (channels==2)
402 {
403 nb_streams=1;
404 nb_coupled_streams=1;
405 } else
406 return 0;
407 } else if (mapping_family==1 && channels<=8 && channels>=1)
408 {
409 nb_streams=vorbis_mappings[channels-1].nb_streams;
410 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
411 } else if (mapping_family==255)
412 {
413 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400414 nb_coupled_streams=0;
Jean-Marc Valin6a74b412018-06-15 16:52:14 -0400415 } else if (mapping_family==2)
Michael Graczyk39256682016-05-02 21:42:18 -0700416 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700417 if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
418 return 0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400419 } else
420 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400421 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
422 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400423 {
424 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
425 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400426 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400427}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500428
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400429static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500430 OpusMSEncoder *st,
431 opus_int32 Fs,
432 int channels,
433 int streams,
434 int coupled_streams,
435 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400436 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700437 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500438)
439{
440 int coupled_size;
441 int mono_size;
442 int i, ret;
443 char *ptr;
444
445 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800446 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500447 return OPUS_BAD_ARG;
448
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500449 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500450 st->layout.nb_channels = channels;
451 st->layout.nb_streams = streams;
452 st->layout.nb_coupled_streams = coupled_streams;
Michael Graczyk39256682016-05-02 21:42:18 -0700453 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400454 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500455 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400456 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500457 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500458 for (i=0;i<st->layout.nb_channels;i++)
459 st->layout.mapping[i] = mapping[i];
Drew Allen17e14fb2017-04-28 09:58:04 -0700460 if (!validate_layout(&st->layout))
461 return OPUS_BAD_ARG;
462 if (mapping_type == MAPPING_TYPE_SURROUND &&
463 !validate_encoder_layout(&st->layout))
464 return OPUS_BAD_ARG;
Drew Allen17e14fb2017-04-28 09:58:04 -0700465 if (mapping_type == MAPPING_TYPE_AMBISONICS &&
466 !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
467 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500468 ptr = (char*)st + align(sizeof(OpusMSEncoder));
469 coupled_size = opus_encoder_get_size(2);
470 mono_size = opus_encoder_get_size(1);
471
472 for (i=0;i<st->layout.nb_coupled_streams;i++)
473 {
474 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400475 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400476 if (i==st->lfe_stream)
477 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500478 ptr += align(coupled_size);
479 }
480 for (;i<st->layout.nb_streams;i++)
481 {
482 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400483 if (i==st->lfe_stream)
484 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500485 if(ret!=OPUS_OK)return ret;
486 ptr += align(mono_size);
487 }
Michael Graczyk39256682016-05-02 21:42:18 -0700488 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400489 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400490 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
491 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400492 }
Michael Graczyk39256682016-05-02 21:42:18 -0700493 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500494 return OPUS_OK;
495}
496
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400497int opus_multistream_encoder_init(
498 OpusMSEncoder *st,
499 opus_int32 Fs,
500 int channels,
501 int streams,
502 int coupled_streams,
503 const unsigned char *mapping,
504 int application
505)
506{
Michael Graczyk39256682016-05-02 21:42:18 -0700507 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
508 coupled_streams, mapping,
509 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400510}
511
512int opus_multistream_surround_encoder_init(
513 OpusMSEncoder *st,
514 opus_int32 Fs,
515 int channels,
516 int mapping_family,
517 int *streams,
518 int *coupled_streams,
519 unsigned char *mapping,
520 int application
521)
522{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700523 MappingType mapping_type;
524
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400525 if ((channels>255) || (channels<1))
526 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400527 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400528 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400529 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400530 if (channels==1)
531 {
532 *streams=1;
533 *coupled_streams=0;
534 mapping[0]=0;
535 } else if (channels==2)
536 {
537 *streams=1;
538 *coupled_streams=1;
539 mapping[0]=0;
540 mapping[1]=1;
541 } else
542 return OPUS_UNIMPLEMENTED;
543 } else if (mapping_family==1 && channels<=8 && channels>=1)
544 {
545 int i;
546 *streams=vorbis_mappings[channels-1].nb_streams;
547 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
548 for (i=0;i<channels;i++)
549 mapping[i] = vorbis_mappings[channels-1].mapping[i];
550 if (channels>=6)
551 st->lfe_stream = *streams-1;
552 } else if (mapping_family==255)
553 {
554 int i;
555 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400556 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400557 for(i=0;i<channels;i++)
558 mapping[i] = i;
Jean-Marc Valin6a74b412018-06-15 16:52:14 -0400559 } else if (mapping_family==2)
Michael Graczyk39256682016-05-02 21:42:18 -0700560 {
561 int i;
Drew Allen17e14fb2017-04-28 09:58:04 -0700562 if (!validate_ambisonics(channels, streams, coupled_streams))
563 return OPUS_BAD_ARG;
564 for(i = 0; i < (*streams - *coupled_streams); i++)
565 mapping[i] = i + (*coupled_streams * 2);
566 for(i = 0; i < *coupled_streams * 2; i++)
567 mapping[i + (*streams - *coupled_streams)] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400568 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400569 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700570
571 if (channels>2 && mapping_family==1) {
572 mapping_type = MAPPING_TYPE_SURROUND;
Jean-Marc Valin6a74b412018-06-15 16:52:14 -0400573 } else if (mapping_family==2)
Michael Graczyk39256682016-05-02 21:42:18 -0700574 {
575 mapping_type = MAPPING_TYPE_AMBISONICS;
Michael Graczyk39256682016-05-02 21:42:18 -0700576 } else
577 {
578 mapping_type = MAPPING_TYPE_NONE;
579 }
580 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
581 *coupled_streams, mapping,
582 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400583}
584
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500585OpusMSEncoder *opus_multistream_encoder_create(
586 opus_int32 Fs,
587 int channels,
588 int streams,
589 int coupled_streams,
590 const unsigned char *mapping,
591 int application,
592 int *error
593)
594{
595 int ret;
596 OpusMSEncoder *st;
597 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800598 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500599 {
600 if (error)
601 *error = OPUS_BAD_ARG;
602 return NULL;
603 }
604 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
605 if (st==NULL)
606 {
607 if (error)
608 *error = OPUS_ALLOC_FAIL;
609 return NULL;
610 }
611 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
612 if (ret != OPUS_OK)
613 {
614 opus_free(st);
615 st = NULL;
616 }
617 if (error)
618 *error = ret;
619 return st;
620}
621
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400622OpusMSEncoder *opus_multistream_surround_encoder_create(
623 opus_int32 Fs,
624 int channels,
625 int mapping_family,
626 int *streams,
627 int *coupled_streams,
628 unsigned char *mapping,
629 int application,
630 int *error
631)
632{
633 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800634 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400635 OpusMSEncoder *st;
636 if ((channels>255) || (channels<1))
637 {
638 if (error)
639 *error = OPUS_BAD_ARG;
640 return NULL;
641 }
Mark Harris25b27a92014-11-27 08:48:09 -0800642 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
643 if (!size)
644 {
645 if (error)
646 *error = OPUS_UNIMPLEMENTED;
647 return NULL;
648 }
649 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400650 if (st==NULL)
651 {
652 if (error)
653 *error = OPUS_ALLOC_FAIL;
654 return NULL;
655 }
656 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
657 if (ret != OPUS_OK)
658 {
659 opus_free(st);
660 st = NULL;
661 }
662 if (error)
663 *error = ret;
664 return st;
665}
666
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700667static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400668 OpusMSEncoder *st,
669 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700670 int frame_size,
671 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400672 )
673{
674 int i;
675 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400676 int stream_offset;
677 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400678 int coupled_ratio; /* Q8 */
679 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400680 int nb_lfe;
681 int nb_uncoupled;
682 int nb_coupled;
683 int nb_normal;
684 opus_int32 channel_offset;
685 opus_int32 bitrate;
686 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400687
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400688 nb_lfe = (st->lfe_stream!=-1);
689 nb_coupled = st->layout.nb_coupled_streams;
690 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
691 nb_normal = 2*nb_coupled + nb_uncoupled;
692
693 /* Give each non-LFE channel enough bits per channel for coding band energy. */
694 channel_offset = 40*IMAX(50, Fs/frame_size);
695
696 if (st->bitrate_bps==OPUS_AUTO)
697 {
698 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
699 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
700 {
701 bitrate = nb_normal*300000 + nb_lfe*128000;
702 } else {
703 bitrate = st->bitrate_bps;
704 }
705
706 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
707 total rate for the non-energy part to avoid problems at really low rate. */
708 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
709
710 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400711 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400712 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
713 stream_offset = IMAX(0, IMIN(20000, stream_offset));
714
715 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400716 coupled_ratio = 512;
717 /* 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 -0400718 lfe_ratio = 32;
719
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400720 total = (nb_uncoupled<<8) /* mono */
721 + coupled_ratio*nb_coupled /* stereo */
722 + nb_lfe*lfe_ratio;
723 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 -0400724
725 for (i=0;i<st->layout.nb_streams;i++)
726 {
727 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400728 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400729 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400730 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400731 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400732 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700733 }
734}
735
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700736static void ambisonics_rate_allocation(
737 OpusMSEncoder *st,
738 opus_int32 *rate,
739 int frame_size,
740 opus_int32 Fs
741 )
742{
743 int i;
Jean-Marc Valindd6d6d52018-07-28 13:50:45 -0400744 opus_int32 total_rate;
745 opus_int32 directional_rate;
746 opus_int32 nondirectional_rate;
747 opus_int32 leftover_bits;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700748
Drew Allen17e14fb2017-04-28 09:58:04 -0700749 /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
750 * as many bits as all other ambisonics channels.
751 */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700752 const int rate_ratio_num = 4;
753 const int rate_ratio_den = 3;
Drew Allen17e14fb2017-04-28 09:58:04 -0700754 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Felicia Lim6adfa702018-07-27 18:10:05 -0700755 /* The omnidirectional ambisonics and non-diegetic stereo channels */
Drew Allen17e14fb2017-04-28 09:58:04 -0700756 const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
Felicia Lim6adfa702018-07-27 18:10:05 -0700757 /* The remaining ambisonics channels */
758 const int nb_directional_channels = nb_channels - nb_nondirectional_channels;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700759
760 if (st->bitrate_bps==OPUS_AUTO)
761 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700762 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
Jean-Marc Valindd6d6d52018-07-28 13:50:45 -0400763 (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700764 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
765 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700766 total_rate = nb_channels * 320000;
767 } else
768 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700769 total_rate = st->bitrate_bps;
770 }
771
Drew Allen17e14fb2017-04-28 09:58:04 -0700772 /* Let y be the directional rate, m be the num of nondirectional channels
773 * m = (s + 1)
774 * and let p, q be integers such that the nondirectional rate is
775 * m_rate = (p / q) * y
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700776 * Also let T be the total bitrate to allocate. Then
Drew Allen17e14fb2017-04-28 09:58:04 -0700777 * T = (n - m) * y + m * m_rate
778 * Solving for y,
779 * y = (q * T) / (m * (p - q) + n * q)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700780 */
Drew Allen17e14fb2017-04-28 09:58:04 -0700781 directional_rate =
782 total_rate * rate_ratio_den
783 / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
784 + nb_channels * rate_ratio_den);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700785
Drew Allen17e14fb2017-04-28 09:58:04 -0700786 /* Calculate the nondirectional rate.
787 * m_rate = y * (p / q)
788 */
789 nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
790
791 /* Calculate the leftover from truncation error.
792 * leftover = T - y * (n - m) - m_rate * m
793 * Place leftover bits in omnidirectional channel.
794 */
795 leftover_bits = total_rate
796 - directional_rate * nb_directional_channels
797 - nondirectional_rate * nb_nondirectional_channels;
798
799 /* Calculate rates for each channel */
800 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700801 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700802 if (i < st->layout.nb_coupled_streams)
803 {
804 rate[i] = nondirectional_rate * 2;
805 } else if (i == st->layout.nb_coupled_streams)
806 {
807 rate[i] = nondirectional_rate + leftover_bits;
808 } else
809 {
810 rate[i] = directional_rate;
811 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700812 }
813}
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700814
815static opus_int32 rate_allocation(
816 OpusMSEncoder *st,
817 opus_int32 *rate,
818 int frame_size
819 )
820{
821 int i;
822 opus_int32 rate_sum=0;
823 opus_int32 Fs;
824 char *ptr;
825
826 ptr = (char*)st + align(sizeof(OpusMSEncoder));
827 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
828
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700829 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
830 ambisonics_rate_allocation(st, rate, frame_size, Fs);
831 } else
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700832 {
833 surround_rate_allocation(st, rate, frame_size, Fs);
834 }
835
836 for (i=0;i<st->layout.nb_streams;i++)
837 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400838 rate[i] = IMAX(rate[i], 500);
839 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400840 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400841 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400842}
843
Felicia Lim0962cbe2016-10-27 17:03:36 -0700844/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
845#define MS_FRAME_TMP (6*1275+12)
Andrew Allen65f11d32017-12-04 15:32:18 -0800846int opus_multistream_encode_native
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500847(
848 OpusMSEncoder *st,
849 opus_copy_channel_in_func copy_channel_in,
850 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400851 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500852 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500853 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400854 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500855 downmix_func downmix,
Andrew Allen65f11d32017-12-04 15:32:18 -0800856 int float_api,
857 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500858)
859{
860 opus_int32 Fs;
861 int coupled_size;
862 int mono_size;
863 int s;
864 char *ptr;
865 int tot_size;
866 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400867 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500868 unsigned char tmp_data[MS_FRAME_TMP];
869 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400870 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500871 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400872 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400873 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400874 opus_val32 *mem = NULL;
875 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400876 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400877 opus_int32 rate_sum;
878 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500879 ALLOC_STACK;
880
Michael Graczyk39256682016-05-02 21:42:18 -0700881 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400882 {
883 preemph_mem = ms_get_preemph_mem(st);
884 mem = ms_get_window_mem(st);
885 }
886
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500887 ptr = (char*)st + align(sizeof(OpusMSEncoder));
888 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400889 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500890 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500891
Mark Harrisd73c5a92016-11-05 22:01:52 -0700892 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
893 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500894 {
895 RESTORE_STACK;
896 return OPUS_BAD_ARG;
897 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400898
899 /* Smallest packet the encoder can produce. */
900 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700901 /* 100 ms needs an extra byte per stream for the ToC. */
902 if (Fs/frame_size == 10)
903 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400904 if (max_data_bytes < smallest_packet)
905 {
906 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400907 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400908 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500909 ALLOC(buf, 2*frame_size, opus_val16);
910 coupled_size = opus_encoder_get_size(2);
911 mono_size = opus_encoder_get_size(1);
912
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400913 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700914 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400915 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500916 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 -0400917 }
918
Jean-Marc Valin74483662012-12-17 16:23:42 -0500919 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700920 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400921
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400922 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400923 {
924 if (st->bitrate_bps == OPUS_AUTO)
925 {
926 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
927 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
928 {
929 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
930 3*st->bitrate_bps/(3*8*Fs/frame_size)));
931 }
932 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500933 ptr = (char*)st + align(sizeof(OpusMSEncoder));
934 for (s=0;s<st->layout.nb_streams;s++)
935 {
936 OpusEncoder *enc;
937 enc = (OpusEncoder*)ptr;
938 if (s < st->layout.nb_coupled_streams)
939 ptr += align(coupled_size);
940 else
941 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400942 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700943 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400944 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400945 opus_int32 equiv_rate;
946 equiv_rate = st->bitrate_bps;
947 if (frame_size*50 < Fs)
948 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500949 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400950 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500951 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400952 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500953 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400954 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
955 else
956 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400957 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400958 {
959 /* To preserve the spatial image, force stereo CELT on coupled streams */
960 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400961 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400962 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400963 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700964 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
965 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
966 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500967 }
968
969 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500970 /* Counting ToC */
971 tot_size = 0;
972 for (s=0;s<st->layout.nb_streams;s++)
973 {
974 OpusEncoder *enc;
975 int len;
976 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400977 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400978 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500979
980 opus_repacketizer_init(&rp);
981 enc = (OpusEncoder*)ptr;
982 if (s < st->layout.nb_coupled_streams)
983 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400984 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500985 int left, right;
986 left = get_left_channel(&st->layout, s, -1);
987 right = get_right_channel(&st->layout, s, -1);
988 (*copy_channel_in)(buf, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -0800989 pcm, st->layout.nb_channels, left, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500990 (*copy_channel_in)(buf+1, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -0800991 pcm, st->layout.nb_channels, right, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500992 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700993 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400994 {
995 for (i=0;i<21;i++)
996 {
997 bandLogE[i] = bandSMR[21*left+i];
998 bandLogE[21+i] = bandSMR[21*right+i];
999 }
1000 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001001 c1 = left;
1002 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001003 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001004 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001005 int chan = get_mono_channel(&st->layout, s, -1);
1006 (*copy_channel_in)(buf, 1,
Andrew Allen65f11d32017-12-04 15:32:18 -08001007 pcm, st->layout.nb_channels, chan, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001008 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001009 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001010 {
1011 for (i=0;i<21;i++)
1012 bandLogE[i] = bandSMR[21*chan+i];
1013 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001014 c1 = chan;
1015 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001016 }
Michael Graczyk39256682016-05-02 21:42:18 -07001017 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001018 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001019 /* number of bytes left (+Toc) */
1020 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001021 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001022 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001023 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001024 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001025 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001026 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001027 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001028 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001029 if (!vbr && s == st->layout.nb_streams-1)
1030 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001031 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001032 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001033 if (len<0)
1034 {
1035 RESTORE_STACK;
1036 return len;
1037 }
1038 /* We need to use the repacketizer to add the self-delimiting lengths
1039 while taking into account the fact that the encoder can now return
1040 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001041 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1042 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1043 with the encoder. */
1044 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001045 {
1046 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001047 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001048 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001049 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1050 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 -05001051 data += len;
1052 tot_size += len;
1053 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001054 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001055 RESTORE_STACK;
1056 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001057}
1058
Pedro Becerra1af7f952013-07-11 00:00:47 -04001059#if !defined(DISABLE_FLOAT_API)
1060static void opus_copy_channel_in_float(
1061 opus_val16 *dst,
1062 int dst_stride,
1063 const void *src,
1064 int src_stride,
1065 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001066 int frame_size,
1067 void *user_data
Pedro Becerra1af7f952013-07-11 00:00:47 -04001068)
1069{
1070 const float *float_src;
1071 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001072 (void)user_data;
Pedro Becerra1af7f952013-07-11 00:00:47 -04001073 float_src = (const float *)src;
1074 for (i=0;i<frame_size;i++)
1075#if defined(FIXED_POINT)
1076 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1077#else
1078 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1079#endif
1080}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001081#endif
1082
1083static void opus_copy_channel_in_short(
1084 opus_val16 *dst,
1085 int dst_stride,
1086 const void *src,
1087 int src_stride,
1088 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001089 int frame_size,
1090 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001091)
1092{
1093 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001094 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001095 (void)user_data;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001096 short_src = (const opus_int16 *)src;
1097 for (i=0;i<frame_size;i++)
1098#if defined(FIXED_POINT)
1099 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1100#else
1101 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1102#endif
1103}
1104
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001105
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001106#ifdef FIXED_POINT
1107int opus_multistream_encode(
1108 OpusMSEncoder *st,
1109 const opus_val16 *pcm,
1110 int frame_size,
1111 unsigned char *data,
1112 opus_int32 max_data_bytes
1113)
1114{
1115 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001116 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001117}
1118
1119#ifndef DISABLE_FLOAT_API
1120int opus_multistream_encode_float(
1121 OpusMSEncoder *st,
1122 const float *pcm,
1123 int frame_size,
1124 unsigned char *data,
1125 opus_int32 max_data_bytes
1126)
1127{
1128 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001129 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001130}
1131#endif
1132
1133#else
1134
1135int opus_multistream_encode_float
1136(
1137 OpusMSEncoder *st,
1138 const opus_val16 *pcm,
1139 int frame_size,
1140 unsigned char *data,
1141 opus_int32 max_data_bytes
1142)
1143{
1144 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001145 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001146}
1147
1148int opus_multistream_encode(
1149 OpusMSEncoder *st,
1150 const opus_int16 *pcm,
1151 int frame_size,
1152 unsigned char *data,
1153 opus_int32 max_data_bytes
1154)
1155{
1156 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001157 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001158}
1159#endif
1160
Andrew Allenf643c032017-11-07 13:26:23 -08001161int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
1162 va_list ap)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001163{
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001164 int coupled_size, mono_size;
1165 char *ptr;
1166 int ret = OPUS_OK;
1167
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001168 coupled_size = opus_encoder_get_size(2);
1169 mono_size = opus_encoder_get_size(1);
1170 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1171 switch (request)
1172 {
1173 case OPUS_SET_BITRATE_REQUEST:
1174 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001175 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001176 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001177 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001178 if (value <= 0)
1179 goto bad_arg;
1180 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001181 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001182 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001183 }
1184 break;
1185 case OPUS_GET_BITRATE_REQUEST:
1186 {
1187 int s;
1188 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001189 if (!value)
1190 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001191 goto bad_arg;
1192 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001193 *value = 0;
1194 for (s=0;s<st->layout.nb_streams;s++)
1195 {
1196 opus_int32 rate;
1197 OpusEncoder *enc;
1198 enc = (OpusEncoder*)ptr;
1199 if (s < st->layout.nb_coupled_streams)
1200 ptr += align(coupled_size);
1201 else
1202 ptr += align(mono_size);
1203 opus_encoder_ctl(enc, request, &rate);
1204 *value += rate;
1205 }
1206 }
1207 break;
1208 case OPUS_GET_LSB_DEPTH_REQUEST:
1209 case OPUS_GET_VBR_REQUEST:
1210 case OPUS_GET_APPLICATION_REQUEST:
1211 case OPUS_GET_BANDWIDTH_REQUEST:
1212 case OPUS_GET_COMPLEXITY_REQUEST:
1213 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1214 case OPUS_GET_DTX_REQUEST:
1215 case OPUS_GET_VOICE_RATIO_REQUEST:
1216 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1217 case OPUS_GET_SIGNAL_REQUEST:
1218 case OPUS_GET_LOOKAHEAD_REQUEST:
1219 case OPUS_GET_SAMPLE_RATE_REQUEST:
1220 case OPUS_GET_INBAND_FEC_REQUEST:
1221 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001222 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001223 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001224 {
1225 OpusEncoder *enc;
1226 /* For int32* GET params, just query the first stream */
1227 opus_int32 *value = va_arg(ap, opus_int32*);
1228 enc = (OpusEncoder*)ptr;
1229 ret = opus_encoder_ctl(enc, request, value);
1230 }
1231 break;
1232 case OPUS_GET_FINAL_RANGE_REQUEST:
1233 {
1234 int s;
1235 opus_uint32 *value = va_arg(ap, opus_uint32*);
1236 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001237 if (!value)
1238 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001239 goto bad_arg;
1240 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001241 *value=0;
1242 for (s=0;s<st->layout.nb_streams;s++)
1243 {
1244 OpusEncoder *enc;
1245 enc = (OpusEncoder*)ptr;
1246 if (s < st->layout.nb_coupled_streams)
1247 ptr += align(coupled_size);
1248 else
1249 ptr += align(mono_size);
1250 ret = opus_encoder_ctl(enc, request, &tmp);
1251 if (ret != OPUS_OK) break;
1252 *value ^= tmp;
1253 }
1254 }
1255 break;
1256 case OPUS_SET_LSB_DEPTH_REQUEST:
1257 case OPUS_SET_COMPLEXITY_REQUEST:
1258 case OPUS_SET_VBR_REQUEST:
1259 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001260 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001261 case OPUS_SET_BANDWIDTH_REQUEST:
1262 case OPUS_SET_SIGNAL_REQUEST:
1263 case OPUS_SET_APPLICATION_REQUEST:
1264 case OPUS_SET_INBAND_FEC_REQUEST:
1265 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1266 case OPUS_SET_DTX_REQUEST:
1267 case OPUS_SET_FORCE_MODE_REQUEST:
1268 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001269 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001270 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001271 {
1272 int s;
1273 /* This works for int32 params */
1274 opus_int32 value = va_arg(ap, opus_int32);
1275 for (s=0;s<st->layout.nb_streams;s++)
1276 {
1277 OpusEncoder *enc;
1278
1279 enc = (OpusEncoder*)ptr;
1280 if (s < st->layout.nb_coupled_streams)
1281 ptr += align(coupled_size);
1282 else
1283 ptr += align(mono_size);
1284 ret = opus_encoder_ctl(enc, request, value);
1285 if (ret != OPUS_OK)
1286 break;
1287 }
1288 }
1289 break;
1290 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1291 {
1292 int s;
1293 opus_int32 stream_id;
1294 OpusEncoder **value;
1295 stream_id = va_arg(ap, opus_int32);
1296 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1297 ret = OPUS_BAD_ARG;
1298 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001299 if (!value)
1300 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001301 goto bad_arg;
1302 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001303 for (s=0;s<stream_id;s++)
1304 {
1305 if (s < st->layout.nb_coupled_streams)
1306 ptr += align(coupled_size);
1307 else
1308 ptr += align(mono_size);
1309 }
1310 *value = (OpusEncoder*)ptr;
1311 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001312 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001313 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001314 {
1315 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001316 st->variable_duration = value;
1317 }
1318 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001319 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001320 {
1321 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001322 if (!value)
1323 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001324 goto bad_arg;
1325 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001326 *value = st->variable_duration;
1327 }
1328 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001329 case OPUS_RESET_STATE:
1330 {
1331 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001332 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001333 {
1334 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1335 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1336 }
1337 for (s=0;s<st->layout.nb_streams;s++)
1338 {
1339 OpusEncoder *enc;
1340 enc = (OpusEncoder*)ptr;
1341 if (s < st->layout.nb_coupled_streams)
1342 ptr += align(coupled_size);
1343 else
1344 ptr += align(mono_size);
1345 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1346 if (ret != OPUS_OK)
1347 break;
1348 }
1349 }
1350 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001351 default:
1352 ret = OPUS_UNIMPLEMENTED;
1353 break;
1354 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001355 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001356bad_arg:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001357 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001358}
1359
Andrew Allenf643c032017-11-07 13:26:23 -08001360int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1361{
1362 int ret;
1363 va_list ap;
1364 va_start(ap, request);
1365 ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
1366 va_end(ap);
1367 return ret;
1368}
1369
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001370void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1371{
1372 opus_free(st);
1373}