int qSpeexDecode(QSpeexCodecPtr handle, void* inputBytes, int inputSize, void* outputSamples, int outputSize) { int offset, remaining; short *out = (short*)outputSamples; /* If there is no input to read, we certainly can't read it. */ if (inputBytes != NULL) { speex_bits_read_from(&handle->decBits, inputBytes, inputSize); } for (offset=0; offset<outputSize; offset+=handle->frameSize) { if (inputBytes != NULL) { if (!speex_bits_remaining(&handle->decBits)) { // Ran out of input data return 2; } speex_decode_int(handle->decState, &handle->decBits, out+offset); } else { /* Extrapolate output-buffer based on current decoder state. */ speex_decode_int(handle->decState, NULL, out+offset); } } remaining = speex_bits_remaining(&handle->decBits); if (remaining >= 8) { /* If less than a byte is left over, that's OK. */ fprintf(stderr, "qSpeexDecode(): %d bits left over\n", remaining); return 1; // Still have encoded bits left over } else return 0; // A-OK!! }
static int libspeex_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibSpeexContext *s = avctx->priv_data; int16_t *output = data, *end; int i, num_samples; num_samples = s->frame_size * avctx->channels; end = output + *data_size / sizeof(*output); speex_bits_read_from(&s->bits, buf, buf_size); for (i = 0; speex_bits_remaining(&s->bits) && output + num_samples < end; i++) { int ret = speex_decode_int(s->dec_state, &s->bits, output); if (ret <= -2) { av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); return -1; } else if (ret == -1) // end of stream break; if (avctx->channels == 2) speex_decode_stereo_int(output, s->frame_size, &s->stereo); output += num_samples; } avctx->frame_size = s->frame_size * i; *data_size = avctx->channels * avctx->frame_size * sizeof(*output); return buf_size; }
/***************************************************************************** * DecodePacket: decodes a Speex packet. *****************************************************************************/ static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; if( p_oggpacket->bytes ) { /* Copy Ogg packet to Speex bitstream */ speex_bits_read_from( &p_sys->bits, (char *)p_oggpacket->packet, p_oggpacket->bytes ); p_sys->i_frame_in_packet = 0; } /* Decode one frame at a time */ if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet ) { block_t *p_aout_buffer; if( p_sys->p_header->frame_size == 0 ) return NULL; p_aout_buffer = decoder_NewAudioBuffer( p_dec, p_sys->p_header->frame_size ); if( !p_aout_buffer ) { return NULL; } switch( speex_decode_int( p_sys->p_state, &p_sys->bits, (int16_t *)p_aout_buffer->p_buffer ) ) { case -2: msg_Err( p_dec, "decoding error: corrupted stream?" ); case -1: /* End of stream */ return NULL; } if( speex_bits_remaining( &p_sys->bits ) < 0 ) { msg_Err( p_dec, "decoding overflow: corrupted stream?" ); } if( p_sys->p_header->nb_channels == 2 ) speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer, p_sys->p_header->frame_size, &p_sys->stereo ); /* Date management */ p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); p_aout_buffer->i_length = date_Increment( &p_sys->end_date, p_sys->p_header->frame_size ) - p_aout_buffer->i_pts; p_sys->i_frame_in_packet++; return p_aout_buffer; } else { return NULL; } }
int Speex_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, unsigned int channels, unsigned int rate, long h_codec ) { SpeexState* ss; short* pcm = (short*) out_buf; int frames_out = 0; ss = (SpeexState*) h_codec; if (!ss || channels!=1) return -1; speex_bits_read_from(&ss->decoder.bits, (char*)in_buf, size); /* We don't know where frame boundaries are, but the minimum frame size is 43 */ while (speex_bits_remaining(&ss->decoder.bits)>40) { int ret; ret = speex_decode_int(ss->decoder.state, &ss->decoder.bits, pcm); pcm+= ss->frame_size; if (ret==-2) { ERROR("while calling speex_decode\n"); return -1; } if (ret==-1) break; frames_out++; } return frames_out*ss->frame_size*sizeof(short); }
static int libspeex_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibSpeexContext *s = avctx->priv_data; AVFrame *frame = data; int16_t *output; int ret, consumed = 0; /* get output buffer */ frame->nb_samples = s->frame_size; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } output = (int16_t *)frame->data[0]; /* if there is not enough data left for the smallest possible frame or the next 5 bits are a terminator code, reset the libspeex buffer using the current packet, otherwise ignore the current packet and keep decoding frames from the libspeex buffer. */ if (speex_bits_remaining(&s->bits) < 5 || speex_bits_peek_unsigned(&s->bits, 5) == 0xF) { /* check for flush packet */ if (!buf || !buf_size) { *got_frame_ptr = 0; return buf_size; } /* set new buffer */ speex_bits_read_from(&s->bits, buf, buf_size); consumed = buf_size; } /* decode a single frame */ ret = speex_decode_int(s->dec_state, &s->bits, output); if (ret <= -2) { av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); return AVERROR_INVALIDDATA; } if (avctx->channels == 2) speex_decode_stereo_int(output, s->frame_size, &s->stereo); *got_frame_ptr = 1; return consumed; }
static int decode(struct audec_state *st, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len) { const size_t n = st->channels * st->frame_size; size_t i = 0; /* Read into bit-stream */ speex_bits_read_from(&st->bits, (char *)buf, (int)len); /* Handle multiple Speex frames in one RTP packet */ while (speex_bits_remaining(&st->bits) >= MIN_FRAME_SIZE) { int ret; if (*sampc < n) return ENOMEM; ret = speex_decode_int(st->dec, &st->bits, (int16_t *)&sampv[i]); if (ret < 0) { if (-1 == ret) { } else if (-2 == ret) { warning("speex: decode: corrupt stream\n"); } else { warning("speex: decode: speex_decode_int:" " ret=%d\n", ret); } break; } /* Transforms a mono frame into a stereo frame using intensity stereo info */ if (2 == st->channels) { speex_decode_stereo_int((int16_t *)&sampv[i], st->frame_size, &st->stereo); } i += n; *sampc -= n; } *sampc = i; return 0; }
tsk_size_t tdav_codec_speex_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr) { int ret; tsk_size_t out_size = 0; tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self; if(!self || !in_data || !in_size || !out_data){ TSK_DEBUG_ERROR("Invalid parameter"); return 0; } // initializes the bit-stream speex_bits_read_from(&speex->decoder.bits, (char*)in_data, in_size); do{ // performs decode() if((ret = speex_decode_int(speex->decoder.state, &speex->decoder.bits, speex->decoder.buffer))){ TSK_DEBUG_ERROR("Failed to decode the buffer. retcode=%d", ret); break; } if(*out_max_size <(out_size + speex->decoder.size)){ if((*out_data = tsk_realloc(*out_data, (out_size + speex->decoder.size)))){ *out_max_size = (out_size + speex->decoder.size); } else{ *out_max_size = 0; return 0; } } // copy output buffer memcpy(&((uint8_t*)*out_data)[out_size], speex->decoder.buffer, speex->decoder.size); out_size += speex->decoder.size; } while(speex_bits_remaining(&speex->decoder.bits) >= 5); return out_size; }
/***************************************************************************** * ProcessPacket: processes a Speex packet. *****************************************************************************/ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = *pp_block; if( p_block && p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) Flush( p_dec ); /* Date management */ if( p_block && p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } if( !date_Get( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ if( p_block ) block_Release( p_block ); return NULL; } *pp_block = NULL; /* To avoid being fed the same packet again */ if( p_sys->b_packetizer ) { if ( p_sys->p_header->frames_per_packet > 1 ) { short *p_frame_holder = NULL; int i_bits_before = 0, i_bits_after = 0, i_bytes_in_speex_frame = 0, i_pcm_output_size = 0, i_bits_in_speex_frame = 0; block_t *p_new_block = NULL; i_pcm_output_size = p_sys->p_header->frame_size; p_frame_holder = (short*)xmalloc( sizeof(short)*i_pcm_output_size ); speex_bits_read_from( &p_sys->bits, (char*)p_oggpacket->packet, p_oggpacket->bytes); i_bits_before = speex_bits_remaining( &p_sys->bits ); speex_decode_int(p_sys->p_state, &p_sys->bits, p_frame_holder); i_bits_after = speex_bits_remaining( &p_sys->bits ); i_bits_in_speex_frame = i_bits_before - i_bits_after; i_bytes_in_speex_frame = ( i_bits_in_speex_frame + (8 - (i_bits_in_speex_frame % 8)) ) / 8; p_new_block = block_Alloc( i_bytes_in_speex_frame ); memset( p_new_block->p_buffer, 0xff, i_bytes_in_speex_frame ); /* * Copy the first frame in this packet to a new packet. */ speex_bits_rewind( &p_sys->bits ); speex_bits_write( &p_sys->bits, (char*)p_new_block->p_buffer, (int)i_bytes_in_speex_frame ); /* * Move the remaining part of the original packet (subsequent * frames, if there are any) into the beginning * of the original packet so * they are preserved following the realloc. * Note: Any bits that * remain in the initial packet * are "filler" if they do not constitute * an entire byte. */ if ( i_bits_after > 7 ) { /* round-down since we rounded-up earlier (to include * the speex terminator code. */ i_bytes_in_speex_frame--; speex_bits_write( &p_sys->bits, (char*)p_block->p_buffer, p_block->i_buffer - i_bytes_in_speex_frame ); p_block = block_Realloc( p_block, 0, p_block->i_buffer-i_bytes_in_speex_frame ); *pp_block = p_block; } else { speex_bits_reset( &p_sys->bits ); } free( p_frame_holder ); return SendPacket( p_dec, p_new_block); } else { return SendPacket( p_dec, p_block ); } } else { block_t *p_aout_buffer = DecodePacket( p_dec, p_oggpacket ); if( p_block ) block_Release( p_block ); return p_aout_buffer; } }
static GstFlowReturn gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf) { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; guint size; guint8 *data; SpeexBits *bits; if (!dec->frame_duration) goto not_negotiated; if (G_LIKELY (GST_BUFFER_SIZE (buf))) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); /* send data to the bitstream */ speex_bits_read_from (&dec->bits, (char *) data, size); fpp = dec->header->frames_per_packet; bits = &dec->bits; GST_DEBUG_OBJECT (dec, "received buffer of size %u, fpp %d, %d bits", size, fpp, speex_bits_remaining (bits)); } else { /* FIXME ? actually consider how much concealment is needed */ /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); fpp = dec->header->frames_per_packet; bits = NULL; } /* now decode each frame, catering for unknown number of them (e.g. rtp) */ for (i = 0; i < fpp; i++) { GstBuffer *outbuf; gint16 *out_data; gint ret; GST_LOG_OBJECT (dec, "decoding frame %d/%d, %d bits remaining", i, fpp, bits ? speex_bits_remaining (bits) : -1); res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (dec)), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } out_data = (gint16 *) GST_BUFFER_DATA (outbuf); ret = speex_decode_int (dec->state, bits, out_data); if (ret == -1) { /* uh? end of stream */ if (fpp == 0 && speex_bits_remaining (bits) < 8) { /* if we did not know how many frames to expect, then we get this at the end if there are leftover bits to pad to the next byte */ GST_DEBUG_OBJECT (dec, "Discarding leftover bits"); } else { GST_WARNING_OBJECT (dec, "Unexpected end of stream found"); } gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } else if (ret == -2) { GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?"); gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } if (bits && speex_bits_remaining (bits) < 0) { GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?"); gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } if (dec->header->nb_channels == 2) speex_decode_stereo_int (out_data, dec->frame_size, dec->stereo); res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); break; } } return res; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("decoder not initialized")); return GST_FLOW_NOT_NEGOTIATED; } }
boost::uint8_t* AudioDecoderSpeex::decode(const EncodedAudioFrame& input, boost::uint32_t& outputSize) { speex_bits_read_from(&_speex_bits, reinterpret_cast<char*>(input.data.get()), input.dataSize); std::vector<DecodedFrame*> decoded_frames; boost::uint32_t total_size = 0; while (speex_bits_remaining(&_speex_bits)) { boost::scoped_array<short> output( new short[_speex_framesize] ); int rv = speex_decode_int(_speex_dec_state, &_speex_bits, output.get()); if (rv != 0) { if (rv != -1) { log_error(_("Corrupt Speex stream!")); } break; } boost::int16_t* conv_data = 0; #ifdef RESAMPLING_SPEEX spx_uint32_t conv_size = 0; conv_data = new boost::int16_t[_target_frame_size]; memset(conv_data, 0, _target_frame_size * 2); spx_uint32_t in_size = _speex_framesize; // Our input format is mono and we want to expand to stereo. Speex // won't do this for us, but we can ask it to skip a sample after // writing one, so all we have to do is duplicate the samples. speex_resampler_set_output_stride(_resampler, 2); conv_size = _target_frame_size; // Assuming this hould be samples. int err = speex_resampler_process_int(_resampler, 0 /* mono */, output.get(), &in_size, conv_data, &conv_size); if (err != RESAMPLER_ERR_SUCCESS) { log_error(_("Failed to resample Speex frame.")); delete [] conv_data; continue; } // The returned size is the number of *mono* samples returned. conv_size *= 2; // Now, duplicate all the samples so we get a stereo sound. for (boost::uint32_t i = 0; i < conv_size; i += 2) { conv_data[i+1] = conv_data[i]; } // Our interface requires returning the audio size in bytes. conv_size *= sizeof(boost::int16_t); #else int outsize = 0; AudioResampler::convert_raw_data(&conv_data, &outsize, output.get(), _speex_framesize /* sample count*/, 2 /* sample size */, 16000, false /* stereo */, 44100 /* new rate */, true /* convert to stereo */); boost::uint32_t conv_size = outsize; #endif total_size += conv_size; decoded_frames.push_back(new DecodedFrame(conv_data, conv_size)); } outputSize = total_size; // We have to jump through hoops because decode() requires as much // data to be returned as possible. boost::uint8_t* rv = new boost::uint8_t[total_size]; boost::uint8_t* ptr = rv; for (std::vector<DecodedFrame*>::iterator it = decoded_frames.begin(), end = decoded_frames.end(); it != end; ++it) { DecodedFrame* frame = *it; memcpy(ptr, frame->data.get(), frame->size); ptr += frame->size; delete frame; } outputSize = total_size; return rv; }
static GstFlowReturn speex_dec_chain_parse_data (GstSpeexDec * dec, GstBuffer * buf, GstClockTime timestamp, GstClockTime duration) { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; guint size; guint8 *data; SpeexBits *bits; if (!dec->frame_duration) goto not_negotiated; if (timestamp != -1) { dec->segment.last_stop = timestamp; } else { timestamp = dec->segment.last_stop; } if (buf) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); /* send data to the bitstream */ speex_bits_read_from (&dec->bits, (char *) data, size); fpp = 0; bits = &dec->bits; GST_DEBUG_OBJECT (dec, "received buffer of size %u, fpp %d", size, fpp); } else { /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); fpp = dec->header->frames_per_packet; bits = NULL; } /* now decode each frame, catering for unknown number of them (e.g. rtp) */ for (i = 0; (!fpp || i < fpp) && (!bits || speex_bits_remaining (bits) > 0); i++) { GstBuffer *outbuf; gint16 *out_data; gint ret; GST_LOG_OBJECT (dec, "decoding frame %d/%d", i, fpp); res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (dec->srcpad), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } out_data = (gint16 *) GST_BUFFER_DATA (outbuf); ret = speex_decode_int (dec->state, bits, out_data); if (ret == -1) { /* uh? end of stream */ GST_WARNING_OBJECT (dec, "Unexpected end of stream found"); gst_buffer_unref (outbuf); outbuf = NULL; break; } else if (ret == -2) { GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?"); gst_buffer_unref (outbuf); outbuf = NULL; break; } if (bits && speex_bits_remaining (bits) < 0) { GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?"); gst_buffer_unref (outbuf); outbuf = NULL; break; } if (dec->header->nb_channels == 2) speex_decode_stereo_int (out_data, dec->frame_size, dec->stereo); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = dec->frame_duration; dec->segment.last_stop += dec->frame_duration; timestamp = dec->segment.last_stop; GST_LOG_OBJECT (dec, "pushing buffer with ts=%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (dec->frame_duration)); res = gst_pad_push (dec->srcpad, outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); break; } } return res; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("decoder not initialized")); return GST_FLOW_NOT_NEGOTIATED; } }
static GstFlowReturn gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf) { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; SpeexBits *bits; GstMapInfo map; if (!dec->frame_duration) goto not_negotiated; if (G_LIKELY (gst_buffer_get_size (buf))) { /* send data to the bitstream */ gst_buffer_map (buf, &map, GST_MAP_READ); speex_bits_read_from (&dec->bits, (gchar *) map.data, map.size); gst_buffer_unmap (buf, &map); fpp = dec->header->frames_per_packet; bits = &dec->bits; GST_DEBUG_OBJECT (dec, "received buffer of size %" G_GSIZE_FORMAT ", fpp %d, %d bits", map.size, fpp, speex_bits_remaining (bits)); } else { /* FIXME ? actually consider how much concealment is needed */ /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); fpp = dec->header->frames_per_packet; bits = NULL; } /* now decode each frame, catering for unknown number of them (e.g. rtp) */ for (i = 0; i < fpp; i++) { GstBuffer *outbuf; gboolean corrupted = FALSE; gint ret; GST_LOG_OBJECT (dec, "decoding frame %d/%d, %d bits remaining", i, fpp, bits ? speex_bits_remaining (bits) : -1); #if 0 res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (dec)), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } #endif /* FIXME, we can use a bufferpool because we have fixed size buffers. We * could also use an allocator */ outbuf = gst_buffer_new_allocate (NULL, dec->frame_size * dec->header->nb_channels * 2, NULL); gst_buffer_map (outbuf, &map, GST_MAP_WRITE); ret = speex_decode_int (dec->state, bits, (spx_int16_t *) map.data); if (ret == -1) { /* uh? end of stream */ GST_WARNING_OBJECT (dec, "Unexpected end of stream found"); corrupted = TRUE; } else if (ret == -2) { GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?"); corrupted = TRUE; } if (bits && speex_bits_remaining (bits) < 0) { GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?"); corrupted = TRUE; } if (dec->header->nb_channels == 2) speex_decode_stereo_int ((spx_int16_t *) map.data, dec->frame_size, dec->stereo); gst_buffer_unmap (outbuf, &map); if (!corrupted) { res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1); } else { res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); break; } } return res; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("decoder not initialized")); return GST_FLOW_NOT_NEGOTIATED; } }
int AudioStreamPlaybackSpeex::mix(int16_t *p_buffer, int p_frames) { //printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs); //printf("playing %i, paused %i\n", (int)playing, (int)paused); if (!active || !playing || !data.size()) return 0; /* if (read_ofs >= data.size()) { if (loops) { reload(); ++loop_count; } else { return; }; }; */ int todo = p_frames; if (todo < page_size) { return 0; }; int eos = 0; while (todo > page_size) { int ret = 0; while ((todo > page_size && packets_available && !eos) || (ret = ogg_sync_pageout(&oy, &og)) == 1) { if (!packets_available) { /*Add page to the bitstream*/ ogg_stream_pagein(&os, &og); page_granule = ogg_page_granulepos(&og); page_nb_packets = ogg_page_packets(&og); packet_no = 0; if (page_granule > 0 && frame_size) { skip_samples = page_nb_packets * frame_size * nframes - (page_granule - last_granule); if (ogg_page_eos(&og)) skip_samples = -skip_samples; /*else if (!ogg_page_bos(&og)) skip_samples = 0;*/ } else { skip_samples = 0; } last_granule = page_granule; packets_available = true; } /*Extract all available packets*/ while (todo > page_size && !eos) { if (ogg_stream_packetout(&os, &op) != 1) { packets_available = false; break; } packet_no++; /*End of stream condition*/ if (op.e_o_s) eos = 1; /*Copy Ogg packet to Speex bitstream*/ speex_bits_read_from(&bits, (char *)op.packet, op.bytes); for (int j = 0; j != nframes; j++) { int16_t *out = p_buffer; int ret; /*Decode frame*/ ret = speex_decode_int(st, &bits, out); /*for (i=0;i<frame_size*channels;i++) printf ("%d\n", (int)output[i]);*/ if (ret == -1) { printf("decode returned -1\n"); break; }; if (ret == -2) { OS::get_singleton()->printerr("Decoding error: corrupted stream?\n"); break; } if (speex_bits_remaining(&bits) < 0) { OS::get_singleton()->printerr("Decoding overflow: corrupted stream?\n"); break; } //if (channels==2) // speex_decode_stereo_int(output, frame_size, &stereo); /*Convert to short and save to output file*/ for (int i = 0; i < frame_size * stream_channels; i++) { out[i] = le_short(out[i]); } { int new_frame_size = frame_size; /*printf ("packet %d %d\n", packet_no, skip_samples);*/ if (packet_no == 1 && j == 0 && skip_samples > 0) { /*printf ("chopping first packet\n");*/ new_frame_size -= skip_samples; } if (packet_no == page_nb_packets && skip_samples < 0) { int packet_length = nframes * frame_size + skip_samples; new_frame_size = packet_length - j * frame_size; if (new_frame_size < 0) new_frame_size = 0; if (new_frame_size > frame_size) new_frame_size = frame_size; /*printf ("chopping end: %d %d %d\n", new_frame_size, packet_length, packet_no);*/ } p_buffer += new_frame_size * stream_channels; todo -= new_frame_size; } } }; }; //todo = get_todo(); //todo is still greater than page size, can write more if (todo > page_size || eos) { if (read_ofs < data.size()) { //char *buf; int nb_read = MIN(data.size() - read_ofs, READ_CHUNK); /*Get the ogg buffer for writing*/ char *ogg_dst = ogg_sync_buffer(&oy, nb_read); /*Read bitstream from input file*/ copymem(ogg_dst, &data[read_ofs], nb_read); read_ofs += nb_read; ogg_sync_wrote(&oy, nb_read); } else { if (loops) { reload(); ++loop_count; //break; } else { playing = false; unload(); break; }; } }; }; return p_frames - todo; };
int universal_speex_decode(void* handle, const void* pCodedData, unsigned cbCodedPacketSize, void* pAudioBuffer, unsigned cbBufferSize, unsigned *pcbDecodedSize, const struct RtpHeader* pRtpHeader) { SpeexBits bits; struct speex_codec_data_decoder *mpSpeexDec = (struct speex_codec_data_decoder *)handle; assert(handle != NULL); if (mpSpeexDec->mNumSamplesPerFrame > cbBufferSize) { return RPLG_INVALID_ARGUMENT; } /* Reset number of decoded samples */ *pcbDecodedSize = 0; /* Decode incoming packet if present. Do PLC if no packet. */ if (pCodedData) { /* Prepare data for Speex decoder */ speex_bits_set_bit_buffer(&bits,(char*)pCodedData, cbCodedPacketSize); /* Decode while there are something to decode and enough space * for decoded data. */ while (cbBufferSize >= mpSpeexDec->mNumSamplesPerFrame && (speex_bits_remaining(&bits) > 0)) { int res; /* Decode frame */ res = speex_decode_int(mpSpeexDec->mpDecoderState, &bits, ((spx_int16_t*)pAudioBuffer)+(*pcbDecodedSize)); if (res == 0) { /* Update number of decoded and available samples on success */ *pcbDecodedSize += mpSpeexDec->mNumSamplesPerFrame; cbBufferSize -= mpSpeexDec->mNumSamplesPerFrame; } else { /* If it's the end of the stream or corrupted stream just return */ break; } } } else { int res; /* Do PLC */ res = speex_decode_int(mpSpeexDec->mpDecoderState, NULL, ((spx_int16_t*)pAudioBuffer)+(*pcbDecodedSize)); if (res == 0) { /* Update number of decoded and available samples on success */ *pcbDecodedSize += mpSpeexDec->mNumSamplesPerFrame; } else { /* This mustn't happen for lost packet, but who knows... */ return RPLG_FAILED; } } return RPLG_SUCCESS; }
JNIEXPORT int JNICALL FUNCSPEEX(decodeRemaining)(JNIEnv* env, jobject obj) { return speex_bits_remaining(&dbits); }
UInt32 OggSpeexDecoder::ReadAudio(AudioBufferList *bufferList, UInt32 frameCount) { if(!IsOpen() || NULL == bufferList || bufferList->mNumberBuffers != mFormat.mChannelsPerFrame || 0 == frameCount) return 0; UInt32 framesRead = 0; // Reset output buffer data size for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i) bufferList->mBuffers[i].mDataByteSize = 0; for(;;) { UInt32 framesRemaining = frameCount - framesRead; UInt32 framesToSkip = static_cast<UInt32>(bufferList->mBuffers[0].mDataByteSize / sizeof(float)); UInt32 framesInBuffer = static_cast<UInt32>(mBufferList->mBuffers[0].mDataByteSize / sizeof(float)); UInt32 framesToCopy = std::min(framesInBuffer, framesRemaining); // Copy data from the buffer to output for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) { float *floatBuffer = static_cast<float *>(bufferList->mBuffers[i].mData); memcpy(floatBuffer + framesToSkip, mBufferList->mBuffers[i].mData, framesToCopy * sizeof(float)); bufferList->mBuffers[i].mDataByteSize += static_cast<UInt32>(framesToCopy * sizeof(float)); // Move remaining data in buffer to beginning if(framesToCopy != framesInBuffer) { floatBuffer = static_cast<float *>(mBufferList->mBuffers[i].mData); memmove(floatBuffer, floatBuffer + framesToCopy, (framesInBuffer - framesToCopy) * sizeof(float)); } mBufferList->mBuffers[i].mDataByteSize -= static_cast<UInt32>(framesToCopy * sizeof(float)); } framesRead += framesToCopy; // All requested frames were read if(framesRead == frameCount) break; // EOS reached if(mSpeexEOSReached) break; // Attempt to process the desired number of packets unsigned packetsDesired = 1; while(0 < packetsDesired && !mSpeexEOSReached) { // Process any packets in the current page while(0 < packetsDesired && !mSpeexEOSReached) { // Grab a packet from the streaming layer ogg_packet oggPacket; int result = ogg_stream_packetout(&mOggStreamState, &oggPacket); if(-1 == result) { LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding error: Ogg loss of streaming"); break; } // If result is 0, there is insufficient data to assemble a packet if(0 == result) break; // Otherwise, we got a valid packet for processing if(1 == result) { if(5 <= oggPacket.bytes && !memcmp(oggPacket.packet, "Speex", 5)) mSpeexSerialNumber = mOggStreamState.serialno; if(-1 == mSpeexSerialNumber || mOggStreamState.serialno != mSpeexSerialNumber) break; // Ignore the following: // - Speex comments in packet #2 // - Extra headers (optionally) in packets 3+ if(1 != mOggPacketCount && 1 + mExtraSpeexHeaderCount <= mOggPacketCount) { // Detect Speex EOS if(oggPacket.e_o_s && mOggStreamState.serialno == mSpeexSerialNumber) mSpeexEOSReached = true; // SPEEX_GET_FRAME_SIZE is in samples spx_int32_t speexFrameSize; speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize); float buffer [(2 == mFormat.mChannelsPerFrame) ? 2 * speexFrameSize : speexFrameSize]; // Copy the Ogg packet to the Speex bitstream speex_bits_read_from(&mSpeexBits, (char *)oggPacket.packet, static_cast<int>(oggPacket.bytes)); // Decode each frame in the Speex packet for(spx_int32_t i = 0; i < mSpeexFramesPerOggPacket; ++i) { result = speex_decode(mSpeexDecoder, &mSpeexBits, buffer); // -1 indicates EOS if(-1 == result) break; else if(-2 == result) { LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding error: possible corrupted stream"); break; } if(0 > speex_bits_remaining(&mSpeexBits)) { LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding overflow: possible corrupted stream"); break; } // Normalize the values float maxSampleValue = 1u << 15; vDSP_vsdiv(buffer, 1, &maxSampleValue, buffer, 1, speexFrameSize); // Copy the frames from the decoding buffer to the output buffer, skipping over any frames already decoded framesInBuffer = static_cast<UInt32>(mBufferList->mBuffers[0].mDataByteSize / sizeof(float)); memcpy(static_cast<float *>(mBufferList->mBuffers[0].mData) + framesInBuffer, buffer, speexFrameSize * sizeof(float)); mBufferList->mBuffers[0].mDataByteSize += static_cast<UInt32>(speexFrameSize * sizeof(float)); // Process stereo channel, if present if(2 == mFormat.mChannelsPerFrame) { speex_decode_stereo(buffer, speexFrameSize, mSpeexStereoState); vDSP_vsdiv(buffer + speexFrameSize, 1, &maxSampleValue, buffer + speexFrameSize, 1, speexFrameSize); memcpy(static_cast<float *>(mBufferList->mBuffers[1].mData) + framesInBuffer, buffer + speexFrameSize, speexFrameSize * sizeof(float)); mBufferList->mBuffers[1].mDataByteSize += static_cast<UInt32>(speexFrameSize * sizeof(float)); } // Packet processing finished --packetsDesired; } } ++mOggPacketCount; } } // Grab a new Ogg page for processing, if necessary if(!mSpeexEOSReached && 0 < packetsDesired) { while(1 != ogg_sync_pageout(&mOggSyncState, &mOggPage)) { // Get the ogg buffer for writing char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES); // Read bitstream from input file ssize_t bytesRead = GetInputSource()->Read(data, READ_SIZE_BYTES); if(-1 == bytesRead) { LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Unable to read from the input file"); break; } ogg_sync_wrote(&mOggSyncState, bytesRead); // No more data available from input file if(0 == bytesRead) break; } // Ensure all Ogg streams are read if(ogg_page_serialno(&mOggPage) != mOggStreamState.serialno) ogg_stream_reset_serialno(&mOggStreamState, ogg_page_serialno(&mOggPage)); // Get the resultant Ogg page int result = ogg_stream_pagein(&mOggStreamState, &mOggPage); if(0 != result) { LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Error reading Ogg page"); break; } } } } mCurrentFrame += framesRead; if(0 == framesRead && mSpeexEOSReached) mTotalFrames = mCurrentFrame; return framesRead; }
/* This function will iterate frames & submodes in the Speex bits. * Returns 0 if a frame found, otherwise returns -1. */ int speex_get_next_frame(SpeexBits *bits) { static const int inband_skip_table[NB_SUBMODES] = {1, 1, 4, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 }; static const int wb_skip_table[SB_SUBMODES] = {SB_SUBMODE_BITS+1, 36, 112, 192, 352, -1, -1, -1}; unsigned submode; unsigned nb_count = 0; while (speex_bits_remaining(bits) >= 5) { unsigned wb_count = 0; unsigned bit_ptr = bits->bitPtr; unsigned char_ptr = bits->charPtr; /* WB frame */ while ((speex_bits_remaining(bits) >= 4) && speex_bits_unpack_unsigned(bits, 1)) { int advance; submode = speex_bits_unpack_unsigned(bits, 3); advance = wb_skip_table[submode]; if (advance < 0) { TRACE__((THIS_FUNC, "Invalid mode encountered. " "The stream is corrupted.")); return -1; } TRACE__((THIS_FUNC, "WB layer skipped: %d bits", advance)); advance -= (SB_SUBMODE_BITS+1); speex_bits_advance(bits, advance); bit_ptr = bits->bitPtr; char_ptr = bits->charPtr; /* Consecutive subband frames may not exceed 2 frames */ if (++wb_count > 2) return -1; } /* End of bits, return the frame */ if (speex_bits_remaining(bits) < 4) { TRACE__((THIS_FUNC, "End of stream")); return 0; } /* Stop iteration, return the frame */ if (nb_count > 0) { bits->bitPtr = bit_ptr; bits->charPtr = char_ptr; return 0; } /* Get control bits */ submode = speex_bits_unpack_unsigned(bits, 4); TRACE__((THIS_FUNC, "Control bits: %d at %d", submode, bits->charPtr*8+bits->bitPtr)); if (submode == 15) { TRACE__((THIS_FUNC, "Found submode: terminator")); return -1; } else if (submode == 14) { /* in-band signal; next 4 bits contain signal id */ submode = speex_bits_unpack_unsigned(bits, 4); TRACE__((THIS_FUNC, "Found submode: in-band %d bits", inband_skip_table[submode])); speex_bits_advance(bits, inband_skip_table[submode]); } else if (submode == 13) { /* user in-band; next 5 bits contain msg len */ submode = speex_bits_unpack_unsigned(bits, 5); TRACE__((THIS_FUNC, "Found submode: user-band %d bytes", submode)); speex_bits_advance(bits, submode * 8); } else if (submode > 8) { TRACE__((THIS_FUNC, "Unknown sub-mode %d", submode)); return -1; } else { /* NB frame */ unsigned int advance = submode; speex_mode_query(&speex_nb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance); if (advance < 0) { TRACE__((THIS_FUNC, "Invalid mode encountered. " "The stream is corrupted.")); return -1; } TRACE__((THIS_FUNC, "Submode %d: %d bits", submode, advance)); advance -= (NB_SUBMODE_BITS+1); speex_bits_advance(bits, advance); ++nb_count; } } return 0; }
static int speex_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t* buf, int buf_size) { SpeexContext *s = avctx->priv_data; int ret, bits_remaining, used = 0, bits_remaining_before; av_log(avctx,AV_LOG_DEBUG,"speexdec: out: %p %p(%d), in: %p, %d\n", data, data_size, data_size?*data_size:0,buf,buf_size); if (data) { /* we'll save this info to log later */ bits_remaining_before = bits_remaining = speex_bits_remaining(&s->bits); *data_size = 0; /* We are not interpolating a frame */ if (buf) { if (bits_remaining > 0) { speex_bits_read_whole_bytes(&s->bits, (char*) buf, buf_size); } else { /*Copy buf to Speex bitstream*/ speex_bits_read_from(&s->bits, (char*) buf, buf_size); } } // end if we are not interpolating a frame ret = speex_decode_int(s->st, buf ? &s->bits : NULL, data); switch (ret) { case -2: av_log(avctx, AV_LOG_ERROR, "Error: corrupted speex stream\n"); speex_bits_reset(&s->bits); return -1; case -1: /* no frame has been decoded, return bytes used */ //av_log(avctx, AV_LOG_INFO, "Warning: no samples have been decoded (end of stream)\n"); speex_bits_rewind(&s->bits); return buf_size; default: if (buf) { /* Calculate how many bytes we've used */ bits_remaining = speex_bits_remaining(&s->bits); if (bits_remaining < 0) { //av_log(avctx, AV_LOG_DEBUG, "Warning: decoding overflow, need more data (%d used)\n", buf_size); speex_bits_rewind(&s->bits); return buf_size; } used = buf_size - (bits_remaining / 8); } else { av_log(avctx, AV_LOG_DEBUG, "Info: interpolating a lost frame\n"); } *data_size = avctx->frame_size * avctx->channels * sizeof(short); if (avctx->channels == 2) speex_decode_stereo_int(data, avctx->frame_size, &s->stereo); if (avctx->debug & FF_DEBUG_BITSTREAM) { int bitrate; speex_decoder_ctl(s->st, SPEEX_GET_BITRATE, &bitrate); av_log(avctx, AV_LOG_DEBUG, "Speex: decoder used: %d/%d bytes, output: %d bytes, bitrate: %d bps (remaining in stream: %.1f bytes after %d bits)\n", used, buf_size, *data_size, bitrate, (float) bits_remaining / 8, bits_remaining_before); } speex_bits_reset(&s->bits); break; } } else { speex_bits_reset(&s->bits); } return used; }
/* this is called for each file to process */ enum codec_status codec_run(void) { int error = CODEC_ERROR; SpeexBits bits; int eof = 0; spx_ogg_sync_state oy; spx_ogg_page og; spx_ogg_packet op; spx_ogg_stream_state os; spx_int64_t page_granule = 0; spx_int64_t cur_granule = 0; int enh_enabled = 1; int nframes = 2; int eos = 0; SpeexStereoState *stereo; int channels = -1; int samplerate = ci->id3->frequency; int extra_headers = 0; int stream_init = 0; /* rockbox: comment 'set but unused' variables int page_nb_packets; */ int frame_size; int packet_count = 0; int lookahead; int headerssize = 0; unsigned long strtoffset = ci->id3->offset; void *st = NULL; int j = 0; intptr_t param; memset(&bits, 0, sizeof(bits)); memset(&oy, 0, sizeof(oy)); /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ if (codec_init()) { goto exit; } ci->seek_buffer(0); ci->set_elapsed(0); stereo = speex_stereo_state_init(); spx_ogg_sync_init(&oy); spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); codec_set_replaygain(ci->id3); eof = 0; while (!eof) { enum codec_command_action action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) break; /*seek (seeks to the page before the position) */ if (action == CODEC_ACTION_SEEK_TIME) { if(samplerate!=0&&packet_count>1){ LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", ((spx_int64_t)param/1000) * (spx_int64_t)samplerate, page_granule, param, (page_granule/samplerate)*1000, samplerate); speex_seek_page_granule(((spx_int64_t)param/1000) * (spx_int64_t)samplerate, page_granule, &oy, headerssize); } ci->set_elapsed(param); ci->seek_complete(); } next_page: /*Get the ogg buffer for writing*/ if(get_more_data(&oy)<1){/*read error*/ goto done; } /* Loop for all complete pages we got (most likely only one) */ while (spx_ogg_sync_pageout(&oy, &og) == 1) { int packet_no; if (stream_init == 0) { spx_ogg_stream_init(&os, spx_ogg_page_serialno(&og)); stream_init = 1; } /* Add page to the bitstream */ spx_ogg_stream_pagein(&os, &og); page_granule = spx_ogg_page_granulepos(&og); /* page_nb_packets = spx_ogg_page_packets(&og); */ cur_granule = page_granule; /* Extract all available packets */ packet_no=0; while (!eos && spx_ogg_stream_packetout(&os, &op)==1){ /* If first packet, process as Speex header */ if (packet_count==0){ st = process_header(&op, enh_enabled, &frame_size, &samplerate, &nframes, &channels, stereo, &extra_headers); speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); if (!nframes) nframes=1; if (!st){ goto done; } ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); ci->configure(DSP_SET_SAMPLE_DEPTH, 16); if (channels == 2) { ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); } else if (channels == 1) { ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } /* Speex header in its own page, add the whole page headersize */ headerssize += og.header_len+og.body_len; } else if (packet_count<=1+extra_headers){ /* add packet to headersize */ headerssize += op.bytes; /* Ignore extra headers */ } else { if (packet_count <= 2+extra_headers) { if (strtoffset) { ci->seek_buffer(strtoffset); spx_ogg_sync_reset(&oy); packet_count++; goto next_page; } } packet_no++; if (op.e_o_s) /* End of stream condition */ eos=1; /* Set Speex bitstream to point to Ogg packet */ speex_bits_set_bit_buffer(&bits, (char *)op.packet, op.bytes); for (j = 0; j != nframes; j++){ int ret; /* Decode frame */ ret = speex_decode_int(st, &bits, output); if (ret == -1) break; if (ret == -2) break; if (speex_bits_remaining(&bits) < 0) break; if (channels == 2) speex_decode_stereo_int(output, frame_size, stereo); if (frame_size > 0) { spx_int16_t *frame_start = output + lookahead; if (channels == 2) frame_start += lookahead; ci->pcmbuf_insert(frame_start, NULL, frame_size - lookahead); lookahead = 0; /* 2 bytes/sample */ cur_granule += frame_size / 2; ci->set_offset((long) ci->curpos); ci->set_elapsed((samplerate == 0) ? 0 : cur_granule * 1000 / samplerate); } } } packet_count++; } } } error = CODEC_OK; done: /* Clean things up for the next track */ speex_bits_destroy(&bits); if (st) speex_decoder_destroy(st); if (stream_init) spx_ogg_stream_destroy(&os); spx_ogg_sync_destroy(&oy); exit: return error; }
static void dec_process(MSFilter *f){ DecState *s=(DecState*)f->data; mblk_t *im; mblk_t *om; int err=-2; SpeexBits bits; int bytes=s->frsz*2; bool_t bits_initd=FALSE; while((im=ms_queue_get(f->inputs[0]))!=NULL){ int rem_bits=(im->b_wptr-im->b_rptr)*8; if (!bits_initd) { speex_bits_init(&bits); bits_initd=TRUE; }else speex_bits_reset(&bits); speex_bits_read_from(&bits,(char*)im->b_rptr,im->b_wptr-im->b_rptr); /* support for multiple frame in one RTP packet */ do{ om=allocb(bytes,0); mblk_meta_copy(im, om); err=speex_decode_int(s->state,&bits,(int16_t*)om->b_wptr); om->b_wptr+=bytes; if (err==0){ ms_queue_put(f->outputs[0],om); if (s->sample_time==0) s->sample_time=f->ticker->time; s->sample_time+=20; if (s->plc_count>0){ // ms_warning("Did speex packet loss concealment during %i ms",s->plc_count*20); s->plc_count=0; } }else { if (err==-1) ms_warning("speex end of stream"); else if (err==-2) ms_warning("speex corrupted stream"); freemsg(om); } }while((rem_bits= speex_bits_remaining(&bits))>10); freemsg(im); } if (s->plc && s->sample_time!=0 && f->ticker->time>=s->sample_time){ /* we should output a frame but no packet were decoded thus do packet loss concealment*/ om=allocb(bytes,0); err=speex_decode_int(s->state,NULL,(int16_t*)om->b_wptr); om->b_wptr+=bytes; mblk_set_plc_flag(om, 1); ms_queue_put(f->outputs[0],om); s->sample_time+=20; s->plc_count++; if (s->plc_count>=plc_max){ s->sample_time=0; } } if (bits_initd) speex_bits_destroy(&bits); }