Commit f2f8e648 authored by Alexandre Savard's avatar Alexandre Savard

[#2209] Add alsa resampler

parent ff1cdf81
......@@ -52,6 +52,8 @@ AlsaLayer::~AlsaLayer (void)
{
_debug ("Destructor of AlsaLayer called\n");
closeLayer();
delete _converter; _converter = NULL;
}
bool
......@@ -119,6 +121,8 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize,
std::string pcmc = buildDeviceTopo (PCM_PLUGHW , indexIn , 0);
_converter = new SamplerateConverter (_sampleRate, _frameSize);
return open_device (pcmp , pcmc , stream);
}
......@@ -768,8 +772,33 @@ void AlsaLayer::audioCallback (void)
if (toGet) {
int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate();
_mainBuffer.getData(out, toGet, spkrVolume);
write (out, toGet);
if (_mainBufferSampleRate && ((int)_sampleRate != _mainBufferSampleRate)) {
SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (framesPerBufferAlsa * sizeof (SFLDataFormat));
// Do sample rate conversion
int nb_sample_down = toGet / sizeof(SFLDataFormat);
_debug(" _sampleRate: %i\n", _sampleRate);
_debug(" _mainBufferSampleRate: %i\n", _mainBufferSampleRate);
_debug(" nbSample (before conversion): %i\n", nb_sample_down);
int nbSample = _converter->upsampleData((SFLDataFormat*)out, rsmpl_out, _mainBufferSampleRate, _sampleRate, nb_sample_down);
_debug(" nbSample (after conversion): %i\n", nbSample);
write (rsmpl_out, nbSample);
free(rsmpl_out);
} else {
write (out, toGet);
}
} else {
......@@ -805,7 +834,25 @@ void AlsaLayer::audioCallback (void)
toPut = read (in, toPut* sizeof(SFLDataFormat));
if (in != 0)
{
_mainBuffer.putData(in, toPut, 100);
int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate();
if (_mainBufferSampleRate && ((int)_sampleRate != _mainBufferSampleRate)) {
SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (framesPerBufferAlsa * sizeof (SFLDataFormat));
int nbSample = toPut / sizeof(SFLDataFormat);
int nb_sample_up = nbSample;
nbSample = _converter->downsampleData ((SFLDataFormat*)in, rsmpl_out, _mainBufferSampleRate, _sampleRate, nb_sample_up);
_mainBuffer.putData(rsmpl_out, nbSample * sizeof (SFLDataFormat), 100);
free(rsmpl_out);
} else {
_mainBuffer.putData(in, toPut, 100);
}
}
free(in); in=0;
}
......
......@@ -21,6 +21,7 @@
#define _ALSA_LAYER_H
#include "audio/audiolayer.h"
#include "audio/samplerateconverter.h"
#include "eventthread.h"
#include <alsa/asoundlib.h>
......@@ -265,6 +266,9 @@ class AlsaLayer : public AudioLayer {
AudioThread *_audioThread;
/** Sample rate converter object */
SamplerateConverter * _converter;
};
#endif // _ALSA_LAYER_H_
......@@ -82,7 +82,7 @@ namespace sfl {
return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate;
}
inline int computeNbByteAudioLayer (float codecFrameSize) {
return (int) ( (float) _layerSampleRate * codecFrameSize * (float) sizeof (SFLDataFormat) / 1000.0);
return (int) ( (float) 8000 * codecFrameSize * (float) sizeof (SFLDataFormat) / 1000.0);
}
void sendMicData(int timestamp);
......@@ -215,8 +215,8 @@ namespace sfl {
template <typename D>
void AudioRtpSession<D>::initBuffers()
{
_converter = new SamplerateConverter (_layerSampleRate , _layerFrameSize);
int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
_converter = new SamplerateConverter (8000, _layerFrameSize);
int nbSamplesMax = (int) (8000 * _layerFrameSize /1000);
_micData = new SFLDataFormat[nbSamplesMax];
_micDataConverted = new SFLDataFormat[nbSamplesMax];
_micDataEncoded = new unsigned char[nbSamplesMax];
......@@ -224,7 +224,7 @@ namespace sfl {
_spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
_manager->addStream(_ca->getCallId());
_audiolayer->getMainBuffer()->setInternalSamplingRate(_layerSampleRate);
_audiolayer->getMainBuffer()->setInternalSamplingRate(8000);
}
template <typename D>
......@@ -300,6 +300,10 @@ namespace sfl {
assert(_audiocodec);
assert(_audiolayer);
_debug("AudioRtpSession::processDataEncode\n");
int _mainBufferSampleRate = _audiolayer->getMainBuffer()->getInternalSamplingRate();
// compute codec framesize in ms
......@@ -323,12 +327,20 @@ namespace sfl {
// nb bytes to be sent over RTP
int compSize = 0;
_debug(" _codecSampleRate: %i\n", _codecSampleRate);
_debug(" _mainBufferSampleRate: %i\n", _mainBufferSampleRate);
_debug(" nbSample (before conversion): %i\n", nbSample);
// test if resampling is required
if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
int nb_sample_up = nbSample;
_nSamplesMic = nbSample;
nbSample = _converter->downsampleData (_micData , _micDataConverted , _audiocodec->getClockRate(), _mainBufferSampleRate, nb_sample_up);
_debug(" nbSample (after conversion): %i\n", nbSample);
compSize = _audiocodec->codecEncode (_micDataEncoded, _micDataConverted, nbSample*sizeof (int16));
} else {
// no resampling required
compSize = _audiocodec->codecEncode (_micDataEncoded, _micData, nbSample*sizeof (int16));
......@@ -340,6 +352,8 @@ namespace sfl {
template <typename D>
void AudioRtpSession<D>::processDataDecode(unsigned char * spkrData, unsigned int size, int& countTime)
{
_debug("AudioRtpSession::processDataDecode\n");
if (_audiocodec != NULL) {
int _mainBufferSampleRate = _audiolayer->getMainBuffer()->getInternalSamplingRate();
......@@ -350,18 +364,27 @@ namespace sfl {
// buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
int nbSample = expandedSize / sizeof (SFLDataFormat);
_debug(" _codecSampleRate: %i\n", _codecSampleRate);
_debug(" _mainBufferSampleRate: %i\n", _mainBufferSampleRate);
_debug(" nbSample (before conversion): %i\n", nbSample);
// test if resampling is required
if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
// Do sample rate conversion
int nb_sample_down = nbSample;
nbSample = _converter->upsampleData (_spkrDataDecoded, _spkrDataConverted, _codecSampleRate, _mainBufferSampleRate, nb_sample_down);
_debug(" nbSample (after conversion): %i\n", nbSample);
// Store the number of samples for recording
_nSamplesSpkr = nbSample;
// put data in audio layer, size in byte
_audiolayer->getMainBuffer()->putData (_spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
} else {
// Store the number of samples for recording
_nSamplesSpkr = nbSample;
......@@ -478,12 +501,18 @@ namespace sfl {
throw AudioRtpSessionException();
}
_audiolayer->startStream();
static_cast<D*>(this)->startRunning();
_debug ("Entering RTP mainloop for callid %s\n",_ca->getCallId().c_str());
while (!testCancel()) {
// if(converterSamplingRate != _audiolayer->getMainBuffer()->getInternalSamplingRate())
// Send session
sessionWaiting = static_cast<D*>(this)->isWaiting();
......
......@@ -358,6 +358,8 @@ void PulseLayer::writeToSpeaker (void)
SFLDataFormat* out;// = (SFLDataFormat*)pa_xmalloc(framesPerBuffer);
urgentAvail = _urgentRingBuffer.AvailForGet();
_debug("PulseLayer::writeToSpeaker\n");
if (urgentAvail > 0) {
// Urgent data (dtmf, incoming call signal) come first.
......@@ -399,7 +401,9 @@ void PulseLayer::writeToSpeaker (void)
out = (SFLDataFormat*) pa_xmalloc (framesPerBuffer * sizeof (SFLDataFormat));
normalAvail = _mainBuffer.availForGet();
_debug(" normalAvail: %i", normalAvail);
toGet = (normalAvail < (int) (framesPerBuffer * sizeof (SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof (SFLDataFormat);
_debug(" toGet: %i", toGet);
if (toGet) {
......@@ -408,14 +412,21 @@ void PulseLayer::writeToSpeaker (void)
_mainBuffer.getData (out, toGet, 100);
// test if resampling is required
if (_sampleRate != _mainBufferSampleRate) {
if (_mainBufferSampleRate && ((int)_sampleRate != _mainBufferSampleRate)) {
SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (framesPerBuffer * sizeof (SFLDataFormat));
SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (framesPerBuffer * sizeof (SFLDataFormat));
// Do sample rate conversion
int nb_sample_down = toGet / sizeof(SFLDataFormat);
_debug(" _sampleRate: %i\n", _sampleRate);
_debug(" _mainBufferSampleRate: %i\n", _mainBufferSampleRate);
_debug(" nbSample (before conversion): %i\n", nb_sample_down);
int nbSample = _converter->upsampleData((SFLDataFormat*)out, rsmpl_out, _mainBufferSampleRate, _sampleRate, nb_sample_down);
_debug(" nbSample (after conversion): %i\n", nbSample);
pa_stream_write (playback->pulseStream(), rsmpl_out, nbSample*sizeof(SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE);
pa_xfree (rsmpl_out);
......@@ -448,20 +459,28 @@ void PulseLayer::readFromMic (void)
//_debug("pa_stream_peek() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
}
_debug("PulseLayer::readFromMic\n");
if (data != 0) {
int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate();
// test if resampling is required
if (_sampleRate != _mainBufferSampleRate) {
if (_mainBufferSampleRate && ((int)_sampleRate != _mainBufferSampleRate)) {
SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (framesPerBuffer * sizeof (SFLDataFormat));
int nbSample = r / sizeof(SFLDataFormat);
int nb_sample_up = nbSample;
_debug(" _sampleRate: %i\n", _sampleRate);
_debug(" _mainBufferSampleRate: %i\n", _mainBufferSampleRate);
_debug(" nbSample (before conversion): %i\n", nbSample);
nbSample = _converter->downsampleData ((SFLDataFormat*)data, rsmpl_out, _mainBufferSampleRate, _sampleRate, nb_sample_up);
_debug(" nbSample (after conversion): %i\n", nbSample);
_mainBuffer.putData ( (void*) rsmpl_out, nbSample*sizeof(SFLDataFormat), 100);
pa_xfree (rsmpl_out);
......
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