static void resample_process_ms2(MSFilter *obj) { ResampleData *dt=(ResampleData*)obj->data; mblk_t *m; if (dt->output_rate==dt->input_rate) { while((m=ms_queue_get(obj->inputs[0]))!=NULL) { ms_queue_put(obj->outputs[0],m); } return; } ms_filter_lock(obj); if (dt->handle!=NULL) { unsigned int inrate=0, outrate=0; speex_resampler_get_rate(dt->handle,&inrate,&outrate); if (inrate!=dt->input_rate || outrate!=dt->output_rate) { speex_resampler_destroy(dt->handle); dt->handle=0; } } if (dt->handle==NULL) { int err=0; dt->handle=speex_resampler_init(dt->nchannels, dt->input_rate, dt->output_rate, SPEEX_RESAMPLER_QUALITY_VOIP, &err); } while((m=ms_queue_get(obj->inputs[0]))!=NULL) { unsigned int inlen=(m->b_wptr-m->b_rptr)/(2*dt->nchannels); unsigned int outlen=((inlen*dt->output_rate)/dt->input_rate)+1; unsigned int inlen_orig=inlen; mblk_t *om=allocb(outlen*2*dt->nchannels,0); if (dt->nchannels==1) { speex_resampler_process_int(dt->handle, 0, (int16_t*)m->b_rptr, &inlen, (int16_t*)om->b_wptr, &outlen); } else { speex_resampler_process_interleaved_int(dt->handle, (int16_t*)m->b_rptr, &inlen, (int16_t*)om->b_wptr, &outlen); } if (inlen_orig!=inlen) { ms_error("Bug in resampler ! only %u samples consumed instead of %u, out=%u", inlen,inlen_orig,outlen); } om->b_wptr+=outlen*2*dt->nchannels; mblk_set_timestamp_info(om,dt->ts); dt->ts+=outlen; ms_queue_put(obj->outputs[0],om); freemsg(m); } ms_filter_unlock(obj); }
static void downsample_audio(Filter_Audio *f_a, int16_t *out_l, int16_t *out_h, const int16_t *in, uint32_t in_length) { int16_t temp[320]; uint32_t out_len = 320; if (f_a->fs != 32000) { speex_resampler_process_int(f_a->downsampler, 0, in, &in_length, temp, &out_len); WebRtcSpl_AnalysisQMF(temp, out_len, out_l, out_h, f_a->split_filter_state_1, f_a->split_filter_state_2); } else { WebRtcSpl_AnalysisQMF(in, out_len, out_l, out_h, f_a->split_filter_state_1, f_a->split_filter_state_2); } }
static void upsample_audio(Filter_Audio *f_a, int16_t *out, uint32_t out_len, const int16_t *in_l, const int16_t *in_h, uint32_t in_length) { int16_t temp[320]; if (f_a->fs != 32000) { WebRtcSpl_SynthesisQMF(in_l, in_h, in_length, temp, f_a->split_filter_state_3, f_a->split_filter_state_4); in_length *= 2; speex_resampler_process_int(f_a->upsampler, 0, temp, &in_length, out, &out_len); } else { WebRtcSpl_SynthesisQMF(in_l, in_h, in_length, out, f_a->split_filter_state_3, f_a->split_filter_state_4); } }
template <> int SpeexResamplerProcess<int16_t>(SpeexResamplerState* aResampler, uint32_t aChannel, const int16_t* aInput, uint32_t* aIn, float* aOutput, uint32_t* aOut) { NS_ASSERTION(*aOut <= SPEEX_RESAMPLER_PROCESS_MAX_OUTPUT, "Bad aOut"); int16_t tmp[SPEEX_RESAMPLER_PROCESS_MAX_OUTPUT]; int result = speex_resampler_process_int(aResampler, aChannel, aInput, aIn, tmp, aOut); if (result == RESAMPLER_ERR_SUCCESS) { for (uint32_t i = 0; i < *aOut; ++i) { aOutput[i] = AudioSampleToFloat(tmp[i]); } } return result; }
void resample(SpeexResamplerState * resampler, int16_t * buffer, size_t & filled, std::vector<int16_t> & out) { uint32_t inputRate, outputRate; speex_resampler_get_rate(resampler, &inputRate, &outputRate); uint32_t inlen = filled; size_t oldSize = out.size(); out.resize(oldSize + (static_cast<int64_t>(inlen) * outputRate / inputRate) + 1); out.resize(out.capacity()); uint32_t outlen = out.size() - oldSize; speex_resampler_process_int(resampler, 0, buffer, &inlen, &out[oldSize], &outlen); out.resize(oldSize + outlen); // out.insert(out.end(), buffer, buffer + inlen); memmove(buffer, buffer + inlen, (filled - inlen) * 2); filled -= inlen; }
bool ResamplePCM(uint32 NumChannels, const TArray<uint8>& InBuffer, uint32 InSampleRate, TArray<uint8>& OutBuffer, uint32 OutSampleRate) const { // Initialize resampler to convert to desired rate for Opus int32 err = 0; SpeexResamplerState* resampler = speex_resampler_init(NumChannels, InSampleRate, OutSampleRate, SPEEX_RESAMPLER_QUALITY_DESKTOP, &err); if (err != RESAMPLER_ERR_SUCCESS) { speex_resampler_destroy(resampler); return false; } // Calculate extra space required for sample rate const uint32 SampleStride = SAMPLE_SIZE * NumChannels; const float Duration = (float)InBuffer.Num() / (InSampleRate * SampleStride); const int32 SafeCopySize = (Duration + 1) * OutSampleRate * SampleStride; OutBuffer.Empty(SafeCopySize); OutBuffer.AddUninitialized(SafeCopySize); uint32 InSamples = InBuffer.Num() / SampleStride; uint32 OutSamples = OutBuffer.Num() / SampleStride; // Do resampling and check results if (NumChannels == 1) { err = speex_resampler_process_int(resampler, 0, (const short*)(InBuffer.GetData()), &InSamples, (short*)(OutBuffer.GetData()), &OutSamples); } else { err = speex_resampler_process_interleaved_int(resampler, (const short*)(InBuffer.GetData()), &InSamples, (short*)(OutBuffer.GetData()), &OutSamples); } speex_resampler_destroy(resampler); if (err != RESAMPLER_ERR_SUCCESS) { return false; } // reduce the size of Out Buffer if more space than necessary was allocated const int32 WrittenBytes = (int32)(OutSamples * SampleStride); if (WrittenBytes < OutBuffer.Num()) { OutBuffer.SetNum(WrittenBytes, true); } return true; }
int WebAudioUtils::SpeexResamplerProcess(SpeexResamplerState* aResampler, uint32_t aChannel, const int16_t* aIn, uint32_t* aInLen, float* aOut, uint32_t* aOutLen) { nsAutoTArray<AudioDataValue, WEBAUDIO_BLOCK_SIZE*4> tmp; #ifdef MOZ_SAMPLE_TYPE_S16 tmp.SetLength(*aOutLen); int result = speex_resampler_process_int(aResampler, aChannel, aIn, aInLen, tmp.Elements(), aOutLen); ConvertAudioSamples(tmp.Elements(), aOut, *aOutLen); return result; #else tmp.SetLength(*aInLen); ConvertAudioSamples(aIn, tmp.Elements(), *aInLen); int result = speex_resampler_process_float(aResampler, aChannel, tmp.Elements(), aInLen, aOut, aOutLen); return result; #endif }
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples ) { if ( resampler != (rl_resampler_t*)&passthrough ) { spx_uint32_t in_len = in_samples; spx_uint32_t out_len = out_samples; int error = speex_resampler_process_int( (SpeexResamplerState*)resampler, 0, in_buffer, &in_len, out_buffer, &out_len ); return error == RESAMPLER_ERR_SUCCESS ? out_len : 0; } else { if ( in_samples > out_samples ) { in_samples = out_samples; } memcpy( out_buffer, in_buffer, in_samples * sizeof( int16_t ) ); return in_samples; } }
JNIEXPORT jint JNICALL Native_NATIVE(speex_1resampler_1process_1int) (JNIEnv *env, jclass that, jlong arg0, jint arg1, jshortArray arg2, jintArray arg3, jshortArray arg4, jintArray arg5) { jshort *lparg2=NULL; jint *lparg3=NULL; jshort *lparg4=NULL; jint *lparg5=NULL; jint rc = 0; Native_NATIVE_ENTER(env, that, Native_speex_1resampler_1process_1int_FUNC); if (arg2) if ((lparg2 = (*env)->GetShortArrayElements(env, arg2, NULL)) == NULL) goto fail; if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail; if (arg4) if ((lparg4 = (*env)->GetShortArrayElements(env, arg4, NULL)) == NULL) goto fail; if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail; rc = speex_resampler_process_int((SpeexResamplerState *)(intptr_t)arg0, arg1, lparg2, lparg3, lparg4, lparg5); fail: if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0); if (arg4 && lparg4) (*env)->ReleaseShortArrayElements(env, arg4, lparg4, 0); if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0); if (arg2 && lparg2) (*env)->ReleaseShortArrayElements(env, arg2, lparg2, JNI_ABORT); Native_NATIVE_EXIT(env, that, Native_speex_1resampler_1process_1int_FUNC); return rc; }
static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) { SpeexResamplerState *resamp_pvt = pvt->pvt; unsigned int out_samples = OUTBUF_SAMPLES - pvt->samples; unsigned int in_samples; if (!f->datalen) { return -1; } in_samples = f->datalen / 2; speex_resampler_process_int(resamp_pvt, 0, f->data.ptr, &in_samples, pvt->outbuf.i16 + pvt->samples, &out_samples); pvt->samples += out_samples; pvt->datalen += out_samples * 2; return 0; }
int resampler_resample_from_input(struct resampler_itfe *resampler, int16_t *in, size_t *inFrameCount, int16_t *out, size_t *outFrameCount) { struct resampler *rsmp = (struct resampler *)resampler; if (rsmp == NULL || in == NULL || inFrameCount == NULL || out == NULL || outFrameCount == NULL) { return -EINVAL; } if (rsmp->provider != NULL) { *outFrameCount = 0; return -ENOSYS; } if (rsmp->channel_count == 1) { speex_resampler_process_int(rsmp->speex_resampler, 0, in, (spx_uint32_t *)inFrameCount, out, (spx_uint32_t *)outFrameCount); } else { speex_resampler_process_interleaved_int(rsmp->speex_resampler, in, (spx_uint32_t *)inFrameCount, out, (spx_uint32_t *)outFrameCount); } ALOGV("resampler_resample_from_input() DONE in %zu out %zu", *inFrameCount, *outFrameCount); return 0; }
static void downsample_audio_echo_in(Filter_Audio *f_a, int16_t *out, const int16_t *in) { uint32_t inlen = f_a->fs / 100; uint32_t outlen = inlen; speex_resampler_process_int(f_a->downsampler_echo, 0, in, &inlen, out, &outlen); }
JNIEXPORT jint JNICALL Java_com_zebra_emc_voip_audiotest_Speex_resample (JNIEnv * env, jclass obj, jstring path_in, jstring path_out, jint channels, jint sample_rate_in, jint sample_rate_out, jint quality) { // size in samples uint32_t in_size_in_sample; // size in samples uint32_t out_size_in_sample; // size in bytes (assumption: 2bytes/sample) uint32_t in_size; // size in bytes (assumption: 2bytes/sample) uint32_t out_size; short *in = NULL; short *out = NULL; FILE *fin = NULL; FILE *fout = NULL; SpeexResamplerState *st = NULL; if((channels != 1) && (channels !=2)) return SPEEX_ERROR; const char *native_path = (*env)->GetStringUTFChars(env, path_in, 0); fin = fopen(native_path, "rb"); (*env)->ReleaseStringUTFChars(env, path_in, native_path); if(NULL == fin) return SPEEX_ERROR; native_path = (*env)->GetStringUTFChars(env, path_out, 0); fout = fopen(native_path, "w+b"); (*env)->ReleaseStringUTFChars(env, path_out, native_path); if(NULL == fout) { fclose(fin); return SPEEX_ERROR; } if(NULL == (st = speex_resampler_init(channels, sample_rate_in, sample_rate_out, SPEEX_RESAMPLER_QUALITY_DEFAULT, NULL))) return SPEEX_ERROR; in_size_in_sample = ((sample_rate_in * TIMEDURATION) / 1000) << (channels == 2 ? 1 : 0); in_size = in_size_in_sample * sizeof(short); out_size_in_sample = ((sample_rate_out * TIMEDURATION) / 1000) << (channels == 2 ? 1 : 0); out_size = out_size_in_sample * sizeof(short); in = malloc(in_size * sizeof(short)); out = malloc(out_size * sizeof(short)); uint32_t rd_len; int end_of_file = 0; int ret = SPEEX_SUCCESS; while (!end_of_file) { rd_len = fread(in, sizeof(short), in_size_in_sample, fin); if (rd_len < in_size_in_sample) { if(!feof(fin)) { ret = SPEEX_ERROR; break; } // the end of the file is reached else end_of_file = 1; } if(RESAMPLER_ERR_SUCCESS != speex_resampler_process_int(st, 0, in, &in_size_in_sample, out, &out_size_in_sample)) { ret = SPEEX_ERROR; break; } fwrite(out, sizeof(short), out_size_in_sample, fout); } speex_resampler_destroy(st); free(in); free(out); fclose(fin); fclose(fout); return ret; }
// outputs a number of frames less or equal to *outFrameCount and updates *outFrameCount // with the actual number of frames produced. int resampler_resample_from_provider(struct resampler_itfe *resampler, int16_t *out, size_t *outFrameCount) { struct resampler *rsmp = (struct resampler *)resampler; if (rsmp == NULL || out == NULL || outFrameCount == NULL) { return -EINVAL; } if (rsmp->provider == NULL) { *outFrameCount = 0; return -ENOSYS; } size_t framesRq = *outFrameCount; // update and cache the number of frames needed at the input sampling rate to produce // the number of frames requested at the output sampling rate if (framesRq != rsmp->frames_rq) { rsmp->frames_needed = (framesRq * rsmp->in_sample_rate) / rsmp->out_sample_rate + 1; rsmp->frames_rq = framesRq; } size_t framesWr = 0; spx_uint32_t inFrames = 0; while (framesWr < framesRq) { if (rsmp->frames_in < rsmp->frames_needed) { // make sure that the number of frames present in rsmp->in_buf (rsmp->frames_in) is at // least the number of frames needed to produce the number of frames requested at // the output sampling rate if (rsmp->in_buf_size < rsmp->frames_needed) { rsmp->in_buf_size = rsmp->frames_needed; rsmp->in_buf = (int16_t *)realloc(rsmp->in_buf, rsmp->in_buf_size * rsmp->channel_count * sizeof(int16_t)); } struct resampler_buffer buf; buf.frame_count = rsmp->frames_needed - rsmp->frames_in; rsmp->provider->get_next_buffer(rsmp->provider, &buf); if (buf.raw == NULL) { break; } memcpy(rsmp->in_buf + rsmp->frames_in * rsmp->channel_count, buf.raw, buf.frame_count * rsmp->channel_count * sizeof(int16_t)); rsmp->frames_in += buf.frame_count; rsmp->provider->release_buffer(rsmp->provider, &buf); } spx_uint32_t outFrames = framesRq - framesWr; inFrames = rsmp->frames_in; if (rsmp->channel_count == 1) { speex_resampler_process_int(rsmp->speex_resampler, 0, rsmp->in_buf, &inFrames, out + framesWr, &outFrames); } else { speex_resampler_process_interleaved_int(rsmp->speex_resampler, rsmp->in_buf, &inFrames, out + framesWr * rsmp->channel_count, &outFrames); } framesWr += outFrames; rsmp->frames_in -= inFrames; ALOGW_IF((framesWr != framesRq) && (rsmp->frames_in != 0), "ReSampler::resample() remaining %zu frames in and %zu frames out", rsmp->frames_in, (framesRq - framesWr)); } if (rsmp->frames_in) { memmove(rsmp->in_buf, rsmp->in_buf + inFrames * rsmp->channel_count, rsmp->frames_in * rsmp->channel_count * sizeof(int16_t)); } *outFrameCount = framesWr; return 0; }
void RtpAudioStream::decode() { if (rtp_packets_.size() < 1) return; // gtk/rtp_player.c:decode_rtp_stream // XXX This is more messy than it should be. gsize resample_buff_len = 0x1000; SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len); spx_uint32_t cur_in_rate = 0, visual_out_rate = 0; char *write_buff = NULL; qint64 write_bytes = 0; unsigned channels = 0; unsigned sample_rate = 0; int last_sequence = 0; double rtp_time_prev = 0.0; double arrive_time_prev = 0.0; double pack_period = 0.0; double start_time = 0.0; double start_rtp_time = 0.0; guint32 start_timestamp = 0; size_t decoded_bytes_prev = 0; for (int cur_packet = 0; cur_packet < rtp_packets_.size(); cur_packet++) { SAMPLE *decode_buff = NULL; // XXX The GTK+ UI updates a progress bar here. rtp_packet_t *rtp_packet = rtp_packets_[cur_packet]; stop_rel_time_ = start_rel_time_ + rtp_packet->arrive_offset; speex_resampler_get_rate(visual_resampler_, &cur_in_rate, &visual_out_rate); QString payload_name; if (rtp_packet->info->info_payload_type_str) { payload_name = rtp_packet->info->info_payload_type_str; } else { payload_name = try_val_to_str_ext(rtp_packet->info->info_payload_type, &rtp_payload_type_short_vals_ext); } if (!payload_name.isEmpty()) { payload_names_ << payload_name; } if (cur_packet < 1) { // First packet start_timestamp = rtp_packet->info->info_timestamp; start_rtp_time = 0; rtp_time_prev = 0; last_sequence = rtp_packet->info->info_seq_num - 1; } size_t decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate); if (decoded_bytes == 0 || sample_rate == 0) { // We didn't decode anything. Clean up and prep for the next packet. last_sequence = rtp_packet->info->info_seq_num; g_free(decode_buff); continue; } if (audio_out_rate_ == 0) { // First non-zero wins audio_out_rate_ = sample_rate; RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_); // Prepend silence to match our sibling streams. tempfile_->seek(0); int prepend_samples = (start_rel_time_ - global_start_rel_time_) * audio_out_rate_; if (prepend_samples > 0) { writeSilence(prepend_samples); } } if (rtp_packet->info->info_seq_num != last_sequence+1) { out_of_seq_timestamps_.append(stop_rel_time_); } last_sequence = rtp_packet->info->info_seq_num; double rtp_time = (double)(rtp_packet->info->info_timestamp-start_timestamp)/sample_rate - start_rtp_time; double arrive_time; if (timing_mode_ == RtpTimestamp) { arrive_time = rtp_time; } else { arrive_time = rtp_packet->arrive_offset - start_time; } double diff = qAbs(arrive_time - rtp_time); if (diff*1000 > jitter_buffer_size_ && timing_mode_ != Uninterrupted) { // rtp_player.c:628 jitter_drop_timestamps_.append(stop_rel_time_); RTP_STREAM_DEBUG("Packet drop by jitter buffer exceeded %f > %d", diff*1000, jitter_buffer_size_); /* if there was a silence period (more than two packetization period) resync the source */ if ((rtp_time - rtp_time_prev) > pack_period*2) { int silence_samples; RTP_STREAM_DEBUG("Resync..."); silence_samples = (int)((arrive_time - arrive_time_prev)*sample_rate - decoded_bytes_prev / sample_bytes_); /* Fix for bug 4119/5902: don't insert too many silence frames. * XXX - is there a better thing to do here? */ silence_samples = qMin(silence_samples, max_silence_samples_); writeSilence(silence_samples); silence_timestamps_.append(stop_rel_time_); decoded_bytes_prev = 0; /* defined start_timestmp to avoid overflow in timestamp. TODO: handle the timestamp correctly */ /* XXX: if timestamps (RTP) are missing/ignored try use packet arrive time only (see also "rtp_time") */ start_timestamp = rtp_packet->info->info_timestamp; start_rtp_time = 0; start_time = rtp_packet->arrive_offset; rtp_time_prev = 0; } } else { // rtp_player.c:664 /* Add silence if it is necessary */ int silence_samples; if (timing_mode_ == Uninterrupted) { silence_samples = 0; } else { silence_samples = (int)((rtp_time - rtp_time_prev)*sample_rate - decoded_bytes_prev / sample_bytes_); } if (silence_samples != 0) { wrong_timestamp_timestamps_.append(stop_rel_time_); } if (silence_samples > 0) { /* Fix for bug 4119/5902: don't insert too many silence frames. * XXX - is there a better thing to do here? */ silence_samples = qMin(silence_samples, max_silence_samples_); writeSilence(silence_samples); silence_timestamps_.append(stop_rel_time_); } // XXX rtp_player.c:696 adds audio here. rtp_time_prev = rtp_time; pack_period = (double) decoded_bytes / sample_bytes_ / sample_rate; decoded_bytes_prev = decoded_bytes; arrive_time_prev = arrive_time; } // Write samples to our file. write_buff = (char *) decode_buff; write_bytes = decoded_bytes; if (audio_out_rate_ != sample_rate) { // Resample the audio to match our previous output rate. if (!audio_resampler_) { audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL); speex_resampler_skip_zeros(audio_resampler_); RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_); } else { spx_uint32_t audio_out_rate; speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate); // Adjust rates if needed. if (sample_rate != cur_in_rate) { speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate); speex_resampler_set_rate(visual_resampler_, sample_rate, visual_out_rate); RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_); } } spx_uint32_t in_len = (spx_uint32_t)rtp_packet->info->info_payload_len; spx_uint32_t out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0); if (out_len * sample_bytes_ > resample_buff_len) { while ((out_len * sample_bytes_ > resample_buff_len)) resample_buff_len *= 2; resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len); } speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len); write_buff = (char *) decode_buff; write_bytes = out_len * sample_bytes_; } // Write the decoded, possibly-resampled audio to our temp file. tempfile_->write(write_buff, write_bytes); // Collect our visual samples. spx_uint32_t in_len = (spx_uint32_t)rtp_packet->info->info_payload_len; spx_uint32_t out_len = (visual_out_rate * in_len / sample_rate) + (visual_out_rate % sample_rate != 0); if (out_len * sample_bytes_ > resample_buff_len) { while ((out_len * sample_bytes_ > resample_buff_len)) resample_buff_len *= 2; resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len); } speex_resampler_process_int(visual_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len); for (unsigned i = 0; i < out_len; i++) { packet_timestamps_[stop_rel_time_ + (double) i / visual_out_rate] = rtp_packet->frame_num; if (qAbs(resample_buff[i]) > max_sample_val_) max_sample_val_ = qAbs(resample_buff[i]); visual_samples_.append(resample_buff[i]); } // Finally, write the resampled audio to our temp file and clean up. g_free(decode_buff); } g_free(resample_buff); }
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; }
int main(int argc, char **argv) { CALLGRIND_STOP_INSTRUMENTATION; CALLGRIND_ZERO_STATS; QCoreApplication a(argc, argv); QFile f((argc >= 2) ? argv[1] : "wb_male.wav"); if (! f.open(QIODevice::ReadOnly)) { qFatal("Failed to open file!"); } f.seek(36 + 8); QFile o("output.raw"); if (!(RUNNING_ON_VALGRIND)) if (! o.open(QIODevice::WriteOnly)) qFatal("Failed to open output!"); QFile vf((argc >= 3) ? argv[2] : "verify.raw"); if (! vf.open(QIODevice::ReadOnly)) { qWarning("Failed to open validate file!"); } QDataStream out(&o); QDataStream verify(&vf); const int iFrameSize = 320; QVector<QByteArray> v; while (1) { QByteArray qba = f.read(iFrameSize * 2); if (qba.size() != iFrameSize * 2) break; v.append(qba); } int nframes = v.size(); qWarning("Ready to process %d frames of %d samples", nframes, iFrameSize); QVector<short *> qvInShort; QVector<float *> qvIn; QVector<float *> qvDirect; QVector<float *> qvInterpolate; QVector<float *> qvInterpolateMC; QVector<short *> qvInterpolateShort; QVector<float *> qv8; QVector<float *> qv96; const float sfraq1 = tfreq1 / 16000.0f; float fOutSize1 = iFrameSize * sfraq1; int iOutSize1 = lroundf(fOutSize1); const float sfraq2 = tfreq2 / 16000.0f; float fOutSize2 = iFrameSize * sfraq2; int iOutSize2 = lroundf(fOutSize2); int iOutSize8 = iFrameSize / 2; int iOutSize96 = iFrameSize * 6; if (RUNNING_ON_VALGRIND) nframes = qMin(nframes, 10); QVector<float> fInput(nframes * iFrameSize); QVector<float> fDirect(nframes * iOutSize1); QVector<float> fInterpolate(nframes * iOutSize2); QVector<float> fInterpolateMC(nframes * iOutSize2); QVector<short> sInterpolate(nframes * iOutSize2); QVector<float> f96(nframes * iOutSize96); QVector<float> f8(nframes *iOutSize8); for (int i=0;i<nframes;i++) { short *s = reinterpret_cast<short *>(v[i].data()); float *f = fInput.data() + i * iFrameSize; for (int j=0;j<iFrameSize;j++) f[j]=s[j]+20; qvInShort.append(s); qvIn.append(f); qvDirect.append(fDirect.data() + i * iOutSize1); qvInterpolate.append(fInterpolate.data() + i * iOutSize2); qvInterpolateMC.append(fInterpolateMC.data() + i * iOutSize2); qvInterpolateShort.append(sInterpolate.data() + i * iOutSize2); qv8.append(f8.data() + i * iOutSize8); qv96.append(f96.data() + i * iOutSize96); } int err; SpeexResamplerState *srs1 = speex_resampler_init(1, 16000, lroundf(tfreq1), qual, &err); SpeexResamplerState *srs2 = speex_resampler_init(1, 16000, lroundf(tfreq2), qual, &err); SpeexResamplerState *srs2i = speex_resampler_init(1, 16000, lroundf(tfreq2), qual, &err); SpeexResamplerState *srss = speex_resampler_init(3, 16000, lroundf(tfreq2), qual, &err); SpeexResamplerState *srsto96 = speex_resampler_init(1, 16000, 96000, 5, &err); SpeexResamplerState *srs8to96 = speex_resampler_init(1, 8000, 96000, qual, &err); SpeexResamplerState *srs96to8 = speex_resampler_init(1, 96000, 8000, qual, &err); #ifdef Q_OS_WIN if (!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) qWarning("Application: Failed to set priority!"); #endif int len; spx_uint32_t inlen; spx_uint32_t outlen; Timer t; quint64 e; if (! RUNNING_ON_VALGRIND) { #ifndef Q_OS_WIN struct sched_param sp; sp.sched_priority = sched_get_priority_max(SCHED_FIFO); cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(1, &cpuset); if (sched_setscheduler(getpid(), SCHED_FIFO, &sp) != 0) qWarning("No realtime."); if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) qWarning("No mlock."); if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) qWarning("No affinity"); sched_yield(); #endif for (int i=0;i<nframes;++i) { inlen = iFrameSize; outlen = iOutSize96; speex_resampler_process_float(srsto96, 0, qvIn[i], &inlen, qv96[i], &outlen); } QVector<unsigned long long> qvTimes; QPair<unsigned long long, unsigned long long> ci; for (int j=0;j<loops;j++) { t.restart(); for (int i=0;i<nframes;i++) { inlen = iFrameSize; outlen = iOutSize1; speex_resampler_process_float(srs1, 0, qvIn[i], &inlen, qvDirect[i], &outlen); } e = t.elapsed(); qvTimes.append(e); } ci = confint(qvTimes); qWarning("Direct: %8llu +/- %3llu usec (%d)", ci.first, ci.second, qvTimes.count(), qvTimes.count()); qvTimes.clear(); for (int j=0;j<loops;j++) { t.restart(); for (int i=0;i<nframes;i++) { inlen = iFrameSize; outlen = iOutSize2; speex_resampler_process_float(srs2, 0, qvIn[i], &inlen, qvInterpolate[i], &outlen); } e = t.elapsed(); qvTimes.append(e); } ci = confint(qvTimes); qWarning("Interpolate: %8llu +/- %3llu usec (%d)", ci.first, ci.second, qvTimes.count()); qvTimes.clear(); for (int j=0;j<loops;j++) { t.restart(); for (int i=0;i<nframes;i++) { inlen = iOutSize96; outlen = iOutSize8; speex_resampler_process_float(srs96to8, 0, qv96[i], &inlen, qv8[i], &outlen); } e = t.elapsed(); qvTimes.append(e); } ci = confint(qvTimes); qWarning("96 => 8: %8llu +/- %3llu usec (%d)", ci.first, ci.second, qvTimes.count()); qvTimes.clear(); t.restart(); for (int j=0;j<loops;j++) { t.restart(); for (int i=0;i<nframes;i++) { inlen = iOutSize8; outlen = iOutSize96; speex_resampler_process_float(srs8to96, 0, qv8[i], &inlen, qv96[i], &outlen); } e = t.elapsed(); qvTimes.append(e); } ci = confint(qvTimes); qWarning("8 => 96: %8llu +/- %3llu usec (%d)", ci.first, ci.second, qvTimes.count()); speex_resampler_reset_mem(srs1); speex_resampler_reset_mem(srs2); } t.restart(); CALLGRIND_START_INSTRUMENTATION; for (int i=0;i<nframes;i++) { inlen = iFrameSize; outlen = iOutSize1; speex_resampler_process_float(srs1, 0, qvIn[i], &inlen, qvDirect[i], &outlen); inlen = iFrameSize; outlen = iOutSize2; speex_resampler_process_float(srs2, 0, qvIn[i], &inlen, qvInterpolate[i], &outlen); inlen = iFrameSize; outlen = iOutSize2; speex_resampler_process_int(srs2i, 0, qvInShort[i], &inlen, qvInterpolateShort[i], &outlen); inlen = iFrameSize / 4; outlen = iOutSize2 / 4; speex_resampler_process_interleaved_float(srss, qvIn[i], &inlen, qvInterpolateMC[i], &outlen); } e = t.elapsed(); #ifdef Q_OS_WIN if (!SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS)) qWarning("Application: Failed to reset priority!"); #endif const int freq[10] = { 22050, 32000, 11025, 16000, 48000, 41000, 8000, 96000, 11025, 1600 }; QVector<float> fMagic; for (int f=0;f<10;f++) { float fbuff[32767]; speex_resampler_set_rate(srs1, 16000, freq[f]); for (int q = 0;q < 10;q++) { speex_resampler_set_quality(srs1, (3*q) % 7); inlen = iFrameSize; outlen = 32767; speex_resampler_process_float(srs1, 0, qvIn[(f*10+q) % nframes], &inlen, fbuff, &outlen); for (int j=0;j<outlen;j++) fMagic.append(fbuff[j]); } inlen = iFrameSize; outlen = 32767; speex_resampler_process_float(srs1, 0, NULL, &inlen, fbuff, &outlen); for (int j=0;j<outlen;j++) fMagic.append(fbuff[j]); } // Cropped magic test for (int f=0;f<10;f++) { float fbuff[32767]; speex_resampler_set_rate(srs1, 16000, freq[f]); for (int q = 0;q < 10;q++) { speex_resampler_set_quality(srs1, (3*q) % 7); inlen = iFrameSize; outlen = 16; speex_resampler_process_float(srs1, 0, qvIn[(f*10+q) % nframes], &inlen, fbuff, &outlen); for (int j=0;j<outlen;j++) fMagic.append(fbuff[j]); } inlen = iFrameSize; outlen = 32767; speex_resampler_process_float(srs1, 0, NULL, &inlen, fbuff, &outlen); for (int j=0;j<outlen;j++) fMagic.append(fbuff[j]); } CALLGRIND_STOP_INSTRUMENTATION; qWarning("Used %llu usec", e); qWarning("%.2f times realtime", (20000ULL * nframes) / (e * 1.0)); if (! RUNNING_ON_VALGRIND) { QVector<float> vDirect; QVector<float> vInterpolate; QVector<short> vsInterpolate; QVector<float> vMagic; QVector<float> vInterpolateMC; out << fDirect << fInterpolate << sInterpolate << fMagic << fInterpolateMC; if (vf.isOpen()) { verify >> vDirect >> vInterpolate >> vsInterpolate >> vMagic >> vInterpolateMC; double rmsd = veccomp(vDirect, fDirect, "SRS1"); double rmsi = veccomp(vInterpolate, fInterpolate, "SRS2"); veccomp(vsInterpolate, sInterpolate, "SRS2i"); veccomp(vMagic, fMagic, "Magic"); veccomp(vInterpolateMC, fInterpolateMC, "MC"); qWarning("Direct: %g", rmsd); qWarning("Interp: %g", rmsi); } else {
void MediaDecodeTask::Decode() { MOZ_ASSERT(!mThreadPool == NS_IsMainThread(), "We should be on the main thread only if we don't have a thread pool"); mBufferDecoder->BeginDecoding(NS_GetCurrentThread()); // Tell the decoder reader that we are not going to play the data directly, // and that we should not reject files with more channels than the audio // bakend support. mDecoderReader->SetIgnoreAudioOutputFormat(); mDecoderReader->OnDecodeThreadStart(); VideoInfo videoInfo; nsAutoPtr<MetadataTags> tags; nsresult rv = mDecoderReader->ReadMetadata(&videoInfo, getter_Transfers(tags)); if (NS_FAILED(rv)) { ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent); return; } if (!mDecoderReader->HasAudio()) { ReportFailureOnMainThread(WebAudioDecodeJob::NoAudio); return; } while (mDecoderReader->DecodeAudioData()) { // consume all of the buffer continue; } mDecoderReader->OnDecodeThreadFinish(); MediaQueue<AudioData>& audioQueue = mDecoderReader->AudioQueue(); uint32_t frameCount = audioQueue.FrameCount(); uint32_t channelCount = videoInfo.mAudioChannels; uint32_t sampleRate = videoInfo.mAudioRate; if (!frameCount || !channelCount || !sampleRate) { ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent); return; } const uint32_t destSampleRate = mDecodeJob.mContext->SampleRate(); AutoResampler resampler; uint32_t resampledFrames = frameCount; if (sampleRate != destSampleRate) { resampledFrames = static_cast<uint32_t>( static_cast<uint64_t>(destSampleRate) * static_cast<uint64_t>(frameCount) / static_cast<uint64_t>(sampleRate) ); resampler = speex_resampler_init(channelCount, sampleRate, destSampleRate, SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr); speex_resampler_skip_zeros(resampler); resampledFrames += speex_resampler_get_output_latency(resampler); } // Allocate the channel buffers. Note that if we end up resampling, we may // write fewer bytes than mResampledFrames to the output buffer, in which // case mWriteIndex will tell us how many valid samples we have. static const fallible_t fallible = fallible_t(); bool memoryAllocationSuccess = true; if (!mDecodeJob.mChannelBuffers.SetLength(channelCount)) { memoryAllocationSuccess = false; } else { for (uint32_t i = 0; i < channelCount; ++i) { mDecodeJob.mChannelBuffers[i] = new(fallible) float[resampledFrames]; if (!mDecodeJob.mChannelBuffers[i]) { memoryAllocationSuccess = false; break; } } } if (!memoryAllocationSuccess) { ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError); return; } nsAutoPtr<AudioData> audioData; while ((audioData = audioQueue.PopFront())) { audioData->EnsureAudioBuffer(); // could lead to a copy :( AudioDataValue* bufferData = static_cast<AudioDataValue*> (audioData->mAudioBuffer->Data()); if (sampleRate != destSampleRate) { const uint32_t expectedOutSamples = static_cast<uint32_t>( static_cast<uint64_t>(destSampleRate) * static_cast<uint64_t>(audioData->mFrames) / static_cast<uint64_t>(sampleRate) ); #ifdef MOZ_SAMPLE_TYPE_S16 AudioDataValue* resampledBuffer = new(fallible) AudioDataValue[channelCount * expectedOutSamples]; #endif for (uint32_t i = 0; i < audioData->mChannels; ++i) { uint32_t inSamples = audioData->mFrames; uint32_t outSamples = expectedOutSamples; #ifdef MOZ_SAMPLE_TYPE_S16 speex_resampler_process_int(resampler, i, &bufferData[i * audioData->mFrames], &inSamples, &resampledBuffer[i * expectedOutSamples], &outSamples); ConvertAudioSamples(&resampledBuffer[i * expectedOutSamples], mDecodeJob.mChannelBuffers[i] + mDecodeJob.mWriteIndex, outSamples); #else speex_resampler_process_float(resampler, i, &bufferData[i * audioData->mFrames], &inSamples, mDecodeJob.mChannelBuffers[i] + mDecodeJob.mWriteIndex, &outSamples); #endif if (i == audioData->mChannels - 1) { mDecodeJob.mWriteIndex += outSamples; MOZ_ASSERT(mDecodeJob.mWriteIndex <= resampledFrames); } } #ifdef MOZ_SAMPLE_TYPE_S16 delete[] resampledBuffer; #endif } else { for (uint32_t i = 0; i < audioData->mChannels; ++i) { ConvertAudioSamples(&bufferData[i * audioData->mFrames], mDecodeJob.mChannelBuffers[i] + mDecodeJob.mWriteIndex, audioData->mFrames); if (i == audioData->mChannels - 1) { mDecodeJob.mWriteIndex += audioData->mFrames; } } } } if (sampleRate != destSampleRate) { int inputLatency = speex_resampler_get_input_latency(resampler); int outputLatency = speex_resampler_get_output_latency(resampler); AudioDataValue* zero = (AudioDataValue*)calloc(inputLatency, sizeof(AudioDataValue)); #ifdef MOZ_SAMPLE_TYPE_S16 AudioDataValue* resampledBuffer = new(fallible) AudioDataValue[channelCount * outputLatency]; if (!resampledBuffer || !zero) { #else if (!zero) { #endif // Out of memory! ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError); return; } for (uint32_t i = 0; i < channelCount; ++i) { uint32_t inSamples = inputLatency; uint32_t outSamples = outputLatency; #ifdef MOZ_SAMPLE_TYPE_S16 speex_resampler_process_int(resampler, i, zero, &inSamples, &resampledBuffer[i * outputLatency], &outSamples); ConvertAudioSamples(&resampledBuffer[i * outputLatency], mDecodeJob.mChannelBuffers[i] + mDecodeJob.mWriteIndex, outSamples); #else speex_resampler_process_float(resampler, i, zero, &inSamples, mDecodeJob.mChannelBuffers[i] + mDecodeJob.mWriteIndex, &outSamples); #endif if (i == channelCount - 1) { mDecodeJob.mWriteIndex += outSamples; MOZ_ASSERT(mDecodeJob.mWriteIndex <= resampledFrames); } } free(zero); #ifdef MOZ_SAMPLE_TYPE_S16 delete[] resampledBuffer; #endif } mPhase = PhaseEnum::AllocateBuffer; RunNextPhase(); } void MediaDecodeTask::AllocateBuffer() { MOZ_ASSERT(NS_IsMainThread()); if (!mDecodeJob.AllocateBuffer()) { ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError); return; } mPhase = PhaseEnum::Done; CallbackTheResult(); }
/* * sample_rate resample. * @param resampler resampler object. * @param prev_frame reuse frame. * @param src_pcms16 source pcms16 data. * @return resampled pcms16 data. */ ttLibC_PcmS16 *ttLibC_SpeexdspResampler_resample(ttLibC_SpeexdspResampler *resampler, ttLibC_PcmS16 *prev_frame, ttLibC_PcmS16 *src_pcms16) { ttLibC_SpeexdspResampler_ *resampler_ = (ttLibC_SpeexdspResampler_ *)resampler; if(resampler_ == NULL) { return NULL; } if(src_pcms16 == NULL) { return NULL; } switch(src_pcms16->type) { case PcmS16Type_bigEndian: case PcmS16Type_bigEndian_planar: resampler_->inherit_super.error = ttLibC_updateError(Target_On_Resampler, Error_InvalidOperation); return NULL; default: return NULL; case PcmS16Type_littleEndian: case PcmS16Type_littleEndian_planar: break; } ttLibC_PcmS16 *pcms16 = prev_frame; uint32_t out_sample_num = (src_pcms16->inherit_super.sample_num * resampler_->inherit_super.output_sample_rate / resampler_->inherit_super.input_sample_rate + 1); uint32_t in_sample_num = src_pcms16->inherit_super.sample_num; // estimate result data size. size_t data_size = out_sample_num * sizeof(int16_t) * resampler_->inherit_super.channel_num; uint8_t *data = NULL; bool alloc_flag = false; if(pcms16 != NULL) { if(!pcms16->inherit_super.inherit_super.is_non_copy) { if(pcms16->inherit_super.inherit_super.data_size >= data_size) { // reuse frame have enough buffer. data = pcms16->inherit_super.inherit_super.data; data_size = pcms16->inherit_super.inherit_super.data_size; } else { ttLibC_free(pcms16->inherit_super.inherit_super.data); } } pcms16->inherit_super.inherit_super.is_non_copy = true; } if(data == NULL) { data = ttLibC_malloc(data_size); if(data == NULL) { resampler_->inherit_super.error = ttLibC_updateError(Target_On_Resampler, Error_MemoryAllocate); return NULL; } alloc_flag = true; } int res; switch(src_pcms16->type) { default: ERR_PRINT("no way to be here.."); if(alloc_flag) { ttLibC_free(data); } return NULL; case PcmS16Type_littleEndian: res = speex_resampler_process_interleaved_int(resampler_->resampler, (const int16_t *)src_pcms16->l_data, &in_sample_num, (int16_t *)data, &out_sample_num); break; case PcmS16Type_littleEndian_planar: res = speex_resampler_process_int(resampler_->resampler, resampler_->inherit_super.channel_num, (const int16_t *)src_pcms16->l_data, &in_sample_num, (int16_t *)data, &out_sample_num); break; } if(res != 0) { ERR_PRINT("failed to resampler: %s", speex_resampler_strerror(res)); if(alloc_flag) { ttLibC_free(data); } resampler_->inherit_super.error = ttLibC_updateError(Target_On_Resampler, Error_LibraryError); return NULL; } uint64_t pts = src_pcms16->inherit_super.inherit_super.pts * resampler_->inherit_super.output_sample_rate / resampler_->inherit_super.input_sample_rate; uint8_t *l_data = NULL; uint32_t l_stride = 0; uint8_t *r_data = NULL; uint32_t r_stride = 0; switch(src_pcms16->type) { case PcmS16Type_bigEndian: case PcmS16Type_littleEndian: l_data = data; l_stride = out_sample_num * 2 * resampler_->inherit_super.channel_num; break; case PcmS16Type_bigEndian_planar: case PcmS16Type_littleEndian_planar: l_data = data; l_stride = out_sample_num * 2; if(resampler_->inherit_super.channel_num == 2) { r_data = data + l_stride; r_stride = l_stride; } break; } pcms16 = ttLibC_PcmS16_make( pcms16, src_pcms16->type, resampler_->inherit_super.output_sample_rate, out_sample_num, resampler_->inherit_super.channel_num, data, data_size, l_data, l_stride, r_data, r_stride, true, pts, resampler_->inherit_super.output_sample_rate); if(pcms16 == NULL) { if(alloc_flag) { ttLibC_free(data); } resampler_->inherit_super.error = ttLibC_updateError(Target_On_Resampler, Error_MemoryAllocate); return NULL; } pcms16->inherit_super.inherit_super.is_non_copy = false; pcms16->inherit_super.inherit_super.buffer_size = pcms16->inherit_super.sample_num * pcms16->inherit_super.channel_num * sizeof(int16_t); return pcms16; }
int COggVorbisFileHelper::decode() { #if defined(HAVE_PTHREAD) pthread_mutex_lock(&mutex1); #endif int cb_len = sizeof(convbuffer) -rcb_len-16; char* p = convbuffer + 16; //pre buffer memcpy(p,remaing_convbuffer,rcb_len); p = p+rcb_len; long ret=ov_read_func(&vf,p,cb_len,0,2,1,¤t_section); #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif if (ret == 0) { /* EOF */ return EOF; } else if (ret < 0) { if(ret==OV_EBADLINK) { m_strLastError = "Corrupt bitstream section! Exiting."; s3eDebugTracePrintf("%s\n",m_strLastError.c_str()); return ERR; } } else { if(bStopDecoding) return EOS; int nr_samples = (ret + rcb_len)/sizeof(ogg_int16_t); if(!bEnableResampling) //store samples in the circular buffer { for(int k=0;k<nr_samples;k++) { //ogg_int16_t val = *(ogg_int16_t*)(convbuffer+k*sizeof(ogg_int16_t)); if(bStopDecoding) return EOS; if(nStatus == OH_BUFFERING) { if(mDecBuffer->GetBusy() >= mDecBuffer->GetCapacity() * m_dBufferingMaxCapacity || k == nr_samples - 1) { s3eDebugTracePrintf("buffering complete. Playing now..\n"); nStatus = OH_PLAYING; Wait_counter(0); } } while(!mDecBuffer->Enqueue(*(ogg_int16_t*)(convbuffer+k*sizeof(ogg_int16_t)))) { s3eDeviceYieldUntilEvent(10); if(bStopDecoding) return EOS;/*fprintf(stderr,"Buffer full\n")*/; if(nStatus == OH_BUFFERING) { s3eDebugTracePrintf("buffering complete. Playing now..\n"); nStatus = OH_PLAYING; Wait_counter(0); } return BFF; } } return EOK; } if (get_nChannels() == 2) nr_samples /= 2; for(int k=0;k<nr_samples;k++) { if (get_nChannels() == 2) { m_tmpbufL[k] = *(ogg_int16_t*)(convbuffer+k*2*sizeof(ogg_int16_t)); m_tmpbufR[k] = *(ogg_int16_t*)(convbuffer+(k*2+1)*sizeof(ogg_int16_t)); } else { m_tmpbufL[k] = *(ogg_int16_t*)(convbuffer+k*sizeof(ogg_int16_t)); } } unsigned int inlengthL = nr_samples; unsigned int inlengthR = nr_samples; unsigned int inused = 0; // output unsigned int outputL,outputR; outputL= m_outbufsizeL; outputR= m_outbufsizeR; if (get_nChannels() == 2) // stereo input { speex_resampler_process_int(res_contL,0,m_tmpbufL,&inlengthL,m_outL,&outputL); speex_resampler_process_int(res_contR,0,m_tmpbufR,&inlengthR,m_outR,&outputR); if(outputL != outputR) { s3eDebugTracePrintf("Left and Right channels out of sync\n"); } if(inlengthL != inlengthR) { s3eDebugTracePrintf("Left and Right channels out of sync\n"); } inused = inlengthL*2; } else { speex_resampler_process_interleaved_int(res_contL,m_tmpbufL,&inlengthL,m_outL,&outputL); inused = inlengthL; } p = convbuffer + inused * sizeof(ogg_int16_t); rcb_len = ret- inused*sizeof(ogg_int16_t); memcpy(remaing_convbuffer,p,rcb_len); for(unsigned int k = 0;k< outputL;k++) { if(bStopDecoding) return EOS; if(k%50 == 0) s3eDeviceYield(1); if(nStatus == OH_BUFFERING) { if(mDecBuffer->GetBusy() >= mDecBuffer->GetCapacity() * m_dBufferingMaxCapacity || k == nr_samples - 1) { s3eDebugTracePrintf("buffering complete. Playing now..\n"); nStatus = OH_PLAYING; Wait_counter(0); } } while(!mDecBuffer->Enqueue((ogg_int16_t)m_outL[k])) { s3eDeviceYieldUntilEvent(10); if(bStopDecoding) return EOS;/*fprintf(stderr,"Buffer full\n")*/; if(nStatus == OH_BUFFERING) { s3eDebugTracePrintf("buffering complete. Playing now..\n"); nStatus = OH_PLAYING; Wait_counter(0); } return BFF; } if(get_nChannels() == 2) { while(!mDecBuffer->Enqueue((ogg_int16_t)m_outR[k])) { s3eDeviceYieldUntilEvent(10); if(bStopDecoding) return EOS;/*fprintf(stderr,"Buffer full\n")*/; if(nStatus == OH_BUFFERING) { s3eDebugTracePrintf("buffering complete. Playing now..\n"); nStatus = OH_PLAYING; Wait_counter(0); } return BFF; } } } } return EOK; }
static void resample_process_ms2(MSFilter *obj){ ResampleData *dt=(ResampleData*)obj->data; mblk_t *im, *om = NULL, *om_chan = NULL; if (dt->output_rate==dt->input_rate){ while((im=ms_queue_get(obj->inputs[0]))!=NULL){ if (resample_channel_adapt(dt->in_nchannels, dt->out_nchannels, im, &om) == 0) { ms_queue_put(obj->outputs[0], im); } else { ms_queue_put(obj->outputs[0], om); freemsg(im); } } return; } ms_filter_lock(obj); if (dt->handle!=NULL){ unsigned int inrate=0, outrate=0; speex_resampler_get_rate(dt->handle,&inrate,&outrate); if (inrate!=dt->input_rate || outrate!=dt->output_rate){ speex_resampler_destroy(dt->handle); dt->handle=0; } } if (dt->handle==NULL){ resample_init_speex(dt); } while((im=ms_queue_get(obj->inputs[0]))!=NULL){ unsigned int inlen=(im->b_wptr-im->b_rptr)/(2*dt->in_nchannels); unsigned int outlen=((inlen*dt->output_rate)/dt->input_rate)+1; unsigned int inlen_orig=inlen; om=allocb(outlen*2*dt->in_nchannels,0); mblk_meta_copy(im, om); if (dt->in_nchannels==1){ speex_resampler_process_int(dt->handle, 0, (int16_t*)im->b_rptr, &inlen, (int16_t*)om->b_wptr, &outlen); }else{ speex_resampler_process_interleaved_int(dt->handle, (int16_t*)im->b_rptr, &inlen, (int16_t*)om->b_wptr, &outlen); } if (inlen_orig!=inlen){ ms_error("Bug in resampler ! only %u samples consumed instead of %u, out=%u", inlen,inlen_orig,outlen); } om->b_wptr+=outlen*2*dt->in_nchannels; mblk_set_timestamp_info(om,dt->ts); dt->ts+=outlen; if (resample_channel_adapt(dt->in_nchannels, dt->out_nchannels, om, &om_chan) == 0) { ms_queue_put(obj->outputs[0], om); } else { ms_queue_put(obj->outputs[0], om_chan); freemsg(om); } freemsg(im); } ms_filter_unlock(obj); }