blob: 07de6ccef9cebb61a3509c9c5e976626c7e9edaa [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 -040064typedef void (*opus_copy_channel_in_func)(
65 opus_val16 *dst,
66 int dst_stride,
67 const void *src,
68 int src_stride,
69 int src_channel,
70 int frame_size
71);
72
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040073static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
74{
75 int s;
76 char *ptr;
77 int coupled_size, mono_size;
78
79 coupled_size = opus_encoder_get_size(2);
80 mono_size = opus_encoder_get_size(1);
81 ptr = (char*)st + align(sizeof(OpusMSEncoder));
82 for (s=0;s<st->layout.nb_streams;s++)
83 {
84 if (s < st->layout.nb_coupled_streams)
85 ptr += align(coupled_size);
86 else
87 ptr += align(mono_size);
88 }
Mark Harris4feb0df2015-08-07 01:24:48 -070089 /* void* cast avoids clang -Wcast-align warning */
90 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040091}
92
93static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
94{
95 int s;
96 char *ptr;
97 int coupled_size, mono_size;
98
99 coupled_size = opus_encoder_get_size(2);
100 mono_size = opus_encoder_get_size(1);
101 ptr = (char*)st + align(sizeof(OpusMSEncoder));
102 for (s=0;s<st->layout.nb_streams;s++)
103 {
104 if (s < st->layout.nb_coupled_streams)
105 ptr += align(coupled_size);
106 else
107 ptr += align(mono_size);
108 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700109 /* void* cast avoids clang -Wcast-align warning */
110 return (opus_val32*)(void*)ptr;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400111}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500112
Drew Allen17e14fb2017-04-28 09:58:04 -0700113#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
114static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
115{
116 int order_plus_one;
117 int acn_channels;
118 int nondiegetic_channels;
119
120 order_plus_one = isqrt32(nb_channels);
121 acn_channels = order_plus_one * order_plus_one;
122 nondiegetic_channels = nb_channels - acn_channels;
123
124 if (order_plus_one < 1 || order_plus_one > 15 ||
125 (nondiegetic_channels != 0 && nondiegetic_channels != 2))
126 return 0;
127
128 if (nb_streams)
129 *nb_streams = acn_channels + (nondiegetic_channels != 0);
130 if (nb_coupled_streams)
131 *nb_coupled_streams = nondiegetic_channels != 0;
132 return 1;
133}
134#endif
135
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500136static int validate_encoder_layout(const ChannelLayout *layout)
137{
138 int s;
139 for (s=0;s<layout->nb_streams;s++)
140 {
141 if (s < layout->nb_coupled_streams)
142 {
143 if (get_left_channel(layout, s, -1)==-1)
144 return 0;
145 if (get_right_channel(layout, s, -1)==-1)
146 return 0;
147 } else {
148 if (get_mono_channel(layout, s, -1)==-1)
149 return 0;
150 }
151 }
152 return 1;
153}
154
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400155static void channel_pos(int channels, int pos[8])
156{
157 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
158 if (channels==4)
159 {
160 pos[0]=1;
161 pos[1]=3;
162 pos[2]=1;
163 pos[3]=3;
164 } else if (channels==3||channels==5||channels==6)
165 {
166 pos[0]=1;
167 pos[1]=2;
168 pos[2]=3;
169 pos[3]=1;
170 pos[4]=3;
171 pos[5]=0;
172 } else if (channels==7)
173 {
174 pos[0]=1;
175 pos[1]=2;
176 pos[2]=3;
177 pos[3]=1;
178 pos[4]=3;
179 pos[5]=2;
180 pos[6]=0;
181 } else if (channels==8)
182 {
183 pos[0]=1;
184 pos[1]=2;
185 pos[2]=3;
186 pos[3]=1;
187 pos[4]=3;
188 pos[5]=1;
189 pos[6]=3;
190 pos[7]=0;
191 }
192}
193
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400194#if 1
195/* Computes a rough approximation of log2(2^a + 2^b) */
196static opus_val16 logSum(opus_val16 a, opus_val16 b)
197{
198 opus_val16 max;
199 opus_val32 diff;
200 opus_val16 frac;
201 static const opus_val16 diff_table[17] = {
202 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
203 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
204 QCONST16(0.0028123f, DB_SHIFT)
205 };
206 int low;
207 if (a>b)
208 {
209 max = a;
210 diff = SUB32(EXTEND32(a),EXTEND32(b));
211 } else {
212 max = b;
213 diff = SUB32(EXTEND32(b),EXTEND32(a));
214 }
Mark Harrisa6595e62015-10-07 09:21:23 -0400215 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400216 return max;
217#ifdef FIXED_POINT
218 low = SHR32(diff, DB_SHIFT-1);
219 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
220#else
Jean-Marc Valina71c9ad2013-11-13 12:07:01 -0500221 low = (int)floor(2*diff);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400222 frac = 2*diff - low;
223#endif
224 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
225}
226#else
227opus_val16 logSum(opus_val16 a, opus_val16 b)
228{
229 return log2(pow(4, a)+ pow(4, b))/2;
230}
231#endif
232
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400233void 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 -0500234 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 -0400235)
236{
237 int c;
238 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400239 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400240 int pos[8] = {0};
241 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400242 int frame_size;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400243 int freq_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400244 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400245 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400246 opus_val16 maskLogE[3][21];
247 VARDECL(opus_val32, in);
248 VARDECL(opus_val16, x);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400249 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400250 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400251
252 upsample = resampling_factor(rate);
253 frame_size = len*upsample;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400254 freq_size = IMIN(960, frame_size);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400255
Michael Graczyk39256682016-05-02 21:42:18 -0700256 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400257 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400258 if (celt_mode->shortMdctSize<<LM==frame_size)
259 break;
260
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400261 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400262 ALLOC(x, len, opus_val16);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400263 ALLOC(freq, freq_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400264
265 channel_pos(channels, pos);
266
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400267 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400268 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400269 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400270
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400271 for (c=0;c<channels;c++)
272 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400273 int frame;
274 int nb_frames = frame_size/freq_size;
275 celt_assert(nb_frames*freq_size == frame_size);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400276 OPUS_COPY(in, mem+c*overlap, overlap);
277 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500278 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400279#ifndef FIXED_POINT
280 {
281 opus_val32 sum;
282 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
283 /* This should filter out both NaNs and ridiculous signals that could
284 cause NaNs further down. */
Jean-Marc Valin0d2ba552017-05-23 03:32:18 -0400285 if (!(sum < 1e18f) || celt_isnan(sum))
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400286 {
287 OPUS_CLEAR(in, frame_size+overlap);
288 preemph_mem[c] = 0;
289 }
290 }
291#endif
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400292 OPUS_CLEAR(bandE, 21);
293 for (frame=0;frame<nb_frames;frame++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400294 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400295 opus_val32 tmpE[21];
296 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
297 overlap, celt_mode->maxLM-LM, 1, arch);
298 if (upsample != 1)
299 {
300 int bound = freq_size/upsample;
301 for (i=0;i<bound;i++)
302 freq[i] *= upsample;
303 for (;i<freq_size;i++)
304 freq[i] = 0;
305 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400306
Linfeng Zhanga1ae8212016-09-07 15:29:03 -0700307 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400308 /* If we have multiple frames, take the max energy. */
309 for (i=0;i<21;i++)
310 bandE[i] = MAX32(bandE[i], tmpE[i]);
311 }
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400312 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400313 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
314 for (i=1;i<21;i++)
315 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
316 for (i=19;i>=0;i--)
317 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 -0400318 if (pos[c]==1)
319 {
320 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400321 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400322 } else if (pos[c]==3)
323 {
324 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400325 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400326 } else if (pos[c]==2)
327 {
328 for (i=0;i<21;i++)
329 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400330 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
331 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400332 }
333 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400334#if 0
335 for (i=0;i<21;i++)
336 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400337 float sum=0;
338 for (i=0;i<21;i++)
339 sum += bandLogE[21*c+i];
340 printf("%f ", sum/21);
341#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400342 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400343 }
344 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400345 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400346 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400347 for (c=0;c<3;c++)
348 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400349 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400350#if 0
351 for (c=0;c<3;c++)
352 {
353 for (i=0;i<21;i++)
354 printf("%f ", maskLogE[c][i]);
355 }
356#endif
357 for (c=0;c<channels;c++)
358 {
359 opus_val16 *mask;
360 if (pos[c]!=0)
361 {
362 mask = &maskLogE[pos[c]-1][0];
363 for (i=0;i<21;i++)
364 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
365 } else {
366 for (i=0;i<21;i++)
367 bandLogE[21*c+i] = 0;
368 }
369#if 0
370 for (i=0;i<21;i++)
371 printf("%f ", bandLogE[21*c+i]);
372 printf("\n");
373#endif
374#if 0
375 float sum=0;
376 for (i=0;i<21;i++)
377 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400378 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400379 printf("\n");
380#endif
381 }
382 RESTORE_STACK;
383}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500384
385opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
386{
387 int coupled_size;
388 int mono_size;
389
390 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
391 coupled_size = opus_encoder_get_size(2);
392 mono_size = opus_encoder_get_size(1);
393 return align(sizeof(OpusMSEncoder))
394 + nb_coupled_streams * align(coupled_size)
395 + (nb_streams-nb_coupled_streams) * align(mono_size);
396}
397
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400398opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
399{
400 int nb_streams;
401 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400402 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400403
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400404 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400405 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400406 if (channels==1)
407 {
408 nb_streams=1;
409 nb_coupled_streams=0;
410 } else if (channels==2)
411 {
412 nb_streams=1;
413 nb_coupled_streams=1;
414 } else
415 return 0;
416 } else if (mapping_family==1 && channels<=8 && channels>=1)
417 {
418 nb_streams=vorbis_mappings[channels-1].nb_streams;
419 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
420 } else if (mapping_family==255)
421 {
422 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400423 nb_coupled_streams=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700424#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
425 } else if (mapping_family==254)
426 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700427 if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
428 return 0;
Michael Graczyk39256682016-05-02 21:42:18 -0700429#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400430 } else
431 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400432 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
433 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400434 {
435 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
436 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400437 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400438}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500439
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400440static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500441 OpusMSEncoder *st,
442 opus_int32 Fs,
443 int channels,
444 int streams,
445 int coupled_streams,
446 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400447 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700448 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500449)
450{
451 int coupled_size;
452 int mono_size;
453 int i, ret;
454 char *ptr;
455
456 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800457 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500458 return OPUS_BAD_ARG;
459
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500460 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500461 st->layout.nb_channels = channels;
462 st->layout.nb_streams = streams;
463 st->layout.nb_coupled_streams = coupled_streams;
Michael Graczyk39256682016-05-02 21:42:18 -0700464 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400465 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500466 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400467 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500468 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500469 for (i=0;i<st->layout.nb_channels;i++)
470 st->layout.mapping[i] = mapping[i];
Drew Allen17e14fb2017-04-28 09:58:04 -0700471 if (!validate_layout(&st->layout))
472 return OPUS_BAD_ARG;
473 if (mapping_type == MAPPING_TYPE_SURROUND &&
474 !validate_encoder_layout(&st->layout))
475 return OPUS_BAD_ARG;
476#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
477 if (mapping_type == MAPPING_TYPE_AMBISONICS &&
478 !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
479 return OPUS_BAD_ARG;
480#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500481 ptr = (char*)st + align(sizeof(OpusMSEncoder));
482 coupled_size = opus_encoder_get_size(2);
483 mono_size = opus_encoder_get_size(1);
484
485 for (i=0;i<st->layout.nb_coupled_streams;i++)
486 {
487 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400488 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400489 if (i==st->lfe_stream)
490 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500491 ptr += align(coupled_size);
492 }
493 for (;i<st->layout.nb_streams;i++)
494 {
495 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400496 if (i==st->lfe_stream)
497 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500498 if(ret!=OPUS_OK)return ret;
499 ptr += align(mono_size);
500 }
Michael Graczyk39256682016-05-02 21:42:18 -0700501 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400502 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400503 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
504 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400505 }
Michael Graczyk39256682016-05-02 21:42:18 -0700506 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500507 return OPUS_OK;
508}
509
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400510int opus_multistream_encoder_init(
511 OpusMSEncoder *st,
512 opus_int32 Fs,
513 int channels,
514 int streams,
515 int coupled_streams,
516 const unsigned char *mapping,
517 int application
518)
519{
Michael Graczyk39256682016-05-02 21:42:18 -0700520 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
521 coupled_streams, mapping,
522 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400523}
524
525int opus_multistream_surround_encoder_init(
526 OpusMSEncoder *st,
527 opus_int32 Fs,
528 int channels,
529 int mapping_family,
530 int *streams,
531 int *coupled_streams,
532 unsigned char *mapping,
533 int application
534)
535{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700536 MappingType mapping_type;
537
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400538 if ((channels>255) || (channels<1))
539 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400540 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400541 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400542 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400543 if (channels==1)
544 {
545 *streams=1;
546 *coupled_streams=0;
547 mapping[0]=0;
548 } else if (channels==2)
549 {
550 *streams=1;
551 *coupled_streams=1;
552 mapping[0]=0;
553 mapping[1]=1;
554 } else
555 return OPUS_UNIMPLEMENTED;
556 } else if (mapping_family==1 && channels<=8 && channels>=1)
557 {
558 int i;
559 *streams=vorbis_mappings[channels-1].nb_streams;
560 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
561 for (i=0;i<channels;i++)
562 mapping[i] = vorbis_mappings[channels-1].mapping[i];
563 if (channels>=6)
564 st->lfe_stream = *streams-1;
565 } else if (mapping_family==255)
566 {
567 int i;
568 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400569 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400570 for(i=0;i<channels;i++)
571 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700572#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
573 } else if (mapping_family==254)
574 {
575 int i;
Drew Allen17e14fb2017-04-28 09:58:04 -0700576 if (!validate_ambisonics(channels, streams, coupled_streams))
577 return OPUS_BAD_ARG;
578 for(i = 0; i < (*streams - *coupled_streams); i++)
579 mapping[i] = i + (*coupled_streams * 2);
580 for(i = 0; i < *coupled_streams * 2; i++)
581 mapping[i + (*streams - *coupled_streams)] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700582#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400583 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400584 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700585
586 if (channels>2 && mapping_family==1) {
587 mapping_type = MAPPING_TYPE_SURROUND;
588#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
589 } else if (mapping_family==254)
590 {
591 mapping_type = MAPPING_TYPE_AMBISONICS;
592#endif
593 } else
594 {
595 mapping_type = MAPPING_TYPE_NONE;
596 }
597 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
598 *coupled_streams, mapping,
599 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400600}
601
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500602OpusMSEncoder *opus_multistream_encoder_create(
603 opus_int32 Fs,
604 int channels,
605 int streams,
606 int coupled_streams,
607 const unsigned char *mapping,
608 int application,
609 int *error
610)
611{
612 int ret;
613 OpusMSEncoder *st;
614 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800615 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500616 {
617 if (error)
618 *error = OPUS_BAD_ARG;
619 return NULL;
620 }
621 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
622 if (st==NULL)
623 {
624 if (error)
625 *error = OPUS_ALLOC_FAIL;
626 return NULL;
627 }
628 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
629 if (ret != OPUS_OK)
630 {
631 opus_free(st);
632 st = NULL;
633 }
634 if (error)
635 *error = ret;
636 return st;
637}
638
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400639OpusMSEncoder *opus_multistream_surround_encoder_create(
640 opus_int32 Fs,
641 int channels,
642 int mapping_family,
643 int *streams,
644 int *coupled_streams,
645 unsigned char *mapping,
646 int application,
647 int *error
648)
649{
650 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800651 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400652 OpusMSEncoder *st;
653 if ((channels>255) || (channels<1))
654 {
655 if (error)
656 *error = OPUS_BAD_ARG;
657 return NULL;
658 }
Mark Harris25b27a92014-11-27 08:48:09 -0800659 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
660 if (!size)
661 {
662 if (error)
663 *error = OPUS_UNIMPLEMENTED;
664 return NULL;
665 }
666 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400667 if (st==NULL)
668 {
669 if (error)
670 *error = OPUS_ALLOC_FAIL;
671 return NULL;
672 }
673 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
674 if (ret != OPUS_OK)
675 {
676 opus_free(st);
677 st = NULL;
678 }
679 if (error)
680 *error = ret;
681 return st;
682}
683
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700684static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400685 OpusMSEncoder *st,
686 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700687 int frame_size,
688 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400689 )
690{
691 int i;
692 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400693 int stream_offset;
694 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400695 int coupled_ratio; /* Q8 */
696 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400697 int nb_lfe;
698 int nb_uncoupled;
699 int nb_coupled;
700 int nb_normal;
701 opus_int32 channel_offset;
702 opus_int32 bitrate;
703 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400704
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400705 nb_lfe = (st->lfe_stream!=-1);
706 nb_coupled = st->layout.nb_coupled_streams;
707 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
708 nb_normal = 2*nb_coupled + nb_uncoupled;
709
710 /* Give each non-LFE channel enough bits per channel for coding band energy. */
711 channel_offset = 40*IMAX(50, Fs/frame_size);
712
713 if (st->bitrate_bps==OPUS_AUTO)
714 {
715 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
716 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
717 {
718 bitrate = nb_normal*300000 + nb_lfe*128000;
719 } else {
720 bitrate = st->bitrate_bps;
721 }
722
723 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
724 total rate for the non-energy part to avoid problems at really low rate. */
725 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
726
727 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400728 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400729 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
730 stream_offset = IMAX(0, IMIN(20000, stream_offset));
731
732 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400733 coupled_ratio = 512;
734 /* 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 -0400735 lfe_ratio = 32;
736
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400737 total = (nb_uncoupled<<8) /* mono */
738 + coupled_ratio*nb_coupled /* stereo */
739 + nb_lfe*lfe_ratio;
740 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 -0400741
742 for (i=0;i<st->layout.nb_streams;i++)
743 {
744 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400745 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400746 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400747 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400748 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400749 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700750 }
751}
752
753#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
754static void ambisonics_rate_allocation(
755 OpusMSEncoder *st,
756 opus_int32 *rate,
757 int frame_size,
758 opus_int32 Fs
759 )
760{
761 int i;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700762 int total_rate;
Drew Allen17e14fb2017-04-28 09:58:04 -0700763 int directional_rate;
764 int nondirectional_rate;
765 int leftover_bits;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700766
Drew Allen17e14fb2017-04-28 09:58:04 -0700767 /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
768 * as many bits as all other ambisonics channels.
769 */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700770 const int rate_ratio_num = 4;
771 const int rate_ratio_den = 3;
Drew Allen17e14fb2017-04-28 09:58:04 -0700772 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
773 const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
774 const int nb_directional_channels = st->layout.nb_streams - 1;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700775
776 if (st->bitrate_bps==OPUS_AUTO)
777 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700778 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
779 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700780 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
781 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700782 total_rate = nb_channels * 320000;
783 } else
784 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700785 total_rate = st->bitrate_bps;
786 }
787
Drew Allen17e14fb2017-04-28 09:58:04 -0700788 /* Let y be the directional rate, m be the num of nondirectional channels
789 * m = (s + 1)
790 * and let p, q be integers such that the nondirectional rate is
791 * m_rate = (p / q) * y
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700792 * Also let T be the total bitrate to allocate. Then
Drew Allen17e14fb2017-04-28 09:58:04 -0700793 * T = (n - m) * y + m * m_rate
794 * Solving for y,
795 * y = (q * T) / (m * (p - q) + n * q)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700796 */
Drew Allen17e14fb2017-04-28 09:58:04 -0700797 directional_rate =
798 total_rate * rate_ratio_den
799 / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
800 + nb_channels * rate_ratio_den);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700801
Drew Allen17e14fb2017-04-28 09:58:04 -0700802 /* Calculate the nondirectional rate.
803 * m_rate = y * (p / q)
804 */
805 nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
806
807 /* Calculate the leftover from truncation error.
808 * leftover = T - y * (n - m) - m_rate * m
809 * Place leftover bits in omnidirectional channel.
810 */
811 leftover_bits = total_rate
812 - directional_rate * nb_directional_channels
813 - nondirectional_rate * nb_nondirectional_channels;
814
815 /* Calculate rates for each channel */
816 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700817 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700818 if (i < st->layout.nb_coupled_streams)
819 {
820 rate[i] = nondirectional_rate * 2;
821 } else if (i == st->layout.nb_coupled_streams)
822 {
823 rate[i] = nondirectional_rate + leftover_bits;
824 } else
825 {
826 rate[i] = directional_rate;
827 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700828 }
829}
830#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
831
832static opus_int32 rate_allocation(
833 OpusMSEncoder *st,
834 opus_int32 *rate,
835 int frame_size
836 )
837{
838 int i;
839 opus_int32 rate_sum=0;
840 opus_int32 Fs;
841 char *ptr;
842
843 ptr = (char*)st + align(sizeof(OpusMSEncoder));
844 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
845
846#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
847 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
848 ambisonics_rate_allocation(st, rate, frame_size, Fs);
849 } else
850#endif
851 {
852 surround_rate_allocation(st, rate, frame_size, Fs);
853 }
854
855 for (i=0;i<st->layout.nb_streams;i++)
856 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400857 rate[i] = IMAX(rate[i], 500);
858 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400859 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400860 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400861}
862
Felicia Lim0962cbe2016-10-27 17:03:36 -0700863/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
864#define MS_FRAME_TMP (6*1275+12)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500865static int opus_multistream_encode_native
866(
867 OpusMSEncoder *st,
868 opus_copy_channel_in_func copy_channel_in,
869 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400870 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500871 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500872 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400873 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500874 downmix_func downmix,
875 int float_api
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500876)
877{
878 opus_int32 Fs;
879 int coupled_size;
880 int mono_size;
881 int s;
882 char *ptr;
883 int tot_size;
884 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400885 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500886 unsigned char tmp_data[MS_FRAME_TMP];
887 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400888 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500889 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400890 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400891 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400892 opus_val32 *mem = NULL;
893 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400894 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400895 opus_int32 rate_sum;
896 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500897 ALLOC_STACK;
898
Michael Graczyk39256682016-05-02 21:42:18 -0700899 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400900 {
901 preemph_mem = ms_get_preemph_mem(st);
902 mem = ms_get_window_mem(st);
903 }
904
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500905 ptr = (char*)st + align(sizeof(OpusMSEncoder));
906 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400907 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500908 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500909
Mark Harrisd73c5a92016-11-05 22:01:52 -0700910 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
911 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500912 {
913 RESTORE_STACK;
914 return OPUS_BAD_ARG;
915 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400916
917 /* Smallest packet the encoder can produce. */
918 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700919 /* 100 ms needs an extra byte per stream for the ToC. */
920 if (Fs/frame_size == 10)
921 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400922 if (max_data_bytes < smallest_packet)
923 {
924 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400925 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400926 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500927 ALLOC(buf, 2*frame_size, opus_val16);
928 coupled_size = opus_encoder_get_size(2);
929 mono_size = opus_encoder_get_size(1);
930
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400931 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700932 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400933 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500934 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 -0400935 }
936
Jean-Marc Valin74483662012-12-17 16:23:42 -0500937 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700938 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400939
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400940 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400941 {
942 if (st->bitrate_bps == OPUS_AUTO)
943 {
944 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
945 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
946 {
947 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
948 3*st->bitrate_bps/(3*8*Fs/frame_size)));
949 }
950 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500951 ptr = (char*)st + align(sizeof(OpusMSEncoder));
952 for (s=0;s<st->layout.nb_streams;s++)
953 {
954 OpusEncoder *enc;
955 enc = (OpusEncoder*)ptr;
956 if (s < st->layout.nb_coupled_streams)
957 ptr += align(coupled_size);
958 else
959 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400960 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700961 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400962 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400963 opus_int32 equiv_rate;
964 equiv_rate = st->bitrate_bps;
965 if (frame_size*50 < Fs)
966 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500967 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400968 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500969 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400970 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500971 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400972 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
973 else
974 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400975 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400976 {
977 /* To preserve the spatial image, force stereo CELT on coupled streams */
978 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400979 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400980 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400981 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700982#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
983 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
984 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
985 }
986#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500987 }
988
989 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500990 /* Counting ToC */
991 tot_size = 0;
992 for (s=0;s<st->layout.nb_streams;s++)
993 {
994 OpusEncoder *enc;
995 int len;
996 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400997 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400998 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500999
1000 opus_repacketizer_init(&rp);
1001 enc = (OpusEncoder*)ptr;
1002 if (s < st->layout.nb_coupled_streams)
1003 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001004 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001005 int left, right;
1006 left = get_left_channel(&st->layout, s, -1);
1007 right = get_right_channel(&st->layout, s, -1);
1008 (*copy_channel_in)(buf, 2,
1009 pcm, st->layout.nb_channels, left, frame_size);
1010 (*copy_channel_in)(buf+1, 2,
1011 pcm, st->layout.nb_channels, right, frame_size);
1012 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001013 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001014 {
1015 for (i=0;i<21;i++)
1016 {
1017 bandLogE[i] = bandSMR[21*left+i];
1018 bandLogE[21+i] = bandSMR[21*right+i];
1019 }
1020 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001021 c1 = left;
1022 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001023 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001024 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001025 int chan = get_mono_channel(&st->layout, s, -1);
1026 (*copy_channel_in)(buf, 1,
1027 pcm, st->layout.nb_channels, chan, frame_size);
1028 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001029 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001030 {
1031 for (i=0;i<21;i++)
1032 bandLogE[i] = bandSMR[21*chan+i];
1033 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001034 c1 = chan;
1035 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001036 }
Michael Graczyk39256682016-05-02 21:42:18 -07001037 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001038 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001039 /* number of bytes left (+Toc) */
1040 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001041 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001042 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001043 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001044 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001045 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001046 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001047 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001048 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001049 if (!vbr && s == st->layout.nb_streams-1)
1050 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001051 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001052 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001053 if (len<0)
1054 {
1055 RESTORE_STACK;
1056 return len;
1057 }
1058 /* We need to use the repacketizer to add the self-delimiting lengths
1059 while taking into account the fact that the encoder can now return
1060 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001061 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1062 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1063 with the encoder. */
1064 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001065 {
1066 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001067 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001068 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001069 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1070 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 -05001071 data += len;
1072 tot_size += len;
1073 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001074 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001075 RESTORE_STACK;
1076 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001077}
1078
Pedro Becerra1af7f952013-07-11 00:00:47 -04001079#if !defined(DISABLE_FLOAT_API)
1080static void opus_copy_channel_in_float(
1081 opus_val16 *dst,
1082 int dst_stride,
1083 const void *src,
1084 int src_stride,
1085 int src_channel,
1086 int frame_size
1087)
1088{
1089 const float *float_src;
1090 opus_int32 i;
1091 float_src = (const float *)src;
1092 for (i=0;i<frame_size;i++)
1093#if defined(FIXED_POINT)
1094 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1095#else
1096 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1097#endif
1098}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001099#endif
1100
1101static void opus_copy_channel_in_short(
1102 opus_val16 *dst,
1103 int dst_stride,
1104 const void *src,
1105 int src_stride,
1106 int src_channel,
1107 int frame_size
1108)
1109{
1110 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001111 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001112 short_src = (const opus_int16 *)src;
1113 for (i=0;i<frame_size;i++)
1114#if defined(FIXED_POINT)
1115 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1116#else
1117 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1118#endif
1119}
1120
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001121
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001122#ifdef FIXED_POINT
1123int opus_multistream_encode(
1124 OpusMSEncoder *st,
1125 const opus_val16 *pcm,
1126 int frame_size,
1127 unsigned char *data,
1128 opus_int32 max_data_bytes
1129)
1130{
1131 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001132 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001133}
1134
1135#ifndef DISABLE_FLOAT_API
1136int opus_multistream_encode_float(
1137 OpusMSEncoder *st,
1138 const float *pcm,
1139 int frame_size,
1140 unsigned char *data,
1141 opus_int32 max_data_bytes
1142)
1143{
1144 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001145 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001146}
1147#endif
1148
1149#else
1150
1151int opus_multistream_encode_float
1152(
1153 OpusMSEncoder *st,
1154 const opus_val16 *pcm,
1155 int frame_size,
1156 unsigned char *data,
1157 opus_int32 max_data_bytes
1158)
1159{
1160 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001161 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001162}
1163
1164int opus_multistream_encode(
1165 OpusMSEncoder *st,
1166 const opus_int16 *pcm,
1167 int frame_size,
1168 unsigned char *data,
1169 opus_int32 max_data_bytes
1170)
1171{
1172 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001173 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001174}
1175#endif
1176
Andrew Allenf643c032017-11-07 13:26:23 -08001177int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
1178 va_list ap)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001179{
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001180 int coupled_size, mono_size;
1181 char *ptr;
1182 int ret = OPUS_OK;
1183
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001184 coupled_size = opus_encoder_get_size(2);
1185 mono_size = opus_encoder_get_size(1);
1186 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1187 switch (request)
1188 {
1189 case OPUS_SET_BITRATE_REQUEST:
1190 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001191 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001192 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001193 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001194 if (value <= 0)
1195 goto bad_arg;
1196 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001197 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001198 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001199 }
1200 break;
1201 case OPUS_GET_BITRATE_REQUEST:
1202 {
1203 int s;
1204 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001205 if (!value)
1206 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001207 goto bad_arg;
1208 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001209 *value = 0;
1210 for (s=0;s<st->layout.nb_streams;s++)
1211 {
1212 opus_int32 rate;
1213 OpusEncoder *enc;
1214 enc = (OpusEncoder*)ptr;
1215 if (s < st->layout.nb_coupled_streams)
1216 ptr += align(coupled_size);
1217 else
1218 ptr += align(mono_size);
1219 opus_encoder_ctl(enc, request, &rate);
1220 *value += rate;
1221 }
1222 }
1223 break;
1224 case OPUS_GET_LSB_DEPTH_REQUEST:
1225 case OPUS_GET_VBR_REQUEST:
1226 case OPUS_GET_APPLICATION_REQUEST:
1227 case OPUS_GET_BANDWIDTH_REQUEST:
1228 case OPUS_GET_COMPLEXITY_REQUEST:
1229 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1230 case OPUS_GET_DTX_REQUEST:
1231 case OPUS_GET_VOICE_RATIO_REQUEST:
1232 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1233 case OPUS_GET_SIGNAL_REQUEST:
1234 case OPUS_GET_LOOKAHEAD_REQUEST:
1235 case OPUS_GET_SAMPLE_RATE_REQUEST:
1236 case OPUS_GET_INBAND_FEC_REQUEST:
1237 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001238 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001239 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001240 {
1241 OpusEncoder *enc;
1242 /* For int32* GET params, just query the first stream */
1243 opus_int32 *value = va_arg(ap, opus_int32*);
1244 enc = (OpusEncoder*)ptr;
1245 ret = opus_encoder_ctl(enc, request, value);
1246 }
1247 break;
1248 case OPUS_GET_FINAL_RANGE_REQUEST:
1249 {
1250 int s;
1251 opus_uint32 *value = va_arg(ap, opus_uint32*);
1252 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001253 if (!value)
1254 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001255 goto bad_arg;
1256 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001257 *value=0;
1258 for (s=0;s<st->layout.nb_streams;s++)
1259 {
1260 OpusEncoder *enc;
1261 enc = (OpusEncoder*)ptr;
1262 if (s < st->layout.nb_coupled_streams)
1263 ptr += align(coupled_size);
1264 else
1265 ptr += align(mono_size);
1266 ret = opus_encoder_ctl(enc, request, &tmp);
1267 if (ret != OPUS_OK) break;
1268 *value ^= tmp;
1269 }
1270 }
1271 break;
1272 case OPUS_SET_LSB_DEPTH_REQUEST:
1273 case OPUS_SET_COMPLEXITY_REQUEST:
1274 case OPUS_SET_VBR_REQUEST:
1275 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001276 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001277 case OPUS_SET_BANDWIDTH_REQUEST:
1278 case OPUS_SET_SIGNAL_REQUEST:
1279 case OPUS_SET_APPLICATION_REQUEST:
1280 case OPUS_SET_INBAND_FEC_REQUEST:
1281 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1282 case OPUS_SET_DTX_REQUEST:
1283 case OPUS_SET_FORCE_MODE_REQUEST:
1284 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001285 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001286 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001287 {
1288 int s;
1289 /* This works for int32 params */
1290 opus_int32 value = va_arg(ap, opus_int32);
1291 for (s=0;s<st->layout.nb_streams;s++)
1292 {
1293 OpusEncoder *enc;
1294
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, request, value);
1301 if (ret != OPUS_OK)
1302 break;
1303 }
1304 }
1305 break;
1306 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1307 {
1308 int s;
1309 opus_int32 stream_id;
1310 OpusEncoder **value;
1311 stream_id = va_arg(ap, opus_int32);
1312 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1313 ret = OPUS_BAD_ARG;
1314 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001315 if (!value)
1316 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001317 goto bad_arg;
1318 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001319 for (s=0;s<stream_id;s++)
1320 {
1321 if (s < st->layout.nb_coupled_streams)
1322 ptr += align(coupled_size);
1323 else
1324 ptr += align(mono_size);
1325 }
1326 *value = (OpusEncoder*)ptr;
1327 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001328 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001329 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001330 {
1331 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001332 st->variable_duration = value;
1333 }
1334 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001335 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001336 {
1337 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001338 if (!value)
1339 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001340 goto bad_arg;
1341 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001342 *value = st->variable_duration;
1343 }
1344 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001345 case OPUS_RESET_STATE:
1346 {
1347 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001348 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001349 {
1350 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1351 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1352 }
1353 for (s=0;s<st->layout.nb_streams;s++)
1354 {
1355 OpusEncoder *enc;
1356 enc = (OpusEncoder*)ptr;
1357 if (s < st->layout.nb_coupled_streams)
1358 ptr += align(coupled_size);
1359 else
1360 ptr += align(mono_size);
1361 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1362 if (ret != OPUS_OK)
1363 break;
1364 }
1365 }
1366 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001367 default:
1368 ret = OPUS_UNIMPLEMENTED;
1369 break;
1370 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001371 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001372bad_arg:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001373 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001374}
1375
Andrew Allenf643c032017-11-07 13:26:23 -08001376int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1377{
1378 int ret;
1379 va_list ap;
1380 va_start(ap, request);
1381 ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
1382 va_end(ap);
1383 return ret;
1384}
1385
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001386void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1387{
1388 opus_free(st);
1389}