template <> int SpeexResamplerProcess<float>(SpeexResamplerState* aResampler, uint32_t aChannel, const float* aInput, uint32_t* aIn, float* aOutput, uint32_t* aOut) { NS_ASSERTION(*aOut <= SPEEX_RESAMPLER_PROCESS_MAX_OUTPUT, "Bad aOut"); return speex_resampler_process_float(aResampler, aChannel, aInput, aIn, aOutput, aOut); }
void AudioInput::addMic(const void *data, unsigned int nsamp) { while (nsamp > 0) { unsigned int left = qMin(nsamp, iMicLength - iMicFilled); imfMic(pfMicInput + iMicFilled, data, left, iMicChannels); iMicFilled += left; nsamp -= left; if (nsamp > 0) { if (eMicFormat == SampleFloat) data = reinterpret_cast<const float *>(data) + left * iMicChannels; else data = reinterpret_cast<const short *>(data) + left * iMicChannels; } if (iMicFilled == iMicLength) { iMicFilled = 0; float *ptr = srsMic ? pfOutput : pfMicInput; if (srsMic) { spx_uint32_t inlen = iMicLength; spx_uint32_t outlen = iFrameSize; speex_resampler_process_float(srsMic, 0, pfMicInput, &inlen, pfOutput, &outlen); } const float mul = 32768.f; for (int j=0;j<iFrameSize;++j) psMic[j] = static_cast<short>(ptr[j] * mul); if (iEchoChannels > 0) { JitterBufferPacket jbp; jbp.data = reinterpret_cast<char *>(psSpeaker); jbp.len = iFrameSize * sizeof(short); jbp.timestamp = 0; jbp.span = 0; jbp.sequence = 0; jbp.user_data = 0; spx_int32_t offs; jitter_buffer_get(jb, &jbp, 10, &offs); jitter_buffer_tick(jb); } encodeAudioFrame(); } } }
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 }
//============================================================================== std::vector<float> AudioAnalysisManager::resamplePlot(std::vector<float> v) { std::vector<float> resampledSignal; resampledSignal.resize(512); float *inF; inF = new float[v.size()]; float *outF; outF = new float[v.size()]; for (int i = 0;i < v.size();i++) { inF[i] = (float) v[i]; } SpeexResamplerState *resampler; int err = 0; resampler = speex_resampler_init(1, (spx_uint32_t) v.size(), 512, 0, &err); spx_uint32_t inLen = (spx_uint32_t) v.size(); spx_uint32_t outLen = (spx_uint32_t) 512; err = speex_resampler_process_float(resampler, 0, inF, &inLen, outF, &outLen); for (int i = 0;i < resampledSignal.size();i++) { resampledSignal[i] = outF[i]; } delete [] inF; delete [] outF; speex_resampler_destroy(resampler); return resampledSignal; }
void AudioInput::addEcho(const void *data, unsigned int nsamp) { while (nsamp > 0) { unsigned int left = qMin(nsamp, iEchoLength - iEchoFilled); imfEcho(pfEchoInput + iEchoFilled, data, left, iEchoChannels); iEchoFilled += left; nsamp -= left; if (nsamp > 0) { if (eEchoFormat == SampleFloat) data = reinterpret_cast<const float *>(data) + left * iEchoChannels; else data = reinterpret_cast<const short *>(data) + left * iEchoChannels; } if (iEchoFilled == iEchoLength) { iEchoFilled = 0; STACKVAR(short, outbuff, iFrameSize); float *ptr = srsEcho ? pfOutput : pfEchoInput; if (srsEcho) { spx_uint32_t inlen = iEchoLength; spx_uint32_t outlen = iFrameSize; speex_resampler_process_float(srsEcho, 0, pfEchoInput, &inlen, pfOutput, &outlen); } const float mul = 32768.f; for (int j=0;j<iFrameSize;++j) outbuff[j] = static_cast<short>(ptr[j] * mul); JitterBufferPacket jbp; jbp.data = reinterpret_cast<char *>(outbuff); jbp.len = iFrameSize * sizeof(short); jbp.timestamp = ++iJitterSeq * 10; jbp.span = 10; jbp.sequence = static_cast<unsigned short>(iJitterSeq); jbp.user_data = 0; jitter_buffer_put(jb, &jbp); } } }
ThreadSharedFloatArrayBufferList* AudioBuffer::GetThreadSharedChannelsForRate(JSContext* aJSContext, uint32_t aRate, uint32_t* aLength) { if (mResampledChannels && mResampledChannelsRate == aRate) { // return cached data *aLength = mResampledChannelsLength; return mResampledChannels; } if (!mSharedChannels) { // Steal JS data mSharedChannels = StealJSArrayDataIntoThreadSharedFloatArrayBufferList(aJSContext, mJSChannels); } if (mSampleRate == aRate) { *aLength = mLength; return mSharedChannels; } mResampledChannels = new ThreadSharedFloatArrayBufferList(NumberOfChannels()); double newLengthD = ceil(Duration()*aRate); uint32_t newLength = uint32_t(newLengthD); *aLength = newLength; double size = sizeof(float)*NumberOfChannels()*newLengthD; if (size != uint32_t(size)) { return mResampledChannels; } float* outputData = static_cast<float*>(malloc(uint32_t(size))); if (!outputData) { nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(mContext->GetParentObject()); nsIDocument* doc = nullptr; if (pWindow) { doc = pWindow->GetExtantDoc(); } nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "Media", doc, nsContentUtils::eDOM_PROPERTIES, "MediaBufferSourceNodeResampleOutOfMemory"); return mResampledChannels; } SpeexResamplerState* resampler = speex_resampler_init(NumberOfChannels(), mSampleRate, aRate, SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr); for (uint32_t i = 0; i < NumberOfChannels(); ++i) { const float* inputData = mSharedChannels->GetData(i); uint32_t inSamples = mLength; uint32_t outSamples = newLength; speex_resampler_process_float(resampler, i, inputData, &inSamples, outputData, &outSamples); mResampledChannels->SetData(i, i == 0 ? outputData : nullptr, outputData); outputData += newLength; } speex_resampler_destroy(resampler); mResampledChannelsRate = aRate; mResampledChannelsLength = newLength; return mResampledChannels; }
bool AudioOutputSample::needSamples(unsigned int snum) { // Forward the buffer for (unsigned int i=iLastConsume;i<iBufferFilled;++i) pfBuffer[i-iLastConsume]=pfBuffer[i]; iBufferFilled -= iLastConsume; iLastConsume = snum; // Check if we can satisfy request with current buffer if (iBufferFilled >= snum) return true; // Calculate the required buffersize to hold the results unsigned int iInputFrames = static_cast<unsigned int>(ceilf(static_cast<float>(snum * sfHandle->samplerate()) / static_cast<float>(iOutSampleRate))); unsigned int iInputSamples = iInputFrames * sfHandle->channels(); float *pOut; bool mix = sfHandle->channels() > 1; STACKVAR(float, fOut, iInputSamples); STACKVAR(float, fMix, iInputFrames); bool eof = false; sf_count_t read; do { resizeBuffer(iBufferFilled + snum); // If we need to resample or mix write to the buffer on stack pOut = (srs || mix) ? fOut : pfBuffer + iBufferFilled; // Try to read all samples needed to satifsy this request if ((read = sfHandle->read(pOut, iInputSamples)) < iInputSamples) { if (sfHandle->error() != SF_ERR_NO_ERROR || !bLoop) { // We reached the eof or encountered an error, stuff with zeroes memset(pOut, 0, sizeof(float) * (iInputSamples - read)); read = iInputSamples; eof = true; } else { sfHandle->seek(SEEK_SET, 0); } } if (mix) { // Mix the channels (only two channels) read /= 2; // If we need to resample after this write to extra buffer pOut = srs ? fMix : pfBuffer + iBufferFilled; for (unsigned int i = 0; i < read; i++) pOut[i] = (fOut[i*2] + fOut[i*2 + 1]) * 0.5f; } spx_uint32_t inlen = static_cast<unsigned int>(read); spx_uint32_t outlen = snum; if (srs) // If necessary resample speex_resampler_process_float(srs, 0, pOut, &inlen, pfBuffer + iBufferFilled, &outlen); iBufferFilled += outlen; } while (iBufferFilled < snum); if (eof && !bEof) { emit playbackFinished(); bEof = true; } return !eof; }
void AudioInput::addMic(const void *data, unsigned int nsamp) { while (nsamp > 0) { unsigned int left = min(nsamp, iMicLength - iMicFilled); imfMic(pfMicInput + iMicFilled, data, left, iMicChannels); iMicFilled += left; nsamp -= left; if (nsamp > 0) { if (eMicFormat == SampleFloat) data = reinterpret_cast<const float *>(data) + left * iMicChannels; else data = reinterpret_cast<const short *>(data) + left * iMicChannels; } if (iMicFilled == iMicLength) { iMicFilled = 0; float *ptr = srsMic ? pfOutput : pfMicInput; if (srsMic) { spx_uint32_t inlen = iMicLength; spx_uint32_t outlen = iFrameSize; speex_resampler_process_float(srsMic, 0, pfMicInput, &inlen, pfOutput, &outlen); } const float mul = 32768.f; for (int j=0;j<iFrameSize;++j) psMic[j] = static_cast<short>(ptr[j] * mul); if (iEchoChannels > 0) { short *echo = NULL; //获取回音数据 { MutexLocker l(&qmEcho); if (qlEchoFrames.empty()) { iJitterSeq = 0; iMinBuffered = 1000; } else { iMinBuffered = min(iMinBuffered, qlEchoFrames.size()); if ((iJitterSeq > 100) && (iMinBuffered > 1)) { iJitterSeq = 0; iMinBuffered = 1000; delete [] qlEchoFrames.front(); qlEchoFrames.pop_front(); } echo = qlEchoFrames.front(); qlEchoFrames.pop_front(); } } if (echo) { if (psSpeaker) delete [] psSpeaker; psSpeaker = echo; } } encodeAudioFrame(); } } }
void AudioInput::addMic(const void *data, unsigned int nsamp) { while (nsamp > 0) { // Make sure we don't overrun the frame buffer const unsigned int left = qMin(nsamp, iMicLength - iMicFilled); // Append mix into pfMicInput frame buffer (converts 16bit pcm->float if necessary) imfMic(pfMicInput + iMicFilled, data, left, iMicChannels); iMicFilled += left; nsamp -= left; // If new samples are left offset data pointer to point at the first one for next iteration if (nsamp > 0) { if (eMicFormat == SampleFloat) data = reinterpret_cast<const float *>(data) + left * iMicChannels; else data = reinterpret_cast<const short *>(data) + left * iMicChannels; } if (iMicFilled == iMicLength) { // Frame complete iMicFilled = 0; // If needed resample frame float *ptr = srsMic ? pfOutput : pfMicInput; if (srsMic) { spx_uint32_t inlen = iMicLength; spx_uint32_t outlen = iFrameSize; speex_resampler_process_float(srsMic, 0, pfMicInput, &inlen, pfOutput, &outlen); } // Convert float to 16bit PCM const float mul = 32768.f; for (int j = 0; j < iFrameSize; ++j) psMic[j] = static_cast<short>(qBound(-32768.f, (ptr[j] * mul), 32767.f)); // If we have echo chancellation enabled... if (iEchoChannels > 0) { short *echo = NULL; { QMutexLocker l(&qmEcho); if (qlEchoFrames.isEmpty()) { iJitterSeq = 0; iMinBuffered = 1000; } else { // Compensate for drift between the microphone and the echo source iMinBuffered = qMin(iMinBuffered, qlEchoFrames.count()); if ((iJitterSeq > 100) && (iMinBuffered > 1)) { iJitterSeq = 0; iMinBuffered = 1000; delete [] qlEchoFrames.takeFirst(); } echo = qlEchoFrames.takeFirst(); } } if (echo) { // We have echo data for the current frame, remember that delete [] psSpeaker; psSpeaker = echo; } } // Encode and send frame encodeAudioFrame(); } } }
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(); }
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 {