Commit 8a9f8f03 authored by Tristan Matthews's avatar Tristan Matthews

* #10213: increase resample buffer size, and check output size when resampling

This avoids a buffer overrun crash when upsampling.
parent c275f30c
......@@ -570,7 +570,8 @@ void AlsaLayer::capture()
int outSamples = toGetSamples * ((double) audioSampleRate_ / mainBufferSampleRate);
std::vector<SFLDataFormat> rsmpl_out(outSamples);
converter_->resample(&(*in.begin()), &(*rsmpl_out.begin()),
mainBufferSampleRate, audioSampleRate_, toGetSamples);
rsmpl_out.size(), mainBufferSampleRate, audioSampleRate_,
toGetSamples);
dcblocker_.process(&(*rsmpl_out.begin()), &(*rsmpl_out.begin()), outSamples);
Manager::instance().getMainBuffer()->putData(&(*rsmpl_out.begin()),
rsmpl_out.size() * sizeof(rsmpl_out[0]), MainBuffer::DEFAULT_ID);
......@@ -631,10 +632,10 @@ void AlsaLayer::playback(int maxSamples)
if (resample) {
int inSamples = toGet / sizeof(SFLDataFormat);
int outSamples = inSamples * resampleFactor;
SFLDataFormat *rsmpl_out = (SFLDataFormat*) malloc(outSamples * sizeof(SFLDataFormat));
converter_->resample(out, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples);
write(rsmpl_out, outSamples * sizeof(SFLDataFormat), playbackHandle_);
free(rsmpl_out);
std::vector<SFLDataFormat> rsmpl_out(outSamples);
converter_->resample(out, &(*rsmpl_out.begin()), rsmpl_out.size(),
mainBufferSampleRate, audioSampleRate_, inSamples);
write(&(*rsmpl_out.begin()), outSamples * sizeof(SFLDataFormat), playbackHandle_);
} else {
write(out, toGet, playbackHandle_);
}
......
......@@ -144,16 +144,20 @@ int AudioRtpRecordHandler::processDataEncode()
echoCanceller.getData(micData);
SFLDataFormat *out = micData;
SFLDataFormat *micDataConverted = audioRtpRecord_.resampledData_.data();
if (codecSampleRate != mainBufferSampleRate) {
out = micDataConverted;
audioRtpRecord_.converter_->resample(micData, micDataConverted,
codecSampleRate, mainBufferSampleRate, samplesToGet);
assert(audioRtpRecord_.converter_);
audioRtpRecord_.converter_->resample(micData,
audioRtpRecord_.resampledData_.data(),
audioRtpRecord_.resampledData_.size(), codecSampleRate,
mainBufferSampleRate,
samplesToGet);
out = audioRtpRecord_.resampledData_.data();
}
if (Manager::instance().audioPreference.getNoiseReduce()) {
ost::MutexLock lock(audioRtpRecord_.audioProcessMutex_);
assert(audioRtpRecord_.noiseSuppress_);
audioRtpRecord_.noiseSuppress_->process(micData, getCodecFrameSize());
}
......@@ -194,7 +198,9 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t si
out = audioRtpRecord_.resampledData_.data();
// Do sample rate conversion
outSamples = ((float) inSamples * ((float) mainBufferSampleRate / (float) codecSampleRate));
audioRtpRecord_.converter_->resample(spkrDataDecoded, out, codecSampleRate, mainBufferSampleRate, inSamples);
audioRtpRecord_.converter_->resample(spkrDataDecoded, out,
audioRtpRecord_.resampledData_.size(), codecSampleRate,
mainBufferSampleRate, inSamples);
}
if (Manager::instance().getEchoCancelState())
......
......@@ -82,7 +82,8 @@ class AudioRtpRecord {
int codecPayloadType_;
bool hasDynamicPayloadType_;
std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE> decData_;
std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE> resampledData_;
// FIXME: resampledData should be resized as needed
std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE * 4> resampledData_;
std::tr1::array<unsigned char, DEC_BUFFER_SIZE> encodedData_;
SamplerateConverter *converter_;
int codecSampleRate_;
......
......@@ -317,7 +317,7 @@ void PulseLayer::writeToSpeaker()
if (urgentBytes > bytes)
urgentBytes = bytes;
void *data;
void *data = 0;
if (urgentBytes) {
pa_stream_begin_write(s, &data, &urgentBytes);
urgentRingBuffer_.Get(data, urgentBytes, MainBuffer::DEFAULT_ID);
......@@ -371,16 +371,17 @@ void PulseLayer::writeToSpeaker()
if (inSamples > availSamples)
inSamples = availSamples;
size_t outBytes = (double)inSamples * resampleFactor * sizeof(SFLDataFormat);
size_t inBytes = inSamples * sizeof(SFLDataFormat);
pa_stream_begin_write(s, &data, &inBytes);
Manager::instance().getMainBuffer()->getData(data, inBytes, MainBuffer::DEFAULT_ID);
if (resample) {
const size_t nResampled = (double) inSamples * resampleFactor;
size_t outBytes = nResampled * sizeof(SFLDataFormat);
SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc(outBytes);
converter_->resample((SFLDataFormat*)data, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples);
applyGain(rsmpl_out, outBytes / sizeof(SFLDataFormat), getPlaybackGain());
converter_->resample((SFLDataFormat*)data, rsmpl_out, nResampled,
mainBufferSampleRate, audioSampleRate_, inSamples);
applyGain(rsmpl_out, nResampled, getPlaybackGain());
pa_stream_write(s, rsmpl_out, outBytes, NULL, 0, PA_SEEK_RELATIVE);
pa_xfree(rsmpl_out);
} else {
......@@ -417,7 +418,7 @@ void PulseLayer::readFromMic()
}
if (resample)
converter_->resample((SFLDataFormat*)data, mic_buffer_, mainBufferSampleRate, audioSampleRate_, samples);
converter_->resample((SFLDataFormat*)data, mic_buffer_, samples, mainBufferSampleRate, audioSampleRate_, samples);
dcblocker_.process(mic_buffer_, resample ? mic_buffer_ : (SFLDataFormat*)data, samples);
applyGain(mic_buffer_, bytes / sizeof(SFLDataFormat), getCaptureGain());
......
......@@ -31,6 +31,7 @@
#include "samplerateconverter.h"
#include "manager.h"
#include <cassert>
#include "logger.h"
SamplerateConverter::SamplerateConverter(int freq) : floatBufferIn_(0),
floatBufferOut_(0), samples_(0), maxFreq_(freq), src_state_(0)
......@@ -63,15 +64,16 @@ SamplerateConverter::Short2FloatArray(const short *in, float *out, int len)
}
void SamplerateConverter::resample(SFLDataFormat *dataIn,
SFLDataFormat *dataOut, int inputFreq,
int outputFreq, int nbSamples)
SFLDataFormat *dataOut,
size_t dataOutSize, int inputFreq,
int outputFreq, size_t nbSamples)
{
double sampleFactor = (double) outputFreq / inputFreq;
if (sampleFactor == 1.0)
return;
const int outSamples = nbSamples * sampleFactor;
size_t outSamples = nbSamples * sampleFactor;
const unsigned int maxSamples = std::max(outSamples, nbSamples);
if (maxSamples > samples_) {
......@@ -91,8 +93,12 @@ void SamplerateConverter::resample(SFLDataFormat *dataIn,
src_data.src_ratio = sampleFactor;
src_data.end_of_input = 0; // More data will come
Short2FloatArray(dataIn , floatBufferIn_, nbSamples);
Short2FloatArray(dataIn, floatBufferIn_, nbSamples);
src_process(src_state_, &src_data);
src_float_to_short_array(floatBufferOut_, dataOut , outSamples);
if (outSamples > dataOutSize) {
ERROR("Outsamples exceeds output buffer size, clamping to %u", dataOutSize);
outSamples = dataOutSize;
}
src_float_to_short_array(floatBufferOut_, dataOut, outSamples);
}
......@@ -59,7 +59,7 @@ class SamplerateConverter {
* @param SamplerateConverter2 The desired sample rate
* @param nbSamples The number of samples to process
*/
void resample(SFLDataFormat* dataIn , SFLDataFormat* dataOut , int oldrate, int newrate, int nbSamples);
void resample(SFLDataFormat* dataIn, SFLDataFormat* dataOut, size_t dataOutSize, int oldrate, int newrate, size_t nbSamples);
/**
* Convert short table to floats for audio processing
......
......@@ -205,7 +205,7 @@ WaveFile::WaveFile(const std::string &fileName, int newRate) : AudioFile(fileNam
const int outSamples = ceil(nbSamples * ratio);
size_ = outSamples;
buffer_ = new SFLDataFormat[size_];
converter.resample(tempBuffer, buffer_, fileRate, newRate, nbSamples);
converter.resample(tempBuffer, buffer_, size_, fileRate, newRate, nbSamples);
delete [] tempBuffer;
} else
buffer_ = tempBuffer;
......
......@@ -38,6 +38,7 @@
#include "hooks/urlhook.h"
#include "audio/audiolayer.h"
#include "audio/samplerateconverter.h"
#include "array_size.h"
#include <cmath>
#include <dlfcn.h>
......@@ -180,7 +181,8 @@ IAXVoIPLink::sendAudioFromMic()
SFLDataFormat *in;
if (audioRate != mainBufferSampleRate) {
converter_.resample(decData_, resampledData_, audioRate, mainBufferSampleRate, samples);
converter_.resample(decData_, resampledData_, ARRAYSIZE(resampledData_),
audioRate, mainBufferSampleRate, samples);
in = resampledData_;
outSamples = 0;
} else {
......@@ -569,7 +571,8 @@ void IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall* call)
if (audioRate != mainBufferSampleRate) {
outSize = (double)outSize * (mainBufferSampleRate / audioRate);
converter_.resample(decData_, resampledData_, mainBufferSampleRate, audioRate, samples);
converter_.resample(decData_, resampledData_, ARRAYSIZE(resampledData_),
mainBufferSampleRate, audioRate, samples);
out = resampledData_;
}
......
......@@ -248,7 +248,8 @@ class IAXVoIPLink : public VoIPLink {
/** encoder/decoder/resampler buffers */
SFLDataFormat decData_[DEC_BUFFER_SIZE];
SFLDataFormat resampledData_[DEC_BUFFER_SIZE];
#warning FIXME: resampled buffer should be resized as appropriate
SFLDataFormat resampledData_[DEC_BUFFER_SIZE * 4];
unsigned char encodedData_[DEC_BUFFER_SIZE];
/** Sample rate converter object */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment