blob: e722e31ab8ee9f10242944954ea6f5ac2018a13b [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
64typedef 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
Felicia Limd03c3732016-07-25 20:28:37 +020073typedef enum {
74 MAPPING_TYPE_NONE,
75 MAPPING_TYPE_SURROUND
76#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
77 , /* Do not include comma at end of enumerator list */
78 MAPPING_TYPE_AMBISONICS
79#endif
80} MappingType;
81
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080082struct OpusMSEncoder {
83 ChannelLayout layout;
flimc91ee5b2016-01-26 14:33:44 +010084 int arch;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080085 int lfe_stream;
86 int application;
87 int variable_duration;
Felicia Limd03c3732016-07-25 20:28:37 +020088 MappingType mapping_type;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -080089 opus_int32 bitrate_bps;
90 float subframe_mem[3];
91 /* Encoder states go here */
92 /* then opus_val32 window_mem[channels*120]; */
93 /* then opus_val32 preemph_mem[channels]; */
94};
95
96static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
97{
98 int s;
99 char *ptr;
100 int coupled_size, mono_size;
101
102 coupled_size = opus_encoder_get_size(2);
103 mono_size = opus_encoder_get_size(1);
104 ptr = (char*)st + align(sizeof(OpusMSEncoder));
105 for (s=0;s<st->layout.nb_streams;s++)
106 {
107 if (s < st->layout.nb_coupled_streams)
108 ptr += align(coupled_size);
109 else
110 ptr += align(mono_size);
111 }
flimc91ee5b2016-01-26 14:33:44 +0100112 /* void* cast avoids clang -Wcast-align warning */
113 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800114}
115
116static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
117{
118 int s;
119 char *ptr;
120 int coupled_size, mono_size;
121
122 coupled_size = opus_encoder_get_size(2);
123 mono_size = opus_encoder_get_size(1);
124 ptr = (char*)st + align(sizeof(OpusMSEncoder));
125 for (s=0;s<st->layout.nb_streams;s++)
126 {
127 if (s < st->layout.nb_coupled_streams)
128 ptr += align(coupled_size);
129 else
130 ptr += align(mono_size);
131 }
flimc91ee5b2016-01-26 14:33:44 +0100132 /* void* cast avoids clang -Wcast-align warning */
133 return (opus_val32*)(void*)ptr;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800134}
135
136static int validate_encoder_layout(const ChannelLayout *layout)
137{
138 int s;
139 for (s=0;s<layout->nb_streams;s++)
140 {
141 if (s < layout->nb_coupled_streams)
142 {
143 if (get_left_channel(layout, s, -1)==-1)
144 return 0;
145 if (get_right_channel(layout, s, -1)==-1)
146 return 0;
147 } else {
148 if (get_mono_channel(layout, s, -1)==-1)
149 return 0;
150 }
151 }
152 return 1;
153}
154
155static void channel_pos(int channels, int pos[8])
156{
157 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
158 if (channels==4)
159 {
160 pos[0]=1;
161 pos[1]=3;
162 pos[2]=1;
163 pos[3]=3;
164 } else if (channels==3||channels==5||channels==6)
165 {
166 pos[0]=1;
167 pos[1]=2;
168 pos[2]=3;
169 pos[3]=1;
170 pos[4]=3;
171 pos[5]=0;
172 } else if (channels==7)
173 {
174 pos[0]=1;
175 pos[1]=2;
176 pos[2]=3;
177 pos[3]=1;
178 pos[4]=3;
179 pos[5]=2;
180 pos[6]=0;
181 } else if (channels==8)
182 {
183 pos[0]=1;
184 pos[1]=2;
185 pos[2]=3;
186 pos[3]=1;
187 pos[4]=3;
188 pos[5]=1;
189 pos[6]=3;
190 pos[7]=0;
191 }
192}
193
194#if 1
195/* Computes a rough approximation of log2(2^a + 2^b) */
196static opus_val16 logSum(opus_val16 a, opus_val16 b)
197{
198 opus_val16 max;
199 opus_val32 diff;
200 opus_val16 frac;
201 static const opus_val16 diff_table[17] = {
202 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
203 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
204 QCONST16(0.0028123f, DB_SHIFT)
205 };
206 int low;
207 if (a>b)
208 {
209 max = a;
210 diff = SUB32(EXTEND32(a),EXTEND32(b));
211 } else {
212 max = b;
213 diff = SUB32(EXTEND32(b),EXTEND32(a));
214 }
flimc91ee5b2016-01-26 14:33:44 +0100215 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800216 return max;
217#ifdef FIXED_POINT
218 low = SHR32(diff, DB_SHIFT-1);
219 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
220#else
221 low = (int)floor(2*diff);
222 frac = 2*diff - low;
223#endif
224 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
225}
226#else
227opus_val16 logSum(opus_val16 a, opus_val16 b)
228{
229 return log2(pow(4, a)+ pow(4, b))/2;
230}
231#endif
232
233void 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 +0100234 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 -0800235)
236{
237 int c;
238 int i;
239 int LM;
240 int pos[8] = {0};
241 int upsample;
242 int frame_size;
243 opus_val16 channel_offset;
244 opus_val32 bandE[21];
245 opus_val16 maskLogE[3][21];
246 VARDECL(opus_val32, in);
247 VARDECL(opus_val16, x);
248 VARDECL(opus_val32, freq);
249 SAVE_STACK;
250
251 upsample = resampling_factor(rate);
252 frame_size = len*upsample;
253
Felicia Limd03c3732016-07-25 20:28:37 +0200254 /* LM = log2(frame_size / 120) */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800255 for (LM=0;LM<celt_mode->maxLM;LM++)
256 if (celt_mode->shortMdctSize<<LM==frame_size)
257 break;
258
259 ALLOC(in, frame_size+overlap, opus_val32);
260 ALLOC(x, len, opus_val16);
261 ALLOC(freq, frame_size, opus_val32);
262
263 channel_pos(channels, pos);
264
265 for (c=0;c<3;c++)
266 for (i=0;i<21;i++)
267 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
268
269 for (c=0;c<channels;c++)
270 {
271 OPUS_COPY(in, mem+c*overlap, overlap);
272 (*copy_channel_in)(x, 1, pcm, channels, c, len);
273 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
flimc91ee5b2016-01-26 14:33:44 +0100274#ifndef FIXED_POINT
275 {
276 opus_val32 sum;
277 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
278 /* This should filter out both NaNs and ridiculous signals that could
279 cause NaNs further down. */
280 if (!(sum < 1e9f) || celt_isnan(sum))
281 {
282 OPUS_CLEAR(in, frame_size+overlap);
283 preemph_mem[c] = 0;
284 }
285 }
286#endif
287 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window,
288 overlap, celt_mode->maxLM-LM, 1, arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800289 if (upsample != 1)
290 {
291 int bound = len;
292 for (i=0;i<bound;i++)
293 freq[i] *= upsample;
294 for (;i<frame_size;i++)
295 freq[i] = 0;
296 }
297
flimc91ee5b2016-01-26 14:33:44 +0100298 compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800299 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
300 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
301 for (i=1;i<21;i++)
302 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
303 for (i=19;i>=0;i--)
304 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
305 if (pos[c]==1)
306 {
307 for (i=0;i<21;i++)
308 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
309 } else if (pos[c]==3)
310 {
311 for (i=0;i<21;i++)
312 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
313 } else if (pos[c]==2)
314 {
315 for (i=0;i<21;i++)
316 {
317 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
318 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
319 }
320 }
321#if 0
322 for (i=0;i<21;i++)
323 printf("%f ", bandLogE[21*c+i]);
324 float sum=0;
325 for (i=0;i<21;i++)
326 sum += bandLogE[21*c+i];
327 printf("%f ", sum/21);
328#endif
329 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
330 }
331 for (i=0;i<21;i++)
332 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
333 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
334 for (c=0;c<3;c++)
335 for (i=0;i<21;i++)
336 maskLogE[c][i] += channel_offset;
337#if 0
338 for (c=0;c<3;c++)
339 {
340 for (i=0;i<21;i++)
341 printf("%f ", maskLogE[c][i]);
342 }
343#endif
344 for (c=0;c<channels;c++)
345 {
346 opus_val16 *mask;
347 if (pos[c]!=0)
348 {
349 mask = &maskLogE[pos[c]-1][0];
350 for (i=0;i<21;i++)
351 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
352 } else {
353 for (i=0;i<21;i++)
354 bandLogE[21*c+i] = 0;
355 }
356#if 0
357 for (i=0;i<21;i++)
358 printf("%f ", bandLogE[21*c+i]);
359 printf("\n");
360#endif
361#if 0
362 float sum=0;
363 for (i=0;i<21;i++)
364 sum += bandLogE[21*c+i];
365 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
366 printf("\n");
367#endif
368 }
369 RESTORE_STACK;
370}
371
372opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
373{
374 int coupled_size;
375 int mono_size;
376
377 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
378 coupled_size = opus_encoder_get_size(2);
379 mono_size = opus_encoder_get_size(1);
380 return align(sizeof(OpusMSEncoder))
381 + nb_coupled_streams * align(coupled_size)
382 + (nb_streams-nb_coupled_streams) * align(mono_size);
383}
384
385opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
386{
387 int nb_streams;
388 int nb_coupled_streams;
389 opus_int32 size;
390
391 if (mapping_family==0)
392 {
393 if (channels==1)
394 {
395 nb_streams=1;
396 nb_coupled_streams=0;
397 } else if (channels==2)
398 {
399 nb_streams=1;
400 nb_coupled_streams=1;
401 } else
402 return 0;
403 } else if (mapping_family==1 && channels<=8 && channels>=1)
404 {
405 nb_streams=vorbis_mappings[channels-1].nb_streams;
406 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
407 } else if (mapping_family==255)
408 {
409 nb_streams=channels;
410 nb_coupled_streams=0;
Felicia Limd03c3732016-07-25 20:28:37 +0200411#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
412 } else if (mapping_family==254)
413 {
414 nb_streams=channels;
415 nb_coupled_streams=0;
416#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800417 } else
418 return 0;
419 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
420 if (channels>2)
421 {
422 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
423 }
424 return size;
425}
426
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800427static int opus_multistream_encoder_init_impl(
428 OpusMSEncoder *st,
429 opus_int32 Fs,
430 int channels,
431 int streams,
432 int coupled_streams,
433 const unsigned char *mapping,
434 int application,
Felicia Limd03c3732016-07-25 20:28:37 +0200435 MappingType mapping_type
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800436)
437{
438 int coupled_size;
439 int mono_size;
440 int i, ret;
441 char *ptr;
442
443 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
flimc91ee5b2016-01-26 14:33:44 +0100444 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800445 return OPUS_BAD_ARG;
446
flimc91ee5b2016-01-26 14:33:44 +0100447 st->arch = opus_select_arch();
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800448 st->layout.nb_channels = channels;
449 st->layout.nb_streams = streams;
450 st->layout.nb_coupled_streams = coupled_streams;
451 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Felicia Limd03c3732016-07-25 20:28:37 +0200452 if (mapping_type != MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800453 st->lfe_stream = -1;
454 st->bitrate_bps = OPUS_AUTO;
455 st->application = application;
456 st->variable_duration = OPUS_FRAMESIZE_ARG;
457 for (i=0;i<st->layout.nb_channels;i++)
458 st->layout.mapping[i] = mapping[i];
459 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
460 return OPUS_BAD_ARG;
461 ptr = (char*)st + align(sizeof(OpusMSEncoder));
462 coupled_size = opus_encoder_get_size(2);
463 mono_size = opus_encoder_get_size(1);
464
465 for (i=0;i<st->layout.nb_coupled_streams;i++)
466 {
467 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
468 if(ret!=OPUS_OK)return ret;
469 if (i==st->lfe_stream)
470 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
471 ptr += align(coupled_size);
472 }
473 for (;i<st->layout.nb_streams;i++)
474 {
475 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
476 if (i==st->lfe_stream)
477 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
478 if(ret!=OPUS_OK)return ret;
479 ptr += align(mono_size);
480 }
Felicia Limd03c3732016-07-25 20:28:37 +0200481 if (mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800482 {
483 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
484 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
485 }
Felicia Limd03c3732016-07-25 20:28:37 +0200486 st->mapping_type = mapping_type;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800487 return OPUS_OK;
488}
489
490int opus_multistream_encoder_init(
491 OpusMSEncoder *st,
492 opus_int32 Fs,
493 int channels,
494 int streams,
495 int coupled_streams,
496 const unsigned char *mapping,
497 int application
498)
499{
Felicia Limd03c3732016-07-25 20:28:37 +0200500 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
501 coupled_streams, mapping,
502 application, MAPPING_TYPE_NONE);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800503}
504
505int opus_multistream_surround_encoder_init(
506 OpusMSEncoder *st,
507 opus_int32 Fs,
508 int channels,
509 int mapping_family,
510 int *streams,
511 int *coupled_streams,
512 unsigned char *mapping,
513 int application
514)
515{
Felicia Limd03c3732016-07-25 20:28:37 +0200516 MappingType mapping_type;
517
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800518 if ((channels>255) || (channels<1))
519 return OPUS_BAD_ARG;
520 st->lfe_stream = -1;
521 if (mapping_family==0)
522 {
523 if (channels==1)
524 {
525 *streams=1;
526 *coupled_streams=0;
527 mapping[0]=0;
528 } else if (channels==2)
529 {
530 *streams=1;
531 *coupled_streams=1;
532 mapping[0]=0;
533 mapping[1]=1;
534 } else
535 return OPUS_UNIMPLEMENTED;
536 } else if (mapping_family==1 && channels<=8 && channels>=1)
537 {
538 int i;
539 *streams=vorbis_mappings[channels-1].nb_streams;
540 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
541 for (i=0;i<channels;i++)
542 mapping[i] = vorbis_mappings[channels-1].mapping[i];
543 if (channels>=6)
544 st->lfe_stream = *streams-1;
545 } else if (mapping_family==255)
546 {
547 int i;
548 *streams=channels;
549 *coupled_streams=0;
550 for(i=0;i<channels;i++)
551 mapping[i] = i;
Felicia Limd03c3732016-07-25 20:28:37 +0200552#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
553 } else if (mapping_family==254)
554 {
555 int i;
556 *streams=channels;
557 *coupled_streams=0;
558 for(i=0;i<channels;i++)
559 mapping[i] = i;
560#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800561 } else
562 return OPUS_UNIMPLEMENTED;
Felicia Limd03c3732016-07-25 20:28:37 +0200563
564 if (channels>2 && mapping_family==1) {
565 mapping_type = MAPPING_TYPE_SURROUND;
566#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
567 } else if (mapping_family==254)
568 {
569 mapping_type = MAPPING_TYPE_AMBISONICS;
570#endif
571 } else
572 {
573 mapping_type = MAPPING_TYPE_NONE;
574 }
575 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
576 *coupled_streams, mapping,
577 application, mapping_type);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800578}
579
580OpusMSEncoder *opus_multistream_encoder_create(
581 opus_int32 Fs,
582 int channels,
583 int streams,
584 int coupled_streams,
585 const unsigned char *mapping,
586 int application,
587 int *error
588)
589{
590 int ret;
591 OpusMSEncoder *st;
592 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
flimc91ee5b2016-01-26 14:33:44 +0100593 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800594 {
595 if (error)
596 *error = OPUS_BAD_ARG;
597 return NULL;
598 }
599 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
600 if (st==NULL)
601 {
602 if (error)
603 *error = OPUS_ALLOC_FAIL;
604 return NULL;
605 }
606 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
607 if (ret != OPUS_OK)
608 {
609 opus_free(st);
610 st = NULL;
611 }
612 if (error)
613 *error = ret;
614 return st;
615}
616
617OpusMSEncoder *opus_multistream_surround_encoder_create(
618 opus_int32 Fs,
619 int channels,
620 int mapping_family,
621 int *streams,
622 int *coupled_streams,
623 unsigned char *mapping,
624 int application,
625 int *error
626)
627{
628 int ret;
flimc91ee5b2016-01-26 14:33:44 +0100629 opus_int32 size;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800630 OpusMSEncoder *st;
631 if ((channels>255) || (channels<1))
632 {
633 if (error)
634 *error = OPUS_BAD_ARG;
635 return NULL;
636 }
flimc91ee5b2016-01-26 14:33:44 +0100637 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
638 if (!size)
639 {
640 if (error)
641 *error = OPUS_UNIMPLEMENTED;
642 return NULL;
643 }
644 st = (OpusMSEncoder *)opus_alloc(size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800645 if (st==NULL)
646 {
647 if (error)
648 *error = OPUS_ALLOC_FAIL;
649 return NULL;
650 }
651 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
652 if (ret != OPUS_OK)
653 {
654 opus_free(st);
655 st = NULL;
656 }
657 if (error)
658 *error = ret;
659 return st;
660}
661
Felicia Limd03c3732016-07-25 20:28:37 +0200662static void surround_rate_allocation(
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800663 OpusMSEncoder *st,
664 opus_int32 *rate,
Felicia Limd03c3732016-07-25 20:28:37 +0200665 int frame_size,
666 opus_int32 Fs
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800667 )
668{
669 int i;
670 opus_int32 channel_rate;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800671 int stream_offset;
672 int lfe_offset;
673 int coupled_ratio; /* Q8 */
674 int lfe_ratio; /* Q8 */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800675
676 if (st->bitrate_bps > st->layout.nb_channels*40000)
677 stream_offset = 20000;
678 else
679 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
680 stream_offset += 60*(Fs/frame_size-50);
681 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
682 This models the main saving of coupled channels over uncoupled. */
683 /* The LFE stream is an exception to the above and gets fewer bits. */
684 lfe_offset = 3500 + 60*(Fs/frame_size-50);
685 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
686 coupled_ratio = 512;
687 /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
688 lfe_ratio = 32;
689
690 /* Compute bitrate allocation between streams */
691 if (st->bitrate_bps==OPUS_AUTO)
692 {
693 channel_rate = Fs+60*Fs/frame_size;
694 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
695 {
696 channel_rate = 300000;
697 } else {
698 int nb_lfe;
699 int nb_uncoupled;
700 int nb_coupled;
701 int total;
702 nb_lfe = (st->lfe_stream!=-1);
703 nb_coupled = st->layout.nb_coupled_streams;
704 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
705 total = (nb_uncoupled<<8) /* mono */
706 + coupled_ratio*nb_coupled /* stereo */
707 + nb_lfe*lfe_ratio;
708 channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
709 }
710#ifndef FIXED_POINT
711 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
712 {
713 opus_int32 bonus;
714 bonus = 60*(Fs/frame_size-50);
715 channel_rate += bonus;
716 }
717#endif
718
719 for (i=0;i<st->layout.nb_streams;i++)
720 {
721 if (i<st->layout.nb_coupled_streams)
722 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
723 else if (i!=st->lfe_stream)
724 rate[i] = stream_offset+channel_rate;
725 else
726 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Felicia Limd03c3732016-07-25 20:28:37 +0200727 }
728}
729
730#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
731static void ambisonics_rate_allocation(
732 OpusMSEncoder *st,
733 opus_int32 *rate,
734 int frame_size,
735 opus_int32 Fs
736 )
737{
738 int i;
739 int non_mono_rate;
740 int total_rate;
741
742 /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
743 * as all other channels */
744 const int rate_ratio_num = 4;
745 const int rate_ratio_den = 3;
746 const int num_channels = st->layout.nb_streams;
747
748 if (st->bitrate_bps==OPUS_AUTO)
749 {
750 total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size));
751 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
752 {
753 total_rate = num_channels * 320000;
754 } else {
755 total_rate = st->bitrate_bps;
756 }
757
758 /* Let y be the non-mono rate and let p, q be integers such that the mono
759 * channel rate is (p/q) * y.
760 * Also let T be the total bitrate to allocate. Then
761 * (n - 1) y + (p/q) y = T
762 * y = (T q) / (qn - q + p)
763 */
764 non_mono_rate =
765 total_rate * rate_ratio_den
766 / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
767
768#ifndef FIXED_POINT
769 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
770 {
771 opus_int32 bonus = 60*(Fs/frame_size-50);
772 non_mono_rate += bonus;
773 }
774#endif
775
776 rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
777 for (i=1;i<st->layout.nb_streams;i++)
778 {
779 rate[i] = non_mono_rate;
780 }
781}
782#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
783
784static opus_int32 rate_allocation(
785 OpusMSEncoder *st,
786 opus_int32 *rate,
787 int frame_size
788 )
789{
790 int i;
791 opus_int32 rate_sum=0;
792 opus_int32 Fs;
793 char *ptr;
794
795 ptr = (char*)st + align(sizeof(OpusMSEncoder));
796 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
797
798#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
799 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
800 ambisonics_rate_allocation(st, rate, frame_size, Fs);
801 } else
802#endif
803 {
804 surround_rate_allocation(st, rate, frame_size, Fs);
805 }
806
807 for (i=0;i<st->layout.nb_streams;i++)
808 {
flimc91ee5b2016-01-26 14:33:44 +0100809 rate[i] = IMAX(rate[i], 500);
810 rate_sum += rate[i];
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800811 }
flimc91ee5b2016-01-26 14:33:44 +0100812 return rate_sum;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800813}
814
815/* Max size in case the encoder decides to return three frames */
816#define MS_FRAME_TMP (3*1275+7)
817static int opus_multistream_encode_native
818(
819 OpusMSEncoder *st,
820 opus_copy_channel_in_func copy_channel_in,
821 const void *pcm,
822 int analysis_frame_size,
823 unsigned char *data,
824 opus_int32 max_data_bytes,
825 int lsb_depth,
flimc91ee5b2016-01-26 14:33:44 +0100826 downmix_func downmix,
827 int float_api
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800828)
829{
830 opus_int32 Fs;
831 int coupled_size;
832 int mono_size;
833 int s;
834 char *ptr;
835 int tot_size;
836 VARDECL(opus_val16, buf);
837 VARDECL(opus_val16, bandSMR);
838 unsigned char tmp_data[MS_FRAME_TMP];
839 OpusRepacketizer rp;
840 opus_int32 vbr;
841 const CELTMode *celt_mode;
842 opus_int32 bitrates[256];
843 opus_val16 bandLogE[42];
844 opus_val32 *mem = NULL;
845 opus_val32 *preemph_mem=NULL;
846 int frame_size;
flimc91ee5b2016-01-26 14:33:44 +0100847 opus_int32 rate_sum;
848 opus_int32 smallest_packet;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800849 ALLOC_STACK;
850
Felicia Limd03c3732016-07-25 20:28:37 +0200851 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800852 {
853 preemph_mem = ms_get_preemph_mem(st);
854 mem = ms_get_window_mem(st);
855 }
856
857 ptr = (char*)st + align(sizeof(OpusMSEncoder));
858 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
859 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
860 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
861
862 {
863 opus_int32 delay_compensation;
864 int channels;
865
866 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
867 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
868 delay_compensation -= Fs/400;
869 frame_size = compute_frame_size(pcm, analysis_frame_size,
870 st->variable_duration, channels, Fs, st->bitrate_bps,
871 delay_compensation, downmix
872#ifndef DISABLE_FLOAT_API
873 , st->subframe_mem
874#endif
875 );
876 }
877
878 if (400*frame_size < Fs)
879 {
880 RESTORE_STACK;
881 return OPUS_BAD_ARG;
882 }
883 /* Validate frame_size before using it to allocate stack space.
884 This mirrors the checks in opus_encode[_float](). */
885 if (400*frame_size != Fs && 200*frame_size != Fs &&
886 100*frame_size != Fs && 50*frame_size != Fs &&
887 25*frame_size != Fs && 50*frame_size != 3*Fs)
888 {
889 RESTORE_STACK;
890 return OPUS_BAD_ARG;
891 }
flimc91ee5b2016-01-26 14:33:44 +0100892
893 /* Smallest packet the encoder can produce. */
894 smallest_packet = st->layout.nb_streams*2-1;
895 if (max_data_bytes < smallest_packet)
896 {
897 RESTORE_STACK;
898 return OPUS_BUFFER_TOO_SMALL;
899 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800900 ALLOC(buf, 2*frame_size, opus_val16);
901 coupled_size = opus_encoder_get_size(2);
902 mono_size = opus_encoder_get_size(1);
903
904 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Felicia Limd03c3732016-07-25 20:28:37 +0200905 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800906 {
flimc91ee5b2016-01-26 14:33:44 +0100907 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 -0800908 }
909
910 /* Compute bitrate allocation between streams (this could be a lot better) */
Felicia Limd03c3732016-07-25 20:28:37 +0200911 rate_sum = rate_allocation(st, bitrates, frame_size);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800912
913 if (!vbr)
flimc91ee5b2016-01-26 14:33:44 +0100914 {
915 if (st->bitrate_bps == OPUS_AUTO)
916 {
917 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
918 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
919 {
920 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
921 3*st->bitrate_bps/(3*8*Fs/frame_size)));
922 }
923 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800924 ptr = (char*)st + align(sizeof(OpusMSEncoder));
925 for (s=0;s<st->layout.nb_streams;s++)
926 {
927 OpusEncoder *enc;
928 enc = (OpusEncoder*)ptr;
929 if (s < st->layout.nb_coupled_streams)
930 ptr += align(coupled_size);
931 else
932 ptr += align(mono_size);
933 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Felicia Limd03c3732016-07-25 20:28:37 +0200934 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800935 {
936 opus_int32 equiv_rate;
937 equiv_rate = st->bitrate_bps;
938 if (frame_size*50 < Fs)
939 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
940 if (equiv_rate > 10000*st->layout.nb_channels)
941 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
942 else if (equiv_rate > 7000*st->layout.nb_channels)
943 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
944 else if (equiv_rate > 5000*st->layout.nb_channels)
945 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
946 else
947 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
948 if (s < st->layout.nb_coupled_streams)
949 {
950 /* To preserve the spatial image, force stereo CELT on coupled streams */
951 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
952 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
953 }
954 }
Felicia Limd03c3732016-07-25 20:28:37 +0200955#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
956 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
957 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
958 }
959#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800960 }
961
962 ptr = (char*)st + align(sizeof(OpusMSEncoder));
963 /* Counting ToC */
964 tot_size = 0;
965 for (s=0;s<st->layout.nb_streams;s++)
966 {
967 OpusEncoder *enc;
968 int len;
969 int curr_max;
970 int c1, c2;
Felicia Limd03c3732016-07-25 20:28:37 +0200971 int ret;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800972
973 opus_repacketizer_init(&rp);
974 enc = (OpusEncoder*)ptr;
975 if (s < st->layout.nb_coupled_streams)
976 {
977 int i;
978 int left, right;
979 left = get_left_channel(&st->layout, s, -1);
980 right = get_right_channel(&st->layout, s, -1);
981 (*copy_channel_in)(buf, 2,
982 pcm, st->layout.nb_channels, left, frame_size);
983 (*copy_channel_in)(buf+1, 2,
984 pcm, st->layout.nb_channels, right, frame_size);
985 ptr += align(coupled_size);
Felicia Limd03c3732016-07-25 20:28:37 +0200986 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800987 {
988 for (i=0;i<21;i++)
989 {
990 bandLogE[i] = bandSMR[21*left+i];
991 bandLogE[21+i] = bandSMR[21*right+i];
992 }
993 }
994 c1 = left;
995 c2 = right;
996 } else {
997 int i;
998 int chan = get_mono_channel(&st->layout, s, -1);
999 (*copy_channel_in)(buf, 1,
1000 pcm, st->layout.nb_channels, chan, frame_size);
1001 ptr += align(mono_size);
Felicia Limd03c3732016-07-25 20:28:37 +02001002 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001003 {
1004 for (i=0;i<21;i++)
1005 bandLogE[i] = bandSMR[21*chan+i];
1006 }
1007 c1 = chan;
1008 c2 = -1;
1009 }
Felicia Limd03c3732016-07-25 20:28:37 +02001010 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001011 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
1012 /* number of bytes left (+Toc) */
1013 curr_max = max_data_bytes - tot_size;
flimc91ee5b2016-01-26 14:33:44 +01001014 /* Reserve one byte for the last stream and two for the others */
1015 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001016 curr_max = IMIN(curr_max,MS_FRAME_TMP);
flimc91ee5b2016-01-26 14:33:44 +01001017 /* Repacketizer will add one or two bytes for self-delimited frames */
1018 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001019 if (!vbr && s == st->layout.nb_streams-1)
1020 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
1021 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
flimc91ee5b2016-01-26 14:33:44 +01001022 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001023 if (len<0)
1024 {
1025 RESTORE_STACK;
1026 return len;
1027 }
1028 /* We need to use the repacketizer to add the self-delimiting lengths
1029 while taking into account the fact that the encoder can now return
1030 more than one frame at a time (e.g. 60 ms CELT-only) */
Felicia Limd03c3732016-07-25 20:28:37 +02001031 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1032 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1033 with the encoder. */
1034 if (ret != OPUS_OK)
1035 {
1036 RESTORE_STACK;
1037 return OPUS_INTERNAL_ERROR;
1038 }
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001039 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1040 data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
1041 data += len;
1042 tot_size += len;
1043 }
1044 /*printf("\n");*/
1045 RESTORE_STACK;
1046 return tot_size;
1047}
1048
1049#if !defined(DISABLE_FLOAT_API)
1050static void opus_copy_channel_in_float(
1051 opus_val16 *dst,
1052 int dst_stride,
1053 const void *src,
1054 int src_stride,
1055 int src_channel,
1056 int frame_size
1057)
1058{
1059 const float *float_src;
1060 opus_int32 i;
1061 float_src = (const float *)src;
1062 for (i=0;i<frame_size;i++)
1063#if defined(FIXED_POINT)
1064 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1065#else
1066 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1067#endif
1068}
1069#endif
1070
1071static void opus_copy_channel_in_short(
1072 opus_val16 *dst,
1073 int dst_stride,
1074 const void *src,
1075 int src_stride,
1076 int src_channel,
1077 int frame_size
1078)
1079{
1080 const opus_int16 *short_src;
1081 opus_int32 i;
1082 short_src = (const opus_int16 *)src;
1083 for (i=0;i<frame_size;i++)
1084#if defined(FIXED_POINT)
1085 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1086#else
1087 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1088#endif
1089}
1090
1091
1092#ifdef FIXED_POINT
1093int opus_multistream_encode(
1094 OpusMSEncoder *st,
1095 const opus_val16 *pcm,
1096 int frame_size,
1097 unsigned char *data,
1098 opus_int32 max_data_bytes
1099)
1100{
1101 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
flimc91ee5b2016-01-26 14:33:44 +01001102 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001103}
1104
1105#ifndef DISABLE_FLOAT_API
1106int opus_multistream_encode_float(
1107 OpusMSEncoder *st,
1108 const float *pcm,
1109 int frame_size,
1110 unsigned char *data,
1111 opus_int32 max_data_bytes
1112)
1113{
1114 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
flimc91ee5b2016-01-26 14:33:44 +01001115 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001116}
1117#endif
1118
1119#else
1120
1121int opus_multistream_encode_float
1122(
1123 OpusMSEncoder *st,
1124 const opus_val16 *pcm,
1125 int frame_size,
1126 unsigned char *data,
1127 opus_int32 max_data_bytes
1128)
1129{
1130 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
flimc91ee5b2016-01-26 14:33:44 +01001131 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001132}
1133
1134int opus_multistream_encode(
1135 OpusMSEncoder *st,
1136 const opus_int16 *pcm,
1137 int frame_size,
1138 unsigned char *data,
1139 opus_int32 max_data_bytes
1140)
1141{
1142 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
flimc91ee5b2016-01-26 14:33:44 +01001143 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001144}
1145#endif
1146
1147int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1148{
1149 va_list ap;
1150 int coupled_size, mono_size;
1151 char *ptr;
1152 int ret = OPUS_OK;
1153
1154 va_start(ap, request);
1155
1156 coupled_size = opus_encoder_get_size(2);
1157 mono_size = opus_encoder_get_size(1);
1158 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1159 switch (request)
1160 {
1161 case OPUS_SET_BITRATE_REQUEST:
1162 {
1163 opus_int32 value = va_arg(ap, opus_int32);
1164 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
1165 {
1166 goto bad_arg;
1167 }
1168 st->bitrate_bps = value;
1169 }
1170 break;
1171 case OPUS_GET_BITRATE_REQUEST:
1172 {
1173 int s;
1174 opus_int32 *value = va_arg(ap, opus_int32*);
1175 if (!value)
1176 {
1177 goto bad_arg;
1178 }
1179 *value = 0;
1180 for (s=0;s<st->layout.nb_streams;s++)
1181 {
1182 opus_int32 rate;
1183 OpusEncoder *enc;
1184 enc = (OpusEncoder*)ptr;
1185 if (s < st->layout.nb_coupled_streams)
1186 ptr += align(coupled_size);
1187 else
1188 ptr += align(mono_size);
1189 opus_encoder_ctl(enc, request, &rate);
1190 *value += rate;
1191 }
1192 }
1193 break;
1194 case OPUS_GET_LSB_DEPTH_REQUEST:
1195 case OPUS_GET_VBR_REQUEST:
1196 case OPUS_GET_APPLICATION_REQUEST:
1197 case OPUS_GET_BANDWIDTH_REQUEST:
1198 case OPUS_GET_COMPLEXITY_REQUEST:
1199 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1200 case OPUS_GET_DTX_REQUEST:
1201 case OPUS_GET_VOICE_RATIO_REQUEST:
1202 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1203 case OPUS_GET_SIGNAL_REQUEST:
1204 case OPUS_GET_LOOKAHEAD_REQUEST:
1205 case OPUS_GET_SAMPLE_RATE_REQUEST:
1206 case OPUS_GET_INBAND_FEC_REQUEST:
1207 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1208 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
1209 {
1210 OpusEncoder *enc;
1211 /* For int32* GET params, just query the first stream */
1212 opus_int32 *value = va_arg(ap, opus_int32*);
1213 enc = (OpusEncoder*)ptr;
1214 ret = opus_encoder_ctl(enc, request, value);
1215 }
1216 break;
1217 case OPUS_GET_FINAL_RANGE_REQUEST:
1218 {
1219 int s;
1220 opus_uint32 *value = va_arg(ap, opus_uint32*);
1221 opus_uint32 tmp;
1222 if (!value)
1223 {
1224 goto bad_arg;
1225 }
1226 *value=0;
1227 for (s=0;s<st->layout.nb_streams;s++)
1228 {
1229 OpusEncoder *enc;
1230 enc = (OpusEncoder*)ptr;
1231 if (s < st->layout.nb_coupled_streams)
1232 ptr += align(coupled_size);
1233 else
1234 ptr += align(mono_size);
1235 ret = opus_encoder_ctl(enc, request, &tmp);
1236 if (ret != OPUS_OK) break;
1237 *value ^= tmp;
1238 }
1239 }
1240 break;
1241 case OPUS_SET_LSB_DEPTH_REQUEST:
1242 case OPUS_SET_COMPLEXITY_REQUEST:
1243 case OPUS_SET_VBR_REQUEST:
1244 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
1245 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
1246 case OPUS_SET_BANDWIDTH_REQUEST:
1247 case OPUS_SET_SIGNAL_REQUEST:
1248 case OPUS_SET_APPLICATION_REQUEST:
1249 case OPUS_SET_INBAND_FEC_REQUEST:
1250 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1251 case OPUS_SET_DTX_REQUEST:
1252 case OPUS_SET_FORCE_MODE_REQUEST:
1253 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1254 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
1255 {
1256 int s;
1257 /* This works for int32 params */
1258 opus_int32 value = va_arg(ap, opus_int32);
1259 for (s=0;s<st->layout.nb_streams;s++)
1260 {
1261 OpusEncoder *enc;
1262
1263 enc = (OpusEncoder*)ptr;
1264 if (s < st->layout.nb_coupled_streams)
1265 ptr += align(coupled_size);
1266 else
1267 ptr += align(mono_size);
1268 ret = opus_encoder_ctl(enc, request, value);
1269 if (ret != OPUS_OK)
1270 break;
1271 }
1272 }
1273 break;
1274 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1275 {
1276 int s;
1277 opus_int32 stream_id;
1278 OpusEncoder **value;
1279 stream_id = va_arg(ap, opus_int32);
1280 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1281 ret = OPUS_BAD_ARG;
1282 value = va_arg(ap, OpusEncoder**);
1283 if (!value)
1284 {
1285 goto bad_arg;
1286 }
1287 for (s=0;s<stream_id;s++)
1288 {
1289 if (s < st->layout.nb_coupled_streams)
1290 ptr += align(coupled_size);
1291 else
1292 ptr += align(mono_size);
1293 }
1294 *value = (OpusEncoder*)ptr;
1295 }
1296 break;
1297 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
1298 {
1299 opus_int32 value = va_arg(ap, opus_int32);
1300 st->variable_duration = value;
1301 }
1302 break;
1303 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
1304 {
1305 opus_int32 *value = va_arg(ap, opus_int32*);
1306 if (!value)
1307 {
1308 goto bad_arg;
1309 }
1310 *value = st->variable_duration;
1311 }
1312 break;
1313 case OPUS_RESET_STATE:
1314 {
1315 int s;
1316 st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
Felicia Limd03c3732016-07-25 20:28:37 +02001317 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001318 {
1319 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1320 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1321 }
1322 for (s=0;s<st->layout.nb_streams;s++)
1323 {
1324 OpusEncoder *enc;
1325 enc = (OpusEncoder*)ptr;
1326 if (s < st->layout.nb_coupled_streams)
1327 ptr += align(coupled_size);
1328 else
1329 ptr += align(mono_size);
1330 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1331 if (ret != OPUS_OK)
1332 break;
1333 }
1334 }
1335 break;
1336 default:
1337 ret = OPUS_UNIMPLEMENTED;
1338 break;
1339 }
1340
1341 va_end(ap);
1342 return ret;
1343bad_arg:
1344 va_end(ap);
1345 return OPUS_BAD_ARG;
1346}
1347
1348void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1349{
1350 opus_free(st);
1351}