blob: 032fc0039b91312e756bf89c6bf0de052f68acf1 [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
Michael Graczyk39256682016-05-02 21:42:18 -070073typedef enum {
74 MAPPING_TYPE_NONE,
Michael Graczykd6642d62016-06-29 20:30:19 -070075 MAPPING_TYPE_SURROUND
Michael Graczyk39256682016-05-02 21:42:18 -070076#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
Michael Graczykd6642d62016-06-29 20:30:19 -070077 , /* Do not include comma at end of enumerator list */
78 MAPPING_TYPE_AMBISONICS
Michael Graczyk39256682016-05-02 21:42:18 -070079#endif
80} MappingType;
81
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050082struct OpusMSEncoder {
83 ChannelLayout layout;
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -050084 int arch;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040085 int lfe_stream;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -040086 int application;
Jean-Marc Valin74483662012-12-17 16:23:42 -050087 int variable_duration;
Michael Graczyk39256682016-05-02 21:42:18 -070088 MappingType mapping_type;
Jean-Marc Valin74483662012-12-17 16:23:42 -050089 opus_int32 bitrate_bps;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050090 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040091 /* then opus_val32 window_mem[channels*120]; */
92 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050093};
94
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040095static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
96{
97 int s;
98 char *ptr;
99 int coupled_size, mono_size;
100
101 coupled_size = opus_encoder_get_size(2);
102 mono_size = opus_encoder_get_size(1);
103 ptr = (char*)st + align(sizeof(OpusMSEncoder));
104 for (s=0;s<st->layout.nb_streams;s++)
105 {
106 if (s < st->layout.nb_coupled_streams)
107 ptr += align(coupled_size);
108 else
109 ptr += align(mono_size);
110 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700111 /* void* cast avoids clang -Wcast-align warning */
112 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400113}
114
115static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
116{
117 int s;
118 char *ptr;
119 int coupled_size, mono_size;
120
121 coupled_size = opus_encoder_get_size(2);
122 mono_size = opus_encoder_get_size(1);
123 ptr = (char*)st + align(sizeof(OpusMSEncoder));
124 for (s=0;s<st->layout.nb_streams;s++)
125 {
126 if (s < st->layout.nb_coupled_streams)
127 ptr += align(coupled_size);
128 else
129 ptr += align(mono_size);
130 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700131 /* void* cast avoids clang -Wcast-align warning */
132 return (opus_val32*)(void*)ptr;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400133}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500134
Drew Allen17e14fb2017-04-28 09:58:04 -0700135#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
136static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
137{
138 int order_plus_one;
139 int acn_channels;
140 int nondiegetic_channels;
141
142 order_plus_one = isqrt32(nb_channels);
143 acn_channels = order_plus_one * order_plus_one;
144 nondiegetic_channels = nb_channels - acn_channels;
145
146 if (order_plus_one < 1 || order_plus_one > 15 ||
147 (nondiegetic_channels != 0 && nondiegetic_channels != 2))
148 return 0;
149
150 if (nb_streams)
151 *nb_streams = acn_channels + (nondiegetic_channels != 0);
152 if (nb_coupled_streams)
153 *nb_coupled_streams = nondiegetic_channels != 0;
154 return 1;
155}
156#endif
157
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500158static int validate_encoder_layout(const ChannelLayout *layout)
159{
160 int s;
161 for (s=0;s<layout->nb_streams;s++)
162 {
163 if (s < layout->nb_coupled_streams)
164 {
165 if (get_left_channel(layout, s, -1)==-1)
166 return 0;
167 if (get_right_channel(layout, s, -1)==-1)
168 return 0;
169 } else {
170 if (get_mono_channel(layout, s, -1)==-1)
171 return 0;
172 }
173 }
174 return 1;
175}
176
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400177static void channel_pos(int channels, int pos[8])
178{
179 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
180 if (channels==4)
181 {
182 pos[0]=1;
183 pos[1]=3;
184 pos[2]=1;
185 pos[3]=3;
186 } else if (channels==3||channels==5||channels==6)
187 {
188 pos[0]=1;
189 pos[1]=2;
190 pos[2]=3;
191 pos[3]=1;
192 pos[4]=3;
193 pos[5]=0;
194 } else if (channels==7)
195 {
196 pos[0]=1;
197 pos[1]=2;
198 pos[2]=3;
199 pos[3]=1;
200 pos[4]=3;
201 pos[5]=2;
202 pos[6]=0;
203 } else if (channels==8)
204 {
205 pos[0]=1;
206 pos[1]=2;
207 pos[2]=3;
208 pos[3]=1;
209 pos[4]=3;
210 pos[5]=1;
211 pos[6]=3;
212 pos[7]=0;
213 }
214}
215
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400216#if 1
217/* Computes a rough approximation of log2(2^a + 2^b) */
218static opus_val16 logSum(opus_val16 a, opus_val16 b)
219{
220 opus_val16 max;
221 opus_val32 diff;
222 opus_val16 frac;
223 static const opus_val16 diff_table[17] = {
224 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
225 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
226 QCONST16(0.0028123f, DB_SHIFT)
227 };
228 int low;
229 if (a>b)
230 {
231 max = a;
232 diff = SUB32(EXTEND32(a),EXTEND32(b));
233 } else {
234 max = b;
235 diff = SUB32(EXTEND32(b),EXTEND32(a));
236 }
Mark Harrisa6595e62015-10-07 09:21:23 -0400237 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400238 return max;
239#ifdef FIXED_POINT
240 low = SHR32(diff, DB_SHIFT-1);
241 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
242#else
Jean-Marc Valina71c9ad2013-11-13 12:07:01 -0500243 low = (int)floor(2*diff);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400244 frac = 2*diff - low;
245#endif
246 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
247}
248#else
249opus_val16 logSum(opus_val16 a, opus_val16 b)
250{
251 return log2(pow(4, a)+ pow(4, b))/2;
252}
253#endif
254
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400255void 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 -0500256 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 -0400257)
258{
259 int c;
260 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400261 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400262 int pos[8] = {0};
263 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400264 int frame_size;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400265 int freq_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400266 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400267 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400268 opus_val16 maskLogE[3][21];
269 VARDECL(opus_val32, in);
270 VARDECL(opus_val16, x);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400271 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400272 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400273
274 upsample = resampling_factor(rate);
275 frame_size = len*upsample;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400276 freq_size = IMIN(960, frame_size);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400277
Michael Graczyk39256682016-05-02 21:42:18 -0700278 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400279 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400280 if (celt_mode->shortMdctSize<<LM==frame_size)
281 break;
282
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400283 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400284 ALLOC(x, len, opus_val16);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400285 ALLOC(freq, freq_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400286
287 channel_pos(channels, pos);
288
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400289 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400290 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400291 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400292
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400293 for (c=0;c<channels;c++)
294 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400295 int frame;
296 int nb_frames = frame_size/freq_size;
297 celt_assert(nb_frames*freq_size == frame_size);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400298 OPUS_COPY(in, mem+c*overlap, overlap);
299 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500300 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400301#ifndef FIXED_POINT
302 {
303 opus_val32 sum;
304 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
305 /* This should filter out both NaNs and ridiculous signals that could
306 cause NaNs further down. */
Jean-Marc Valin0d2ba552017-05-23 03:32:18 -0400307 if (!(sum < 1e18f) || celt_isnan(sum))
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400308 {
309 OPUS_CLEAR(in, frame_size+overlap);
310 preemph_mem[c] = 0;
311 }
312 }
313#endif
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400314 OPUS_CLEAR(bandE, 21);
315 for (frame=0;frame<nb_frames;frame++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400316 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400317 opus_val32 tmpE[21];
318 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
319 overlap, celt_mode->maxLM-LM, 1, arch);
320 if (upsample != 1)
321 {
322 int bound = freq_size/upsample;
323 for (i=0;i<bound;i++)
324 freq[i] *= upsample;
325 for (;i<freq_size;i++)
326 freq[i] = 0;
327 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400328
Linfeng Zhanga1ae8212016-09-07 15:29:03 -0700329 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400330 /* If we have multiple frames, take the max energy. */
331 for (i=0;i<21;i++)
332 bandE[i] = MAX32(bandE[i], tmpE[i]);
333 }
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400334 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400335 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
336 for (i=1;i<21;i++)
337 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
338 for (i=19;i>=0;i--)
339 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 -0400340 if (pos[c]==1)
341 {
342 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400343 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400344 } else if (pos[c]==3)
345 {
346 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400347 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400348 } else if (pos[c]==2)
349 {
350 for (i=0;i<21;i++)
351 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400352 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
353 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400354 }
355 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400356#if 0
357 for (i=0;i<21;i++)
358 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400359 float sum=0;
360 for (i=0;i<21;i++)
361 sum += bandLogE[21*c+i];
362 printf("%f ", sum/21);
363#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400364 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400365 }
366 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400367 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400368 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400369 for (c=0;c<3;c++)
370 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400371 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400372#if 0
373 for (c=0;c<3;c++)
374 {
375 for (i=0;i<21;i++)
376 printf("%f ", maskLogE[c][i]);
377 }
378#endif
379 for (c=0;c<channels;c++)
380 {
381 opus_val16 *mask;
382 if (pos[c]!=0)
383 {
384 mask = &maskLogE[pos[c]-1][0];
385 for (i=0;i<21;i++)
386 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
387 } else {
388 for (i=0;i<21;i++)
389 bandLogE[21*c+i] = 0;
390 }
391#if 0
392 for (i=0;i<21;i++)
393 printf("%f ", bandLogE[21*c+i]);
394 printf("\n");
395#endif
396#if 0
397 float sum=0;
398 for (i=0;i<21;i++)
399 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400400 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400401 printf("\n");
402#endif
403 }
404 RESTORE_STACK;
405}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500406
407opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
408{
409 int coupled_size;
410 int mono_size;
411
412 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
413 coupled_size = opus_encoder_get_size(2);
414 mono_size = opus_encoder_get_size(1);
415 return align(sizeof(OpusMSEncoder))
416 + nb_coupled_streams * align(coupled_size)
417 + (nb_streams-nb_coupled_streams) * align(mono_size);
418}
419
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400420opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
421{
422 int nb_streams;
423 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400424 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400425
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400426 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400427 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400428 if (channels==1)
429 {
430 nb_streams=1;
431 nb_coupled_streams=0;
432 } else if (channels==2)
433 {
434 nb_streams=1;
435 nb_coupled_streams=1;
436 } else
437 return 0;
438 } else if (mapping_family==1 && channels<=8 && channels>=1)
439 {
440 nb_streams=vorbis_mappings[channels-1].nb_streams;
441 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
442 } else if (mapping_family==255)
443 {
444 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400445 nb_coupled_streams=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700446#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
447 } else if (mapping_family==254)
448 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700449 if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
450 return 0;
Michael Graczyk39256682016-05-02 21:42:18 -0700451#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400452 } else
453 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400454 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
455 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400456 {
457 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
458 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400459 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400460}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500461
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400462static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500463 OpusMSEncoder *st,
464 opus_int32 Fs,
465 int channels,
466 int streams,
467 int coupled_streams,
468 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400469 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700470 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500471)
472{
473 int coupled_size;
474 int mono_size;
475 int i, ret;
476 char *ptr;
477
478 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800479 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500480 return OPUS_BAD_ARG;
481
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500482 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500483 st->layout.nb_channels = channels;
484 st->layout.nb_streams = streams;
485 st->layout.nb_coupled_streams = coupled_streams;
Michael Graczyk39256682016-05-02 21:42:18 -0700486 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400487 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500488 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400489 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500490 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500491 for (i=0;i<st->layout.nb_channels;i++)
492 st->layout.mapping[i] = mapping[i];
Drew Allen17e14fb2017-04-28 09:58:04 -0700493 if (!validate_layout(&st->layout))
494 return OPUS_BAD_ARG;
495 if (mapping_type == MAPPING_TYPE_SURROUND &&
496 !validate_encoder_layout(&st->layout))
497 return OPUS_BAD_ARG;
498#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
499 if (mapping_type == MAPPING_TYPE_AMBISONICS &&
500 !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
501 return OPUS_BAD_ARG;
502#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500503 ptr = (char*)st + align(sizeof(OpusMSEncoder));
504 coupled_size = opus_encoder_get_size(2);
505 mono_size = opus_encoder_get_size(1);
506
507 for (i=0;i<st->layout.nb_coupled_streams;i++)
508 {
509 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400510 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400511 if (i==st->lfe_stream)
512 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500513 ptr += align(coupled_size);
514 }
515 for (;i<st->layout.nb_streams;i++)
516 {
517 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400518 if (i==st->lfe_stream)
519 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500520 if(ret!=OPUS_OK)return ret;
521 ptr += align(mono_size);
522 }
Michael Graczyk39256682016-05-02 21:42:18 -0700523 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400524 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400525 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
526 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400527 }
Michael Graczyk39256682016-05-02 21:42:18 -0700528 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500529 return OPUS_OK;
530}
531
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400532int opus_multistream_encoder_init(
533 OpusMSEncoder *st,
534 opus_int32 Fs,
535 int channels,
536 int streams,
537 int coupled_streams,
538 const unsigned char *mapping,
539 int application
540)
541{
Michael Graczyk39256682016-05-02 21:42:18 -0700542 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
543 coupled_streams, mapping,
544 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400545}
546
547int opus_multistream_surround_encoder_init(
548 OpusMSEncoder *st,
549 opus_int32 Fs,
550 int channels,
551 int mapping_family,
552 int *streams,
553 int *coupled_streams,
554 unsigned char *mapping,
555 int application
556)
557{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700558 MappingType mapping_type;
559
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400560 if ((channels>255) || (channels<1))
561 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400562 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400563 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400564 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400565 if (channels==1)
566 {
567 *streams=1;
568 *coupled_streams=0;
569 mapping[0]=0;
570 } else if (channels==2)
571 {
572 *streams=1;
573 *coupled_streams=1;
574 mapping[0]=0;
575 mapping[1]=1;
576 } else
577 return OPUS_UNIMPLEMENTED;
578 } else if (mapping_family==1 && channels<=8 && channels>=1)
579 {
580 int i;
581 *streams=vorbis_mappings[channels-1].nb_streams;
582 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
583 for (i=0;i<channels;i++)
584 mapping[i] = vorbis_mappings[channels-1].mapping[i];
585 if (channels>=6)
586 st->lfe_stream = *streams-1;
587 } else if (mapping_family==255)
588 {
589 int i;
590 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400591 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400592 for(i=0;i<channels;i++)
593 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700594#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
595 } else if (mapping_family==254)
596 {
597 int i;
Drew Allen17e14fb2017-04-28 09:58:04 -0700598 if (!validate_ambisonics(channels, streams, coupled_streams))
599 return OPUS_BAD_ARG;
600 for(i = 0; i < (*streams - *coupled_streams); i++)
601 mapping[i] = i + (*coupled_streams * 2);
602 for(i = 0; i < *coupled_streams * 2; i++)
603 mapping[i + (*streams - *coupled_streams)] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700604#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400605 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400606 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700607
608 if (channels>2 && mapping_family==1) {
609 mapping_type = MAPPING_TYPE_SURROUND;
610#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
611 } else if (mapping_family==254)
612 {
613 mapping_type = MAPPING_TYPE_AMBISONICS;
614#endif
615 } else
616 {
617 mapping_type = MAPPING_TYPE_NONE;
618 }
619 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
620 *coupled_streams, mapping,
621 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400622}
623
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500624OpusMSEncoder *opus_multistream_encoder_create(
625 opus_int32 Fs,
626 int channels,
627 int streams,
628 int coupled_streams,
629 const unsigned char *mapping,
630 int application,
631 int *error
632)
633{
634 int ret;
635 OpusMSEncoder *st;
636 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800637 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500638 {
639 if (error)
640 *error = OPUS_BAD_ARG;
641 return NULL;
642 }
643 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
644 if (st==NULL)
645 {
646 if (error)
647 *error = OPUS_ALLOC_FAIL;
648 return NULL;
649 }
650 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
651 if (ret != OPUS_OK)
652 {
653 opus_free(st);
654 st = NULL;
655 }
656 if (error)
657 *error = ret;
658 return st;
659}
660
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400661OpusMSEncoder *opus_multistream_surround_encoder_create(
662 opus_int32 Fs,
663 int channels,
664 int mapping_family,
665 int *streams,
666 int *coupled_streams,
667 unsigned char *mapping,
668 int application,
669 int *error
670)
671{
672 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800673 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400674 OpusMSEncoder *st;
675 if ((channels>255) || (channels<1))
676 {
677 if (error)
678 *error = OPUS_BAD_ARG;
679 return NULL;
680 }
Mark Harris25b27a92014-11-27 08:48:09 -0800681 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
682 if (!size)
683 {
684 if (error)
685 *error = OPUS_UNIMPLEMENTED;
686 return NULL;
687 }
688 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400689 if (st==NULL)
690 {
691 if (error)
692 *error = OPUS_ALLOC_FAIL;
693 return NULL;
694 }
695 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
696 if (ret != OPUS_OK)
697 {
698 opus_free(st);
699 st = NULL;
700 }
701 if (error)
702 *error = ret;
703 return st;
704}
705
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700706static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400707 OpusMSEncoder *st,
708 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700709 int frame_size,
710 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400711 )
712{
713 int i;
714 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400715 int stream_offset;
716 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400717 int coupled_ratio; /* Q8 */
718 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400719 int nb_lfe;
720 int nb_uncoupled;
721 int nb_coupled;
722 int nb_normal;
723 opus_int32 channel_offset;
724 opus_int32 bitrate;
725 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400726
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400727 nb_lfe = (st->lfe_stream!=-1);
728 nb_coupled = st->layout.nb_coupled_streams;
729 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
730 nb_normal = 2*nb_coupled + nb_uncoupled;
731
732 /* Give each non-LFE channel enough bits per channel for coding band energy. */
733 channel_offset = 40*IMAX(50, Fs/frame_size);
734
735 if (st->bitrate_bps==OPUS_AUTO)
736 {
737 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
738 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
739 {
740 bitrate = nb_normal*300000 + nb_lfe*128000;
741 } else {
742 bitrate = st->bitrate_bps;
743 }
744
745 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
746 total rate for the non-energy part to avoid problems at really low rate. */
747 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
748
749 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400750 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400751 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
752 stream_offset = IMAX(0, IMIN(20000, stream_offset));
753
754 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400755 coupled_ratio = 512;
756 /* 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 -0400757 lfe_ratio = 32;
758
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400759 total = (nb_uncoupled<<8) /* mono */
760 + coupled_ratio*nb_coupled /* stereo */
761 + nb_lfe*lfe_ratio;
762 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 -0400763
764 for (i=0;i<st->layout.nb_streams;i++)
765 {
766 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400767 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400768 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400769 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400770 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400771 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700772 }
773}
774
775#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
776static void ambisonics_rate_allocation(
777 OpusMSEncoder *st,
778 opus_int32 *rate,
779 int frame_size,
780 opus_int32 Fs
781 )
782{
783 int i;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700784 int total_rate;
Drew Allen17e14fb2017-04-28 09:58:04 -0700785 int directional_rate;
786 int nondirectional_rate;
787 int leftover_bits;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700788
Drew Allen17e14fb2017-04-28 09:58:04 -0700789 /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
790 * as many bits as all other ambisonics channels.
791 */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700792 const int rate_ratio_num = 4;
793 const int rate_ratio_den = 3;
Drew Allen17e14fb2017-04-28 09:58:04 -0700794 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
795 const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
796 const int nb_directional_channels = st->layout.nb_streams - 1;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700797
798 if (st->bitrate_bps==OPUS_AUTO)
799 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700800 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
801 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700802 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
803 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700804 total_rate = nb_channels * 320000;
805 } else
806 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700807 total_rate = st->bitrate_bps;
808 }
809
Drew Allen17e14fb2017-04-28 09:58:04 -0700810 /* Let y be the directional rate, m be the num of nondirectional channels
811 * m = (s + 1)
812 * and let p, q be integers such that the nondirectional rate is
813 * m_rate = (p / q) * y
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700814 * Also let T be the total bitrate to allocate. Then
Drew Allen17e14fb2017-04-28 09:58:04 -0700815 * T = (n - m) * y + m * m_rate
816 * Solving for y,
817 * y = (q * T) / (m * (p - q) + n * q)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700818 */
Drew Allen17e14fb2017-04-28 09:58:04 -0700819 directional_rate =
820 total_rate * rate_ratio_den
821 / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
822 + nb_channels * rate_ratio_den);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700823
Drew Allen17e14fb2017-04-28 09:58:04 -0700824 /* Calculate the nondirectional rate.
825 * m_rate = y * (p / q)
826 */
827 nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
828
829 /* Calculate the leftover from truncation error.
830 * leftover = T - y * (n - m) - m_rate * m
831 * Place leftover bits in omnidirectional channel.
832 */
833 leftover_bits = total_rate
834 - directional_rate * nb_directional_channels
835 - nondirectional_rate * nb_nondirectional_channels;
836
837 /* Calculate rates for each channel */
838 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700839 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700840 if (i < st->layout.nb_coupled_streams)
841 {
842 rate[i] = nondirectional_rate * 2;
843 } else if (i == st->layout.nb_coupled_streams)
844 {
845 rate[i] = nondirectional_rate + leftover_bits;
846 } else
847 {
848 rate[i] = directional_rate;
849 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700850 }
851}
852#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
853
854static opus_int32 rate_allocation(
855 OpusMSEncoder *st,
856 opus_int32 *rate,
857 int frame_size
858 )
859{
860 int i;
861 opus_int32 rate_sum=0;
862 opus_int32 Fs;
863 char *ptr;
864
865 ptr = (char*)st + align(sizeof(OpusMSEncoder));
866 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
867
868#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
869 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
870 ambisonics_rate_allocation(st, rate, frame_size, Fs);
871 } else
872#endif
873 {
874 surround_rate_allocation(st, rate, frame_size, Fs);
875 }
876
877 for (i=0;i<st->layout.nb_streams;i++)
878 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400879 rate[i] = IMAX(rate[i], 500);
880 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400881 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400882 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400883}
884
Felicia Lim0962cbe2016-10-27 17:03:36 -0700885/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
886#define MS_FRAME_TMP (6*1275+12)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500887static int opus_multistream_encode_native
888(
889 OpusMSEncoder *st,
890 opus_copy_channel_in_func copy_channel_in,
891 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400892 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500893 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500894 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400895 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500896 downmix_func downmix,
897 int float_api
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500898)
899{
900 opus_int32 Fs;
901 int coupled_size;
902 int mono_size;
903 int s;
904 char *ptr;
905 int tot_size;
906 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400907 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500908 unsigned char tmp_data[MS_FRAME_TMP];
909 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400910 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500911 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400912 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400913 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400914 opus_val32 *mem = NULL;
915 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400916 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400917 opus_int32 rate_sum;
918 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500919 ALLOC_STACK;
920
Michael Graczyk39256682016-05-02 21:42:18 -0700921 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400922 {
923 preemph_mem = ms_get_preemph_mem(st);
924 mem = ms_get_window_mem(st);
925 }
926
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500927 ptr = (char*)st + align(sizeof(OpusMSEncoder));
928 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400929 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500930 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500931
Mark Harrisd73c5a92016-11-05 22:01:52 -0700932 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
933 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500934 {
935 RESTORE_STACK;
936 return OPUS_BAD_ARG;
937 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400938
939 /* Smallest packet the encoder can produce. */
940 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700941 /* 100 ms needs an extra byte per stream for the ToC. */
942 if (Fs/frame_size == 10)
943 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400944 if (max_data_bytes < smallest_packet)
945 {
946 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400947 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400948 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500949 ALLOC(buf, 2*frame_size, opus_val16);
950 coupled_size = opus_encoder_get_size(2);
951 mono_size = opus_encoder_get_size(1);
952
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400953 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700954 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400955 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500956 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 -0400957 }
958
Jean-Marc Valin74483662012-12-17 16:23:42 -0500959 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700960 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400961
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400962 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400963 {
964 if (st->bitrate_bps == OPUS_AUTO)
965 {
966 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
967 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
968 {
969 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
970 3*st->bitrate_bps/(3*8*Fs/frame_size)));
971 }
972 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500973 ptr = (char*)st + align(sizeof(OpusMSEncoder));
974 for (s=0;s<st->layout.nb_streams;s++)
975 {
976 OpusEncoder *enc;
977 enc = (OpusEncoder*)ptr;
978 if (s < st->layout.nb_coupled_streams)
979 ptr += align(coupled_size);
980 else
981 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400982 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700983 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400984 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400985 opus_int32 equiv_rate;
986 equiv_rate = st->bitrate_bps;
987 if (frame_size*50 < Fs)
988 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500989 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400990 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500991 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400992 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500993 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400994 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
995 else
996 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400997 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400998 {
999 /* To preserve the spatial image, force stereo CELT on coupled streams */
1000 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001001 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001002 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001003 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -07001004#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
1005 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
1006 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
1007 }
1008#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -05001009 }
1010
1011 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001012 /* Counting ToC */
1013 tot_size = 0;
1014 for (s=0;s<st->layout.nb_streams;s++)
1015 {
1016 OpusEncoder *enc;
1017 int len;
1018 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001019 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001020 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001021
1022 opus_repacketizer_init(&rp);
1023 enc = (OpusEncoder*)ptr;
1024 if (s < st->layout.nb_coupled_streams)
1025 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001026 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001027 int left, right;
1028 left = get_left_channel(&st->layout, s, -1);
1029 right = get_right_channel(&st->layout, s, -1);
1030 (*copy_channel_in)(buf, 2,
1031 pcm, st->layout.nb_channels, left, frame_size);
1032 (*copy_channel_in)(buf+1, 2,
1033 pcm, st->layout.nb_channels, right, frame_size);
1034 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001035 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001036 {
1037 for (i=0;i<21;i++)
1038 {
1039 bandLogE[i] = bandSMR[21*left+i];
1040 bandLogE[21+i] = bandSMR[21*right+i];
1041 }
1042 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001043 c1 = left;
1044 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001045 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001046 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001047 int chan = get_mono_channel(&st->layout, s, -1);
1048 (*copy_channel_in)(buf, 1,
1049 pcm, st->layout.nb_channels, chan, frame_size);
1050 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001051 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001052 {
1053 for (i=0;i<21;i++)
1054 bandLogE[i] = bandSMR[21*chan+i];
1055 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001056 c1 = chan;
1057 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001058 }
Michael Graczyk39256682016-05-02 21:42:18 -07001059 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001060 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001061 /* number of bytes left (+Toc) */
1062 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001063 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001064 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001065 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001066 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001067 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001068 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001069 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001070 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001071 if (!vbr && s == st->layout.nb_streams-1)
1072 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001073 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001074 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001075 if (len<0)
1076 {
1077 RESTORE_STACK;
1078 return len;
1079 }
1080 /* We need to use the repacketizer to add the self-delimiting lengths
1081 while taking into account the fact that the encoder can now return
1082 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001083 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1084 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1085 with the encoder. */
1086 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001087 {
1088 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001089 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001090 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001091 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1092 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 -05001093 data += len;
1094 tot_size += len;
1095 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001096 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001097 RESTORE_STACK;
1098 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001099}
1100
Pedro Becerra1af7f952013-07-11 00:00:47 -04001101#if !defined(DISABLE_FLOAT_API)
1102static void opus_copy_channel_in_float(
1103 opus_val16 *dst,
1104 int dst_stride,
1105 const void *src,
1106 int src_stride,
1107 int src_channel,
1108 int frame_size
1109)
1110{
1111 const float *float_src;
1112 opus_int32 i;
1113 float_src = (const float *)src;
1114 for (i=0;i<frame_size;i++)
1115#if defined(FIXED_POINT)
1116 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1117#else
1118 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1119#endif
1120}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001121#endif
1122
1123static void opus_copy_channel_in_short(
1124 opus_val16 *dst,
1125 int dst_stride,
1126 const void *src,
1127 int src_stride,
1128 int src_channel,
1129 int frame_size
1130)
1131{
1132 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001133 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001134 short_src = (const opus_int16 *)src;
1135 for (i=0;i<frame_size;i++)
1136#if defined(FIXED_POINT)
1137 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1138#else
1139 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1140#endif
1141}
1142
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001143
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001144#ifdef FIXED_POINT
1145int opus_multistream_encode(
1146 OpusMSEncoder *st,
1147 const opus_val16 *pcm,
1148 int frame_size,
1149 unsigned char *data,
1150 opus_int32 max_data_bytes
1151)
1152{
1153 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001154 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001155}
1156
1157#ifndef DISABLE_FLOAT_API
1158int opus_multistream_encode_float(
1159 OpusMSEncoder *st,
1160 const float *pcm,
1161 int frame_size,
1162 unsigned char *data,
1163 opus_int32 max_data_bytes
1164)
1165{
1166 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001167 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001168}
1169#endif
1170
1171#else
1172
1173int opus_multistream_encode_float
1174(
1175 OpusMSEncoder *st,
1176 const opus_val16 *pcm,
1177 int frame_size,
1178 unsigned char *data,
1179 opus_int32 max_data_bytes
1180)
1181{
1182 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001183 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001184}
1185
1186int opus_multistream_encode(
1187 OpusMSEncoder *st,
1188 const opus_int16 *pcm,
1189 int frame_size,
1190 unsigned char *data,
1191 opus_int32 max_data_bytes
1192)
1193{
1194 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001195 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001196}
1197#endif
1198
1199int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1200{
1201 va_list ap;
1202 int coupled_size, mono_size;
1203 char *ptr;
1204 int ret = OPUS_OK;
1205
1206 va_start(ap, request);
1207
1208 coupled_size = opus_encoder_get_size(2);
1209 mono_size = opus_encoder_get_size(1);
1210 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1211 switch (request)
1212 {
1213 case OPUS_SET_BITRATE_REQUEST:
1214 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001215 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001216 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001217 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001218 if (value <= 0)
1219 goto bad_arg;
1220 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001221 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001222 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001223 }
1224 break;
1225 case OPUS_GET_BITRATE_REQUEST:
1226 {
1227 int s;
1228 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001229 if (!value)
1230 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001231 goto bad_arg;
1232 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001233 *value = 0;
1234 for (s=0;s<st->layout.nb_streams;s++)
1235 {
1236 opus_int32 rate;
1237 OpusEncoder *enc;
1238 enc = (OpusEncoder*)ptr;
1239 if (s < st->layout.nb_coupled_streams)
1240 ptr += align(coupled_size);
1241 else
1242 ptr += align(mono_size);
1243 opus_encoder_ctl(enc, request, &rate);
1244 *value += rate;
1245 }
1246 }
1247 break;
1248 case OPUS_GET_LSB_DEPTH_REQUEST:
1249 case OPUS_GET_VBR_REQUEST:
1250 case OPUS_GET_APPLICATION_REQUEST:
1251 case OPUS_GET_BANDWIDTH_REQUEST:
1252 case OPUS_GET_COMPLEXITY_REQUEST:
1253 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1254 case OPUS_GET_DTX_REQUEST:
1255 case OPUS_GET_VOICE_RATIO_REQUEST:
1256 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1257 case OPUS_GET_SIGNAL_REQUEST:
1258 case OPUS_GET_LOOKAHEAD_REQUEST:
1259 case OPUS_GET_SAMPLE_RATE_REQUEST:
1260 case OPUS_GET_INBAND_FEC_REQUEST:
1261 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001262 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001263 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001264 {
1265 OpusEncoder *enc;
1266 /* For int32* GET params, just query the first stream */
1267 opus_int32 *value = va_arg(ap, opus_int32*);
1268 enc = (OpusEncoder*)ptr;
1269 ret = opus_encoder_ctl(enc, request, value);
1270 }
1271 break;
1272 case OPUS_GET_FINAL_RANGE_REQUEST:
1273 {
1274 int s;
1275 opus_uint32 *value = va_arg(ap, opus_uint32*);
1276 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001277 if (!value)
1278 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001279 goto bad_arg;
1280 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001281 *value=0;
1282 for (s=0;s<st->layout.nb_streams;s++)
1283 {
1284 OpusEncoder *enc;
1285 enc = (OpusEncoder*)ptr;
1286 if (s < st->layout.nb_coupled_streams)
1287 ptr += align(coupled_size);
1288 else
1289 ptr += align(mono_size);
1290 ret = opus_encoder_ctl(enc, request, &tmp);
1291 if (ret != OPUS_OK) break;
1292 *value ^= tmp;
1293 }
1294 }
1295 break;
1296 case OPUS_SET_LSB_DEPTH_REQUEST:
1297 case OPUS_SET_COMPLEXITY_REQUEST:
1298 case OPUS_SET_VBR_REQUEST:
1299 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001300 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001301 case OPUS_SET_BANDWIDTH_REQUEST:
1302 case OPUS_SET_SIGNAL_REQUEST:
1303 case OPUS_SET_APPLICATION_REQUEST:
1304 case OPUS_SET_INBAND_FEC_REQUEST:
1305 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1306 case OPUS_SET_DTX_REQUEST:
1307 case OPUS_SET_FORCE_MODE_REQUEST:
1308 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001309 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001310 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001311 {
1312 int s;
1313 /* This works for int32 params */
1314 opus_int32 value = va_arg(ap, opus_int32);
1315 for (s=0;s<st->layout.nb_streams;s++)
1316 {
1317 OpusEncoder *enc;
1318
1319 enc = (OpusEncoder*)ptr;
1320 if (s < st->layout.nb_coupled_streams)
1321 ptr += align(coupled_size);
1322 else
1323 ptr += align(mono_size);
1324 ret = opus_encoder_ctl(enc, request, value);
1325 if (ret != OPUS_OK)
1326 break;
1327 }
1328 }
1329 break;
1330 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1331 {
1332 int s;
1333 opus_int32 stream_id;
1334 OpusEncoder **value;
1335 stream_id = va_arg(ap, opus_int32);
1336 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1337 ret = OPUS_BAD_ARG;
1338 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001339 if (!value)
1340 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001341 goto bad_arg;
1342 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001343 for (s=0;s<stream_id;s++)
1344 {
1345 if (s < st->layout.nb_coupled_streams)
1346 ptr += align(coupled_size);
1347 else
1348 ptr += align(mono_size);
1349 }
1350 *value = (OpusEncoder*)ptr;
1351 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001352 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001353 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001354 {
1355 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001356 st->variable_duration = value;
1357 }
1358 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001359 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001360 {
1361 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001362 if (!value)
1363 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001364 goto bad_arg;
1365 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001366 *value = st->variable_duration;
1367 }
1368 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001369 case OPUS_RESET_STATE:
1370 {
1371 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001372 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001373 {
1374 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1375 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1376 }
1377 for (s=0;s<st->layout.nb_streams;s++)
1378 {
1379 OpusEncoder *enc;
1380 enc = (OpusEncoder*)ptr;
1381 if (s < st->layout.nb_coupled_streams)
1382 ptr += align(coupled_size);
1383 else
1384 ptr += align(mono_size);
1385 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1386 if (ret != OPUS_OK)
1387 break;
1388 }
1389 }
1390 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001391 default:
1392 ret = OPUS_UNIMPLEMENTED;
1393 break;
1394 }
1395
1396 va_end(ap);
1397 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001398bad_arg:
1399 va_end(ap);
1400 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001401}
1402
1403void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1404{
1405 opus_free(st);
1406}