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);
}
Exemple #2
0
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);
    }
}
Exemple #3
0
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;
}
Exemple #5
0
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;
}
Exemple #10
0
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;
}
Exemple #12
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);
}
Exemple #13
0
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;
}
Exemple #15
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;
}
Exemple #17
0
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 {
Exemple #18
0
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();
}
Exemple #19
0
/*
 * 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,&current_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);
}