blob: 1df9e7db84bab676c782caa5f62fcd600eccb3de [file] [log] [blame]
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001/* Copyright (c) 2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "opus_multistream.h"
33#include "opus.h"
34#include "opus_private.h"
35#include "stack_alloc.h"
36#include <stdarg.h>
37#include "float_cast.h"
38#include "os_support.h"
Jean-Marc Valin49587512013-07-07 02:50:18 -040039#include "mathops.h"
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040040#include "mdct.h"
41#include "modes.h"
42#include "bands.h"
43#include "quant_bands.h"
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -040044#include "pitch.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050045
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040046typedef struct {
47 int nb_streams;
48 int nb_coupled_streams;
49 unsigned char mapping[8];
50} VorbisLayout;
51
52/* Index is nb_channel-1*/
53static const VorbisLayout vorbis_mappings[8] = {
54 {1, 0, {0}}, /* 1: mono */
55 {1, 1, {0, 1}}, /* 2: stereo */
56 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
57 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
58 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
59 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
60 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
61 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
62};
63
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040064static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
65{
66 int s;
67 char *ptr;
68 int coupled_size, mono_size;
69
70 coupled_size = opus_encoder_get_size(2);
71 mono_size = opus_encoder_get_size(1);
72 ptr = (char*)st + align(sizeof(OpusMSEncoder));
73 for (s=0;s<st->layout.nb_streams;s++)
74 {
75 if (s < st->layout.nb_coupled_streams)
76 ptr += align(coupled_size);
77 else
78 ptr += align(mono_size);
79 }
Mark Harris4feb0df2015-08-07 01:24:48 -070080 /* void* cast avoids clang -Wcast-align warning */
81 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040082}
83
84static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
85{
86 int s;
87 char *ptr;
88 int coupled_size, mono_size;
89
90 coupled_size = opus_encoder_get_size(2);
91 mono_size = opus_encoder_get_size(1);
92 ptr = (char*)st + align(sizeof(OpusMSEncoder));
93 for (s=0;s<st->layout.nb_streams;s++)
94 {
95 if (s < st->layout.nb_coupled_streams)
96 ptr += align(coupled_size);
97 else
98 ptr += align(mono_size);
99 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700100 /* void* cast avoids clang -Wcast-align warning */
101 return (opus_val32*)(void*)ptr;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400102}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500103
Drew Allen17e14fb2017-04-28 09:58:04 -0700104#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
105static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
106{
107 int order_plus_one;
108 int acn_channels;
109 int nondiegetic_channels;
110
111 order_plus_one = isqrt32(nb_channels);
112 acn_channels = order_plus_one * order_plus_one;
113 nondiegetic_channels = nb_channels - acn_channels;
114
115 if (order_plus_one < 1 || order_plus_one > 15 ||
116 (nondiegetic_channels != 0 && nondiegetic_channels != 2))
117 return 0;
118
119 if (nb_streams)
120 *nb_streams = acn_channels + (nondiegetic_channels != 0);
121 if (nb_coupled_streams)
122 *nb_coupled_streams = nondiegetic_channels != 0;
123 return 1;
124}
125#endif
126
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;
Michael Graczyk39256682016-05-02 21:42:18 -0700415#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
416 } else if (mapping_family==254)
417 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700418 if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
419 return 0;
Michael Graczyk39256682016-05-02 21:42:18 -0700420#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400421 } else
422 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400423 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
424 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400425 {
426 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
427 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400428 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400429}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500430
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400431static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500432 OpusMSEncoder *st,
433 opus_int32 Fs,
434 int channels,
435 int streams,
436 int coupled_streams,
437 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400438 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700439 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500440)
441{
442 int coupled_size;
443 int mono_size;
444 int i, ret;
445 char *ptr;
446
447 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800448 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500449 return OPUS_BAD_ARG;
450
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500451 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500452 st->layout.nb_channels = channels;
453 st->layout.nb_streams = streams;
454 st->layout.nb_coupled_streams = coupled_streams;
Michael Graczyk39256682016-05-02 21:42:18 -0700455 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400456 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500457 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400458 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500459 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500460 for (i=0;i<st->layout.nb_channels;i++)
461 st->layout.mapping[i] = mapping[i];
Drew Allen17e14fb2017-04-28 09:58:04 -0700462 if (!validate_layout(&st->layout))
463 return OPUS_BAD_ARG;
464 if (mapping_type == MAPPING_TYPE_SURROUND &&
465 !validate_encoder_layout(&st->layout))
466 return OPUS_BAD_ARG;
467#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
468 if (mapping_type == MAPPING_TYPE_AMBISONICS &&
469 !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
470 return OPUS_BAD_ARG;
471#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500472 ptr = (char*)st + align(sizeof(OpusMSEncoder));
473 coupled_size = opus_encoder_get_size(2);
474 mono_size = opus_encoder_get_size(1);
475
476 for (i=0;i<st->layout.nb_coupled_streams;i++)
477 {
478 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400479 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400480 if (i==st->lfe_stream)
481 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500482 ptr += align(coupled_size);
483 }
484 for (;i<st->layout.nb_streams;i++)
485 {
486 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400487 if (i==st->lfe_stream)
488 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500489 if(ret!=OPUS_OK)return ret;
490 ptr += align(mono_size);
491 }
Michael Graczyk39256682016-05-02 21:42:18 -0700492 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400493 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400494 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
495 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400496 }
Michael Graczyk39256682016-05-02 21:42:18 -0700497 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500498 return OPUS_OK;
499}
500
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400501int opus_multistream_encoder_init(
502 OpusMSEncoder *st,
503 opus_int32 Fs,
504 int channels,
505 int streams,
506 int coupled_streams,
507 const unsigned char *mapping,
508 int application
509)
510{
Michael Graczyk39256682016-05-02 21:42:18 -0700511 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
512 coupled_streams, mapping,
513 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400514}
515
516int opus_multistream_surround_encoder_init(
517 OpusMSEncoder *st,
518 opus_int32 Fs,
519 int channels,
520 int mapping_family,
521 int *streams,
522 int *coupled_streams,
523 unsigned char *mapping,
524 int application
525)
526{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700527 MappingType mapping_type;
528
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400529 if ((channels>255) || (channels<1))
530 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400531 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400532 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400533 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400534 if (channels==1)
535 {
536 *streams=1;
537 *coupled_streams=0;
538 mapping[0]=0;
539 } else if (channels==2)
540 {
541 *streams=1;
542 *coupled_streams=1;
543 mapping[0]=0;
544 mapping[1]=1;
545 } else
546 return OPUS_UNIMPLEMENTED;
547 } else if (mapping_family==1 && channels<=8 && channels>=1)
548 {
549 int i;
550 *streams=vorbis_mappings[channels-1].nb_streams;
551 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
552 for (i=0;i<channels;i++)
553 mapping[i] = vorbis_mappings[channels-1].mapping[i];
554 if (channels>=6)
555 st->lfe_stream = *streams-1;
556 } else if (mapping_family==255)
557 {
558 int i;
559 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400560 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400561 for(i=0;i<channels;i++)
562 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700563#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
564 } else if (mapping_family==254)
565 {
566 int i;
Drew Allen17e14fb2017-04-28 09:58:04 -0700567 if (!validate_ambisonics(channels, streams, coupled_streams))
568 return OPUS_BAD_ARG;
569 for(i = 0; i < (*streams - *coupled_streams); i++)
570 mapping[i] = i + (*coupled_streams * 2);
571 for(i = 0; i < *coupled_streams * 2; i++)
572 mapping[i + (*streams - *coupled_streams)] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700573#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400574 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400575 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700576
577 if (channels>2 && mapping_family==1) {
578 mapping_type = MAPPING_TYPE_SURROUND;
579#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
580 } else if (mapping_family==254)
581 {
582 mapping_type = MAPPING_TYPE_AMBISONICS;
583#endif
584 } else
585 {
586 mapping_type = MAPPING_TYPE_NONE;
587 }
588 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
589 *coupled_streams, mapping,
590 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400591}
592
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500593OpusMSEncoder *opus_multistream_encoder_create(
594 opus_int32 Fs,
595 int channels,
596 int streams,
597 int coupled_streams,
598 const unsigned char *mapping,
599 int application,
600 int *error
601)
602{
603 int ret;
604 OpusMSEncoder *st;
605 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800606 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500607 {
608 if (error)
609 *error = OPUS_BAD_ARG;
610 return NULL;
611 }
612 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
613 if (st==NULL)
614 {
615 if (error)
616 *error = OPUS_ALLOC_FAIL;
617 return NULL;
618 }
619 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
620 if (ret != OPUS_OK)
621 {
622 opus_free(st);
623 st = NULL;
624 }
625 if (error)
626 *error = ret;
627 return st;
628}
629
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400630OpusMSEncoder *opus_multistream_surround_encoder_create(
631 opus_int32 Fs,
632 int channels,
633 int mapping_family,
634 int *streams,
635 int *coupled_streams,
636 unsigned char *mapping,
637 int application,
638 int *error
639)
640{
641 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800642 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400643 OpusMSEncoder *st;
644 if ((channels>255) || (channels<1))
645 {
646 if (error)
647 *error = OPUS_BAD_ARG;
648 return NULL;
649 }
Mark Harris25b27a92014-11-27 08:48:09 -0800650 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
651 if (!size)
652 {
653 if (error)
654 *error = OPUS_UNIMPLEMENTED;
655 return NULL;
656 }
657 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400658 if (st==NULL)
659 {
660 if (error)
661 *error = OPUS_ALLOC_FAIL;
662 return NULL;
663 }
664 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
665 if (ret != OPUS_OK)
666 {
667 opus_free(st);
668 st = NULL;
669 }
670 if (error)
671 *error = ret;
672 return st;
673}
674
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700675static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400676 OpusMSEncoder *st,
677 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700678 int frame_size,
679 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400680 )
681{
682 int i;
683 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400684 int stream_offset;
685 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400686 int coupled_ratio; /* Q8 */
687 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400688 int nb_lfe;
689 int nb_uncoupled;
690 int nb_coupled;
691 int nb_normal;
692 opus_int32 channel_offset;
693 opus_int32 bitrate;
694 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400695
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400696 nb_lfe = (st->lfe_stream!=-1);
697 nb_coupled = st->layout.nb_coupled_streams;
698 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
699 nb_normal = 2*nb_coupled + nb_uncoupled;
700
701 /* Give each non-LFE channel enough bits per channel for coding band energy. */
702 channel_offset = 40*IMAX(50, Fs/frame_size);
703
704 if (st->bitrate_bps==OPUS_AUTO)
705 {
706 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
707 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
708 {
709 bitrate = nb_normal*300000 + nb_lfe*128000;
710 } else {
711 bitrate = st->bitrate_bps;
712 }
713
714 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
715 total rate for the non-energy part to avoid problems at really low rate. */
716 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
717
718 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400719 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400720 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
721 stream_offset = IMAX(0, IMIN(20000, stream_offset));
722
723 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400724 coupled_ratio = 512;
725 /* 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 -0400726 lfe_ratio = 32;
727
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400728 total = (nb_uncoupled<<8) /* mono */
729 + coupled_ratio*nb_coupled /* stereo */
730 + nb_lfe*lfe_ratio;
731 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 -0400732
733 for (i=0;i<st->layout.nb_streams;i++)
734 {
735 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400736 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400737 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400738 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400739 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400740 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700741 }
742}
743
744#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
745static void ambisonics_rate_allocation(
746 OpusMSEncoder *st,
747 opus_int32 *rate,
748 int frame_size,
749 opus_int32 Fs
750 )
751{
752 int i;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700753 int total_rate;
Drew Allen17e14fb2017-04-28 09:58:04 -0700754 int directional_rate;
755 int nondirectional_rate;
756 int leftover_bits;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700757
Drew Allen17e14fb2017-04-28 09:58:04 -0700758 /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
759 * as many bits as all other ambisonics channels.
760 */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700761 const int rate_ratio_num = 4;
762 const int rate_ratio_den = 3;
Drew Allen17e14fb2017-04-28 09:58:04 -0700763 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
764 const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
765 const int nb_directional_channels = st->layout.nb_streams - 1;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700766
767 if (st->bitrate_bps==OPUS_AUTO)
768 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700769 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
770 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700771 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
772 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700773 total_rate = nb_channels * 320000;
774 } else
775 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700776 total_rate = st->bitrate_bps;
777 }
778
Drew Allen17e14fb2017-04-28 09:58:04 -0700779 /* Let y be the directional rate, m be the num of nondirectional channels
780 * m = (s + 1)
781 * and let p, q be integers such that the nondirectional rate is
782 * m_rate = (p / q) * y
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700783 * Also let T be the total bitrate to allocate. Then
Drew Allen17e14fb2017-04-28 09:58:04 -0700784 * T = (n - m) * y + m * m_rate
785 * Solving for y,
786 * y = (q * T) / (m * (p - q) + n * q)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700787 */
Drew Allen17e14fb2017-04-28 09:58:04 -0700788 directional_rate =
789 total_rate * rate_ratio_den
790 / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
791 + nb_channels * rate_ratio_den);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700792
Drew Allen17e14fb2017-04-28 09:58:04 -0700793 /* Calculate the nondirectional rate.
794 * m_rate = y * (p / q)
795 */
796 nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
797
798 /* Calculate the leftover from truncation error.
799 * leftover = T - y * (n - m) - m_rate * m
800 * Place leftover bits in omnidirectional channel.
801 */
802 leftover_bits = total_rate
803 - directional_rate * nb_directional_channels
804 - nondirectional_rate * nb_nondirectional_channels;
805
806 /* Calculate rates for each channel */
807 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700808 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700809 if (i < st->layout.nb_coupled_streams)
810 {
811 rate[i] = nondirectional_rate * 2;
812 } else if (i == st->layout.nb_coupled_streams)
813 {
814 rate[i] = nondirectional_rate + leftover_bits;
815 } else
816 {
817 rate[i] = directional_rate;
818 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700819 }
820}
821#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
822
823static opus_int32 rate_allocation(
824 OpusMSEncoder *st,
825 opus_int32 *rate,
826 int frame_size
827 )
828{
829 int i;
830 opus_int32 rate_sum=0;
831 opus_int32 Fs;
832 char *ptr;
833
834 ptr = (char*)st + align(sizeof(OpusMSEncoder));
835 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
836
837#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
838 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
839 ambisonics_rate_allocation(st, rate, frame_size, Fs);
840 } else
841#endif
842 {
843 surround_rate_allocation(st, rate, frame_size, Fs);
844 }
845
846 for (i=0;i<st->layout.nb_streams;i++)
847 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400848 rate[i] = IMAX(rate[i], 500);
849 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400850 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400851 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400852}
853
Felicia Lim0962cbe2016-10-27 17:03:36 -0700854/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
855#define MS_FRAME_TMP (6*1275+12)
Andrew Allen65f11d32017-12-04 15:32:18 -0800856int opus_multistream_encode_native
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500857(
858 OpusMSEncoder *st,
859 opus_copy_channel_in_func copy_channel_in,
860 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400861 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500862 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500863 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400864 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500865 downmix_func downmix,
Andrew Allen65f11d32017-12-04 15:32:18 -0800866 int float_api,
867 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500868)
869{
870 opus_int32 Fs;
871 int coupled_size;
872 int mono_size;
873 int s;
874 char *ptr;
875 int tot_size;
876 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400877 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500878 unsigned char tmp_data[MS_FRAME_TMP];
879 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400880 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500881 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400882 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400883 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400884 opus_val32 *mem = NULL;
885 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400886 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400887 opus_int32 rate_sum;
888 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500889 ALLOC_STACK;
890
Michael Graczyk39256682016-05-02 21:42:18 -0700891 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400892 {
893 preemph_mem = ms_get_preemph_mem(st);
894 mem = ms_get_window_mem(st);
895 }
896
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500897 ptr = (char*)st + align(sizeof(OpusMSEncoder));
898 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400899 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500900 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500901
Mark Harrisd73c5a92016-11-05 22:01:52 -0700902 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
903 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500904 {
905 RESTORE_STACK;
906 return OPUS_BAD_ARG;
907 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400908
909 /* Smallest packet the encoder can produce. */
910 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700911 /* 100 ms needs an extra byte per stream for the ToC. */
912 if (Fs/frame_size == 10)
913 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400914 if (max_data_bytes < smallest_packet)
915 {
916 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400917 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400918 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500919 ALLOC(buf, 2*frame_size, opus_val16);
920 coupled_size = opus_encoder_get_size(2);
921 mono_size = opus_encoder_get_size(1);
922
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400923 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700924 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400925 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500926 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 -0400927 }
928
Jean-Marc Valin74483662012-12-17 16:23:42 -0500929 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700930 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400931
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400932 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400933 {
934 if (st->bitrate_bps == OPUS_AUTO)
935 {
936 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
937 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
938 {
939 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
940 3*st->bitrate_bps/(3*8*Fs/frame_size)));
941 }
942 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500943 ptr = (char*)st + align(sizeof(OpusMSEncoder));
944 for (s=0;s<st->layout.nb_streams;s++)
945 {
946 OpusEncoder *enc;
947 enc = (OpusEncoder*)ptr;
948 if (s < st->layout.nb_coupled_streams)
949 ptr += align(coupled_size);
950 else
951 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400952 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700953 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400954 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400955 opus_int32 equiv_rate;
956 equiv_rate = st->bitrate_bps;
957 if (frame_size*50 < Fs)
958 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500959 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400960 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500961 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400962 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500963 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400964 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
965 else
966 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400967 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400968 {
969 /* To preserve the spatial image, force stereo CELT on coupled streams */
970 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400971 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400972 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400973 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700974#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
975 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
976 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
977 }
978#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500979 }
980
981 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500982 /* Counting ToC */
983 tot_size = 0;
984 for (s=0;s<st->layout.nb_streams;s++)
985 {
986 OpusEncoder *enc;
987 int len;
988 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400989 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400990 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500991
992 opus_repacketizer_init(&rp);
993 enc = (OpusEncoder*)ptr;
994 if (s < st->layout.nb_coupled_streams)
995 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400996 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500997 int left, right;
998 left = get_left_channel(&st->layout, s, -1);
999 right = get_right_channel(&st->layout, s, -1);
1000 (*copy_channel_in)(buf, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -08001001 pcm, st->layout.nb_channels, left, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001002 (*copy_channel_in)(buf+1, 2,
Andrew Allen65f11d32017-12-04 15:32:18 -08001003 pcm, st->layout.nb_channels, right, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001004 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001005 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001006 {
1007 for (i=0;i<21;i++)
1008 {
1009 bandLogE[i] = bandSMR[21*left+i];
1010 bandLogE[21+i] = bandSMR[21*right+i];
1011 }
1012 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001013 c1 = left;
1014 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001015 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001016 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001017 int chan = get_mono_channel(&st->layout, s, -1);
1018 (*copy_channel_in)(buf, 1,
Andrew Allen65f11d32017-12-04 15:32:18 -08001019 pcm, st->layout.nb_channels, chan, frame_size, user_data);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001020 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001021 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001022 {
1023 for (i=0;i<21;i++)
1024 bandLogE[i] = bandSMR[21*chan+i];
1025 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001026 c1 = chan;
1027 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001028 }
Michael Graczyk39256682016-05-02 21:42:18 -07001029 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001030 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001031 /* number of bytes left (+Toc) */
1032 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001033 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001034 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001035 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001036 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001037 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001038 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001039 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001040 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001041 if (!vbr && s == st->layout.nb_streams-1)
1042 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001043 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001044 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001045 if (len<0)
1046 {
1047 RESTORE_STACK;
1048 return len;
1049 }
1050 /* We need to use the repacketizer to add the self-delimiting lengths
1051 while taking into account the fact that the encoder can now return
1052 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001053 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1054 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1055 with the encoder. */
1056 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001057 {
1058 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001059 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001060 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001061 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1062 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 -05001063 data += len;
1064 tot_size += len;
1065 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001066 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001067 RESTORE_STACK;
1068 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001069}
1070
Pedro Becerra1af7f952013-07-11 00:00:47 -04001071#if !defined(DISABLE_FLOAT_API)
1072static void opus_copy_channel_in_float(
1073 opus_val16 *dst,
1074 int dst_stride,
1075 const void *src,
1076 int src_stride,
1077 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001078 int frame_size,
1079 void *user_data
Pedro Becerra1af7f952013-07-11 00:00:47 -04001080)
1081{
1082 const float *float_src;
1083 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001084 (void)user_data;
Pedro Becerra1af7f952013-07-11 00:00:47 -04001085 float_src = (const float *)src;
1086 for (i=0;i<frame_size;i++)
1087#if defined(FIXED_POINT)
1088 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1089#else
1090 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1091#endif
1092}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001093#endif
1094
1095static void opus_copy_channel_in_short(
1096 opus_val16 *dst,
1097 int dst_stride,
1098 const void *src,
1099 int src_stride,
1100 int src_channel,
Andrew Allen65f11d32017-12-04 15:32:18 -08001101 int frame_size,
1102 void *user_data
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001103)
1104{
1105 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001106 opus_int32 i;
Andrew Allen65f11d32017-12-04 15:32:18 -08001107 (void)user_data;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001108 short_src = (const opus_int16 *)src;
1109 for (i=0;i<frame_size;i++)
1110#if defined(FIXED_POINT)
1111 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1112#else
1113 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1114#endif
1115}
1116
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001117
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001118#ifdef FIXED_POINT
1119int opus_multistream_encode(
1120 OpusMSEncoder *st,
1121 const opus_val16 *pcm,
1122 int frame_size,
1123 unsigned char *data,
1124 opus_int32 max_data_bytes
1125)
1126{
1127 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001128 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001129}
1130
1131#ifndef DISABLE_FLOAT_API
1132int opus_multistream_encode_float(
1133 OpusMSEncoder *st,
1134 const float *pcm,
1135 int frame_size,
1136 unsigned char *data,
1137 opus_int32 max_data_bytes
1138)
1139{
1140 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001141 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001142}
1143#endif
1144
1145#else
1146
1147int opus_multistream_encode_float
1148(
1149 OpusMSEncoder *st,
1150 const opus_val16 *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_float,
Andrew Allen65f11d32017-12-04 15:32:18 -08001157 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001158}
1159
1160int opus_multistream_encode(
1161 OpusMSEncoder *st,
1162 const opus_int16 *pcm,
1163 int frame_size,
1164 unsigned char *data,
1165 opus_int32 max_data_bytes
1166)
1167{
1168 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Andrew Allen65f11d32017-12-04 15:32:18 -08001169 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001170}
1171#endif
1172
Andrew Allenf643c032017-11-07 13:26:23 -08001173int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
1174 va_list ap)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001175{
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001176 int coupled_size, mono_size;
1177 char *ptr;
1178 int ret = OPUS_OK;
1179
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001180 coupled_size = opus_encoder_get_size(2);
1181 mono_size = opus_encoder_get_size(1);
1182 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1183 switch (request)
1184 {
1185 case OPUS_SET_BITRATE_REQUEST:
1186 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001187 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001188 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001189 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001190 if (value <= 0)
1191 goto bad_arg;
1192 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001193 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001194 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001195 }
1196 break;
1197 case OPUS_GET_BITRATE_REQUEST:
1198 {
1199 int s;
1200 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001201 if (!value)
1202 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001203 goto bad_arg;
1204 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001205 *value = 0;
1206 for (s=0;s<st->layout.nb_streams;s++)
1207 {
1208 opus_int32 rate;
1209 OpusEncoder *enc;
1210 enc = (OpusEncoder*)ptr;
1211 if (s < st->layout.nb_coupled_streams)
1212 ptr += align(coupled_size);
1213 else
1214 ptr += align(mono_size);
1215 opus_encoder_ctl(enc, request, &rate);
1216 *value += rate;
1217 }
1218 }
1219 break;
1220 case OPUS_GET_LSB_DEPTH_REQUEST:
1221 case OPUS_GET_VBR_REQUEST:
1222 case OPUS_GET_APPLICATION_REQUEST:
1223 case OPUS_GET_BANDWIDTH_REQUEST:
1224 case OPUS_GET_COMPLEXITY_REQUEST:
1225 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1226 case OPUS_GET_DTX_REQUEST:
1227 case OPUS_GET_VOICE_RATIO_REQUEST:
1228 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1229 case OPUS_GET_SIGNAL_REQUEST:
1230 case OPUS_GET_LOOKAHEAD_REQUEST:
1231 case OPUS_GET_SAMPLE_RATE_REQUEST:
1232 case OPUS_GET_INBAND_FEC_REQUEST:
1233 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001234 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001235 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001236 {
1237 OpusEncoder *enc;
1238 /* For int32* GET params, just query the first stream */
1239 opus_int32 *value = va_arg(ap, opus_int32*);
1240 enc = (OpusEncoder*)ptr;
1241 ret = opus_encoder_ctl(enc, request, value);
1242 }
1243 break;
1244 case OPUS_GET_FINAL_RANGE_REQUEST:
1245 {
1246 int s;
1247 opus_uint32 *value = va_arg(ap, opus_uint32*);
1248 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001249 if (!value)
1250 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001251 goto bad_arg;
1252 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001253 *value=0;
1254 for (s=0;s<st->layout.nb_streams;s++)
1255 {
1256 OpusEncoder *enc;
1257 enc = (OpusEncoder*)ptr;
1258 if (s < st->layout.nb_coupled_streams)
1259 ptr += align(coupled_size);
1260 else
1261 ptr += align(mono_size);
1262 ret = opus_encoder_ctl(enc, request, &tmp);
1263 if (ret != OPUS_OK) break;
1264 *value ^= tmp;
1265 }
1266 }
1267 break;
1268 case OPUS_SET_LSB_DEPTH_REQUEST:
1269 case OPUS_SET_COMPLEXITY_REQUEST:
1270 case OPUS_SET_VBR_REQUEST:
1271 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001272 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001273 case OPUS_SET_BANDWIDTH_REQUEST:
1274 case OPUS_SET_SIGNAL_REQUEST:
1275 case OPUS_SET_APPLICATION_REQUEST:
1276 case OPUS_SET_INBAND_FEC_REQUEST:
1277 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1278 case OPUS_SET_DTX_REQUEST:
1279 case OPUS_SET_FORCE_MODE_REQUEST:
1280 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001281 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001282 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001283 {
1284 int s;
1285 /* This works for int32 params */
1286 opus_int32 value = va_arg(ap, opus_int32);
1287 for (s=0;s<st->layout.nb_streams;s++)
1288 {
1289 OpusEncoder *enc;
1290
1291 enc = (OpusEncoder*)ptr;
1292 if (s < st->layout.nb_coupled_streams)
1293 ptr += align(coupled_size);
1294 else
1295 ptr += align(mono_size);
1296 ret = opus_encoder_ctl(enc, request, value);
1297 if (ret != OPUS_OK)
1298 break;
1299 }
1300 }
1301 break;
1302 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1303 {
1304 int s;
1305 opus_int32 stream_id;
1306 OpusEncoder **value;
1307 stream_id = va_arg(ap, opus_int32);
1308 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1309 ret = OPUS_BAD_ARG;
1310 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001311 if (!value)
1312 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001313 goto bad_arg;
1314 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001315 for (s=0;s<stream_id;s++)
1316 {
1317 if (s < st->layout.nb_coupled_streams)
1318 ptr += align(coupled_size);
1319 else
1320 ptr += align(mono_size);
1321 }
1322 *value = (OpusEncoder*)ptr;
1323 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001324 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001325 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001326 {
1327 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001328 st->variable_duration = value;
1329 }
1330 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001331 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001332 {
1333 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001334 if (!value)
1335 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001336 goto bad_arg;
1337 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001338 *value = st->variable_duration;
1339 }
1340 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001341 case OPUS_RESET_STATE:
1342 {
1343 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001344 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001345 {
1346 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1347 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1348 }
1349 for (s=0;s<st->layout.nb_streams;s++)
1350 {
1351 OpusEncoder *enc;
1352 enc = (OpusEncoder*)ptr;
1353 if (s < st->layout.nb_coupled_streams)
1354 ptr += align(coupled_size);
1355 else
1356 ptr += align(mono_size);
1357 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1358 if (ret != OPUS_OK)
1359 break;
1360 }
1361 }
1362 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001363 default:
1364 ret = OPUS_UNIMPLEMENTED;
1365 break;
1366 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001367 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001368bad_arg:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001369 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001370}
1371
Andrew Allenf643c032017-11-07 13:26:23 -08001372int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1373{
1374 int ret;
1375 va_list ap;
1376 va_start(ap, request);
1377 ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
1378 va_end(ap);
1379 return ret;
1380}
1381
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001382void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1383{
1384 opus_free(st);
1385}