Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1141)

Side by Side Diff: opus/src/opus_multistream.c

Issue 11196031: Add copy of opus library in deps/third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « opus/src/opus_encoder.c ('k') | opus/src/opus_private.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /* 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
40 typedef struct ChannelLayout {
41 int nb_channels;
42 int nb_streams;
43 int nb_coupled_streams;
44 unsigned char mapping[256];
45 } ChannelLayout;
46
47 struct OpusMSEncoder {
48 ChannelLayout layout;
49 int bitrate;
50 /* Encoder states go here */
51 };
52
53 struct OpusMSDecoder {
54 ChannelLayout layout;
55 /* Decoder states go here */
56 };
57
58
59 #ifdef FIXED_POINT
60 #define opus_encode_native opus_encode
61 #else
62 #define opus_encode_native opus_encode_float
63 #endif
64
65 static int validate_layout(const ChannelLayout *layout)
66 {
67 int i, max_channel;
68
69 max_channel = layout->nb_streams+layout->nb_coupled_streams;
70 if (max_channel>255)
71 return 0;
72 for (i=0;i<layout->nb_channels;i++)
73 {
74 if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
75 return 0;
76 }
77 return 1;
78 }
79
80
81 static int get_left_channel(const ChannelLayout *layout, int stream_id, int prev )
82 {
83 int i;
84 i = (prev<0) ? 0 : prev+1;
85 for (;i<layout->nb_channels;i++)
86 {
87 if (layout->mapping[i]==stream_id*2)
88 return i;
89 }
90 return -1;
91 }
92
93 static int get_right_channel(const ChannelLayout *layout, int stream_id, int pre v)
94 {
95 int i;
96 i = (prev<0) ? 0 : prev+1;
97 for (;i<layout->nb_channels;i++)
98 {
99 if (layout->mapping[i]==stream_id*2+1)
100 return i;
101 }
102 return -1;
103 }
104
105 static int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev )
106 {
107 int i;
108 i = (prev<0) ? 0 : prev+1;
109 for (;i<layout->nb_channels;i++)
110 {
111 if (layout->mapping[i]==stream_id+layout->nb_coupled_streams)
112 return i;
113 }
114 return -1;
115 }
116
117 static int validate_encoder_layout(const ChannelLayout *layout)
118 {
119 int s;
120 for (s=0;s<layout->nb_streams;s++)
121 {
122 if (s < layout->nb_coupled_streams)
123 {
124 if (get_left_channel(layout, s, -1)==-1)
125 return 0;
126 if (get_right_channel(layout, s, -1)==-1)
127 return 0;
128 } else {
129 if (get_mono_channel(layout, s, -1)==-1)
130 return 0;
131 }
132 }
133 return 1;
134 }
135
136 opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_stre ams)
137 {
138 int coupled_size;
139 int mono_size;
140
141 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0 ;
142 coupled_size = opus_encoder_get_size(2);
143 mono_size = opus_encoder_get_size(1);
144 return align(sizeof(OpusMSEncoder))
145 + nb_coupled_streams * align(coupled_size)
146 + (nb_streams-nb_coupled_streams) * align(mono_size);
147 }
148
149
150
151 int opus_multistream_encoder_init(
152 OpusMSEncoder *st,
153 opus_int32 Fs,
154 int channels,
155 int streams,
156 int coupled_streams,
157 const unsigned char *mapping,
158 int application
159 )
160 {
161 int coupled_size;
162 int mono_size;
163 int i;
164 char *ptr;
165
166 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
167 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
168 return OPUS_BAD_ARG;
169
170 st->layout.nb_channels = channels;
171 st->layout.nb_streams = streams;
172 st->layout.nb_coupled_streams = coupled_streams;
173
174 for (i=0;i<st->layout.nb_channels;i++)
175 st->layout.mapping[i] = mapping[i];
176 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
177 return OPUS_BAD_ARG;
178 ptr = (char*)st + align(sizeof(OpusMSEncoder));
179 coupled_size = opus_encoder_get_size(2);
180 mono_size = opus_encoder_get_size(1);
181
182 for (i=0;i<st->layout.nb_coupled_streams;i++)
183 {
184 opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
185 ptr += align(coupled_size);
186 }
187 for (;i<st->layout.nb_streams;i++)
188 {
189 opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
190 ptr += align(mono_size);
191 }
192 return OPUS_OK;
193 }
194
195 OpusMSEncoder *opus_multistream_encoder_create(
196 opus_int32 Fs,
197 int channels,
198 int streams,
199 int coupled_streams,
200 const unsigned char *mapping,
201 int application,
202 int *error
203 )
204 {
205 int ret;
206 OpusMSEncoder *st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_ size(streams, coupled_streams));
207 if (st==NULL)
208 {
209 if (error)
210 *error = OPUS_ALLOC_FAIL;
211 return NULL;
212 }
213 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_stream s, mapping, application);
214 if (ret != OPUS_OK)
215 {
216 opus_free(st);
217 st = NULL;
218 }
219 if (error)
220 *error = ret;
221 return st;
222 }
223
224 /* Max size in case the encoder decides to return three frames */
225 #define MS_FRAME_TMP (3*1275+7)
226 #ifdef FIXED_POINT
227 int opus_multistream_encode(
228 #else
229 int opus_multistream_encode_float(
230 #endif
231 OpusMSEncoder *st,
232 const opus_val16 *pcm,
233 int frame_size,
234 unsigned char *data,
235 opus_int32 max_data_bytes
236 )
237 {
238 int coupled_size;
239 int mono_size;
240 int s, i;
241 char *ptr;
242 int tot_size;
243 VARDECL(opus_val16, buf);
244 unsigned char tmp_data[MS_FRAME_TMP];
245 OpusRepacketizer rp;
246 ALLOC_STACK;
247
248 ALLOC(buf, 2*frame_size, opus_val16);
249 ptr = (char*)st + align(sizeof(OpusMSEncoder));
250 coupled_size = opus_encoder_get_size(2);
251 mono_size = opus_encoder_get_size(1);
252
253 if (max_data_bytes < 4*st->layout.nb_streams-1)
254 {
255 RESTORE_STACK;
256 return OPUS_BUFFER_TOO_SMALL;
257 }
258 /* Counting ToC */
259 tot_size = 0;
260 for (s=0;s<st->layout.nb_streams;s++)
261 {
262 OpusEncoder *enc;
263 int len;
264 int curr_max;
265
266 opus_repacketizer_init(&rp);
267 enc = (OpusEncoder*)ptr;
268 if (s < st->layout.nb_coupled_streams)
269 {
270 int left, right;
271 left = get_left_channel(&st->layout, s, -1);
272 right = get_right_channel(&st->layout, s, -1);
273 for (i=0;i<frame_size;i++)
274 {
275 buf[2*i] = pcm[st->layout.nb_channels*i+left];
276 buf[2*i+1] = pcm[st->layout.nb_channels*i+right];
277 }
278 ptr += align(coupled_size);
279 } else {
280 int chan = get_mono_channel(&st->layout, s, -1);
281 for (i=0;i<frame_size;i++)
282 buf[i] = pcm[st->layout.nb_channels*i+chan];
283 ptr += align(mono_size);
284 }
285 /* number of bytes left (+Toc) */
286 curr_max = max_data_bytes - tot_size;
287 /* Reserve three bytes for the last stream and four for the others */
288 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
289 curr_max = IMIN(curr_max,MS_FRAME_TMP);
290 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max);
291 if (len<0)
292 {
293 RESTORE_STACK;
294 return len;
295 }
296 /* We need to use the repacketizer to add the self-delimiting lengths
297 while taking into account the fact that the encoder can now return
298 more than one frame at a time (e.g. 60 ms CELT-only) */
299 opus_repacketizer_cat(&rp, tmp_data, len);
300 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_fr ames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1);
301 data += len;
302 tot_size += len;
303 }
304 RESTORE_STACK;
305 return tot_size;
306
307 }
308
309 #ifdef FIXED_POINT
310
311 #ifndef DISABLE_FLOAT_API
312 int opus_multistream_encode_float(
313 OpusMSEncoder *st,
314 const float *pcm,
315 int frame_size,
316 unsigned char *data,
317 opus_int32 max_data_bytes
318 )
319 {
320 int i, ret;
321 VARDECL(opus_int16, in);
322 ALLOC_STACK;
323
324 ALLOC(in, frame_size*st->layout.nb_channels, opus_int16);
325
326 for (i=0;i<frame_size*st->layout.nb_channels;i++)
327 in[i] = FLOAT2INT16(pcm[i]);
328 ret = opus_multistream_encode(st, in, frame_size, data, max_data_bytes);
329 RESTORE_STACK;
330 return ret;
331 }
332 #endif
333
334 #else
335
336 int opus_multistream_encode(
337 OpusMSEncoder *st,
338 const opus_int16 *pcm,
339 int frame_size,
340 unsigned char *data,
341 opus_int32 max_data_bytes
342 )
343 {
344 int i, ret;
345 VARDECL(float, in);
346 ALLOC_STACK;
347
348 ALLOC(in, frame_size*st->layout.nb_channels, float);
349
350 for (i=0;i<frame_size*st->layout.nb_channels;i++)
351 in[i] = (1.f/32768.f)*pcm[i];
352 ret = opus_multistream_encode_float(st, in, frame_size, data, max_data_bytes) ;
353 RESTORE_STACK;
354 return ret;
355 }
356
357 #endif
358
359 int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
360 {
361 va_list ap;
362 int coupled_size, mono_size;
363 char *ptr;
364 int ret = OPUS_OK;
365
366 va_start(ap, request);
367
368 coupled_size = opus_encoder_get_size(2);
369 mono_size = opus_encoder_get_size(1);
370 ptr = (char*)st + align(sizeof(OpusMSEncoder));
371 switch (request)
372 {
373 case OPUS_SET_BITRATE_REQUEST:
374 {
375 int chan, s;
376 opus_int32 value = va_arg(ap, opus_int32);
377 chan = st->layout.nb_streams + st->layout.nb_coupled_streams;
378 value /= chan;
379 for (s=0;s<st->layout.nb_streams;s++)
380 {
381 OpusEncoder *enc;
382 enc = (OpusEncoder*)ptr;
383 if (s < st->layout.nb_coupled_streams)
384 ptr += align(coupled_size);
385 else
386 ptr += align(mono_size);
387 opus_encoder_ctl(enc, request, value * (s < st->layout.nb_coupled_strea ms ? 2 : 1));
388 }
389 }
390 break;
391 case OPUS_GET_BITRATE_REQUEST:
392 {
393 int s;
394 opus_int32 *value = va_arg(ap, opus_int32*);
395 *value = 0;
396 for (s=0;s<st->layout.nb_streams;s++)
397 {
398 opus_int32 rate;
399 OpusEncoder *enc;
400 enc = (OpusEncoder*)ptr;
401 if (s < st->layout.nb_coupled_streams)
402 ptr += align(coupled_size);
403 else
404 ptr += align(mono_size);
405 opus_encoder_ctl(enc, request, &rate);
406 *value += rate;
407 }
408 }
409 break;
410 case OPUS_GET_LSB_DEPTH_REQUEST:
411 case OPUS_GET_VBR_REQUEST:
412 case OPUS_GET_APPLICATION_REQUEST:
413 case OPUS_GET_BANDWIDTH_REQUEST:
414 case OPUS_GET_COMPLEXITY_REQUEST:
415 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
416 case OPUS_GET_DTX_REQUEST:
417 case OPUS_GET_VOICE_RATIO_REQUEST:
418 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
419 case OPUS_GET_SIGNAL_REQUEST:
420 case OPUS_GET_LOOKAHEAD_REQUEST:
421 case OPUS_GET_INBAND_FEC_REQUEST:
422 {
423 OpusEncoder *enc;
424 /* For int32* GET params, just query the first stream */
425 opus_int32 *value = va_arg(ap, opus_int32*);
426 enc = (OpusEncoder*)ptr;
427 ret = opus_encoder_ctl(enc, request, value);
428 }
429 break;
430 case OPUS_GET_FINAL_RANGE_REQUEST:
431 {
432 int s;
433 opus_uint32 *value = va_arg(ap, opus_uint32*);
434 opus_uint32 tmp;
435 *value=0;
436 for (s=0;s<st->layout.nb_streams;s++)
437 {
438 OpusEncoder *enc;
439 enc = (OpusEncoder*)ptr;
440 if (s < st->layout.nb_coupled_streams)
441 ptr += align(coupled_size);
442 else
443 ptr += align(mono_size);
444 ret = opus_encoder_ctl(enc, request, &tmp);
445 if (ret != OPUS_OK) break;
446 *value ^= tmp;
447 }
448 }
449 break;
450 case OPUS_SET_LSB_DEPTH_REQUEST:
451 case OPUS_SET_COMPLEXITY_REQUEST:
452 case OPUS_SET_VBR_REQUEST:
453 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
454 case OPUS_SET_BANDWIDTH_REQUEST:
455 case OPUS_SET_SIGNAL_REQUEST:
456 case OPUS_SET_APPLICATION_REQUEST:
457 case OPUS_SET_INBAND_FEC_REQUEST:
458 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
459 case OPUS_SET_DTX_REQUEST:
460 case OPUS_SET_FORCE_MODE_REQUEST:
461 {
462 int s;
463 /* This works for int32 params */
464 opus_int32 value = va_arg(ap, opus_int32);
465 for (s=0;s<st->layout.nb_streams;s++)
466 {
467 OpusEncoder *enc;
468
469 enc = (OpusEncoder*)ptr;
470 if (s < st->layout.nb_coupled_streams)
471 ptr += align(coupled_size);
472 else
473 ptr += align(mono_size);
474 ret = opus_encoder_ctl(enc, request, value);
475 if (ret != OPUS_OK)
476 break;
477 }
478 }
479 break;
480 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
481 {
482 int s;
483 opus_int32 stream_id;
484 OpusEncoder **value;
485 stream_id = va_arg(ap, opus_int32);
486 if (stream_id<0 || stream_id >= st->layout.nb_streams)
487 ret = OPUS_BAD_ARG;
488 value = va_arg(ap, OpusEncoder**);
489 for (s=0;s<stream_id;s++)
490 {
491 if (s < st->layout.nb_coupled_streams)
492 ptr += align(coupled_size);
493 else
494 ptr += align(mono_size);
495 }
496 *value = (OpusEncoder*)ptr;
497 }
498 break;
499 default:
500 ret = OPUS_UNIMPLEMENTED;
501 break;
502 }
503
504 va_end(ap);
505 return ret;
506 }
507
508 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
509 {
510 opus_free(st);
511 }
512
513
514 /* DECODER */
515
516 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_stre ams)
517 {
518 int coupled_size;
519 int mono_size;
520
521 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0 ;
522 coupled_size = opus_decoder_get_size(2);
523 mono_size = opus_decoder_get_size(1);
524 return align(sizeof(OpusMSDecoder))
525 + nb_coupled_streams * align(coupled_size)
526 + (nb_streams-nb_coupled_streams) * align(mono_size);
527 }
528
529 int opus_multistream_decoder_init(
530 OpusMSDecoder *st,
531 opus_int32 Fs,
532 int channels,
533 int streams,
534 int coupled_streams,
535 const unsigned char *mapping
536 )
537 {
538 int coupled_size;
539 int mono_size;
540 int i, ret;
541 char *ptr;
542
543 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
544 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
545 return OPUS_BAD_ARG;
546
547 st->layout.nb_channels = channels;
548 st->layout.nb_streams = streams;
549 st->layout.nb_coupled_streams = coupled_streams;
550
551 for (i=0;i<st->layout.nb_channels;i++)
552 st->layout.mapping[i] = mapping[i];
553 if (!validate_layout(&st->layout))
554 return OPUS_BAD_ARG;
555
556 ptr = (char*)st + align(sizeof(OpusMSDecoder));
557 coupled_size = opus_decoder_get_size(2);
558 mono_size = opus_decoder_get_size(1);
559
560 for (i=0;i<st->layout.nb_coupled_streams;i++)
561 {
562 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
563 if(ret!=OPUS_OK)return ret;
564 ptr += align(coupled_size);
565 }
566 for (;i<st->layout.nb_streams;i++)
567 {
568 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
569 if(ret!=OPUS_OK)return ret;
570 ptr += align(mono_size);
571 }
572 return OPUS_OK;
573 }
574
575
576 OpusMSDecoder *opus_multistream_decoder_create(
577 opus_int32 Fs,
578 int channels,
579 int streams,
580 int coupled_streams,
581 const unsigned char *mapping,
582 int *error
583 )
584 {
585 int ret;
586 OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_ size(streams, coupled_streams));
587 if (st==NULL)
588 {
589 if (error)
590 *error = OPUS_ALLOC_FAIL;
591 return NULL;
592 }
593 ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_stream s, mapping);
594 if (error)
595 *error = ret;
596 if (ret != OPUS_OK)
597 {
598 opus_free(st);
599 st = NULL;
600 }
601 return st;
602
603
604 }
605
606 static int opus_multistream_decode_native(
607 OpusMSDecoder *st,
608 const unsigned char *data,
609 opus_int32 len,
610 opus_val16 *pcm,
611 int frame_size,
612 int decode_fec
613 )
614 {
615 int coupled_size;
616 int mono_size;
617 int s, i, c;
618 char *ptr;
619 int do_plc=0;
620 VARDECL(opus_val16, buf);
621 ALLOC_STACK;
622
623 ALLOC(buf, 2*frame_size, opus_val16);
624 ptr = (char*)st + align(sizeof(OpusMSDecoder));
625 coupled_size = opus_decoder_get_size(2);
626 mono_size = opus_decoder_get_size(1);
627
628 if (len==0)
629 do_plc = 1;
630 if (len < 0)
631 return OPUS_BAD_ARG;
632 if (!do_plc && len < 2*st->layout.nb_streams-1)
633 return OPUS_INVALID_PACKET;
634 for (s=0;s<st->layout.nb_streams;s++)
635 {
636 OpusDecoder *dec;
637 int packet_offset, ret;
638
639 dec = (OpusDecoder*)ptr;
640 ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(m ono_size);
641
642 if (!do_plc && len<=0)
643 {
644 RESTORE_STACK;
645 return OPUS_INVALID_PACKET;
646 }
647 packet_offset = 0;
648 ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=s t->layout.nb_streams-1, &packet_offset);
649 data += packet_offset;
650 len -= packet_offset;
651 if (ret > frame_size)
652 {
653 RESTORE_STACK;
654 return OPUS_BUFFER_TOO_SMALL;
655 }
656 if (s>0 && ret != frame_size)
657 {
658 RESTORE_STACK;
659 return OPUS_INVALID_PACKET;
660 }
661 if (ret <= 0)
662 {
663 RESTORE_STACK;
664 return ret;
665 }
666 frame_size = ret;
667 if (s < st->layout.nb_coupled_streams)
668 {
669 int chan, prev;
670 prev = -1;
671 /* Copy "left" audio to the channel(s) where it belongs */
672 while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
673 {
674 for (i=0;i<frame_size;i++)
675 pcm[st->layout.nb_channels*i+chan] = buf[2*i];
676 prev = chan;
677 }
678 prev = -1;
679 /* Copy "right" audio to the channel(s) where it belongs */
680 while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
681 {
682 for (i=0;i<frame_size;i++)
683 pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
684 prev = chan;
685 }
686 } else {
687 int chan, prev;
688 prev = -1;
689 /* Copy audio to the channel(s) where it belongs */
690 while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
691 {
692 for (i=0;i<frame_size;i++)
693 pcm[st->layout.nb_channels*i+chan] = buf[i];
694 prev = chan;
695 }
696 }
697 }
698 /* Handle muted channels */
699 for (c=0;c<st->layout.nb_channels;c++)
700 {
701 if (st->layout.mapping[c] == 255)
702 {
703 for (i=0;i<frame_size;i++)
704 pcm[st->layout.nb_channels*i+c] = 0;
705 }
706 }
707 RESTORE_STACK;
708 return frame_size;
709 }
710
711 #ifdef FIXED_POINT
712 int opus_multistream_decode(
713 OpusMSDecoder *st,
714 const unsigned char *data,
715 opus_int32 len,
716 opus_int16 *pcm,
717 int frame_size,
718 int decode_fec
719 )
720 {
721 return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_ fec);
722 }
723
724 #ifndef DISABLE_FLOAT_API
725 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
726 opus_int32 len, float *pcm, int frame_size, int decode_fec)
727 {
728 VARDECL(opus_int16, out);
729 int ret, i;
730 ALLOC_STACK;
731
732 ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
733
734 ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_f ec);
735 if (ret > 0)
736 {
737 for (i=0;i<ret*st->layout.nb_channels;i++)
738 pcm[i] = (1.f/32768.f)*(out[i]);
739 }
740 RESTORE_STACK;
741 return ret;
742 }
743 #endif
744
745 #else
746
747 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
748 opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
749 {
750 VARDECL(float, out);
751 int ret, i;
752 ALLOC_STACK;
753
754 ALLOC(out, frame_size*st->layout.nb_channels, float);
755
756 ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_f ec);
757 if (ret > 0)
758 {
759 for (i=0;i<ret*st->layout.nb_channels;i++)
760 pcm[i] = FLOAT2INT16(out[i]);
761 }
762 RESTORE_STACK;
763 return ret;
764 }
765
766 int opus_multistream_decode_float(
767 OpusMSDecoder *st,
768 const unsigned char *data,
769 opus_int32 len,
770 float *pcm,
771 int frame_size,
772 int decode_fec
773 )
774 {
775 return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_ fec);
776 }
777 #endif
778
779 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
780 {
781 va_list ap;
782 int coupled_size, mono_size;
783 char *ptr;
784 int ret = OPUS_OK;
785
786 va_start(ap, request);
787
788 coupled_size = opus_decoder_get_size(2);
789 mono_size = opus_decoder_get_size(1);
790 ptr = (char*)st + align(sizeof(OpusMSDecoder));
791 switch (request)
792 {
793 case OPUS_GET_BANDWIDTH_REQUEST:
794 {
795 OpusDecoder *dec;
796 /* For int32* GET params, just query the first stream */
797 opus_int32 *value = va_arg(ap, opus_int32*);
798 dec = (OpusDecoder*)ptr;
799 ret = opus_decoder_ctl(dec, request, value);
800 }
801 break;
802 case OPUS_GET_FINAL_RANGE_REQUEST:
803 {
804 int s;
805 opus_uint32 *value = va_arg(ap, opus_uint32*);
806 opus_uint32 tmp;
807 *value = 0;
808 for (s=0;s<st->layout.nb_streams;s++)
809 {
810 OpusDecoder *dec;
811 dec = (OpusDecoder*)ptr;
812 if (s < st->layout.nb_coupled_streams)
813 ptr += align(coupled_size);
814 else
815 ptr += align(mono_size);
816 ret = opus_decoder_ctl(dec, request, &tmp);
817 if (ret != OPUS_OK) break;
818 *value ^= tmp;
819 }
820 }
821 break;
822 case OPUS_RESET_STATE:
823 {
824 int s;
825 for (s=0;s<st->layout.nb_streams;s++)
826 {
827 OpusDecoder *dec;
828
829 dec = (OpusDecoder*)ptr;
830 if (s < st->layout.nb_coupled_streams)
831 ptr += align(coupled_size);
832 else
833 ptr += align(mono_size);
834 ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
835 if (ret != OPUS_OK)
836 break;
837 }
838 }
839 break;
840 case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
841 {
842 int s;
843 opus_int32 stream_id;
844 OpusDecoder **value;
845 stream_id = va_arg(ap, opus_int32);
846 if (stream_id<0 || stream_id >= st->layout.nb_streams)
847 ret = OPUS_BAD_ARG;
848 value = va_arg(ap, OpusDecoder**);
849 for (s=0;s<stream_id;s++)
850 {
851 if (s < st->layout.nb_coupled_streams)
852 ptr += align(coupled_size);
853 else
854 ptr += align(mono_size);
855 }
856 *value = (OpusDecoder*)ptr;
857 }
858 break;
859 case OPUS_SET_GAIN_REQUEST:
860 {
861 int s;
862 /* This works for int32 params */
863 opus_int32 value = va_arg(ap, opus_int32);
864 for (s=0;s<st->layout.nb_streams;s++)
865 {
866 OpusDecoder *dec;
867
868 dec = (OpusDecoder*)ptr;
869 if (s < st->layout.nb_coupled_streams)
870 ptr += align(coupled_size);
871 else
872 ptr += align(mono_size);
873 ret = opus_decoder_ctl(dec, request, value);
874 if (ret != OPUS_OK)
875 break;
876 }
877 }
878 break;
879 default:
880 ret = OPUS_UNIMPLEMENTED;
881 break;
882 }
883
884 va_end(ap);
885 return ret;
886 }
887
888
889 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
890 {
891 opus_free(st);
892 }
OLDNEW
« no previous file with comments | « opus/src/opus_encoder.c ('k') | opus/src/opus_private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698