blob: 9dcbb71c663b4485e1cf566432f5a9f14eba5575 [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 Valin51f4a322013-02-20 04:08:04 -050039#include "analysis.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050040
41struct OpusMSEncoder {
Jean-Marc Valin51f4a322013-02-20 04:08:04 -050042 TonalityAnalysisState analysis;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050043 ChannelLayout layout;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040044 int lfe_stream;
Jean-Marc Valin74483662012-12-17 16:23:42 -050045 int variable_duration;
46 opus_int32 bitrate_bps;
47 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050048 /* Encoder states go here */
49};
50
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050051
52static int validate_encoder_layout(const ChannelLayout *layout)
53{
54 int s;
55 for (s=0;s<layout->nb_streams;s++)
56 {
57 if (s < layout->nb_coupled_streams)
58 {
59 if (get_left_channel(layout, s, -1)==-1)
60 return 0;
61 if (get_right_channel(layout, s, -1)==-1)
62 return 0;
63 } else {
64 if (get_mono_channel(layout, s, -1)==-1)
65 return 0;
66 }
67 }
68 return 1;
69}
70
71
72opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
73{
74 int coupled_size;
75 int mono_size;
76
77 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
78 coupled_size = opus_encoder_get_size(2);
79 mono_size = opus_encoder_get_size(1);
80 return align(sizeof(OpusMSEncoder))
81 + nb_coupled_streams * align(coupled_size)
82 + (nb_streams-nb_coupled_streams) * align(mono_size);
83}
84
Jean-Marc Valin1b723862013-04-25 21:34:04 -040085opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
86{
87 int nb_streams;
88 int nb_coupled_streams;
89
90 if (channels==1 && mapping_family<=1)
91 {
92 nb_streams = 1;
93 nb_coupled_streams=0;
94 } else if (channels==2 && mapping_family<=1)
95 {
96 nb_streams = 1;
97 nb_coupled_streams=1;
98 } else if (channels==6 && mapping_family==1)
99 {
100 nb_streams = 4;
101 nb_coupled_streams=2;
102 } else
103 return 0;
104 return opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
105}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500106
107
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400108static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500109 OpusMSEncoder *st,
110 opus_int32 Fs,
111 int channels,
112 int streams,
113 int coupled_streams,
114 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400115 int application,
116 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500117)
118{
119 int coupled_size;
120 int mono_size;
121 int i, ret;
122 char *ptr;
123
124 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
125 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
126 return OPUS_BAD_ARG;
127
128 st->layout.nb_channels = channels;
129 st->layout.nb_streams = streams;
130 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400131 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
132 OPUS_CLEAR(&st->analysis,1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400133 if (!surround)
134 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500135 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500136 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500137 for (i=0;i<st->layout.nb_channels;i++)
138 st->layout.mapping[i] = mapping[i];
139 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
140 return OPUS_BAD_ARG;
141 ptr = (char*)st + align(sizeof(OpusMSEncoder));
142 coupled_size = opus_encoder_get_size(2);
143 mono_size = opus_encoder_get_size(1);
144
145 for (i=0;i<st->layout.nb_coupled_streams;i++)
146 {
147 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400148 if (i==st->lfe_stream)
149 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500150 if(ret!=OPUS_OK)return ret;
151 ptr += align(coupled_size);
152 }
153 for (;i<st->layout.nb_streams;i++)
154 {
155 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400156 if (i==st->lfe_stream)
157 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500158 if(ret!=OPUS_OK)return ret;
159 ptr += align(mono_size);
160 }
161 return OPUS_OK;
162}
163
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400164int opus_multistream_encoder_init(
165 OpusMSEncoder *st,
166 opus_int32 Fs,
167 int channels,
168 int streams,
169 int coupled_streams,
170 const unsigned char *mapping,
171 int application
172)
173{
174 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
175}
176
177int opus_multistream_surround_encoder_init(
178 OpusMSEncoder *st,
179 opus_int32 Fs,
180 int channels,
181 int mapping_family,
182 int *streams,
183 int *coupled_streams,
184 unsigned char *mapping,
185 int application
186)
187{
188 st->lfe_stream = -1;
189 if (channels==1 && mapping_family<=1)
190 {
191 *streams=1;
192 *coupled_streams=0;
193 mapping[0]=0;
194 } else if (channels==2 && mapping_family<=1)
195 {
196 *streams=1;
197 *coupled_streams=1;
198 mapping[0]=0;
199 mapping[1]=1;
200 } else if (channels==6 && mapping_family==1)
201 {
202 *streams=4;
203 *coupled_streams=2;
204 mapping[0]=0;
205 mapping[1]=4;
206 mapping[2]=1;
207 mapping[3]=2;
208 mapping[4]=3;
209 mapping[5]=5;
210 st->lfe_stream = 3;
211 } else
212 return OPUS_BAD_ARG;
213 opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams, mapping, application, 1);
214 return OPUS_OK;
215}
216
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500217OpusMSEncoder *opus_multistream_encoder_create(
218 opus_int32 Fs,
219 int channels,
220 int streams,
221 int coupled_streams,
222 const unsigned char *mapping,
223 int application,
224 int *error
225)
226{
227 int ret;
228 OpusMSEncoder *st;
229 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
230 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
231 {
232 if (error)
233 *error = OPUS_BAD_ARG;
234 return NULL;
235 }
236 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
237 if (st==NULL)
238 {
239 if (error)
240 *error = OPUS_ALLOC_FAIL;
241 return NULL;
242 }
243 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
244 if (ret != OPUS_OK)
245 {
246 opus_free(st);
247 st = NULL;
248 }
249 if (error)
250 *error = ret;
251 return st;
252}
253
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400254OpusMSEncoder *opus_multistream_surround_encoder_create(
255 opus_int32 Fs,
256 int channels,
257 int mapping_family,
258 int *streams,
259 int *coupled_streams,
260 unsigned char *mapping,
261 int application,
262 int *error
263)
264{
265 int ret;
266 OpusMSEncoder *st;
267 if ((channels>255) || (channels<1))
268 {
269 if (error)
270 *error = OPUS_BAD_ARG;
271 return NULL;
272 }
273 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
274 if (st==NULL)
275 {
276 if (error)
277 *error = OPUS_ALLOC_FAIL;
278 return NULL;
279 }
280 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
281 if (ret != OPUS_OK)
282 {
283 opus_free(st);
284 st = NULL;
285 }
286 if (error)
287 *error = ret;
288 return st;
289}
290
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500291typedef void (*opus_copy_channel_in_func)(
292 opus_val16 *dst,
293 int dst_stride,
294 const void *src,
295 int src_stride,
296 int src_channel,
297 int frame_size
298);
299
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400300static void surround_rate_allocation(
301 OpusMSEncoder *st,
302 opus_int32 *rate,
303 int frame_size
304 )
305{
306 int i;
307 opus_int32 channel_rate;
308 opus_int32 Fs;
309 char *ptr;
310 int coupled_ratio; /* Q8 */
311 int lfe_ratio; /* Q8 */
312
313 ptr = (char*)st + align(sizeof(OpusMSEncoder));
314 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
315
316 /* Should depend on the bitrate, for now we assume coupled streams get 60% more bits than mono */
317 coupled_ratio = 410;
318 /* Should depend on the bitrate, for now we assume LFE gets 1/12 the bits of mono */
319 lfe_ratio = 32;
320
321 /* Compute bitrate allocation between streams */
322 if (st->bitrate_bps==OPUS_AUTO)
323 {
324 channel_rate = Fs+60*Fs/frame_size;
325 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
326 {
327 channel_rate = 300000;
328 } else {
329 int total = ((st->layout.nb_streams-st->layout.nb_coupled_streams-(st->lfe_stream!=-1))<<8) /* mono */
330 + coupled_ratio*st->layout.nb_coupled_streams /* stereo */
331 + (st->lfe_stream!=-1)*lfe_ratio;
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -0400332 channel_rate = 256*(st->bitrate_bps-2000)/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400333 }
334#ifndef FIXED_POINT
335 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
336 {
337 opus_int32 bonus;
338 bonus = 60*(Fs/frame_size-50);
339 channel_rate += bonus;
340 }
341#endif
342
343 for (i=0;i<st->layout.nb_streams;i++)
344 {
345 if (i<st->layout.nb_coupled_streams)
346 rate[i] = channel_rate*coupled_ratio>>8;
347 else if (i!=st->lfe_stream)
348 rate[i] = channel_rate;
349 else
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -0400350 rate[i] = 2000+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400351 }
352
353
354}
355
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500356/* Max size in case the encoder decides to return three frames */
357#define MS_FRAME_TMP (3*1275+7)
358static int opus_multistream_encode_native
359(
360 OpusMSEncoder *st,
361 opus_copy_channel_in_func copy_channel_in,
362 const void *pcm,
363 int frame_size,
364 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500365 opus_int32 max_data_bytes,
366 int lsb_depth
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500367#ifndef FIXED_POINT
368 , downmix_func downmix
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500369 , const void *pcm_analysis
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500370#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500371)
372{
373 opus_int32 Fs;
374 int coupled_size;
375 int mono_size;
376 int s;
377 char *ptr;
378 int tot_size;
379 VARDECL(opus_val16, buf);
380 unsigned char tmp_data[MS_FRAME_TMP];
381 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500382 opus_int32 complexity;
383 AnalysisInfo analysis_info;
384 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400385 opus_int32 bitrates[256];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500386 ALLOC_STACK;
387
388 ptr = (char*)st + align(sizeof(OpusMSEncoder));
389 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500390 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
391 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500392
393 if (400*frame_size < Fs)
394 {
395 RESTORE_STACK;
396 return OPUS_BAD_ARG;
397 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500398#ifndef FIXED_POINT
399 analysis_info.valid = 0;
400 if (complexity >= 7 && Fs==48000)
Jean-Marc Valin74483662012-12-17 16:23:42 -0500401 {
Jean-Marc Valin74483662012-12-17 16:23:42 -0500402 opus_int32 delay_compensation;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500403 int channels;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500404
405 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
406 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
407 delay_compensation -= Fs/400;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500408
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500409 frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
410 frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
411 } else
412#endif
413 {
414 frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
415 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500416 /* Validate frame_size before using it to allocate stack space.
417 This mirrors the checks in opus_encode[_float](). */
418 if (400*frame_size != Fs && 200*frame_size != Fs &&
419 100*frame_size != Fs && 50*frame_size != Fs &&
420 25*frame_size != Fs && 50*frame_size != 3*Fs)
421 {
422 RESTORE_STACK;
423 return OPUS_BAD_ARG;
424 }
425 ALLOC(buf, 2*frame_size, opus_val16);
426 coupled_size = opus_encoder_get_size(2);
427 mono_size = opus_encoder_get_size(1);
428
429 if (max_data_bytes < 4*st->layout.nb_streams-1)
430 {
431 RESTORE_STACK;
432 return OPUS_BUFFER_TOO_SMALL;
433 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500434
435 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400436 surround_rate_allocation(st, bitrates, frame_size);
437
Jean-Marc Valin74483662012-12-17 16:23:42 -0500438 ptr = (char*)st + align(sizeof(OpusMSEncoder));
439 for (s=0;s<st->layout.nb_streams;s++)
440 {
441 OpusEncoder *enc;
442 enc = (OpusEncoder*)ptr;
443 if (s < st->layout.nb_coupled_streams)
444 ptr += align(coupled_size);
445 else
446 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400447 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500448 }
449
450 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500451 /* Counting ToC */
452 tot_size = 0;
453 for (s=0;s<st->layout.nb_streams;s++)
454 {
455 OpusEncoder *enc;
456 int len;
457 int curr_max;
458
459 opus_repacketizer_init(&rp);
460 enc = (OpusEncoder*)ptr;
461 if (s < st->layout.nb_coupled_streams)
462 {
463 int left, right;
464 left = get_left_channel(&st->layout, s, -1);
465 right = get_right_channel(&st->layout, s, -1);
466 (*copy_channel_in)(buf, 2,
467 pcm, st->layout.nb_channels, left, frame_size);
468 (*copy_channel_in)(buf+1, 2,
469 pcm, st->layout.nb_channels, right, frame_size);
470 ptr += align(coupled_size);
471 } else {
472 int chan = get_mono_channel(&st->layout, s, -1);
473 (*copy_channel_in)(buf, 1,
474 pcm, st->layout.nb_channels, chan, frame_size);
475 ptr += align(mono_size);
476 }
477 /* number of bytes left (+Toc) */
478 curr_max = max_data_bytes - tot_size;
479 /* Reserve three bytes for the last stream and four for the others */
480 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
481 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500482 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
483#ifndef FIXED_POINT
484 , &analysis_info
485#endif
486 );
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500487 if (len<0)
488 {
489 RESTORE_STACK;
490 return len;
491 }
492 /* We need to use the repacketizer to add the self-delimiting lengths
493 while taking into account the fact that the encoder can now return
494 more than one frame at a time (e.g. 60 ms CELT-only) */
495 opus_repacketizer_cat(&rp, tmp_data, len);
496 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1);
497 data += len;
498 tot_size += len;
499 }
500 RESTORE_STACK;
501 return tot_size;
502
503}
504
505#if !defined(DISABLE_FLOAT_API)
506static void opus_copy_channel_in_float(
507 opus_val16 *dst,
508 int dst_stride,
509 const void *src,
510 int src_stride,
511 int src_channel,
512 int frame_size
513)
514{
515 const float *float_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700516 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500517 float_src = (const float *)src;
518 for (i=0;i<frame_size;i++)
519#if defined(FIXED_POINT)
520 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
521#else
522 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
523#endif
524}
525#endif
526
527static void opus_copy_channel_in_short(
528 opus_val16 *dst,
529 int dst_stride,
530 const void *src,
531 int src_stride,
532 int src_channel,
533 int frame_size
534)
535{
536 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700537 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500538 short_src = (const opus_int16 *)src;
539 for (i=0;i<frame_size;i++)
540#if defined(FIXED_POINT)
541 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
542#else
543 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
544#endif
545}
546
547#ifdef FIXED_POINT
548int opus_multistream_encode(
549 OpusMSEncoder *st,
550 const opus_val16 *pcm,
551 int frame_size,
552 unsigned char *data,
553 opus_int32 max_data_bytes
554)
555{
556 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500557 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500558}
559
560#ifndef DISABLE_FLOAT_API
561int opus_multistream_encode_float(
562 OpusMSEncoder *st,
563 const float *pcm,
564 int frame_size,
565 unsigned char *data,
566 opus_int32 max_data_bytes
567)
568{
569 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500570 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500571}
572#endif
573
574#else
575
576int opus_multistream_encode_float
577(
578 OpusMSEncoder *st,
579 const opus_val16 *pcm,
580 int frame_size,
581 unsigned char *data,
582 opus_int32 max_data_bytes
583)
584{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500585 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500586 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500587 pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500588}
589
590int opus_multistream_encode(
591 OpusMSEncoder *st,
592 const opus_int16 *pcm,
593 int frame_size,
594 unsigned char *data,
595 opus_int32 max_data_bytes
596)
597{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500598 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500599 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500600 pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500601}
602#endif
603
604int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
605{
606 va_list ap;
607 int coupled_size, mono_size;
608 char *ptr;
609 int ret = OPUS_OK;
610
611 va_start(ap, request);
612
613 coupled_size = opus_encoder_get_size(2);
614 mono_size = opus_encoder_get_size(1);
615 ptr = (char*)st + align(sizeof(OpusMSEncoder));
616 switch (request)
617 {
618 case OPUS_SET_BITRATE_REQUEST:
619 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500620 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500621 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
622 goto bad_arg;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500623 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500624 }
625 break;
626 case OPUS_GET_BITRATE_REQUEST:
627 {
628 int s;
629 opus_int32 *value = va_arg(ap, opus_int32*);
630 *value = 0;
631 for (s=0;s<st->layout.nb_streams;s++)
632 {
633 opus_int32 rate;
634 OpusEncoder *enc;
635 enc = (OpusEncoder*)ptr;
636 if (s < st->layout.nb_coupled_streams)
637 ptr += align(coupled_size);
638 else
639 ptr += align(mono_size);
640 opus_encoder_ctl(enc, request, &rate);
641 *value += rate;
642 }
643 }
644 break;
645 case OPUS_GET_LSB_DEPTH_REQUEST:
646 case OPUS_GET_VBR_REQUEST:
647 case OPUS_GET_APPLICATION_REQUEST:
648 case OPUS_GET_BANDWIDTH_REQUEST:
649 case OPUS_GET_COMPLEXITY_REQUEST:
650 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
651 case OPUS_GET_DTX_REQUEST:
652 case OPUS_GET_VOICE_RATIO_REQUEST:
653 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
654 case OPUS_GET_SIGNAL_REQUEST:
655 case OPUS_GET_LOOKAHEAD_REQUEST:
656 case OPUS_GET_SAMPLE_RATE_REQUEST:
657 case OPUS_GET_INBAND_FEC_REQUEST:
658 case OPUS_GET_FORCE_CHANNELS_REQUEST:
659 {
660 OpusEncoder *enc;
661 /* For int32* GET params, just query the first stream */
662 opus_int32 *value = va_arg(ap, opus_int32*);
663 enc = (OpusEncoder*)ptr;
664 ret = opus_encoder_ctl(enc, request, value);
665 }
666 break;
667 case OPUS_GET_FINAL_RANGE_REQUEST:
668 {
669 int s;
670 opus_uint32 *value = va_arg(ap, opus_uint32*);
671 opus_uint32 tmp;
672 *value=0;
673 for (s=0;s<st->layout.nb_streams;s++)
674 {
675 OpusEncoder *enc;
676 enc = (OpusEncoder*)ptr;
677 if (s < st->layout.nb_coupled_streams)
678 ptr += align(coupled_size);
679 else
680 ptr += align(mono_size);
681 ret = opus_encoder_ctl(enc, request, &tmp);
682 if (ret != OPUS_OK) break;
683 *value ^= tmp;
684 }
685 }
686 break;
687 case OPUS_SET_LSB_DEPTH_REQUEST:
688 case OPUS_SET_COMPLEXITY_REQUEST:
689 case OPUS_SET_VBR_REQUEST:
690 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
691 case OPUS_SET_BANDWIDTH_REQUEST:
692 case OPUS_SET_SIGNAL_REQUEST:
693 case OPUS_SET_APPLICATION_REQUEST:
694 case OPUS_SET_INBAND_FEC_REQUEST:
695 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
696 case OPUS_SET_DTX_REQUEST:
697 case OPUS_SET_FORCE_MODE_REQUEST:
698 case OPUS_SET_FORCE_CHANNELS_REQUEST:
699 {
700 int s;
701 /* This works for int32 params */
702 opus_int32 value = va_arg(ap, opus_int32);
703 for (s=0;s<st->layout.nb_streams;s++)
704 {
705 OpusEncoder *enc;
706
707 enc = (OpusEncoder*)ptr;
708 if (s < st->layout.nb_coupled_streams)
709 ptr += align(coupled_size);
710 else
711 ptr += align(mono_size);
712 ret = opus_encoder_ctl(enc, request, value);
713 if (ret != OPUS_OK)
714 break;
715 }
716 }
717 break;
718 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
719 {
720 int s;
721 opus_int32 stream_id;
722 OpusEncoder **value;
723 stream_id = va_arg(ap, opus_int32);
724 if (stream_id<0 || stream_id >= st->layout.nb_streams)
725 ret = OPUS_BAD_ARG;
726 value = va_arg(ap, OpusEncoder**);
727 for (s=0;s<stream_id;s++)
728 {
729 if (s < st->layout.nb_coupled_streams)
730 ptr += align(coupled_size);
731 else
732 ptr += align(mono_size);
733 }
734 *value = (OpusEncoder*)ptr;
735 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500736 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500737 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -0500738 {
739 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -0500740 st->variable_duration = value;
741 }
742 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500743 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -0500744 {
745 opus_int32 *value = va_arg(ap, opus_int32*);
746 *value = st->variable_duration;
747 }
748 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500749 default:
750 ret = OPUS_UNIMPLEMENTED;
751 break;
752 }
753
754 va_end(ap);
755 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500756bad_arg:
757 va_end(ap);
758 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500759}
760
761void opus_multistream_encoder_destroy(OpusMSEncoder *st)
762{
763 opus_free(st);
764}
765
766