blob: 9cb9bf3458f7d633abc3a0c8b349cb29886c6b17 [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;
Marcin Gorzelc2a6ac42018-08-30 13:15:21 +0100745 opus_int32 per_stream_rate;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700746
Drew Allen17e14fb2017-04-28 09:58:04 -0700747 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700748
749 if (st->bitrate_bps==OPUS_AUTO)
750 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700751 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
Jean-Marc Valindd6d6d52018-07-28 13:50:45 -0400752 (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700753 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
754 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700755 total_rate = nb_channels * 320000;
756 } else
757 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700758 total_rate = st->bitrate_bps;
759 }
760
Marcin Gorzelc2a6ac42018-08-30 13:15:21 +0100761 /* Allocate equal number of bits to Ambisonic (uncoupled) and non-diegetic
762 * (coupled) streams */
763 per_stream_rate = total_rate / st->layout.nb_streams;
Drew Allen17e14fb2017-04-28 09:58:04 -0700764 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700765 {
Marcin Gorzelc2a6ac42018-08-30 13:15:21 +0100766 rate[i] = per_stream_rate;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700767 }
768}
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700769
770static opus_int32 rate_allocation(
771 OpusMSEncoder *st,
772 opus_int32 *rate,
773 int frame_size
774 )
775{
776 int i;
777 opus_int32 rate_sum=0;
778 opus_int32 Fs;
779 char *ptr;
780
781 ptr = (char*)st + align(sizeof(OpusMSEncoder));
782 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
783
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700784 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
785 ambisonics_rate_allocation(st, rate, frame_size, Fs);
786 } else
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700787 {
788 surround_rate_allocation(st, rate, frame_size, Fs);
789 }
790
791 for (i=0;i<st->layout.nb_streams;i++)
792 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400793 rate[i] = IMAX(rate[i], 500);
794 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400795 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400796 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400797}
798
Felicia Lim0962cbe2016-10-27 17:03:36 -0700799/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
800#define MS_FRAME_TMP (6*1275+12)
Andrew Allen65f11d32017-12-04 15:32:18 -0800801int opus_multistream_encode_native
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500802(
803 OpusMSEncoder *st,
804 opus_copy_channel_in_func copy_channel_in,
805 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400806 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500807 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500808 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400809 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500810 downmix_func downmix,
Andrew Allen65f11d32017-12-04 15:32:18 -0800811 int float_api,
812 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500813)
814{
815 opus_int32 Fs;
816 int coupled_size;
817 int mono_size;
818 int s;
819 char *ptr;
820 int tot_size;
821 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400822 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500823 unsigned char tmp_data[MS_FRAME_TMP];
824 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400825 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500826 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400827 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400828 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400829 opus_val32 *mem = NULL;
830 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400831 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400832 opus_int32 rate_sum;
833 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500834 ALLOC_STACK;
835
Michael Graczyk39256682016-05-02 21:42:18 -0700836 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400837 {
838 preemph_mem = ms_get_preemph_mem(st);
839 mem = ms_get_window_mem(st);
840 }
841
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500842 ptr = (char*)st + align(sizeof(OpusMSEncoder));
843 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400844 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500845 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500846
Mark Harrisd73c5a92016-11-05 22:01:52 -0700847 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
848 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500849 {
850 RESTORE_STACK;
851 return OPUS_BAD_ARG;
852 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400853
854 /* Smallest packet the encoder can produce. */
855 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700856 /* 100 ms needs an extra byte per stream for the ToC. */
857 if (Fs/frame_size == 10)
858 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400859 if (max_data_bytes < smallest_packet)
860 {
861 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400862 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400863 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500864 ALLOC(buf, 2*frame_size, opus_val16);
865 coupled_size = opus_encoder_get_size(2);
866 mono_size = opus_encoder_get_size(1);
867
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400868 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700869 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400870 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500871 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 -0400872 }
873
Jean-Marc Valin74483662012-12-17 16:23:42 -0500874 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700875 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400876
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400877 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400878 {
879 if (st->bitrate_bps == OPUS_AUTO)
880 {
881 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
882 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
883 {
884 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
885 3*st->bitrate_bps/(3*8*Fs/frame_size)));
886 }
887 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500888 ptr = (char*)st + align(sizeof(OpusMSEncoder));
889 for (s=0;s<st->layout.nb_streams;s++)
890 {
891 OpusEncoder *enc;
892 enc = (OpusEncoder*)ptr;
893 if (s < st->layout.nb_coupled_streams)
894 ptr += align(coupled_size);
895 else
896 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400897 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700898 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400899 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400900 opus_int32 equiv_rate;
901 equiv_rate = st->bitrate_bps;
902 if (frame_size*50 < Fs)
903 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500904 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400905 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500906 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400907 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500908 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400909 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
910 else
911 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400912 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400913 {
914 /* To preserve the spatial image, force stereo CELT on coupled streams */
915 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400916 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400917 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400918 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700919 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
920 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
921 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500922 }
923
924 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500925 /* Counting ToC */
926 tot_size = 0;
927 for (s=0;s<st->layout.nb_streams;s++)
928 {
929 OpusEncoder *enc;
930 int len;
931 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400932 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400933 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500934
935 opus_repacketizer_init(&rp);
936 enc = (OpusEncoder*)ptr;
937 if (s < st->layout.nb_coupled_streams)
938 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400939 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500940 int left, right;
941 left = get_left_channel(&st->layout, s, -1);
942 right = get_right_channel(&st->layout, s, -1);
943 (*copy_channel_in)(buf, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -0800944 pcm, st->layout.nb_channels, left, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500945 (*copy_channel_in)(buf+1, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -0800946 pcm, st->layout.nb_channels, right, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500947 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700948 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400949 {
950 for (i=0;i<21;i++)
951 {
952 bandLogE[i] = bandSMR[21*left+i];
953 bandLogE[21+i] = bandSMR[21*right+i];
954 }
955 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400956 c1 = left;
957 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500958 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400959 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500960 int chan = get_mono_channel(&st->layout, s, -1);
961 (*copy_channel_in)(buf, 1,
Andrew Allen65f11d32017-12-04 15:32:18 -0800962 pcm, st->layout.nb_channels, chan, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500963 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700964 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400965 {
966 for (i=0;i<21;i++)
967 bandLogE[i] = bandSMR[21*chan+i];
968 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400969 c1 = chan;
970 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500971 }
Michael Graczyk39256682016-05-02 21:42:18 -0700972 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400973 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500974 /* number of bytes left (+Toc) */
975 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -0400976 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400977 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -0700978 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -0700979 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -0700980 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500981 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -0400982 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -0400983 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400984 if (!vbr && s == st->layout.nb_streams-1)
985 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400986 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500987 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500988 if (len<0)
989 {
990 RESTORE_STACK;
991 return len;
992 }
993 /* We need to use the repacketizer to add the self-delimiting lengths
994 while taking into account the fact that the encoder can now return
995 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400996 ret = opus_repacketizer_cat(&rp, tmp_data, len);
997 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
998 with the encoder. */
999 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001000 {
1001 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001002 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001003 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001004 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1005 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 -05001006 data += len;
1007 tot_size += len;
1008 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001009 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001010 RESTORE_STACK;
1011 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001012}
1013
Pedro Becerra1af7f952013-07-11 00:00:47 -04001014#if !defined(DISABLE_FLOAT_API)
1015static void opus_copy_channel_in_float(
1016 opus_val16 *dst,
1017 int dst_stride,
1018 const void *src,
1019 int src_stride,
1020 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001021 int frame_size,
1022 void *user_data
Pedro Becerra1af7f952013-07-11 00:00:47 -04001023)
1024{
1025 const float *float_src;
1026 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001027 (void)user_data;
Pedro Becerra1af7f952013-07-11 00:00:47 -04001028 float_src = (const float *)src;
1029 for (i=0;i<frame_size;i++)
1030#if defined(FIXED_POINT)
1031 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1032#else
1033 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1034#endif
1035}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001036#endif
1037
1038static void opus_copy_channel_in_short(
1039 opus_val16 *dst,
1040 int dst_stride,
1041 const void *src,
1042 int src_stride,
1043 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001044 int frame_size,
1045 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001046)
1047{
1048 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001049 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001050 (void)user_data;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001051 short_src = (const opus_int16 *)src;
1052 for (i=0;i<frame_size;i++)
1053#if defined(FIXED_POINT)
1054 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1055#else
1056 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1057#endif
1058}
1059
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001060
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001061#ifdef FIXED_POINT
1062int opus_multistream_encode(
1063 OpusMSEncoder *st,
1064 const opus_val16 *pcm,
1065 int frame_size,
1066 unsigned char *data,
1067 opus_int32 max_data_bytes
1068)
1069{
1070 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001071 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001072}
1073
1074#ifndef DISABLE_FLOAT_API
1075int opus_multistream_encode_float(
1076 OpusMSEncoder *st,
1077 const float *pcm,
1078 int frame_size,
1079 unsigned char *data,
1080 opus_int32 max_data_bytes
1081)
1082{
1083 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001084 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001085}
1086#endif
1087
1088#else
1089
1090int opus_multistream_encode_float
1091(
1092 OpusMSEncoder *st,
1093 const opus_val16 *pcm,
1094 int frame_size,
1095 unsigned char *data,
1096 opus_int32 max_data_bytes
1097)
1098{
1099 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001100 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001101}
1102
1103int opus_multistream_encode(
1104 OpusMSEncoder *st,
1105 const opus_int16 *pcm,
1106 int frame_size,
1107 unsigned char *data,
1108 opus_int32 max_data_bytes
1109)
1110{
1111 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001112 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001113}
1114#endif
1115
Andrew Allenf643c032017-11-07 13:26:23 -08001116int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
1117 va_list ap)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001118{
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001119 int coupled_size, mono_size;
1120 char *ptr;
1121 int ret = OPUS_OK;
1122
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001123 coupled_size = opus_encoder_get_size(2);
1124 mono_size = opus_encoder_get_size(1);
1125 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1126 switch (request)
1127 {
1128 case OPUS_SET_BITRATE_REQUEST:
1129 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001130 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001131 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001132 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001133 if (value <= 0)
1134 goto bad_arg;
1135 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001136 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001137 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001138 }
1139 break;
1140 case OPUS_GET_BITRATE_REQUEST:
1141 {
1142 int s;
1143 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001144 if (!value)
1145 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001146 goto bad_arg;
1147 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001148 *value = 0;
1149 for (s=0;s<st->layout.nb_streams;s++)
1150 {
1151 opus_int32 rate;
1152 OpusEncoder *enc;
1153 enc = (OpusEncoder*)ptr;
1154 if (s < st->layout.nb_coupled_streams)
1155 ptr += align(coupled_size);
1156 else
1157 ptr += align(mono_size);
1158 opus_encoder_ctl(enc, request, &rate);
1159 *value += rate;
1160 }
1161 }
1162 break;
1163 case OPUS_GET_LSB_DEPTH_REQUEST:
1164 case OPUS_GET_VBR_REQUEST:
1165 case OPUS_GET_APPLICATION_REQUEST:
1166 case OPUS_GET_BANDWIDTH_REQUEST:
1167 case OPUS_GET_COMPLEXITY_REQUEST:
1168 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1169 case OPUS_GET_DTX_REQUEST:
1170 case OPUS_GET_VOICE_RATIO_REQUEST:
1171 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1172 case OPUS_GET_SIGNAL_REQUEST:
1173 case OPUS_GET_LOOKAHEAD_REQUEST:
1174 case OPUS_GET_SAMPLE_RATE_REQUEST:
1175 case OPUS_GET_INBAND_FEC_REQUEST:
1176 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001177 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001178 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001179 {
1180 OpusEncoder *enc;
1181 /* For int32* GET params, just query the first stream */
1182 opus_int32 *value = va_arg(ap, opus_int32*);
1183 enc = (OpusEncoder*)ptr;
1184 ret = opus_encoder_ctl(enc, request, value);
1185 }
1186 break;
1187 case OPUS_GET_FINAL_RANGE_REQUEST:
1188 {
1189 int s;
1190 opus_uint32 *value = va_arg(ap, opus_uint32*);
1191 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001192 if (!value)
1193 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001194 goto bad_arg;
1195 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001196 *value=0;
1197 for (s=0;s<st->layout.nb_streams;s++)
1198 {
1199 OpusEncoder *enc;
1200 enc = (OpusEncoder*)ptr;
1201 if (s < st->layout.nb_coupled_streams)
1202 ptr += align(coupled_size);
1203 else
1204 ptr += align(mono_size);
1205 ret = opus_encoder_ctl(enc, request, &tmp);
1206 if (ret != OPUS_OK) break;
1207 *value ^= tmp;
1208 }
1209 }
1210 break;
1211 case OPUS_SET_LSB_DEPTH_REQUEST:
1212 case OPUS_SET_COMPLEXITY_REQUEST:
1213 case OPUS_SET_VBR_REQUEST:
1214 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001215 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001216 case OPUS_SET_BANDWIDTH_REQUEST:
1217 case OPUS_SET_SIGNAL_REQUEST:
1218 case OPUS_SET_APPLICATION_REQUEST:
1219 case OPUS_SET_INBAND_FEC_REQUEST:
1220 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1221 case OPUS_SET_DTX_REQUEST:
1222 case OPUS_SET_FORCE_MODE_REQUEST:
1223 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001224 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001225 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001226 {
1227 int s;
1228 /* This works for int32 params */
1229 opus_int32 value = va_arg(ap, opus_int32);
1230 for (s=0;s<st->layout.nb_streams;s++)
1231 {
1232 OpusEncoder *enc;
1233
1234 enc = (OpusEncoder*)ptr;
1235 if (s < st->layout.nb_coupled_streams)
1236 ptr += align(coupled_size);
1237 else
1238 ptr += align(mono_size);
1239 ret = opus_encoder_ctl(enc, request, value);
1240 if (ret != OPUS_OK)
1241 break;
1242 }
1243 }
1244 break;
1245 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1246 {
1247 int s;
1248 opus_int32 stream_id;
1249 OpusEncoder **value;
1250 stream_id = va_arg(ap, opus_int32);
1251 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1252 ret = OPUS_BAD_ARG;
1253 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001254 if (!value)
1255 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001256 goto bad_arg;
1257 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001258 for (s=0;s<stream_id;s++)
1259 {
1260 if (s < st->layout.nb_coupled_streams)
1261 ptr += align(coupled_size);
1262 else
1263 ptr += align(mono_size);
1264 }
1265 *value = (OpusEncoder*)ptr;
1266 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001267 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001268 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001269 {
1270 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001271 st->variable_duration = value;
1272 }
1273 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001274 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001275 {
1276 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001277 if (!value)
1278 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001279 goto bad_arg;
1280 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001281 *value = st->variable_duration;
1282 }
1283 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001284 case OPUS_RESET_STATE:
1285 {
1286 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001287 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001288 {
1289 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1290 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1291 }
1292 for (s=0;s<st->layout.nb_streams;s++)
1293 {
1294 OpusEncoder *enc;
1295 enc = (OpusEncoder*)ptr;
1296 if (s < st->layout.nb_coupled_streams)
1297 ptr += align(coupled_size);
1298 else
1299 ptr += align(mono_size);
1300 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1301 if (ret != OPUS_OK)
1302 break;
1303 }
1304 }
1305 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001306 default:
1307 ret = OPUS_UNIMPLEMENTED;
1308 break;
1309 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001310 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001311bad_arg:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001312 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001313}
1314
Andrew Allenf643c032017-11-07 13:26:23 -08001315int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1316{
1317 int ret;
1318 va_list ap;
1319 va_start(ap, request);
1320 ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
1321 va_end(ap);
1322 return ret;
1323}
1324
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001325void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1326{
1327 opus_free(st);
1328}