blob: 98e174bc50b65a5479f3a31243f865c24cea7fde [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. */
307 if (!(sum < 1e9f) || celt_isnan(sum))
308 {
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
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400329 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM);
330 /* 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
503 )
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500504 return OPUS_BAD_ARG;
505 ptr = (char*)st + align(sizeof(OpusMSEncoder));
506 coupled_size = opus_encoder_get_size(2);
507 mono_size = opus_encoder_get_size(1);
508
509 for (i=0;i<st->layout.nb_coupled_streams;i++)
510 {
511 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400512 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400513 if (i==st->lfe_stream)
514 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500515 ptr += align(coupled_size);
516 }
517 for (;i<st->layout.nb_streams;i++)
518 {
519 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400520 if (i==st->lfe_stream)
521 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500522 if(ret!=OPUS_OK)return ret;
523 ptr += align(mono_size);
524 }
Michael Graczyk39256682016-05-02 21:42:18 -0700525 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400526 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400527 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
528 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400529 }
Michael Graczyk39256682016-05-02 21:42:18 -0700530 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500531 return OPUS_OK;
532}
533
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400534int opus_multistream_encoder_init(
535 OpusMSEncoder *st,
536 opus_int32 Fs,
537 int channels,
538 int streams,
539 int coupled_streams,
540 const unsigned char *mapping,
541 int application
542)
543{
Michael Graczyk39256682016-05-02 21:42:18 -0700544 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
545 coupled_streams, mapping,
546 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400547}
548
549int opus_multistream_surround_encoder_init(
550 OpusMSEncoder *st,
551 opus_int32 Fs,
552 int channels,
553 int mapping_family,
554 int *streams,
555 int *coupled_streams,
556 unsigned char *mapping,
557 int application
558)
559{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700560 MappingType mapping_type;
561
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400562 if ((channels>255) || (channels<1))
563 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400564 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400565 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400566 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400567 if (channels==1)
568 {
569 *streams=1;
570 *coupled_streams=0;
571 mapping[0]=0;
572 } else if (channels==2)
573 {
574 *streams=1;
575 *coupled_streams=1;
576 mapping[0]=0;
577 mapping[1]=1;
578 } else
579 return OPUS_UNIMPLEMENTED;
580 } else if (mapping_family==1 && channels<=8 && channels>=1)
581 {
582 int i;
583 *streams=vorbis_mappings[channels-1].nb_streams;
584 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
585 for (i=0;i<channels;i++)
586 mapping[i] = vorbis_mappings[channels-1].mapping[i];
587 if (channels>=6)
588 st->lfe_stream = *streams-1;
589 } else if (mapping_family==255)
590 {
591 int i;
592 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400593 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400594 for(i=0;i<channels;i++)
595 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700596#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
597 } else if (mapping_family==254)
598 {
599 int i;
Drew Allen17e14fb2017-04-28 09:58:04 -0700600 if (!validate_ambisonics(channels, streams, coupled_streams))
601 return OPUS_BAD_ARG;
602 for(i = 0; i < (*streams - *coupled_streams); i++)
603 mapping[i] = i + (*coupled_streams * 2);
604 for(i = 0; i < *coupled_streams * 2; i++)
605 mapping[i + (*streams - *coupled_streams)] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700606#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400607 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400608 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700609
610 if (channels>2 && mapping_family==1) {
611 mapping_type = MAPPING_TYPE_SURROUND;
612#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
613 } else if (mapping_family==254)
614 {
615 mapping_type = MAPPING_TYPE_AMBISONICS;
616#endif
617 } else
618 {
619 mapping_type = MAPPING_TYPE_NONE;
620 }
621 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
622 *coupled_streams, mapping,
623 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400624}
625
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500626OpusMSEncoder *opus_multistream_encoder_create(
627 opus_int32 Fs,
628 int channels,
629 int streams,
630 int coupled_streams,
631 const unsigned char *mapping,
632 int application,
633 int *error
634)
635{
636 int ret;
637 OpusMSEncoder *st;
638 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800639 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500640 {
641 if (error)
642 *error = OPUS_BAD_ARG;
643 return NULL;
644 }
645 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
646 if (st==NULL)
647 {
648 if (error)
649 *error = OPUS_ALLOC_FAIL;
650 return NULL;
651 }
652 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
653 if (ret != OPUS_OK)
654 {
655 opus_free(st);
656 st = NULL;
657 }
658 if (error)
659 *error = ret;
660 return st;
661}
662
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400663OpusMSEncoder *opus_multistream_surround_encoder_create(
664 opus_int32 Fs,
665 int channels,
666 int mapping_family,
667 int *streams,
668 int *coupled_streams,
669 unsigned char *mapping,
670 int application,
671 int *error
672)
673{
674 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800675 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400676 OpusMSEncoder *st;
677 if ((channels>255) || (channels<1))
678 {
679 if (error)
680 *error = OPUS_BAD_ARG;
681 return NULL;
682 }
Mark Harris25b27a92014-11-27 08:48:09 -0800683 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
684 if (!size)
685 {
686 if (error)
687 *error = OPUS_UNIMPLEMENTED;
688 return NULL;
689 }
690 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400691 if (st==NULL)
692 {
693 if (error)
694 *error = OPUS_ALLOC_FAIL;
695 return NULL;
696 }
697 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
698 if (ret != OPUS_OK)
699 {
700 opus_free(st);
701 st = NULL;
702 }
703 if (error)
704 *error = ret;
705 return st;
706}
707
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700708static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400709 OpusMSEncoder *st,
710 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700711 int frame_size,
712 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400713 )
714{
715 int i;
716 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400717 int stream_offset;
718 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400719 int coupled_ratio; /* Q8 */
720 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400721 int nb_lfe;
722 int nb_uncoupled;
723 int nb_coupled;
724 int nb_normal;
725 opus_int32 channel_offset;
726 opus_int32 bitrate;
727 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400728
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400729 nb_lfe = (st->lfe_stream!=-1);
730 nb_coupled = st->layout.nb_coupled_streams;
731 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
732 nb_normal = 2*nb_coupled + nb_uncoupled;
733
734 /* Give each non-LFE channel enough bits per channel for coding band energy. */
735 channel_offset = 40*IMAX(50, Fs/frame_size);
736
737 if (st->bitrate_bps==OPUS_AUTO)
738 {
739 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
740 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
741 {
742 bitrate = nb_normal*300000 + nb_lfe*128000;
743 } else {
744 bitrate = st->bitrate_bps;
745 }
746
747 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
748 total rate for the non-energy part to avoid problems at really low rate. */
749 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
750
751 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400752 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400753 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
754 stream_offset = IMAX(0, IMIN(20000, stream_offset));
755
756 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400757 coupled_ratio = 512;
758 /* 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 -0400759 lfe_ratio = 32;
760
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400761 total = (nb_uncoupled<<8) /* mono */
762 + coupled_ratio*nb_coupled /* stereo */
763 + nb_lfe*lfe_ratio;
764 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 -0400765
766 for (i=0;i<st->layout.nb_streams;i++)
767 {
768 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400769 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400770 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400771 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400772 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400773 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700774 }
775}
776
777#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
778static void ambisonics_rate_allocation(
779 OpusMSEncoder *st,
780 opus_int32 *rate,
781 int frame_size,
782 opus_int32 Fs
783 )
784{
785 int i;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700786 int total_rate;
Drew Allen17e14fb2017-04-28 09:58:04 -0700787 int directional_rate;
788 int nondirectional_rate;
789 int leftover_bits;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700790
Drew Allen17e14fb2017-04-28 09:58:04 -0700791 /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
792 * as many bits as all other ambisonics channels.
793 */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700794 const int rate_ratio_num = 4;
795 const int rate_ratio_den = 3;
Drew Allen17e14fb2017-04-28 09:58:04 -0700796 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
797 const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
798 const int nb_directional_channels = st->layout.nb_streams - 1;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700799
800 if (st->bitrate_bps==OPUS_AUTO)
801 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700802 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
803 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700804 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
805 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700806 total_rate = nb_channels * 320000;
807 } else
808 {
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700809 total_rate = st->bitrate_bps;
810 }
811
Drew Allen17e14fb2017-04-28 09:58:04 -0700812 /* Let y be the directional rate, m be the num of nondirectional channels
813 * m = (s + 1)
814 * and let p, q be integers such that the nondirectional rate is
815 * m_rate = (p / q) * y
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700816 * Also let T be the total bitrate to allocate. Then
Drew Allen17e14fb2017-04-28 09:58:04 -0700817 * T = (n - m) * y + m * m_rate
818 * Solving for y,
819 * y = (q * T) / (m * (p - q) + n * q)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700820 */
Drew Allen17e14fb2017-04-28 09:58:04 -0700821 directional_rate =
822 total_rate * rate_ratio_den
823 / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
824 + nb_channels * rate_ratio_den);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700825
Drew Allen17e14fb2017-04-28 09:58:04 -0700826 /* Calculate the nondirectional rate.
827 * m_rate = y * (p / q)
828 */
829 nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
830
831 /* Calculate the leftover from truncation error.
832 * leftover = T - y * (n - m) - m_rate * m
833 * Place leftover bits in omnidirectional channel.
834 */
835 leftover_bits = total_rate
836 - directional_rate * nb_directional_channels
837 - nondirectional_rate * nb_nondirectional_channels;
838
839 /* Calculate rates for each channel */
840 for (i = 0; i < st->layout.nb_streams; i++)
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700841 {
Drew Allen17e14fb2017-04-28 09:58:04 -0700842 if (i < st->layout.nb_coupled_streams)
843 {
844 rate[i] = nondirectional_rate * 2;
845 } else if (i == st->layout.nb_coupled_streams)
846 {
847 rate[i] = nondirectional_rate + leftover_bits;
848 } else
849 {
850 rate[i] = directional_rate;
851 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700852 }
853}
854#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
855
856static opus_int32 rate_allocation(
857 OpusMSEncoder *st,
858 opus_int32 *rate,
859 int frame_size
860 )
861{
862 int i;
863 opus_int32 rate_sum=0;
864 opus_int32 Fs;
865 char *ptr;
866
867 ptr = (char*)st + align(sizeof(OpusMSEncoder));
868 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
869
870#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
871 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
872 ambisonics_rate_allocation(st, rate, frame_size, Fs);
873 } else
874#endif
875 {
876 surround_rate_allocation(st, rate, frame_size, Fs);
877 }
878
879 for (i=0;i<st->layout.nb_streams;i++)
880 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400881 rate[i] = IMAX(rate[i], 500);
882 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400883 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400884 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400885}
886
Felicia Lim0962cbe2016-10-27 17:03:36 -0700887/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
888#define MS_FRAME_TMP (6*1275+12)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500889static int opus_multistream_encode_native
890(
891 OpusMSEncoder *st,
892 opus_copy_channel_in_func copy_channel_in,
893 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400894 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500895 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500896 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400897 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500898 downmix_func downmix,
899 int float_api
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500900)
901{
902 opus_int32 Fs;
903 int coupled_size;
904 int mono_size;
905 int s;
906 char *ptr;
907 int tot_size;
908 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400909 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500910 unsigned char tmp_data[MS_FRAME_TMP];
911 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400912 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500913 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400914 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400915 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400916 opus_val32 *mem = NULL;
917 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400918 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400919 opus_int32 rate_sum;
920 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500921 ALLOC_STACK;
922
Michael Graczyk39256682016-05-02 21:42:18 -0700923 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400924 {
925 preemph_mem = ms_get_preemph_mem(st);
926 mem = ms_get_window_mem(st);
927 }
928
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500929 ptr = (char*)st + align(sizeof(OpusMSEncoder));
930 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400931 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500932 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500933
Mark Harrisd73c5a92016-11-05 22:01:52 -0700934 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
935 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500936 {
937 RESTORE_STACK;
938 return OPUS_BAD_ARG;
939 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400940
941 /* Smallest packet the encoder can produce. */
942 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700943 /* 100 ms needs an extra byte per stream for the ToC. */
944 if (Fs/frame_size == 10)
945 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400946 if (max_data_bytes < smallest_packet)
947 {
948 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400949 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400950 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500951 ALLOC(buf, 2*frame_size, opus_val16);
952 coupled_size = opus_encoder_get_size(2);
953 mono_size = opus_encoder_get_size(1);
954
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400955 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700956 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400957 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500958 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 -0400959 }
960
Jean-Marc Valin74483662012-12-17 16:23:42 -0500961 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700962 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400963
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400964 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400965 {
966 if (st->bitrate_bps == OPUS_AUTO)
967 {
968 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
969 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
970 {
971 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
972 3*st->bitrate_bps/(3*8*Fs/frame_size)));
973 }
974 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500975 ptr = (char*)st + align(sizeof(OpusMSEncoder));
976 for (s=0;s<st->layout.nb_streams;s++)
977 {
978 OpusEncoder *enc;
979 enc = (OpusEncoder*)ptr;
980 if (s < st->layout.nb_coupled_streams)
981 ptr += align(coupled_size);
982 else
983 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400984 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700985 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400986 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400987 opus_int32 equiv_rate;
988 equiv_rate = st->bitrate_bps;
989 if (frame_size*50 < Fs)
990 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500991 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400992 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500993 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400994 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500995 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400996 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
997 else
998 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400999 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001000 {
1001 /* To preserve the spatial image, force stereo CELT on coupled streams */
1002 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001003 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001004 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001005 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -07001006#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
1007 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
1008 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
1009 }
1010#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -05001011 }
1012
1013 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001014 /* Counting ToC */
1015 tot_size = 0;
1016 for (s=0;s<st->layout.nb_streams;s++)
1017 {
1018 OpusEncoder *enc;
1019 int len;
1020 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001021 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001022 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001023
1024 opus_repacketizer_init(&rp);
1025 enc = (OpusEncoder*)ptr;
1026 if (s < st->layout.nb_coupled_streams)
1027 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001028 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001029 int left, right;
1030 left = get_left_channel(&st->layout, s, -1);
1031 right = get_right_channel(&st->layout, s, -1);
1032 (*copy_channel_in)(buf, 2,
1033 pcm, st->layout.nb_channels, left, frame_size);
1034 (*copy_channel_in)(buf+1, 2,
1035 pcm, st->layout.nb_channels, right, frame_size);
1036 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001037 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001038 {
1039 for (i=0;i<21;i++)
1040 {
1041 bandLogE[i] = bandSMR[21*left+i];
1042 bandLogE[21+i] = bandSMR[21*right+i];
1043 }
1044 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001045 c1 = left;
1046 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001047 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001048 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001049 int chan = get_mono_channel(&st->layout, s, -1);
1050 (*copy_channel_in)(buf, 1,
1051 pcm, st->layout.nb_channels, chan, frame_size);
1052 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001053 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001054 {
1055 for (i=0;i<21;i++)
1056 bandLogE[i] = bandSMR[21*chan+i];
1057 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001058 c1 = chan;
1059 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001060 }
Michael Graczyk39256682016-05-02 21:42:18 -07001061 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001062 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001063 /* number of bytes left (+Toc) */
1064 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001065 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001066 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001067 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001068 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001069 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001070 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001071 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001072 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001073 if (!vbr && s == st->layout.nb_streams-1)
1074 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001075 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001076 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001077 if (len<0)
1078 {
1079 RESTORE_STACK;
1080 return len;
1081 }
1082 /* We need to use the repacketizer to add the self-delimiting lengths
1083 while taking into account the fact that the encoder can now return
1084 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001085 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1086 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1087 with the encoder. */
1088 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001089 {
1090 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001091 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001092 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001093 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1094 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 -05001095 data += len;
1096 tot_size += len;
1097 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001098 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001099 RESTORE_STACK;
1100 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001101}
1102
Pedro Becerra1af7f952013-07-11 00:00:47 -04001103#if !defined(DISABLE_FLOAT_API)
1104static void opus_copy_channel_in_float(
1105 opus_val16 *dst,
1106 int dst_stride,
1107 const void *src,
1108 int src_stride,
1109 int src_channel,
1110 int frame_size
1111)
1112{
1113 const float *float_src;
1114 opus_int32 i;
1115 float_src = (const float *)src;
1116 for (i=0;i<frame_size;i++)
1117#if defined(FIXED_POINT)
1118 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1119#else
1120 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1121#endif
1122}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001123#endif
1124
1125static void opus_copy_channel_in_short(
1126 opus_val16 *dst,
1127 int dst_stride,
1128 const void *src,
1129 int src_stride,
1130 int src_channel,
1131 int frame_size
1132)
1133{
1134 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001135 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001136 short_src = (const opus_int16 *)src;
1137 for (i=0;i<frame_size;i++)
1138#if defined(FIXED_POINT)
1139 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1140#else
1141 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1142#endif
1143}
1144
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001145
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001146#ifdef FIXED_POINT
1147int opus_multistream_encode(
1148 OpusMSEncoder *st,
1149 const opus_val16 *pcm,
1150 int frame_size,
1151 unsigned char *data,
1152 opus_int32 max_data_bytes
1153)
1154{
1155 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001156 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001157}
1158
1159#ifndef DISABLE_FLOAT_API
1160int opus_multistream_encode_float(
1161 OpusMSEncoder *st,
1162 const float *pcm,
1163 int frame_size,
1164 unsigned char *data,
1165 opus_int32 max_data_bytes
1166)
1167{
1168 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001169 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001170}
1171#endif
1172
1173#else
1174
1175int opus_multistream_encode_float
1176(
1177 OpusMSEncoder *st,
1178 const opus_val16 *pcm,
1179 int frame_size,
1180 unsigned char *data,
1181 opus_int32 max_data_bytes
1182)
1183{
1184 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001185 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001186}
1187
1188int opus_multistream_encode(
1189 OpusMSEncoder *st,
1190 const opus_int16 *pcm,
1191 int frame_size,
1192 unsigned char *data,
1193 opus_int32 max_data_bytes
1194)
1195{
1196 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001197 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001198}
1199#endif
1200
1201int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1202{
1203 va_list ap;
1204 int coupled_size, mono_size;
1205 char *ptr;
1206 int ret = OPUS_OK;
1207
1208 va_start(ap, request);
1209
1210 coupled_size = opus_encoder_get_size(2);
1211 mono_size = opus_encoder_get_size(1);
1212 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1213 switch (request)
1214 {
1215 case OPUS_SET_BITRATE_REQUEST:
1216 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001217 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001218 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001219 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001220 if (value <= 0)
1221 goto bad_arg;
1222 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001223 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001224 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001225 }
1226 break;
1227 case OPUS_GET_BITRATE_REQUEST:
1228 {
1229 int s;
1230 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001231 if (!value)
1232 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001233 goto bad_arg;
1234 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001235 *value = 0;
1236 for (s=0;s<st->layout.nb_streams;s++)
1237 {
1238 opus_int32 rate;
1239 OpusEncoder *enc;
1240 enc = (OpusEncoder*)ptr;
1241 if (s < st->layout.nb_coupled_streams)
1242 ptr += align(coupled_size);
1243 else
1244 ptr += align(mono_size);
1245 opus_encoder_ctl(enc, request, &rate);
1246 *value += rate;
1247 }
1248 }
1249 break;
1250 case OPUS_GET_LSB_DEPTH_REQUEST:
1251 case OPUS_GET_VBR_REQUEST:
1252 case OPUS_GET_APPLICATION_REQUEST:
1253 case OPUS_GET_BANDWIDTH_REQUEST:
1254 case OPUS_GET_COMPLEXITY_REQUEST:
1255 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1256 case OPUS_GET_DTX_REQUEST:
1257 case OPUS_GET_VOICE_RATIO_REQUEST:
1258 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1259 case OPUS_GET_SIGNAL_REQUEST:
1260 case OPUS_GET_LOOKAHEAD_REQUEST:
1261 case OPUS_GET_SAMPLE_RATE_REQUEST:
1262 case OPUS_GET_INBAND_FEC_REQUEST:
1263 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001264 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001265 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001266 {
1267 OpusEncoder *enc;
1268 /* For int32* GET params, just query the first stream */
1269 opus_int32 *value = va_arg(ap, opus_int32*);
1270 enc = (OpusEncoder*)ptr;
1271 ret = opus_encoder_ctl(enc, request, value);
1272 }
1273 break;
1274 case OPUS_GET_FINAL_RANGE_REQUEST:
1275 {
1276 int s;
1277 opus_uint32 *value = va_arg(ap, opus_uint32*);
1278 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001279 if (!value)
1280 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001281 goto bad_arg;
1282 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001283 *value=0;
1284 for (s=0;s<st->layout.nb_streams;s++)
1285 {
1286 OpusEncoder *enc;
1287 enc = (OpusEncoder*)ptr;
1288 if (s < st->layout.nb_coupled_streams)
1289 ptr += align(coupled_size);
1290 else
1291 ptr += align(mono_size);
1292 ret = opus_encoder_ctl(enc, request, &tmp);
1293 if (ret != OPUS_OK) break;
1294 *value ^= tmp;
1295 }
1296 }
1297 break;
1298 case OPUS_SET_LSB_DEPTH_REQUEST:
1299 case OPUS_SET_COMPLEXITY_REQUEST:
1300 case OPUS_SET_VBR_REQUEST:
1301 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001302 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001303 case OPUS_SET_BANDWIDTH_REQUEST:
1304 case OPUS_SET_SIGNAL_REQUEST:
1305 case OPUS_SET_APPLICATION_REQUEST:
1306 case OPUS_SET_INBAND_FEC_REQUEST:
1307 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1308 case OPUS_SET_DTX_REQUEST:
1309 case OPUS_SET_FORCE_MODE_REQUEST:
1310 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001311 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001312 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001313 {
1314 int s;
1315 /* This works for int32 params */
1316 opus_int32 value = va_arg(ap, opus_int32);
1317 for (s=0;s<st->layout.nb_streams;s++)
1318 {
1319 OpusEncoder *enc;
1320
1321 enc = (OpusEncoder*)ptr;
1322 if (s < st->layout.nb_coupled_streams)
1323 ptr += align(coupled_size);
1324 else
1325 ptr += align(mono_size);
1326 ret = opus_encoder_ctl(enc, request, value);
1327 if (ret != OPUS_OK)
1328 break;
1329 }
1330 }
1331 break;
1332 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1333 {
1334 int s;
1335 opus_int32 stream_id;
1336 OpusEncoder **value;
1337 stream_id = va_arg(ap, opus_int32);
1338 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1339 ret = OPUS_BAD_ARG;
1340 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001341 if (!value)
1342 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001343 goto bad_arg;
1344 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001345 for (s=0;s<stream_id;s++)
1346 {
1347 if (s < st->layout.nb_coupled_streams)
1348 ptr += align(coupled_size);
1349 else
1350 ptr += align(mono_size);
1351 }
1352 *value = (OpusEncoder*)ptr;
1353 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001354 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001355 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001356 {
1357 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001358 st->variable_duration = value;
1359 }
1360 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001361 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001362 {
1363 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001364 if (!value)
1365 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001366 goto bad_arg;
1367 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001368 *value = st->variable_duration;
1369 }
1370 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001371 case OPUS_RESET_STATE:
1372 {
1373 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001374 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001375 {
1376 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1377 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1378 }
1379 for (s=0;s<st->layout.nb_streams;s++)
1380 {
1381 OpusEncoder *enc;
1382 enc = (OpusEncoder*)ptr;
1383 if (s < st->layout.nb_coupled_streams)
1384 ptr += align(coupled_size);
1385 else
1386 ptr += align(mono_size);
1387 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1388 if (ret != OPUS_OK)
1389 break;
1390 }
1391 }
1392 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001393 default:
1394 ret = OPUS_UNIMPLEMENTED;
1395 break;
1396 }
1397
1398 va_end(ap);
1399 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001400bad_arg:
1401 va_end(ap);
1402 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001403}
1404
1405void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1406{
1407 opus_free(st);
1408}