//***************************************************************************** // //! This function decodes a single frame of Speex encoded audio. //! //! \param pui8InBuffer is the buffer that contains the Speex encoded audio. //! \param ui32InSize is the number of valid bytes in the \e pui8InBuffer //! buffer. //! \param pui8OutBuffer is a pointer to the buffer to store decoded audio. //! \param ui32OutSize is the size of the buffer pointed to by the //! \e pui8OutBuffer pointer. //! //! This function will take a buffer of Speex encoded audio and decode it into //! raw PCM audio. The \e pui16InBuffer parameter should contain a single //! frame encoded Speex audio. The \e pui8OutBuffer will contain the decoded //! audio after returning from this function. //! //! \return This function returns the number of decoded bytes in the //! \e pui8OutBuffer buffer. // //***************************************************************************** int32_t SpeexDecode(uint8_t *pui8InBuffer, uint32_t ui32InSize, uint8_t *pui8OutBuffer, uint32_t ui32OutSize) { int32_t i32Bytes; // // Read in the bit stream to the Speex library. // speex_bits_read_from(&g_sSpeexDecoder.sBits, (char *)pui8InBuffer, ui32InSize); // // Decode one frame of data. // i32Bytes = speex_decode_int(g_sSpeexDecoder.pvState, &g_sSpeexDecoder.sBits, (int16_t *)pui8OutBuffer); return(i32Bytes); }
JNIEXPORT jint JNICALL Java_com_speex_Speex_decode(JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) { jbyte buffer[dec_frame_size]; jshort output_buffer[size]; jsize encoded_length = size; int nsamples = (size - 1) / dec_frame_size + 1; int i, offset = 0, tot_shorts = 0; if (!codec_open) return 0; speex_bits_reset(&dbits); // 把数据写入buffer for(i = 0; i < nsamples; i++){ if(offset + i * dec_frame_size + dec_frame_size > size) { env->GetByteArrayRegion(encoded, offset + i * dec_frame_size, size - (offset + i * dec_frame_size), buffer); speex_bits_read_from(&dbits, (char *) buffer, size - (offset + i * dec_frame_size)); } else { env->GetByteArrayRegion(encoded, offset + i * dec_frame_size, dec_frame_size, buffer); speex_bits_read_from(&dbits, (char *) buffer, dec_frame_size); } } // env->GetByteArrayRegion(encoded, 0, encoded_length, buffer); // // buffer数据写入dbits // speex_bits_read_fdrom(&dbits, (char *) buffer, encoded_length); // dbits数据写入output_buffer speex_decode_int(dec_state, &dbits, output_buffer); // TODO env->SetShortArrayRegion(lin, 0, encoded_length, output_buffer); /*env->SetShortArrayRegion(lin, 0, dec_frame_size, output_buffer);*/ /*return (jint) dec_frame_size;*/ /*return (jint) encoded_length;*/ return (jint) encoded_length; }
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; }
/* * Recover lost frame. */ static pj_status_t spx_codec_recover(pjmedia_codec *codec, unsigned output_buf_len, struct pjmedia_frame *output) { struct spx_private *spx; unsigned count; /* output_buf_len is unreferenced when building in Release mode */ PJ_UNUSED_ARG(output_buf_len); spx = (struct spx_private*) codec->codec_data; count = spx_factory.speex_param[spx->param_id].clock_rate * 20 / 1000; pj_assert(count <= output_buf_len/2); /* Recover packet loss */ speex_decode_int(spx->dec, NULL, (spx_int16_t*) output->buf); output->size = count * 2; return PJ_SUCCESS; }
static int codec_drv_control( ErlDrvData handle, unsigned int command, char *buf, int len, char **rbuf, int rlen) { codec_data* d = (codec_data*)handle; int i; int ret = 0; ErlDrvBinary *out; *rbuf = NULL; float frame[FRAME_SIZE]; char cbits[200]; switch(command) { case CMD_ENCODE: for (i=0; i < len / 2; i++){ frame[i] = (buf[2*i] & 0xff) | (buf[2*i+1] << 8); } speex_bits_reset(&d->bits); speex_encode(d->estate, frame, &d->bits); ret = speex_bits_write(&d->bits, cbits, 200); out = driver_alloc_binary(ret); memcpy(out->orig_bytes, cbits, ret); *rbuf = (char *) out; break; case CMD_DECODE: out = driver_alloc_binary(2*FRAME_SIZE); speex_bits_read_from(&d->bits, buf, len); speex_decode_int(d->dstate, &d->bits, (spx_int16_t *)out->orig_bytes); ret = 2*FRAME_SIZE; *rbuf = (char *) out; break; default: break; } return ret; }
JNIEXPORT jshortArray JNICALL Java_com_purplefrog_speexjni_SpeexDecoder_decode (JNIEnv *env, jclass cls, jint slot, jbyteArray input_frame_) { if (throwIfBadSlot(env, slot)) return; struct Slot * gob = slots.slots[slot]; int frame_length = (*env)->GetArrayLength(env, input_frame_); int frame_size; speex_decoder_ctl(gob->state, SPEEX_GET_FRAME_SIZE, &frame_size); // char* input_frame = (*env)->GetByteArrayElements(env, input_frame_, 0); speex_bits_read_from(&gob->bits, input_frame, frame_length); (*env)->ReleaseByteArrayElements(env, input_frame_, input_frame, 0); // jshortArray rval; rval = (*env)->NewShortArray(env, frame_size); if (rval==0) { throwOutOfMemoryError(env, "failed to allocate speex output frame"); return; } short* output_frame = (*env)->GetShortArrayElements(env, rval, 0); speex_decode_int(gob->state, &gob->bits, output_frame); (*env)->ReleaseShortArrayElements(env, rval, output_frame, 0); return rval; }
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; }
/* * Decode frame. */ static pj_status_t spx_codec_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct spx_private *spx; unsigned samples_per_frame; spx = (struct spx_private*) codec->codec_data; samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1, PJMEDIA_CODEC_EPCMTOOSHORT); if (input->type != PJMEDIA_FRAME_TYPE_AUDIO) { pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame); output->size = samples_per_frame << 1; output->timestamp.u64 = input->timestamp.u64; output->type = PJMEDIA_FRAME_TYPE_AUDIO; return PJ_SUCCESS; } /* Copy the data into the bit-stream struct */ speex_bits_read_from(&spx->dec_bits, (char*)input->buf, (int)input->size); /* Set Speex dec_bits pointer to the start bit of the frame */ speex_bits_advance(&spx->dec_bits, input->bit_info); /* Decode the data */ speex_decode_int(spx->dec, &spx->dec_bits, (spx_int16_t*)output->buf); output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->size = samples_per_frame << 1; output->timestamp.u64 = input->timestamp.u64; return PJ_SUCCESS; }
uint16 SpeexPlugin::decode(uint8 *payload, uint16 payload_size, int16 *pcm_buf, uint16 pcm_buf_size) throw(OperationNotPerfomedException) { int retval; int speex_frame_size; if (!decoder || !decoder->state) throw OperationNotPerfomedException("Decoder not initialized"); speex_decoder_ctl(decoder->state, SPEEX_GET_FRAME_SIZE, &speex_frame_size); if (pcm_buf_size < speex_frame_size) throw OperationNotPerfomedException("The buffer is not large enough"); // if (usingEchoCancellation && echoCapturedLast) { // uint32 samplesize = getSampleSize(); // spx_int16_t *input_buf = new spx_int16_t[samplesize / 2]; // // for (int i = 0; i < getSampleSize() / 2; i++) { // input_buf[i] = sample_buf[i]; // } // // speex_echo_capture(echocancellation, input_buf, sample_buf); // echoCapturedLast = false; // delete input_buf; // } speex_bits_read_from(&decoder->bits, reinterpret_cast<char *> (payload), payload_size); retval = speex_decode_int(decoder->state, &decoder->bits, pcm_buf); if (retval < 0) { throw OperationNotPerfomedException("Error on decode frame"); } return speex_frame_size; }
int main(int argc, char **argv) { // char *outFile; // FILE *fout; FILE *fout=NULL; int channels=1; int rate=16000; /*Holds the audio that will be written to file (16 bits per sample)*/ short out[FRAME_SIZE]; /*Speex handle samples as float, so we need an array of floats*/ short output[FRAME_SIZE]; char cbits[1500]; int nbBytes; /*Holds the state of the decoder*/ void *state; /*Holds bits so they can be read and written to by the Speex routines*/ SpeexBits bits; int i, tmp; fout = out_file_open("", rate, &channels); /*Create a new decoder state in narrowband mode*/ state = speex_decoder_init(&speex_wb_mode); /*Set the perceptual enhancement on*/ tmp=1; speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp); int frame_size; speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &frame_size); // outFile = argv[1]; // fout = fopen(outFile, "w"); /*Initialization of the structure that holds the bits*/ speex_bits_init(&bits); while (1) { /*Read the size encoded by sampleenc, this part will likely be different in your application*/ fread(&nbBytes, sizeof(int), 1, stdin); fprintf (stderr, "nbBytes: %d\n", nbBytes); if (feof(stdin)) break; /*Read the "packet" encoded by sampleenc*/ fread(cbits, 1, nbBytes, stdin); /*Copy the data into the bit-stream struct*/ speex_bits_read_from(&bits, cbits, nbBytes); int nFrames = 1; while(nFrames<= FRAMES_PER_RTP_PACKET){ /*Decode the data*/ speex_decode_int(state, &bits, output); // speex_decode(state, &bits, output); /*Copy from float to short (16 bits) for output*/ // for (i=0;i<frame_size;i++) // out[i]=output[i]; /*Write the decoded audio to file*/ fwrite(output, sizeof(short), FRAME_SIZE, fout); fflush(fout); nFrames++; } } if (fout != NULL) fclose(fout); /*Destroy the decoder state*/ speex_decoder_destroy(state); /*Destroy the bit-stream truct*/ speex_bits_destroy(&bits); // fclose(fout); return 0; }
void speex_decoder::decode(void const* data, size_t size, void* output) { speex_bits_read_from(&bits_, const_cast<char*>(static_cast<char const*>(data)), size); speex_decode_int(decoder_state_, &bits_, static_cast<spx_int16_t*>(output)); }
void *receive_audio(void *data) { struct connection_data conn = *((struct connection_data *)data); struct sockaddr_in other = conn.other; char buffer[512]; char compressed[SPEEX_FRAME_SIZE]; short audio_samples[SPEEX_FRAME_SIZE]; int sockfd = conn.udp_sock_tx; /* Descriptor for UDP socket */ /* receive data from socket, add to buffer */ int addrlen = sizeof other; int rc; /* variables for speex */ SpeexBits bits; void *state; /* For holding encoder state */ int tmp; int nbytes; int i; int ret; unsigned int rate = 8000; int size; short playback_samples[SAMPLES_PER_PERIOD]; int fd; int frame_size = 2; snd_pcm_t *handle; snd_pcm_hw_params_t *params; /* write many data at a time to device */ /* the value of 5512 comes from aplay, investigate * why it is so */ int buffer_size = SAMPLES_PER_PERIOD * sizeof(short); printf("rate is =%d \n", rate); dbg("Preparing audio playback"); ret = voip_init_pcm(&handle, ¶ms, &buffer_size, &rate, PLAYBACK); if (ret < 0) { fprintf(stderr, "Failed to prepare audio system\n"); goto rcv_audio_end; } printf("Pointer address to handle=%p \n", &handle); printf("Pointer to handle=%p \n", handle); printf("Pointer to params=%p \n", params); dbg("Preparing speex for de-compression"); state = speex_decoder_init(&speex_nb_mode); tmp = 1; speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp); speex_bits_init(&bits); while(1) { memset(audio_samples, 0, sizeof audio_samples); memset(compressed, 0, sizeof compressed); memset(buffer, 0, sizeof buffer); printf("Waiting for data\n"); if ((rc = recvfrom(sockfd, buffer, sizeof buffer, 0, (struct sockaddr *)&other, &addrlen)) < 0) { fprintf(stderr, "Unable to receive audio data: %s \n", strerror(errno)); goto rcv_sock_close; } printf("Received %d compressed bytes on UDP socket \n", rc); for (i = 0; i < 5; i++) { speex_bits_reset(&bits); /* each encoded speex frame takes 38 bytes */ memcpy(compressed, buffer + i * 38, 38); speex_bits_read_from(&bits, compressed, 38); /* Decode here */ speex_decode_int(state, &bits, audio_samples); ring_write(rbuff, (char *)audio_samples, sizeof audio_samples); } ret = ring_read(rbuff, (char *)audio_samples, buffer_size); if ( ret != buffer_size) { fprintf(stderr, "short read: read %d bytes \n", ret); } printf("Playing audio \n"); /* write frames in one period to device */ ret = voip_playback(handle, buffer_size / frame_size, audio_samples); } voip_end_pcm(handle); /* Destroy the encoder state */ speex_decoder_destroy(state); /* Destroy the bits-packing */ speex_bits_destroy(&bits); rcv_sock_close: close(sockfd); rcv_audio_end: pthread_exit(NULL); }
int main(int argc, char **argv) { char *outFile; char *inFile[1]; // FILE *fout; FILE *fin[1]; /*Holds the audio that will be written to file (16 bits per sample)*/ short out[FRAME_SIZE]; //int i; int result, length, tot_len; /*保存编码的状态*/ static void *stateDecode; /*保存字节因此他们可以被speex常规读写*/ static SpeexBits bitsDecode; //模式寄存器 static const SpeexMode *mode=NULL; //解码器的采样频率 static int speexFrequency = SAMPLERATE; //编码器的采样率 /*得到的缓冲区的大小*/ static spx_int32_t frame_size; /*得到的缓冲区的大小*/ //static int channe = CHANNELS; /*得到是立体声*/ //static SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; //单声到 立体声 /* 初始话IP端口结构*/ #if (SAMPLERATE == 8000) mode = speex_lib_get_mode (SPEEX_MODEID_NB); //宽带编码 #elif (SAMPLERATE == 16000) mode = speex_lib_get_mode (SPEEX_MODEID_WB); //宽带编码 #elif (SAMPLERATE == 32000) mode = speex_lib_get_mode (SPEEX_MODEID_UWB); //宽带编码 #endif //mode = speex_lib_get_mode (SPEEX_MODEID_UWB); //在宽带模式解码 stateDecode = speex_decoder_init(mode); //新建一个解码器 speex_encoder_ctl(stateDecode, SPEEX_GET_FRAME_SIZE, &frame_size); //得到缓冲区大小 speex_decoder_ctl(stateDecode, SPEEX_SET_SAMPLING_RATE, &speexFrequency); //设置解码器的采样频率 speex_bits_init(&bitsDecode); //初始解码器 char cbits[200]; int nbBytes; /*Holds the state of the decoder*/ //void *state; /*Holds bits so they can be read and written to by the Speex routines*/ //SpeexBits bits; int i, tmp; int rc; printf("%s: start\n", __func__); #if (SOUND_INTERFACE == SOUND_OSS) init_oss_play(); #elif (SOUND_INTERFACE == SOUND_ALSA) init_alsa_play(); #endif /*Create a new decoder state in narrowband mode*/ stateDecode = speex_decoder_init(&speex_uwb_mode); /*Set the perceptual enhancement on*/ tmp=1; speex_decoder_ctl(stateDecode, SPEEX_SET_ENH, &tmp); //printf("%s: 22222222\n", __func__); inFile[0] = argv[1]; //inFile[1] = argv[2]; // outFile = argv[1]; //fout = fopen(outFile, "w"); fin[0] = fopen(inFile[0], "r");//打开输入的spx文件 if(fin[0] ==NULL) { perror("打开文件错误"); exit(1); } //printf("%s: 3333333\n", __func__); /*Initialization of the structure that holds the bits*/ speex_bits_init(&bitsDecode); //printf("%s: 4444444\n", __func__); while (1) { //printf("%s: 55555\n", __func__); //printf("%s: 1111111\n", __func__); speex_bits_reset(&bitsDecode); /*Read the size encoded by sampleenc, this part will likely be different in your application*/ fread(&nbBytes, sizeof(int), 1, fin[0]); fprintf (stderr, "nbBytes: %d\n", nbBytes); if (feof(fin[0])) break; //printf("%s: 666\n", __func__); /*Read the "packet" encoded by sampleenc*/ fread(cbits, 1, nbBytes, fin[0]); /*Copy the data into the bit-stream struct*/ speex_bits_read_from(&bitsDecode, cbits, nbBytes); /*Decode the data*/ speex_decode_int(stateDecode, &bitsDecode, out); #if 0 /*Copy from float to short (16 bits) for output*/ for (i=0;i<FRAME_SIZE;i++) out[i]=output[i]; //printf("%s: 88888\n", __func__); /*Write the decoded audio to file*/ //fwrite(out, sizeof(short), FRAME_SIZE, fout); #endif #if (SOUND_INTERFACE == SOUND_OSS) rc = write(fdsoundplay, out, (SAMPLERATE/1000*READMSFORONCE)*sizeof(short)); if(rc != (SAMPLERATE/1000*READMSFORONCE)*sizeof(short)) { printf("写入数据长度与预期不符合\n"); } #elif (SOUND_INTERFACE == SOUND_ALSA) rc = snd_pcm_writei(handle, out, (SAMPLERATE/1000*READMSFORONCE)); //printf("%s: 99999\n", __func__); if (rc == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(rc)); rc = xrun_recovery(handle, rc); if (rc < 0) { printf("Write error: %s\n", snd_strerror(rc)); //return -1; } } else if (rc != (int)(SAMPLERATE/1000*READMSFORONCE)) { fprintf(stderr, "short write, write %d frames\n", rc); } #endif } printf("end\n"); /*Destroy the decoder state*/ speex_decoder_destroy(stateDecode); /*Destroy the bit-stream truct*/ speex_bits_destroy(&bitsDecode); fclose(fin[0]); return 0; }
int main(int argc, char **argv) { char *inFile, *outFile, *bitsFile; FILE *fin, *fout, *fbits=NULL; short in_short[FRAME_SIZE]; short out_short[FRAME_SIZE]; float sigpow,errpow,snr, seg_snr=0; int snr_frames = 0; char cbits[200]; int nbBits; int i; void *st; void *dec; SpeexBits bits; spx_int32_t tmp; int bitCount=0; spx_int32_t skip_group_delay; SpeexCallback callback; sigpow = 0; errpow = 0; st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_WB)); dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_WB)); callback.callback_id = SPEEX_INBAND_CHAR; callback.func = speex_std_char_handler; callback.data = stderr; speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); callback.callback_id = SPEEX_INBAND_MODE_REQUEST; callback.func = speex_std_mode_request_handler; callback.data = st; speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); tmp=1; speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); tmp=0; speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); tmp=8; speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); tmp=3; speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); /*tmp=3; speex_encoder_ctl(st, SPEEX_SET_HIGH_MODE, &tmp); tmp=6; speex_encoder_ctl(st, SPEEX_SET_LOW_MODE, &tmp); */ speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); skip_group_delay += tmp; if (argc != 4 && argc != 3) { fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); exit(1); } inFile = argv[1]; fin = fopen(inFile, "rb"); outFile = argv[2]; fout = fopen(outFile, "wb+"); if (argc==4) { bitsFile = argv[3]; fbits = fopen(bitsFile, "wb"); } speex_bits_init(&bits); while (!feof(fin)) { fread(in_short, sizeof(short), FRAME_SIZE, fin); if (feof(fin)) break; speex_bits_reset(&bits); speex_encode_int(st, in_short, &bits); nbBits = speex_bits_write(&bits, cbits, 200); bitCount+=bits.nbBits; if (argc==4) fwrite(cbits, 1, nbBits, fbits); speex_bits_rewind(&bits); speex_decode_int(dec, &bits, out_short); speex_bits_reset(&bits); fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); skip_group_delay = 0; } fprintf (stderr, "Total encoded size: %d bits\n", bitCount); speex_encoder_destroy(st); speex_decoder_destroy(dec); speex_bits_destroy(&bits); rewind(fin); rewind(fout); while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) && FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) { float s=0, e=0; for (i=0;i<FRAME_SIZE;++i) { s += (float)in_short[i] * in_short[i]; e += ((float)in_short[i]-out_short[i]) * ((float)in_short[i]-out_short[i]); } seg_snr += 10*log10((s+160)/(e+160)); sigpow += s; errpow += e; snr_frames++; } fclose(fin); fclose(fout); snr = 10 * log10( sigpow / errpow ); seg_snr /= snr_frames; fprintf(stderr,"SNR = %f\nsegmental SNR = %f\n",snr, seg_snr); #ifdef FIXED_DEBUG printf ("Total: %f MIPS\n", (float)(1e-6*50*spx_mips/snr_frames)); #endif return 1; }
int do_decode(int client, int server, esd_format_t format, int speed, char* ident) { /* Decoder specific variables */ void *dec_state; SpeexBits bits; const SpeexMode* mode = NULL; int frame_size, frame_size2; SpeexCallback callback; SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; unsigned int do_sync_seq; /* Configuration variables */ /* FIXME: Depend on NX setting and read from network */ int modeID = SPEEX_MODEID_UWB; /* Encoder initialisation */ speex_bits_init(&bits); mode = speex_lib_get_mode (modeID); dec_state=speex_decoder_init(mode); speex_decoder_ctl(dec_state, SPEEX_SET_SAMPLING_RATE, &speed); if (format & ESD_STEREO) { callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; callback.data = &stereo; speex_decoder_ctl(dec_state, SPEEX_SET_HANDLER, &callback); } speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &frame_size); frame_size2=frame_size*((format & ESD_STEREO)?2:1); /* Lower the latency a bit */ //do_sockopts(client, 200); do_sockopts(server, frame_size2 * (((format & ESD_BITS16)?16:8) / 8)); //esd_set_socket_buffers(server, format, speed, 44100); // /* Get do_sync_seq from encoder */ if (do_read_complete(client, &do_sync_seq, sizeof(do_sync_seq)) != sizeof(do_sync_seq)) goto out; /* Main decoding loop */ while (1) { unsigned int seqNr = 0; int nbBytes; char input[MAX_FRAME_BYTES+1]; short output[MAX_FRAME_SIZE+1]; if (do_read_complete(client, &seqNr, sizeof(seqNr)) != sizeof(seqNr)) break; #ifdef DEBUG fprintf(stderr, "SeqNr: %d\n", seqNr); #endif if (seqNr % do_sync_seq == 0) if (write(client, &seqNr, sizeof(seqNr)) != sizeof(seqNr)) break; if (do_read_complete(client, &nbBytes, sizeof(nbBytes)) != sizeof(nbBytes)) break; if (do_read_complete(client, input, nbBytes) != nbBytes) break; speex_bits_read_from(&bits, input, nbBytes); speex_decode_int(dec_state, &bits, output); if (format & ESD_STEREO) speex_decode_stereo_int(output, frame_size, &stereo); if (do_write_samples(server, output, frame_size2, ((format & ESD_BITS16)?16:8)) != frame_size2) break; } out: /* Decoder shutdown */ speex_bits_destroy(&bits); speex_decoder_destroy(dec_state); return 0; }
void RakVoice::OnVoiceData(Packet *packet) { bool objectExists; unsigned index; unsigned short packetMessageNumber, messagesSkipped; VoiceChannel *channel; char tempOutput[2048]; unsigned int i; // 1 byte for ID, 2 bytes(short) for message number static const int headerSize=sizeof(unsigned char) + sizeof(unsigned short); index = voiceChannels.GetIndexFromKey(packet->guid, &objectExists); if (objectExists) { SpeexBits speexBits; speex_bits_init(&speexBits); channel=voiceChannels[index]; memcpy(&packetMessageNumber, packet->data+1, sizeof(unsigned short)); // Intentional overflow messagesSkipped=packetMessageNumber-channel->incomingMessageNumber; if (messagesSkipped > ((unsigned short)-1)/2) { #ifdef PRINT_DEBUG_INFO printf("--- UNDERFLOW ---\n"); #endif // Underflow, just ignore it return; } #ifdef PRINT_DEBUG_INFO if (messagesSkipped>0) printf("%i messages skipped\n", messagesSkipped); #endif // Don't do more than 100 ms of messages skipped. Discard the rest. int maxSkip = (int)(100.0f / (float) sampleRate); for (i=0; i < (unsigned) messagesSkipped && i < (unsigned) maxSkip; i++) { speex_decode_int(channel->dec_state, 0, (spx_int16_t*)tempOutput); // Write to buffer a 'message skipped' interpolation WriteOutputToChannel(channel, tempOutput); } channel->incomingMessageNumber=packetMessageNumber+1; // Write to incomingBuffer the decoded data speex_bits_read_from(&speexBits, (char*)(packet->data+headerSize), packet->length-headerSize); speex_decode_int(channel->dec_state, &speexBits, (spx_int16_t*)tempOutput); #ifdef _DEBUG { /* printf("Out: "); if (channel->remoteIsShortSampleType) { short *blah = (short*) tempOutput; for (int p=0; p < 5; p++) { printf("%.i ", blah[p]); } } else { float *blah = (float*) tempOutput; for (int p=0; p < 5; p++) { printf("%.3f ", blah[p]); } } printf("\n"); */ } #endif // Write to buffer WriteOutputToChannel(channel, tempOutput); speex_bits_destroy(&speexBits); } }
void main() { char *outFile, *bitsFile; FILE *fout, *fbits=NULL; #ifndef DECODE_ONLY char *inFile; FILE *fin; #endif #if 0 char *dbgoutFile; FILE *fdbgout; #endif short out_short[FRAME_SIZE]; #ifndef DECODE_ONLY short in_short[FRAME_SIZE]; float sigpow,errpow,snr, seg_snr=0; int snr_frames = 0; int nbBits; int i; #endif char cbits[200]; void *st; void *dec; SpeexBits bits; int tmp; int bitCount=0; int skip_group_delay; SpeexCallback callback; #ifndef DECODE_ONLY sigpow = 0; errpow = 0; #endif #ifdef MANUAL_ALLOC spxGlobalHeapPtr = spxHeap; spxGlobalHeapEnd = spxHeap + sizeof(spxHeap); spxGlobalScratchPtr = spxScratch; spxGlobalScratchEnd = spxScratch + sizeof(spxScratch); #endif st = speex_encoder_init(&speex_nb_mode); #ifdef MANUAL_ALLOC spxGlobalScratchPtr = spxScratch; /* Reuse scratch for decoder */ #endif dec = speex_decoder_init(&speex_nb_mode); callback.callback_id = SPEEX_INBAND_CHAR; callback.func = speex_std_char_handler; callback.data = stderr; speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); callback.callback_id = SPEEX_INBAND_MODE_REQUEST; callback.func = speex_std_mode_request_handler; callback.data = st; speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); tmp=0; speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); tmp=0; speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); tmp=4; speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); tmp=1; speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); speex_mode_query(&speex_nb_mode, SPEEX_MODE_FRAME_SIZE, &tmp); fprintf (stderr, "frame size: %d\n", tmp); skip_group_delay = tmp / 2; #ifdef DECODE_ONLY bitsFile = "e:\\speextrunktest\\samples\\malebitsin54.dat"; fbits = fopen(bitsFile, "rb"); #else bitsFile = "e:\\speextrunktest\\samples\\malebits.dat"; fbits = fopen(bitsFile, "wb"); #endif inFile = "e:\\speextrunktest\\samples\\male.snd"; fin = fopen(inFile, "rb"); outFile = "e:\\speextrunktest\\samples\\maleout.snd"; fout = fopen(outFile, "wb+"); #if 0 dbgoutFile = "e:\\speextrunktest\\samples\\maledbgout.snd"; fdbgout = fopen(dbgoutFile, "wb+"); #endif speex_bits_init(&bits); #ifndef DECODE_ONLY while (!feof(fin)) { fread(in_short, sizeof(short), FRAME_SIZE, fin); #if 0 fwrite(in_short, sizeof(short), FRAME_SIZE, fdbgout); #endif if (feof(fin)) break; speex_bits_reset(&bits); speex_encode_int(st, in_short, &bits); nbBits = speex_bits_write(&bits, cbits, 200); bitCount+=bits.nbBits; fwrite(cbits, 1, nbBits, fbits); speex_bits_rewind(&bits); #else /* DECODE_ONLY */ while (!feof(fbits)) { fread(cbits, 1, 20, fbits); if (feof(fbits)) break; speex_bits_read_from(&bits, cbits, 20); bitCount+=160; #endif speex_decode_int(dec, &bits, out_short); speex_bits_reset(&bits); fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); skip_group_delay = 0; #if 1 fprintf (stderr, "Bits so far: %d \n", bitCount); #endif } fprintf (stderr, "Total encoded size: %d bits\n", bitCount); speex_encoder_destroy(st); speex_decoder_destroy(dec); #ifndef DECODE_ONLY rewind(fin); rewind(fout); while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) && FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) { float s=0, e=0; for (i=0;i<FRAME_SIZE;++i) { s += (float)in_short[i] * in_short[i]; e += ((float)in_short[i]-out_short[i]) * ((float)in_short[i]-out_short[i]); } seg_snr += 10*log10((s+160)/(e+160)); sigpow += s; errpow += e; snr_frames++; } fclose(fin); #endif fclose(fout); fclose(fbits); #ifndef DECODE_ONLY snr = 10 * log10( sigpow / errpow ); seg_snr /= snr_frames; fprintf(stderr,"SNR = %f\nsegmental SNR = %f\n",snr, seg_snr); #ifdef FIXED_DEBUG printf ("Total: %f MIPS\n", (float)(1e-6*50*spx_mips/snr_frames)); #endif #endif }
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; } }
//function decodes input buffer of length bytes, and stores output in out void decode(char* in, char* out, int bytes){ speex_bits_read_from(&dec_bits, in, bytes); speex_decode_int(dec_state, &dec_bits, (short*)out); }
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 main(int argc, char **argv) { if (argc != 3) { fprintf(stdout, "Usage:%s input.speex output.pcm\n", argv[0]); fprintf(stdout, "\t input.speex is audio data encoded by speex, output.pcm is audio raw data.\n"); return -1; } char *infile; char *outfile; FILE *fin; FILE *fout; /*Speex handle samples as float, so we need an array of floats*/ short output[FRAME_SIZE]; char cbits[200]; int nbBytes; /*Holds the state of the decoder*/ void *state; /*Holds bits so they can be read and written to by the Speex routines*/ SpeexBits bits; int tmp; int ret = 0; /*Create a new decoder state in narrowband mode*/ state = speex_decoder_init(&speex_wb_mode); /*Set the perceptual enhancement on*/ tmp = 1; speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp); infile = argv[1]; fin = fopen(infile, "r"); outfile = argv[2]; fout = fopen(outfile, "w+"); /*Initialization of the structure that holds the bits*/ speex_bits_init(&bits); while(1) { /*Read the size encoded by sampleenc, this part will likely be different in your application*/ fread(&nbBytes, sizeof(int), 1, fin); //fprintf(stderr, "nbBytes: %d\n", nbBytes); if (feof(fin)) break; /*Read the "packet" encoded by sampleenc*/ fread(cbits, 1, nbBytes, fin); /*Copy the data into the bit-stream struct*/ speex_bits_read_from(&bits, cbits, nbBytes); while (true) { /*Decode the data*/ ret = speex_decode_int(state, &bits, output); if (!ret) { /*Write the decoded audio to file*/ fwrite(output, sizeof(short), FRAME_SIZE, fout); } else { break; } } } /*Destroy the decoder state*/ speex_decoder_destroy(state); /*Destroy the bit-stream struct*/ speex_bits_destroy(&bits); fclose(fin); fclose(fout); return 0; }
/***************************************************************************** * 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; } }
int _v3_audio_decode( v3_handle v3h, /* payload input */ int16_t index, int16_t format, v3_coder *coder, const uint8_t *data, int32_t datalen, /* pcm output */ uint8_t *pcm, uint32_t *pcmlen, /* optional args */ uint32_t *rate, uint8_t *channels) { uint32_t maxpcmlen; int ret = V3_OK; _v3_enter(v3h, __func__); if (!coder || !data || !datalen || !pcm || !pcmlen || (pcmlen && !*pcmlen)) { _v3_leave(v3h, __func__); return V3_FAILURE; } maxpcmlen = *pcmlen; *pcmlen = 0; if (channels) { *channels = 1; } if (coder->state && (coder->index != index || coder->format != format)) { _v3_coder_destroy(v3h, coder); } switch (index) { #ifdef HAVE_GSM case 0: { const v3_codec *codec = v3_codec_get(index, format); int opt = 1; _v3_debug(v3h, V3_DBG_INFO, "decoding %i bytes of gsm to pcm @ %u", datalen, codec->rate); if (!coder->state) { if (!(coder->state = gsm_create())) { _v3_debug(v3h, V3_DBG_INFO, "failed to create gsm decoder"); ret = V3_FAILURE; break; } _v3_debug(v3h, V3_DBG_MEMORY, "initialized gsm decoder state"); gsm_option(coder->state, GSM_OPT_WAV49, &opt); coder->index = index; coder->format = format; coder->encoder = false; } while ((datalen -= 65) >= 0 && *pcmlen + codec->framesize <= maxpcmlen) { if (gsm_decode(coder->state, (void *)data, (void *)pcm) || gsm_decode(coder->state, (void *)data+33, (void *)pcm+(codec->framesize/2))) { _v3_debug(v3h, V3_DBG_INFO, "failed to decode gsm packet"); } data += 65; pcm += codec->framesize; *pcmlen += codec->framesize; } if (rate) { *rate = codec->rate; } } break; #endif #ifdef HAVE_OPUS case 1: case 2: { const v3_codec *codec = v3_codec_get(index, format); int tmp; _v3_debug(v3h, V3_DBG_INFO, "decoding %i bytes of opus to pcm @ %u", datalen, codec->rate); if (!coder->state) { if (!(coder->state = opus_decoder_create(codec->rate, 2, &tmp))) { _v3_debug(v3h, V3_DBG_INFO, "failed to create opus decoder: %s", opus_strerror(tmp)); ret = V3_FAILURE; break; } _v3_debug(v3h, V3_DBG_MEMORY, "initialized opus decoder state"); coder->index = index; coder->format = format; coder->encoder = false; } if ((tmp = opus_decode(coder->state, data, datalen, (void *)pcm, maxpcmlen / sizeof(int16_t), 0)) <= 0) { _v3_debug(v3h, V3_DBG_INFO, "failed to decode opus packet"); } *pcmlen += tmp * sizeof(int16_t) * 2; if (rate) { *rate = codec->rate; } if (channels) { *channels = 2; } } break; #endif #ifdef HAVE_SPEEX case 3: { const v3_codec *codec = v3_codec_get(index, format); uint16_t framesize; SpeexBits bits; _v3_debug(v3h, V3_DBG_INFO, "decoding %i bytes of speex to pcm @ %u", datalen, codec->rate); if (!coder->state) { switch (codec->rate) { case 8000: coder->state = speex_decoder_init(&speex_nb_mode); break; case 16000: coder->state = speex_decoder_init(&speex_wb_mode); break; case 32000: coder->state = speex_decoder_init(&speex_uwb_mode); break; } if (!coder->state) { _v3_debug(v3h, V3_DBG_INFO, "failed to create speex decoder"); ret = V3_FAILURE; break; } _v3_debug(v3h, V3_DBG_MEMORY, "initialized speex decoder state"); coder->index = index; coder->format = format; coder->encoder = false; } datalen -= sizeof(uint16_t) * 2; if (datalen < 0) { _v3_debug(v3h, V3_DBG_INFO, "received a malformed speex packet"); ret = V3_MALFORM; break; } data += sizeof(uint16_t) * 2; speex_bits_init(&bits); while (datalen) { framesize = ntohs(*(uint16_t *)data); datalen -= framesize + sizeof(uint16_t); if (!framesize || datalen < 0 || *pcmlen + codec->framesize > maxpcmlen) { _v3_debug(v3h, V3_DBG_INFO, "received a malformed speex packet"); ret = V3_MALFORM; break; } data += sizeof(uint16_t); speex_bits_read_from(&bits, (void *)data, framesize); speex_decode_int(coder->state, &bits, (void *)pcm); speex_bits_reset(&bits); data += framesize; pcm += codec->framesize; *pcmlen += codec->framesize; } speex_bits_destroy(&bits); if (rate) { *rate = codec->rate; } } break; #endif default: (void)rate, (void)maxpcmlen; _v3_debug(v3h, V3_DBG_INFO, "unsupported codec: index: %i | format: %i", index, format); ret = V3_FAILURE; break; } _v3_leave(v3h, __func__); return ret; }
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); }
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; } }
/* 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; }
/* ===================== CL_ParseVoip A VoIP message has been received from the server ===================== */ static void CL_ParseVoip( msg_t *msg ) { static short decoded[ 4096 ]; // !!! FIXME: don't hardcode. const int sender = MSG_ReadShort( msg ); const int generation = MSG_ReadByte( msg ); const int sequence = MSG_ReadLong( msg ); const int frames = MSG_ReadByte( msg ); const int packetsize = MSG_ReadShort( msg ); const int flags = MSG_ReadBits( msg, VOIP_FLAGCNT ); char encoded[ 1024 ]; int seqdiff = sequence - clc.voipIncomingSequence[ sender ]; int written = 0; int i; Com_DPrintf( "VoIP: %d-byte packet from client %d\n", packetsize, sender ); if ( sender < 0 ) { return; // short/invalid packet, bail. } else if ( generation < 0 ) { return; // short/invalid packet, bail. } else if ( sequence < 0 ) { return; // short/invalid packet, bail. } else if ( frames < 0 ) { return; // short/invalid packet, bail. } else if ( packetsize < 0 ) { return; // short/invalid packet, bail. } if ( packetsize > sizeof( encoded ) ) // overlarge packet? { int bytesleft = packetsize; while ( bytesleft ) { int br = bytesleft; if ( br > sizeof( encoded ) ) { br = sizeof( encoded ); } MSG_ReadData( msg, encoded, br ); bytesleft -= br; } return; // overlarge packet, bail. } if ( !clc.speexInitialized ) { MSG_ReadData( msg, encoded, packetsize ); // skip payload. return; // can't handle VoIP without libspeex! } else if ( sender >= MAX_CLIENTS ) { MSG_ReadData( msg, encoded, packetsize ); // skip payload. return; // bogus sender. } else if ( CL_ShouldIgnoreVoipSender( sender ) ) { MSG_ReadData( msg, encoded, packetsize ); // skip payload. return; // Channel is muted, bail. } // !!! FIXME: make sure data is narrowband? Does decoder handle this? Com_DPrintf( "VoIP: packet accepted!\n" ); // This is a new "generation" ... a new recording started, reset the bits. if ( generation != clc.voipIncomingGeneration[ sender ] ) { Com_DPrintf( "VoIP: new generation %d!\n", generation ); speex_bits_reset( &clc.speexDecoderBits[ sender ] ); clc.voipIncomingGeneration[ sender ] = generation; seqdiff = 0; } else if ( seqdiff < 0 ) // we're ahead of the sequence?! { // This shouldn't happen unless the packet is corrupted or something. Com_DPrintf( "VoIP: misordered sequence! %d < %d!\n", sequence, clc.voipIncomingSequence[ sender ] ); // reset the bits just in case. speex_bits_reset( &clc.speexDecoderBits[ sender ] ); seqdiff = 0; } else if ( seqdiff > 100 ) // more than 2 seconds of audio dropped? { // just start over. Com_DPrintf( "VoIP: Dropped way too many (%d) frames from client #%d\n", seqdiff, sender ); speex_bits_reset( &clc.speexDecoderBits[ sender ] ); seqdiff = 0; } if ( seqdiff != 0 ) { Com_DPrintf( "VoIP: Dropped %d frames from client #%d\n", seqdiff, sender ); // tell speex that we're missing frames... for ( i = 0; i < seqdiff; i++ ) { assert( ( written + clc.speexFrameSize ) * 2 < sizeof( decoded ) ); speex_decode_int( clc.speexDecoder[ sender ], NULL, decoded + written ); written += clc.speexFrameSize; } } for ( i = 0; i < frames; i++ ) { const int len = MSG_ReadByte( msg ); if ( len < 0 ) { Com_DPrintf( "VoIP: Short packet!\n" ); break; } MSG_ReadData( msg, encoded, len ); // shouldn't happen, but just in case... if ( ( written + clc.speexFrameSize ) * 2 > sizeof( decoded ) ) { Com_DPrintf( "VoIP: playback %d bytes, %d samples, %d frames\n", written * 2, written, i ); CL_PlayVoip( sender, written, ( const byte * ) decoded, flags ); written = 0; } speex_bits_read_from( &clc.speexDecoderBits[ sender ], encoded, len ); speex_decode_int( clc.speexDecoder[ sender ], &clc.speexDecoderBits[ sender ], decoded + written ); #if 0 static FILE *encio = NULL; if ( encio == NULL ) { encio = fopen( "voip-incoming-encoded.bin", "wb" ); } if ( encio != NULL ) { fwrite( encoded, len, 1, encio ); fflush( encio ); } static FILE *decio = NULL; if ( decio == NULL ) { decio = fopen( "voip-incoming-decoded.bin", "wb" ); } if ( decio != NULL ) { fwrite( decoded + written, clc.speexFrameSize * 2, 1, decio ); fflush( decio ); } #endif written += clc.speexFrameSize; } Com_DPrintf( "VoIP: playback %d bytes, %d samples, %d frames\n", written * 2, written, i ); if ( written > 0 ) { CL_PlayVoip( sender, written, ( const byte * ) decoded, flags ); } clc.voipIncomingSequence[ sender ] = sequence + frames; }
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; }
void SndSysSpeexSoundStream::AdvancePosition(size_t frame_delta) { if (m_bPaused || m_bPlaybackReadComplete || frame_delta==0) return; // Figure out how many bytes we need to fill for this advancement size_t needed_bytes = frame_delta * (m_RenderFormat.Bits/8) * m_RenderFormat.Channels; // If we need more space than is available in the whole cyclic buffer, then we already underbuffered, reduce to just 1 cycle full if ((size_t)needed_bytes > m_pCyclicBuffer->GetLength()) needed_bytes=(size_t)(m_pCyclicBuffer->GetLength() & 0x7FFFFFFF); // Free space in the cyclic buffer if necessary if ((size_t)needed_bytes > m_pCyclicBuffer->GetFreeBytes()) m_pCyclicBuffer->AdvanceStartValue(needed_bytes - (size_t)(m_pCyclicBuffer->GetFreeBytes() & 0x7FFFFFFF)); // Fill in leftover decoded data if needed if (m_PreparedDataBufferUsage > 0) needed_bytes-=CopyBufferBytes(needed_bytes); while (needed_bytes > 0) { if(newPage) { if(ogg_sync_pageout(&oy, &og) != 1) { // Mark as complete if not looping. if (!m_bLooping) { m_bPlaybackReadComplete = true; } // Reset stream. ResetPosition(); return; } if (!stream_init) { ogg_stream_init(&os, ogg_page_serialno(&og)); stream_init = true; } if (ogg_page_serialno(&og) != os.serialno) { ogg_stream_reset_serialno(&os, ogg_page_serialno(&og)); } ogg_stream_pagein(&os, &og); newPage = false; } if(ogg_stream_packetout(&os, &op) != 1) { newPage = true; continue; } // First packets contain header data. if(packet_count == 0) { if(header) { speex_header_free(header); } header = speex_packet_to_header((char*)op.packet, op.bytes); // const_cast for version compatibility. SpeexMode* mode = const_cast<SpeexMode*>(speex_lib_get_mode (header->mode)); state = speex_decoder_init(mode); speex_decoder_ctl(state, SPEEX_SET_SAMPLING_RATE, &header->rate); m_OutputFrequency=m_NewOutputFrequency; // Create the pcm sample converter if it's not yet created if (m_pPCMConverter == 0) m_pPCMConverter = new PCMSampleConverter ( m_RenderFormat.Channels, m_RenderFormat.Bits, m_RenderFormat.Freq); // Calculate the size of one source sample int source_sample_size = m_RenderFormat.Channels * m_RenderFormat.Bits; // Calculate the needed buffer size for this conversion int needed_buffer = (m_pPCMConverter->GetRequiredOutputBufferMultiple ( m_RenderFormat.Channels, m_RenderFormat.Bits, m_OutputFrequency) * (4096 + source_sample_size))/1024; // Allocate a new buffer. if (m_PreparedDataBufferSize < needed_buffer) { delete[] m_pPreparedDataBuffer; m_pPreparedDataBuffer = new char[needed_buffer]; m_PreparedDataBufferSize=needed_buffer; } } if(packet_count++ < uint(2+header->extra_headers)) { continue; } // Read and decode. speex_bits_read_from(&bits, (char*)op.packet, op.bytes); speex_decode_int(state, &bits, (int16*)m_pPreparedDataBuffer); // Frame size is in shorts. speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &m_PreparedDataBufferUsage); m_PreparedDataBufferUsage *= sizeof(short); if (m_PreparedDataBufferUsage > 0) needed_bytes -= CopyBufferBytes (needed_bytes); } }