blob: 9cb9bf3458f7d633abc3a0c8b349cb29886c6b17 [file] [log] [blame]
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001/* 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"
39#include "mathops.h"
40#include "mdct.h"
41#include "modes.h"
42#include "bands.h"
43#include "quant_bands.h"
flimc91ee5b2016-01-26 14:33:44 +010044#include "pitch.h"
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080045
46typedef 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
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080064static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
65{
66 int s;
67 char *ptr;
68 int coupled_size, mono_size;
69
70 coupled_size = opus_encoder_get_size(2);
71 mono_size = opus_encoder_get_size(1);
72 ptr = (char*)st + align(sizeof(OpusMSEncoder));
73 for (s=0;s<st->layout.nb_streams;s++)
74 {
75 if (s < st->layout.nb_coupled_streams)
76 ptr += align(coupled_size);
77 else
78 ptr += align(mono_size);
79 }
flimc91ee5b2016-01-26 14:33:44 +010080 /* void* cast avoids clang -Wcast-align warning */
81 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080082}
83
84static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
85{
86 int s;
87 char *ptr;
88 int coupled_size, mono_size;
89
90 coupled_size = opus_encoder_get_size(2);
91 mono_size = opus_encoder_get_size(1);
92 ptr = (char*)st + align(sizeof(OpusMSEncoder));
93 for (s=0;s<st->layout.nb_streams;s++)
94 {
95 if (s < st->layout.nb_coupled_streams)
96 ptr += align(coupled_size);
97 else
98 ptr += align(mono_size);
99 }
flimc91ee5b2016-01-26 14:33:44 +0100100 /* void* cast avoids clang -Wcast-align warning */
101 return (opus_val32*)(void*)ptr;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800102}
103
Felicia Lim0c2090c2017-07-05 17:36:56 -0700104static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
105{
106 int order_plus_one;
107 int acn_channels;
108 int nondiegetic_channels;
109
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800110 if (nb_channels < 1 || nb_channels > 227)
111 return 0;
112
Felicia Lim0c2090c2017-07-05 17:36:56 -0700113 order_plus_one = isqrt32(nb_channels);
114 acn_channels = order_plus_one * order_plus_one;
115 nondiegetic_channels = nb_channels - acn_channels;
116
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800117 if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
Felicia Lim0c2090c2017-07-05 17:36:56 -0700118 return 0;
119
120 if (nb_streams)
121 *nb_streams = acn_channels + (nondiegetic_channels != 0);
122 if (nb_coupled_streams)
123 *nb_coupled_streams = nondiegetic_channels != 0;
124 return 1;
125}
Felicia Lim0c2090c2017-07-05 17:36:56 -0700126
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800127static int validate_encoder_layout(const ChannelLayout *layout)
128{
129 int s;
130 for (s=0;s<layout->nb_streams;s++)
131 {
132 if (s < layout->nb_coupled_streams)
133 {
134 if (get_left_channel(layout, s, -1)==-1)
135 return 0;
136 if (get_right_channel(layout, s, -1)==-1)
137 return 0;
138 } else {
139 if (get_mono_channel(layout, s, -1)==-1)
140 return 0;
141 }
142 }
143 return 1;
144}
145
146static void channel_pos(int channels, int pos[8])
147{
148 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
149 if (channels==4)
150 {
151 pos[0]=1;
152 pos[1]=3;
153 pos[2]=1;
154 pos[3]=3;
155 } else if (channels==3||channels==5||channels==6)
156 {
157 pos[0]=1;
158 pos[1]=2;
159 pos[2]=3;
160 pos[3]=1;
161 pos[4]=3;
162 pos[5]=0;
163 } else if (channels==7)
164 {
165 pos[0]=1;
166 pos[1]=2;
167 pos[2]=3;
168 pos[3]=1;
169 pos[4]=3;
170 pos[5]=2;
171 pos[6]=0;
172 } else if (channels==8)
173 {
174 pos[0]=1;
175 pos[1]=2;
176 pos[2]=3;
177 pos[3]=1;
178 pos[4]=3;
179 pos[5]=1;
180 pos[6]=3;
181 pos[7]=0;
182 }
183}
184
185#if 1
186/* Computes a rough approximation of log2(2^a + 2^b) */
187static opus_val16 logSum(opus_val16 a, opus_val16 b)
188{
189 opus_val16 max;
190 opus_val32 diff;
191 opus_val16 frac;
192 static const opus_val16 diff_table[17] = {
193 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
194 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
195 QCONST16(0.0028123f, DB_SHIFT)
196 };
197 int low;
198 if (a>b)
199 {
200 max = a;
201 diff = SUB32(EXTEND32(a),EXTEND32(b));
202 } else {
203 max = b;
204 diff = SUB32(EXTEND32(b),EXTEND32(a));
205 }
flimc91ee5b2016-01-26 14:33:44 +0100206 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800207 return max;
208#ifdef FIXED_POINT
209 low = SHR32(diff, DB_SHIFT-1);
210 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
211#else
212 low = (int)floor(2*diff);
213 frac = 2*diff - low;
214#endif
215 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
216}
217#else
218opus_val16 logSum(opus_val16 a, opus_val16 b)
219{
220 return log2(pow(4, a)+ pow(4, b))/2;
221}
222#endif
223
224void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
flimc91ee5b2016-01-26 14:33:44 +0100225 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800226)
227{
228 int c;
229 int i;
230 int LM;
231 int pos[8] = {0};
232 int upsample;
233 int frame_size;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700234 int freq_size;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800235 opus_val16 channel_offset;
236 opus_val32 bandE[21];
237 opus_val16 maskLogE[3][21];
238 VARDECL(opus_val32, in);
239 VARDECL(opus_val16, x);
240 VARDECL(opus_val32, freq);
241 SAVE_STACK;
242
243 upsample = resampling_factor(rate);
244 frame_size = len*upsample;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700245 freq_size = IMIN(960, frame_size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800246
Felicia Limd03c3732016-07-25 20:28:37 +0200247 /* LM = log2(frame_size / 120) */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800248 for (LM=0;LM<celt_mode->maxLM;LM++)
249 if (celt_mode->shortMdctSize<<LM==frame_size)
250 break;
251
252 ALLOC(in, frame_size+overlap, opus_val32);
253 ALLOC(x, len, opus_val16);
Felicia Lim0c2090c2017-07-05 17:36:56 -0700254 ALLOC(freq, freq_size, opus_val32);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800255
256 channel_pos(channels, pos);
257
258 for (c=0;c<3;c++)
259 for (i=0;i<21;i++)
260 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
261
262 for (c=0;c<channels;c++)
263 {
Felicia Lim0c2090c2017-07-05 17:36:56 -0700264 int frame;
265 int nb_frames = frame_size/freq_size;
266 celt_assert(nb_frames*freq_size == frame_size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800267 OPUS_COPY(in, mem+c*overlap, overlap);
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800268 (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800269 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
flimc91ee5b2016-01-26 14:33:44 +0100270#ifndef FIXED_POINT
271 {
272 opus_val32 sum;
273 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
274 /* This should filter out both NaNs and ridiculous signals that could
275 cause NaNs further down. */
Felicia Lim0c2090c2017-07-05 17:36:56 -0700276 if (!(sum < 1e18f) || celt_isnan(sum))
flimc91ee5b2016-01-26 14:33:44 +0100277 {
278 OPUS_CLEAR(in, frame_size+overlap);
279 preemph_mem[c] = 0;
280 }
281 }
282#endif
Felicia Lim0c2090c2017-07-05 17:36:56 -0700283 OPUS_CLEAR(bandE, 21);
284 for (frame=0;frame<nb_frames;frame++)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800285 {
Felicia Lim0c2090c2017-07-05 17:36:56 -0700286 opus_val32 tmpE[21];
287 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
288 overlap, celt_mode->maxLM-LM, 1, arch);
289 if (upsample != 1)
290 {
291 int bound = freq_size/upsample;
292 for (i=0;i<bound;i++)
293 freq[i] *= upsample;
294 for (;i<freq_size;i++)
295 freq[i] = 0;
296 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800297
Felicia Lim0c2090c2017-07-05 17:36:56 -0700298 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
299 /* If we have multiple frames, take the max energy. */
300 for (i=0;i<21;i++)
301 bandE[i] = MAX32(bandE[i], tmpE[i]);
302 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800303 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
304 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
305 for (i=1;i<21;i++)
306 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
307 for (i=19;i>=0;i--)
308 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
309 if (pos[c]==1)
310 {
311 for (i=0;i<21;i++)
312 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
313 } else if (pos[c]==3)
314 {
315 for (i=0;i<21;i++)
316 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
317 } else if (pos[c]==2)
318 {
319 for (i=0;i<21;i++)
320 {
321 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
322 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
323 }
324 }
325#if 0
326 for (i=0;i<21;i++)
327 printf("%f ", bandLogE[21*c+i]);
328 float sum=0;
329 for (i=0;i<21;i++)
330 sum += bandLogE[21*c+i];
331 printf("%f ", sum/21);
332#endif
333 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
334 }
335 for (i=0;i<21;i++)
336 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
337 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
338 for (c=0;c<3;c++)
339 for (i=0;i<21;i++)
340 maskLogE[c][i] += channel_offset;
341#if 0
342 for (c=0;c<3;c++)
343 {
344 for (i=0;i<21;i++)
345 printf("%f ", maskLogE[c][i]);
346 }
347#endif
348 for (c=0;c<channels;c++)
349 {
350 opus_val16 *mask;
351 if (pos[c]!=0)
352 {
353 mask = &maskLogE[pos[c]-1][0];
354 for (i=0;i<21;i++)
355 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
356 } else {
357 for (i=0;i<21;i++)
358 bandLogE[21*c+i] = 0;
359 }
360#if 0
361 for (i=0;i<21;i++)
362 printf("%f ", bandLogE[21*c+i]);
363 printf("\n");
364#endif
365#if 0
366 float sum=0;
367 for (i=0;i<21;i++)
368 sum += bandLogE[21*c+i];
369 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
370 printf("\n");
371#endif
372 }
373 RESTORE_STACK;
374}
375
376opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
377{
378 int coupled_size;
379 int mono_size;
380
381 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
382 coupled_size = opus_encoder_get_size(2);
383 mono_size = opus_encoder_get_size(1);
384 return align(sizeof(OpusMSEncoder))
385 + nb_coupled_streams * align(coupled_size)
386 + (nb_streams-nb_coupled_streams) * align(mono_size);
387}
388
389opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
390{
391 int nb_streams;
392 int nb_coupled_streams;
393 opus_int32 size;
394
395 if (mapping_family==0)
396 {
397 if (channels==1)
398 {
399 nb_streams=1;
400 nb_coupled_streams=0;
401 } else if (channels==2)
402 {
403 nb_streams=1;
404 nb_coupled_streams=1;
405 } else
406 return 0;
407 } else if (mapping_family==1 && channels<=8 && channels>=1)
408 {
409 nb_streams=vorbis_mappings[channels-1].nb_streams;
410 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
411 } else if (mapping_family==255)
412 {
413 nb_streams=channels;
414 nb_coupled_streams=0;
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800415 } else if (mapping_family==2)
Felicia Limd03c3732016-07-25 20:28:37 +0200416 {
Felicia Lim0c2090c2017-07-05 17:36:56 -0700417 if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
418 return 0;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800419 } else
420 return 0;
421 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
422 if (channels>2)
423 {
424 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
425 }
426 return size;
427}
428
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800429static int opus_multistream_encoder_init_impl(
430 OpusMSEncoder *st,
431 opus_int32 Fs,
432 int channels,
433 int streams,
434 int coupled_streams,
435 const unsigned char *mapping,
436 int application,
Felicia Limd03c3732016-07-25 20:28:37 +0200437 MappingType mapping_type
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800438)
439{
440 int coupled_size;
441 int mono_size;
442 int i, ret;
443 char *ptr;
444
445 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
flimc91ee5b2016-01-26 14:33:44 +0100446 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800447 return OPUS_BAD_ARG;
448
flimc91ee5b2016-01-26 14:33:44 +0100449 st->arch = opus_select_arch();
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800450 st->layout.nb_channels = channels;
451 st->layout.nb_streams = streams;
452 st->layout.nb_coupled_streams = coupled_streams;
Felicia Limd03c3732016-07-25 20:28:37 +0200453 if (mapping_type != MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800454 st->lfe_stream = -1;
455 st->bitrate_bps = OPUS_AUTO;
456 st->application = application;
457 st->variable_duration = OPUS_FRAMESIZE_ARG;
458 for (i=0;i<st->layout.nb_channels;i++)
459 st->layout.mapping[i] = mapping[i];
Felicia Lim0c2090c2017-07-05 17:36:56 -0700460 if (!validate_layout(&st->layout))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800461 return OPUS_BAD_ARG;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700462 if (mapping_type == MAPPING_TYPE_SURROUND &&
463 !validate_encoder_layout(&st->layout))
464 return OPUS_BAD_ARG;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700465 if (mapping_type == MAPPING_TYPE_AMBISONICS &&
466 !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
467 return OPUS_BAD_ARG;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800468 ptr = (char*)st + align(sizeof(OpusMSEncoder));
469 coupled_size = opus_encoder_get_size(2);
470 mono_size = opus_encoder_get_size(1);
471
472 for (i=0;i<st->layout.nb_coupled_streams;i++)
473 {
474 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
475 if(ret!=OPUS_OK)return ret;
476 if (i==st->lfe_stream)
477 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
478 ptr += align(coupled_size);
479 }
480 for (;i<st->layout.nb_streams;i++)
481 {
482 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
483 if (i==st->lfe_stream)
484 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
485 if(ret!=OPUS_OK)return ret;
486 ptr += align(mono_size);
487 }
Felicia Limd03c3732016-07-25 20:28:37 +0200488 if (mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800489 {
490 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
491 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
492 }
Felicia Limd03c3732016-07-25 20:28:37 +0200493 st->mapping_type = mapping_type;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800494 return OPUS_OK;
495}
496
497int opus_multistream_encoder_init(
498 OpusMSEncoder *st,
499 opus_int32 Fs,
500 int channels,
501 int streams,
502 int coupled_streams,
503 const unsigned char *mapping,
504 int application
505)
506{
Felicia Limd03c3732016-07-25 20:28:37 +0200507 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
508 coupled_streams, mapping,
509 application, MAPPING_TYPE_NONE);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800510}
511
512int opus_multistream_surround_encoder_init(
513 OpusMSEncoder *st,
514 opus_int32 Fs,
515 int channels,
516 int mapping_family,
517 int *streams,
518 int *coupled_streams,
519 unsigned char *mapping,
520 int application
521)
522{
Felicia Limd03c3732016-07-25 20:28:37 +0200523 MappingType mapping_type;
524
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800525 if ((channels>255) || (channels<1))
526 return OPUS_BAD_ARG;
527 st->lfe_stream = -1;
528 if (mapping_family==0)
529 {
530 if (channels==1)
531 {
532 *streams=1;
533 *coupled_streams=0;
534 mapping[0]=0;
535 } else if (channels==2)
536 {
537 *streams=1;
538 *coupled_streams=1;
539 mapping[0]=0;
540 mapping[1]=1;
541 } else
542 return OPUS_UNIMPLEMENTED;
543 } else if (mapping_family==1 && channels<=8 && channels>=1)
544 {
545 int i;
546 *streams=vorbis_mappings[channels-1].nb_streams;
547 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
548 for (i=0;i<channels;i++)
549 mapping[i] = vorbis_mappings[channels-1].mapping[i];
550 if (channels>=6)
551 st->lfe_stream = *streams-1;
552 } else if (mapping_family==255)
553 {
554 int i;
555 *streams=channels;
556 *coupled_streams=0;
557 for(i=0;i<channels;i++)
558 mapping[i] = i;
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800559 } else if (mapping_family==2)
Felicia Limd03c3732016-07-25 20:28:37 +0200560 {
561 int i;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700562 if (!validate_ambisonics(channels, streams, coupled_streams))
563 return OPUS_BAD_ARG;
564 for(i = 0; i < (*streams - *coupled_streams); i++)
565 mapping[i] = i + (*coupled_streams * 2);
566 for(i = 0; i < *coupled_streams * 2; i++)
567 mapping[i + (*streams - *coupled_streams)] = i;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800568 } else
569 return OPUS_UNIMPLEMENTED;
Felicia Limd03c3732016-07-25 20:28:37 +0200570
571 if (channels>2 && mapping_family==1) {
572 mapping_type = MAPPING_TYPE_SURROUND;
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800573 } else if (mapping_family==2)
Felicia Limd03c3732016-07-25 20:28:37 +0200574 {
575 mapping_type = MAPPING_TYPE_AMBISONICS;
Felicia Limd03c3732016-07-25 20:28:37 +0200576 } else
577 {
578 mapping_type = MAPPING_TYPE_NONE;
579 }
580 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
581 *coupled_streams, mapping,
582 application, mapping_type);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800583}
584
585OpusMSEncoder *opus_multistream_encoder_create(
586 opus_int32 Fs,
587 int channels,
588 int streams,
589 int coupled_streams,
590 const unsigned char *mapping,
591 int application,
592 int *error
593)
594{
595 int ret;
596 OpusMSEncoder *st;
597 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
flimc91ee5b2016-01-26 14:33:44 +0100598 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800599 {
600 if (error)
601 *error = OPUS_BAD_ARG;
602 return NULL;
603 }
604 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
605 if (st==NULL)
606 {
607 if (error)
608 *error = OPUS_ALLOC_FAIL;
609 return NULL;
610 }
611 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
612 if (ret != OPUS_OK)
613 {
614 opus_free(st);
615 st = NULL;
616 }
617 if (error)
618 *error = ret;
619 return st;
620}
621
622OpusMSEncoder *opus_multistream_surround_encoder_create(
623 opus_int32 Fs,
624 int channels,
625 int mapping_family,
626 int *streams,
627 int *coupled_streams,
628 unsigned char *mapping,
629 int application,
630 int *error
631)
632{
633 int ret;
flimc91ee5b2016-01-26 14:33:44 +0100634 opus_int32 size;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800635 OpusMSEncoder *st;
636 if ((channels>255) || (channels<1))
637 {
638 if (error)
639 *error = OPUS_BAD_ARG;
640 return NULL;
641 }
flimc91ee5b2016-01-26 14:33:44 +0100642 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
643 if (!size)
644 {
645 if (error)
646 *error = OPUS_UNIMPLEMENTED;
647 return NULL;
648 }
649 st = (OpusMSEncoder *)opus_alloc(size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800650 if (st==NULL)
651 {
652 if (error)
653 *error = OPUS_ALLOC_FAIL;
654 return NULL;
655 }
656 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
657 if (ret != OPUS_OK)
658 {
659 opus_free(st);
660 st = NULL;
661 }
662 if (error)
663 *error = ret;
664 return st;
665}
666
Felicia Limd03c3732016-07-25 20:28:37 +0200667static void surround_rate_allocation(
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800668 OpusMSEncoder *st,
669 opus_int32 *rate,
Felicia Limd03c3732016-07-25 20:28:37 +0200670 int frame_size,
671 opus_int32 Fs
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800672 )
673{
674 int i;
675 opus_int32 channel_rate;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800676 int stream_offset;
677 int lfe_offset;
678 int coupled_ratio; /* Q8 */
679 int lfe_ratio; /* Q8 */
Felicia Lim0c2090c2017-07-05 17:36:56 -0700680 int nb_lfe;
681 int nb_uncoupled;
682 int nb_coupled;
683 int nb_normal;
684 opus_int32 channel_offset;
685 opus_int32 bitrate;
686 int total;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800687
Felicia Lim0c2090c2017-07-05 17:36:56 -0700688 nb_lfe = (st->lfe_stream!=-1);
689 nb_coupled = st->layout.nb_coupled_streams;
690 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
691 nb_normal = 2*nb_coupled + nb_uncoupled;
692
693 /* Give each non-LFE channel enough bits per channel for coding band energy. */
694 channel_offset = 40*IMAX(50, Fs/frame_size);
695
696 if (st->bitrate_bps==OPUS_AUTO)
697 {
698 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
699 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
700 {
701 bitrate = nb_normal*300000 + nb_lfe*128000;
702 } else {
703 bitrate = st->bitrate_bps;
704 }
705
706 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
707 total rate for the non-energy part to avoid problems at really low rate. */
708 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
709
710 /* We give each stream (coupled or uncoupled) a starting bitrate.
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800711 This models the main saving of coupled channels over uncoupled. */
Felicia Lim0c2090c2017-07-05 17:36:56 -0700712 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
713 stream_offset = IMAX(0, IMIN(20000, stream_offset));
714
715 /* Coupled streams get twice the mono rate after the offset is allocated. */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800716 coupled_ratio = 512;
717 /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
718 lfe_ratio = 32;
719
Felicia Lim0c2090c2017-07-05 17:36:56 -0700720 total = (nb_uncoupled<<8) /* mono */
721 + coupled_ratio*nb_coupled /* stereo */
722 + nb_lfe*lfe_ratio;
723 channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800724
725 for (i=0;i<st->layout.nb_streams;i++)
726 {
727 if (i<st->layout.nb_coupled_streams)
Felicia Lim0c2090c2017-07-05 17:36:56 -0700728 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800729 else if (i!=st->lfe_stream)
Felicia Lim0c2090c2017-07-05 17:36:56 -0700730 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800731 else
Felicia Lim0c2090c2017-07-05 17:36:56 -0700732 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Felicia Limd03c3732016-07-25 20:28:37 +0200733 }
734}
735
Felicia Limd03c3732016-07-25 20:28:37 +0200736static void ambisonics_rate_allocation(
737 OpusMSEncoder *st,
738 opus_int32 *rate,
739 int frame_size,
740 opus_int32 Fs
741 )
742{
743 int i;
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800744 opus_int32 total_rate;
745 opus_int32 per_stream_rate;
Felicia Limd03c3732016-07-25 20:28:37 +0200746
Felicia Lim0c2090c2017-07-05 17:36:56 -0700747 const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Felicia Limd03c3732016-07-25 20:28:37 +0200748
749 if (st->bitrate_bps==OPUS_AUTO)
750 {
Felicia Lim0c2090c2017-07-05 17:36:56 -0700751 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800752 (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000;
Felicia Limd03c3732016-07-25 20:28:37 +0200753 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
754 {
Felicia Lim0c2090c2017-07-05 17:36:56 -0700755 total_rate = nb_channels * 320000;
756 } else
757 {
Felicia Limd03c3732016-07-25 20:28:37 +0200758 total_rate = st->bitrate_bps;
759 }
760
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800761 /* Allocate equal number of bits to Ambisonic (uncoupled) and non-diegetic
762 * (coupled) streams */
763 per_stream_rate = total_rate / st->layout.nb_streams;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700764 for (i = 0; i < st->layout.nb_streams; i++)
Felicia Limd03c3732016-07-25 20:28:37 +0200765 {
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800766 rate[i] = per_stream_rate;
Felicia Limd03c3732016-07-25 20:28:37 +0200767 }
768}
Felicia Limd03c3732016-07-25 20:28:37 +0200769
770static opus_int32 rate_allocation(
771 OpusMSEncoder *st,
772 opus_int32 *rate,
773 int frame_size
774 )
775{
776 int i;
777 opus_int32 rate_sum=0;
778 opus_int32 Fs;
779 char *ptr;
780
781 ptr = (char*)st + align(sizeof(OpusMSEncoder));
782 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
783
Felicia Limd03c3732016-07-25 20:28:37 +0200784 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
785 ambisonics_rate_allocation(st, rate, frame_size, Fs);
786 } else
Felicia Limd03c3732016-07-25 20:28:37 +0200787 {
788 surround_rate_allocation(st, rate, frame_size, Fs);
789 }
790
791 for (i=0;i<st->layout.nb_streams;i++)
792 {
flimc91ee5b2016-01-26 14:33:44 +0100793 rate[i] = IMAX(rate[i], 500);
794 rate_sum += rate[i];
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800795 }
flimc91ee5b2016-01-26 14:33:44 +0100796 return rate_sum;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800797}
798
Felicia Lim0c2090c2017-07-05 17:36:56 -0700799/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
800#define MS_FRAME_TMP (6*1275+12)
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800801int opus_multistream_encode_native
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800802(
803 OpusMSEncoder *st,
804 opus_copy_channel_in_func copy_channel_in,
805 const void *pcm,
806 int analysis_frame_size,
807 unsigned char *data,
808 opus_int32 max_data_bytes,
809 int lsb_depth,
flimc91ee5b2016-01-26 14:33:44 +0100810 downmix_func downmix,
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800811 int float_api,
812 void *user_data
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800813)
814{
815 opus_int32 Fs;
816 int coupled_size;
817 int mono_size;
818 int s;
819 char *ptr;
820 int tot_size;
821 VARDECL(opus_val16, buf);
822 VARDECL(opus_val16, bandSMR);
823 unsigned char tmp_data[MS_FRAME_TMP];
824 OpusRepacketizer rp;
825 opus_int32 vbr;
826 const CELTMode *celt_mode;
827 opus_int32 bitrates[256];
828 opus_val16 bandLogE[42];
829 opus_val32 *mem = NULL;
830 opus_val32 *preemph_mem=NULL;
831 int frame_size;
flimc91ee5b2016-01-26 14:33:44 +0100832 opus_int32 rate_sum;
833 opus_int32 smallest_packet;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800834 ALLOC_STACK;
835
Felicia Limd03c3732016-07-25 20:28:37 +0200836 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800837 {
838 preemph_mem = ms_get_preemph_mem(st);
839 mem = ms_get_window_mem(st);
840 }
841
842 ptr = (char*)st + align(sizeof(OpusMSEncoder));
843 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
844 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
845 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
846
Felicia Lim0c2090c2017-07-05 17:36:56 -0700847 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
848 if (frame_size <= 0)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800849 {
850 RESTORE_STACK;
851 return OPUS_BAD_ARG;
852 }
flimc91ee5b2016-01-26 14:33:44 +0100853
854 /* Smallest packet the encoder can produce. */
855 smallest_packet = st->layout.nb_streams*2-1;
Felicia Lim0c2090c2017-07-05 17:36:56 -0700856 /* 100 ms needs an extra byte per stream for the ToC. */
857 if (Fs/frame_size == 10)
858 smallest_packet += st->layout.nb_streams;
flimc91ee5b2016-01-26 14:33:44 +0100859 if (max_data_bytes < smallest_packet)
860 {
861 RESTORE_STACK;
862 return OPUS_BUFFER_TOO_SMALL;
863 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800864 ALLOC(buf, 2*frame_size, opus_val16);
865 coupled_size = opus_encoder_get_size(2);
866 mono_size = opus_encoder_get_size(1);
867
868 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Felicia Limd03c3732016-07-25 20:28:37 +0200869 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800870 {
flimc91ee5b2016-01-26 14:33:44 +0100871 surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800872 }
873
874 /* Compute bitrate allocation between streams (this could be a lot better) */
Felicia Limd03c3732016-07-25 20:28:37 +0200875 rate_sum = rate_allocation(st, bitrates, frame_size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800876
877 if (!vbr)
flimc91ee5b2016-01-26 14:33:44 +0100878 {
879 if (st->bitrate_bps == OPUS_AUTO)
880 {
881 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
882 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
883 {
884 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
885 3*st->bitrate_bps/(3*8*Fs/frame_size)));
886 }
887 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800888 ptr = (char*)st + align(sizeof(OpusMSEncoder));
889 for (s=0;s<st->layout.nb_streams;s++)
890 {
891 OpusEncoder *enc;
892 enc = (OpusEncoder*)ptr;
893 if (s < st->layout.nb_coupled_streams)
894 ptr += align(coupled_size);
895 else
896 ptr += align(mono_size);
897 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Felicia Limd03c3732016-07-25 20:28:37 +0200898 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800899 {
900 opus_int32 equiv_rate;
901 equiv_rate = st->bitrate_bps;
902 if (frame_size*50 < Fs)
903 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
904 if (equiv_rate > 10000*st->layout.nb_channels)
905 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
906 else if (equiv_rate > 7000*st->layout.nb_channels)
907 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
908 else if (equiv_rate > 5000*st->layout.nb_channels)
909 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
910 else
911 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
912 if (s < st->layout.nb_coupled_streams)
913 {
914 /* To preserve the spatial image, force stereo CELT on coupled streams */
915 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
916 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
917 }
918 }
Felicia Limd03c3732016-07-25 20:28:37 +0200919 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
920 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
921 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800922 }
923
924 ptr = (char*)st + align(sizeof(OpusMSEncoder));
925 /* Counting ToC */
926 tot_size = 0;
927 for (s=0;s<st->layout.nb_streams;s++)
928 {
929 OpusEncoder *enc;
930 int len;
931 int curr_max;
932 int c1, c2;
Felicia Limd03c3732016-07-25 20:28:37 +0200933 int ret;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800934
935 opus_repacketizer_init(&rp);
936 enc = (OpusEncoder*)ptr;
937 if (s < st->layout.nb_coupled_streams)
938 {
939 int i;
940 int left, right;
941 left = get_left_channel(&st->layout, s, -1);
942 right = get_right_channel(&st->layout, s, -1);
943 (*copy_channel_in)(buf, 2,
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800944 pcm, st->layout.nb_channels, left, frame_size, user_data);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800945 (*copy_channel_in)(buf+1, 2,
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800946 pcm, st->layout.nb_channels, right, frame_size, user_data);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800947 ptr += align(coupled_size);
Felicia Limd03c3732016-07-25 20:28:37 +0200948 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800949 {
950 for (i=0;i<21;i++)
951 {
952 bandLogE[i] = bandSMR[21*left+i];
953 bandLogE[21+i] = bandSMR[21*right+i];
954 }
955 }
956 c1 = left;
957 c2 = right;
958 } else {
959 int i;
960 int chan = get_mono_channel(&st->layout, s, -1);
961 (*copy_channel_in)(buf, 1,
Felicia Lim0efcc2b2018-11-06 12:35:39 -0800962 pcm, st->layout.nb_channels, chan, frame_size, user_data);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800963 ptr += align(mono_size);
Felicia Limd03c3732016-07-25 20:28:37 +0200964 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800965 {
966 for (i=0;i<21;i++)
967 bandLogE[i] = bandSMR[21*chan+i];
968 }
969 c1 = chan;
970 c2 = -1;
971 }
Felicia Limd03c3732016-07-25 20:28:37 +0200972 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800973 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
974 /* number of bytes left (+Toc) */
975 curr_max = max_data_bytes - tot_size;
flimc91ee5b2016-01-26 14:33:44 +0100976 /* Reserve one byte for the last stream and two for the others */
977 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim0c2090c2017-07-05 17:36:56 -0700978 /* For 100 ms, reserve an extra byte per stream for the ToC */
979 if (Fs/frame_size == 10)
980 curr_max -= st->layout.nb_streams-s-1;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800981 curr_max = IMIN(curr_max,MS_FRAME_TMP);
flimc91ee5b2016-01-26 14:33:44 +0100982 /* Repacketizer will add one or two bytes for self-delimited frames */
983 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800984 if (!vbr && s == st->layout.nb_streams-1)
985 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
986 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
flimc91ee5b2016-01-26 14:33:44 +0100987 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800988 if (len<0)
989 {
990 RESTORE_STACK;
991 return len;
992 }
993 /* We need to use the repacketizer to add the self-delimiting lengths
994 while taking into account the fact that the encoder can now return
995 more than one frame at a time (e.g. 60 ms CELT-only) */
Felicia Limd03c3732016-07-25 20:28:37 +0200996 ret = opus_repacketizer_cat(&rp, tmp_data, len);
997 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
998 with the encoder. */
999 if (ret != OPUS_OK)
1000 {
1001 RESTORE_STACK;
1002 return OPUS_INTERNAL_ERROR;
1003 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001004 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1005 data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
1006 data += len;
1007 tot_size += len;
1008 }
1009 /*printf("\n");*/
1010 RESTORE_STACK;
1011 return tot_size;
1012}
1013
1014#if !defined(DISABLE_FLOAT_API)
1015static void opus_copy_channel_in_float(
1016 opus_val16 *dst,
1017 int dst_stride,
1018 const void *src,
1019 int src_stride,
1020 int src_channel,
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001021 int frame_size,
1022 void *user_data
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001023)
1024{
1025 const float *float_src;
1026 opus_int32 i;
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001027 (void)user_data;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001028 float_src = (const float *)src;
1029 for (i=0;i<frame_size;i++)
1030#if defined(FIXED_POINT)
1031 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1032#else
1033 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1034#endif
1035}
1036#endif
1037
1038static void opus_copy_channel_in_short(
1039 opus_val16 *dst,
1040 int dst_stride,
1041 const void *src,
1042 int src_stride,
1043 int src_channel,
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001044 int frame_size,
1045 void *user_data
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001046)
1047{
1048 const opus_int16 *short_src;
1049 opus_int32 i;
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001050 (void)user_data;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001051 short_src = (const opus_int16 *)src;
1052 for (i=0;i<frame_size;i++)
1053#if defined(FIXED_POINT)
1054 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1055#else
1056 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1057#endif
1058}
1059
1060
1061#ifdef FIXED_POINT
1062int opus_multistream_encode(
1063 OpusMSEncoder *st,
1064 const opus_val16 *pcm,
1065 int frame_size,
1066 unsigned char *data,
1067 opus_int32 max_data_bytes
1068)
1069{
1070 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001071 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001072}
1073
1074#ifndef DISABLE_FLOAT_API
1075int opus_multistream_encode_float(
1076 OpusMSEncoder *st,
1077 const float *pcm,
1078 int frame_size,
1079 unsigned char *data,
1080 opus_int32 max_data_bytes
1081)
1082{
1083 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001084 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001085}
1086#endif
1087
1088#else
1089
1090int opus_multistream_encode_float
1091(
1092 OpusMSEncoder *st,
1093 const opus_val16 *pcm,
1094 int frame_size,
1095 unsigned char *data,
1096 opus_int32 max_data_bytes
1097)
1098{
1099 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001100 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001101}
1102
1103int opus_multistream_encode(
1104 OpusMSEncoder *st,
1105 const opus_int16 *pcm,
1106 int frame_size,
1107 unsigned char *data,
1108 opus_int32 max_data_bytes
1109)
1110{
1111 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001112 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001113}
1114#endif
1115
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001116int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
1117 va_list ap)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001118{
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001119 int coupled_size, mono_size;
1120 char *ptr;
1121 int ret = OPUS_OK;
1122
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001123 coupled_size = opus_encoder_get_size(2);
1124 mono_size = opus_encoder_get_size(1);
1125 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1126 switch (request)
1127 {
1128 case OPUS_SET_BITRATE_REQUEST:
1129 {
1130 opus_int32 value = va_arg(ap, opus_int32);
Felicia Lim0c2090c2017-07-05 17:36:56 -07001131 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001132 {
Felicia Lim0c2090c2017-07-05 17:36:56 -07001133 if (value <= 0)
1134 goto bad_arg;
1135 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001136 }
1137 st->bitrate_bps = value;
1138 }
1139 break;
1140 case OPUS_GET_BITRATE_REQUEST:
1141 {
1142 int s;
1143 opus_int32 *value = va_arg(ap, opus_int32*);
1144 if (!value)
1145 {
1146 goto bad_arg;
1147 }
1148 *value = 0;
1149 for (s=0;s<st->layout.nb_streams;s++)
1150 {
1151 opus_int32 rate;
1152 OpusEncoder *enc;
1153 enc = (OpusEncoder*)ptr;
1154 if (s < st->layout.nb_coupled_streams)
1155 ptr += align(coupled_size);
1156 else
1157 ptr += align(mono_size);
1158 opus_encoder_ctl(enc, request, &rate);
1159 *value += rate;
1160 }
1161 }
1162 break;
1163 case OPUS_GET_LSB_DEPTH_REQUEST:
1164 case OPUS_GET_VBR_REQUEST:
1165 case OPUS_GET_APPLICATION_REQUEST:
1166 case OPUS_GET_BANDWIDTH_REQUEST:
1167 case OPUS_GET_COMPLEXITY_REQUEST:
1168 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1169 case OPUS_GET_DTX_REQUEST:
1170 case OPUS_GET_VOICE_RATIO_REQUEST:
1171 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1172 case OPUS_GET_SIGNAL_REQUEST:
1173 case OPUS_GET_LOOKAHEAD_REQUEST:
1174 case OPUS_GET_SAMPLE_RATE_REQUEST:
1175 case OPUS_GET_INBAND_FEC_REQUEST:
1176 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1177 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Felicia Lim0c2090c2017-07-05 17:36:56 -07001178 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001179 {
1180 OpusEncoder *enc;
1181 /* For int32* GET params, just query the first stream */
1182 opus_int32 *value = va_arg(ap, opus_int32*);
1183 enc = (OpusEncoder*)ptr;
1184 ret = opus_encoder_ctl(enc, request, value);
1185 }
1186 break;
1187 case OPUS_GET_FINAL_RANGE_REQUEST:
1188 {
1189 int s;
1190 opus_uint32 *value = va_arg(ap, opus_uint32*);
1191 opus_uint32 tmp;
1192 if (!value)
1193 {
1194 goto bad_arg;
1195 }
1196 *value=0;
1197 for (s=0;s<st->layout.nb_streams;s++)
1198 {
1199 OpusEncoder *enc;
1200 enc = (OpusEncoder*)ptr;
1201 if (s < st->layout.nb_coupled_streams)
1202 ptr += align(coupled_size);
1203 else
1204 ptr += align(mono_size);
1205 ret = opus_encoder_ctl(enc, request, &tmp);
1206 if (ret != OPUS_OK) break;
1207 *value ^= tmp;
1208 }
1209 }
1210 break;
1211 case OPUS_SET_LSB_DEPTH_REQUEST:
1212 case OPUS_SET_COMPLEXITY_REQUEST:
1213 case OPUS_SET_VBR_REQUEST:
1214 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
1215 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
1216 case OPUS_SET_BANDWIDTH_REQUEST:
1217 case OPUS_SET_SIGNAL_REQUEST:
1218 case OPUS_SET_APPLICATION_REQUEST:
1219 case OPUS_SET_INBAND_FEC_REQUEST:
1220 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1221 case OPUS_SET_DTX_REQUEST:
1222 case OPUS_SET_FORCE_MODE_REQUEST:
1223 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1224 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Felicia Lim0c2090c2017-07-05 17:36:56 -07001225 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001226 {
1227 int s;
1228 /* This works for int32 params */
1229 opus_int32 value = va_arg(ap, opus_int32);
1230 for (s=0;s<st->layout.nb_streams;s++)
1231 {
1232 OpusEncoder *enc;
1233
1234 enc = (OpusEncoder*)ptr;
1235 if (s < st->layout.nb_coupled_streams)
1236 ptr += align(coupled_size);
1237 else
1238 ptr += align(mono_size);
1239 ret = opus_encoder_ctl(enc, request, value);
1240 if (ret != OPUS_OK)
1241 break;
1242 }
1243 }
1244 break;
1245 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1246 {
1247 int s;
1248 opus_int32 stream_id;
1249 OpusEncoder **value;
1250 stream_id = va_arg(ap, opus_int32);
1251 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1252 ret = OPUS_BAD_ARG;
1253 value = va_arg(ap, OpusEncoder**);
1254 if (!value)
1255 {
1256 goto bad_arg;
1257 }
1258 for (s=0;s<stream_id;s++)
1259 {
1260 if (s < st->layout.nb_coupled_streams)
1261 ptr += align(coupled_size);
1262 else
1263 ptr += align(mono_size);
1264 }
1265 *value = (OpusEncoder*)ptr;
1266 }
1267 break;
1268 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
1269 {
1270 opus_int32 value = va_arg(ap, opus_int32);
1271 st->variable_duration = value;
1272 }
1273 break;
1274 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
1275 {
1276 opus_int32 *value = va_arg(ap, opus_int32*);
1277 if (!value)
1278 {
1279 goto bad_arg;
1280 }
1281 *value = st->variable_duration;
1282 }
1283 break;
1284 case OPUS_RESET_STATE:
1285 {
1286 int s;
Felicia Limd03c3732016-07-25 20:28:37 +02001287 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001288 {
1289 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1290 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1291 }
1292 for (s=0;s<st->layout.nb_streams;s++)
1293 {
1294 OpusEncoder *enc;
1295 enc = (OpusEncoder*)ptr;
1296 if (s < st->layout.nb_coupled_streams)
1297 ptr += align(coupled_size);
1298 else
1299 ptr += align(mono_size);
1300 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1301 if (ret != OPUS_OK)
1302 break;
1303 }
1304 }
1305 break;
1306 default:
1307 ret = OPUS_UNIMPLEMENTED;
1308 break;
1309 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001310 return ret;
1311bad_arg:
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001312 return OPUS_BAD_ARG;
1313}
1314
Felicia Lim0efcc2b2018-11-06 12:35:39 -08001315int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1316{
1317 int ret;
1318 va_list ap;
1319 va_start(ap, request);
1320 ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
1321 va_end(ap);
1322 return ret;
1323}
1324
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001325void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1326{
1327 opus_free(st);
1328}