int opus_decode(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) { VARDECL(float, out); int ret, i; int nb_samples; ALLOC_STACK; if(frame_size<=0) { RESTORE_STACK; return OPUS_BAD_ARG; } if (data != NULL && len > 0 && !decode_fec) { nb_samples = opus_decoder_get_nb_samples(st, data, len); if (nb_samples>0) frame_size = IMIN(frame_size, nb_samples); else return OPUS_INVALID_PACKET; } ALLOC(out, frame_size*st->channels, float); ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); if (ret > 0) { for (i=0; i<ret*st->channels; i++) pcm[i] = FLOAT2INT16(out[i]); } RESTORE_STACK; return ret; }
int opus_decode_float(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) { if(frame_size<=0) return OPUS_BAD_ARG; return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); }
int opus_decode_float(OpusDecoder *st, const unsigned char *data, opus_int32 len, float *pcm, int frame_size, int decode_fec) { VARDECL(opus_int16, out); int ret, i; ALLOC_STACK; ALLOC(out, frame_size*st->channels, opus_int16); ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); if (ret > 0) { for (i=0;i<ret*st->channels;i++) pcm[i] = (1.f/32768.f)*(out[i]); } RESTORE_STACK; return ret; }
int opus_decode(OpusDecoder *st, const unsigned char *data, int len, opus_int16 *pcm, int frame_size, int decode_fec) { VARDECL(float, out); int ret, i; ALLOC_STACK; if(frame_size<0)return OPUS_BAD_ARG; ALLOC(out, frame_size*st->channels, float); ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL); if (ret > 0) { for (i=0;i<ret*st->channels;i++) pcm[i] = FLOAT2INT16(out[i]); } RESTORE_STACK; return ret; }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, opus_int32 *packet_offset, int soft_clip) { int i, nb_samples; int count, offset; unsigned char toc; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ opus_int16 size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) return OPUS_BAD_ARG; if (len==0 || data==NULL) { int pcm_count=0; do { int ret; ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); if (ret<0) return ret; pcm_count += ret; } while (pcm_count < frame_size); celt_assert(pcm_count == frame_size); if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) OPUS_PRINT_INT(pcm_count); st->last_packet_duration = pcm_count; return pcm_count; } else if (len<0) return OPUS_BAD_ARG; packet_mode = opus_packet_get_mode(data); packet_bandwidth = opus_packet_get_bandwidth(data); packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset, packet_offset); if (count<0) return count; data += offset; if (decode_fec) { int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip); /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = st->last_packet_duration; if (frame_size-packet_frame_size!=0) { ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); if (ret<0) { st->last_packet_duration = duration_copy; return ret; } celt_assert(ret==frame_size-packet_frame_size); } /* Complete with FEC */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), packet_frame_size, 1); if (ret<0) return ret; else { if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) OPUS_PRINT_INT(frame_size); st->last_packet_duration = frame_size; return frame_size; } } if (count*packet_frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; /* Update the state as the last step to avoid updating it on an invalid packet */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; nb_samples=0; for (i=0; i<count; i++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); if (ret<0) return ret; celt_assert(ret==packet_frame_size); data += size[i]; nb_samples += ret; } st->last_packet_duration = nb_samples; if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) OPUS_PRINT_INT(nb_samples); #ifndef FIXED_POINT if (soft_clip) opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); else st->softclip_mem[0]=st->softclip_mem[1]=0; #endif return nb_samples; }
static int opus_multistream_decode_native( OpusMSDecoder *st, const unsigned char *data, opus_int32 len, void *pcm, opus_copy_channel_out_func copy_channel_out, int frame_size, int decode_fec, int soft_clip ) { opus_int32 Fs; int coupled_size; int mono_size; int s, c; char *ptr; int do_plc=0; VARDECL(opus_val16, buf); ALLOC_STACK; /* Limit frame_size to avoid excessive stack allocations. */ opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)); frame_size = IMIN(frame_size, Fs/25*3); ALLOC(buf, 2*frame_size, opus_val16); ptr = (char*)st + align(sizeof(OpusMSDecoder)); coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); if (len==0) do_plc = 1; if (len < 0) return OPUS_BAD_ARG; if (!do_plc && len < 2*st->layout.nb_streams-1) return OPUS_INVALID_PACKET; for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; int packet_offset, ret; dec = (OpusDecoder*)ptr; ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size); if (!do_plc && len<=0) { RESTORE_STACK; return OPUS_INVALID_PACKET; } packet_offset = 0; ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip); data += packet_offset; len -= packet_offset; if (ret > frame_size) { RESTORE_STACK; return OPUS_BUFFER_TOO_SMALL; } if (s>0 && ret != frame_size) { RESTORE_STACK; return OPUS_INVALID_PACKET; } if (ret <= 0) { RESTORE_STACK; return ret; } frame_size = ret; if (s < st->layout.nb_coupled_streams) { int chan, prev; prev = -1; /* Copy "left" audio to the channel(s) where it belongs */ while ( (chan = get_left_channel(&st->layout, s, prev)) != -1) { (*copy_channel_out)(pcm, st->layout.nb_channels, chan, buf, 2, frame_size); prev = chan; } prev = -1; /* Copy "right" audio to the channel(s) where it belongs */ while ( (chan = get_right_channel(&st->layout, s, prev)) != -1) { (*copy_channel_out)(pcm, st->layout.nb_channels, chan, buf+1, 2, frame_size); prev = chan; } } else { int chan, prev; prev = -1; /* Copy audio to the channel(s) where it belongs */ while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1) { (*copy_channel_out)(pcm, st->layout.nb_channels, chan, buf, 1, frame_size); prev = chan; } } } /* Handle muted channels */ for (c=0;c<st->layout.nb_channels;c++) { if (st->layout.mapping[c] == 255) { (*copy_channel_out)(pcm, st->layout.nb_channels, c, NULL, 0, frame_size); } } RESTORE_STACK; return frame_size; }
int opus_decode(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) { return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); }
static int opus_multistream_decode_native( OpusMSDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec ) { int coupled_size; int mono_size; int s, i, c; char *ptr; int do_plc=0; VARDECL(opus_val16, buf); ALLOC_STACK; ALLOC(buf, 2*frame_size, opus_val16); ptr = (char*)st + align(sizeof(OpusMSDecoder)); coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); if (len==0) do_plc = 1; if (len < 0) return OPUS_BAD_ARG; if (!do_plc && len < 2*st->layout.nb_streams-1) return OPUS_INVALID_PACKET; for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; int packet_offset, ret; dec = (OpusDecoder*)ptr; ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size); if (!do_plc && len<=0) { RESTORE_STACK; return OPUS_INVALID_PACKET; } packet_offset = 0; ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset); data += packet_offset; len -= packet_offset; if (ret > frame_size) { RESTORE_STACK; return OPUS_BUFFER_TOO_SMALL; } if (s>0 && ret != frame_size) { RESTORE_STACK; return OPUS_INVALID_PACKET; } if (ret <= 0) { RESTORE_STACK; return ret; } frame_size = ret; if (s < st->layout.nb_coupled_streams) { int chan, prev; prev = -1; /* Copy "left" audio to the channel(s) where it belongs */ while ( (chan = get_left_channel(&st->layout, s, prev)) != -1) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+chan] = buf[2*i]; prev = chan; } prev = -1; /* Copy "right" audio to the channel(s) where it belongs */ while ( (chan = get_right_channel(&st->layout, s, prev)) != -1) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+chan] = buf[2*i+1]; prev = chan; } } else { int chan, prev; prev = -1; /* Copy audio to the channel(s) where it belongs */ while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+chan] = buf[i]; prev = chan; } } } /* Handle muted channels */ for (c=0;c<st->layout.nb_channels;c++) { if (st->layout.mapping[c] == 255) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+c] = 0; } } RESTORE_STACK; return frame_size; }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, int *packet_offset) { int i, nb_samples; int count, offset; unsigned char toc; int tot_offset; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ short size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) return OPUS_BAD_ARG; if (len==0 || data==NULL) { int pcm_count=0; do { int ret; ret = opus_decode_frame(st, NULL, 0, pcm, frame_size-pcm_count, 0); if (ret<0) return ret; pcm += st->channels*ret; pcm_count += ret; } while (pcm_count < frame_size); st->last_packet_duration = pcm_count; return pcm_count; } else if (len<0) return OPUS_BAD_ARG; packet_mode = opus_packet_get_mode(data); packet_bandwidth = opus_packet_get_bandwidth(data); packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); data += offset; if (decode_fec) { int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size <= packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL); /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = st->last_packet_duration; ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL); if (ret<0) { st->last_packet_duration = duration_copy; return ret; } /* Complete with FEC */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), packet_frame_size, 1); if (ret<0) return ret; st->last_packet_duration = frame_size; return frame_size; } tot_offset = 0; if (count < 0) return count; tot_offset += offset; if (count*packet_frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; /* Update the state as the last step to avoid updating it on an invalid packet */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; nb_samples=0; for (i=0;i<count;i++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm, frame_size-nb_samples, decode_fec); if (ret<0) return ret; data += size[i]; tot_offset += size[i]; pcm += ret*st->channels; nb_samples += ret; } if (packet_offset != NULL) *packet_offset = tot_offset; st->last_packet_duration = nb_samples; return nb_samples; }