Commit 6b3029e1 authored by Alexandre Savard's avatar Alexandre Savard
Browse files

[#1966] Add pulseaudio stream timing info update

parent 850b42b2
......@@ -52,6 +52,9 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate),
spkrFile = new ofstream("spkrData", ofstream::binary);
*/
micLearningData = new ofstream("micLearningData", ofstream::binary);
spkrLearningData = new ofstream("spkrLearningData", ofstream::binary);
_micData = new RingBuffer(50000);
_spkrData = new RingBuffer(50000);
......@@ -115,11 +118,17 @@ EchoCancel::~EchoCancel()
delete echoFile;
*/
micLearningData->close();
spkrLearningData->close();
delete micLearningData;
delete spkrLearningData;
}
void EchoCancel::reset()
{
_debug("EchoCancel: Reset internal state, Sampling rate %d, Frame size %d", _samplingRate, _smplPerFrame);
_debug("SIZEOF INT %d", sizeof(int));
memset(_avgSpkrLevelHist, 0, BUFF_SIZE*sizeof(int));
memset(_avgMicLevelHist, 0, BUFF_SIZE*sizeof(int));
......@@ -139,11 +148,22 @@ void EchoCancel::reset()
memset(_delayLineAmplify, 0, MAX_DELAY_LINE_AMPL*sizeof(float));
_amplDelayIndexIn = 0;
_amplDelayIndexOut = DELAY_AMPLIFY / SEGMENT_LENGTH;
_amplDelayIndexOut = 0;
_adaptDone = false;
_adaptStarted = false;
_adaptCnt = 0;
_spkrAdaptCnt = 0;
_micAdaptCnt = 0;
_micData->flushAll();
_spkrData->flushAll();
// SFLDataFormat delay[960];
// memset(delay, 0, sizeof(SFLDataFormat));
// _micData->Put(delay, 960*2);
speex_preprocess_state_destroy(_noiseState);
_noiseState = speex_preprocess_state_init(_smplPerFrame, _samplingRate);
......@@ -169,6 +189,7 @@ void EchoCancel::putData(SFLDataFormat *inputData, int nbBytes)
// std::cout << "putData nbBytes: " << nbBytes << std::endl;
if(_spkrStoped) {
_debug("EchoCancel: Flush data");
_micData->flushAll();
_spkrData->flushAll();
_spkrStoped = false;
......@@ -202,6 +223,8 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int
int spkrAvail = _spkrData->AvailForGet();
int micAvail = _micData->AvailForGet();
_debug("EchoCancel: speaker avail %d, mic avail %d", spkrAvail, micAvail);
// Init number of frame processed
int nbFrame = 0;
......@@ -263,7 +286,8 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa
increaseFactor(0.05);
}
else {
decreaseFactor();
// decreaseFactor();
_amplFactor = 0.0;
}
}
else {
......@@ -271,13 +295,13 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa
increaseFactor(0.02);
}
else {
decreaseFactor();
// decreaseFactor();
_amplFactor = 0.0;
}
}
// lowpass filtering
float amplify = (_lastAmplFactor + _amplFactor) / 2;
_lastAmplFactor = _amplFactor;
amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), amplify);
......@@ -323,7 +347,8 @@ void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDat
// perform correlation if spkr size is reached
if(_adaptCnt > _spkrAdaptSize) {
int k = _adaptCnt - _spkrAdaptSize;
_correlationArray[k] = performCorrelation(_spkrAdaptArray, _micAdaptArray+k, _correlationSize);
_correlationArray[k] = performCorrelation(_spkrAdaptArray, _micAdaptArray+k, _correlationSize);
_debug("EchoCancel: Correlation: %d", _correlationArray[k]);
}
_adaptCnt++;
......@@ -333,6 +358,9 @@ void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDat
_debug("EchoCancel: Echo path adaptation completed");
_adaptDone = true;
_amplDelayIndexOut = getMaximumIndex(_correlationArray, _correlationSize);
_debug("EchoCancel: Echo length %d", _amplDelayIndexOut);
spkrLearningData->write((const char *)_spkrAdaptArray, _spkrAdaptSize*sizeof(int));
micLearningData->write((const char *)_micAdaptArray, _micAdaptSize*sizeof(int));
}
}
......@@ -373,9 +401,23 @@ void EchoCancel::amplifySignal(SFLDataFormat *micData, SFLDataFormat *outputData
// Use delayed amplification factor due to sound card latency
for(int i = 0; i < _smplPerSeg; i++) {
outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayLineAmplify[_amplDelayIndexOut]);
outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayLineAmplify[_amplDelayIndexOut]);
}
// do not increment amplitude array if adaptation is not done
if (_adaptDone) {
for(int i = 0; i < _smplPerSeg; i++) {
outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayLineAmplify[_amplDelayIndexOut]);
}
}
else {
for(int i = 0; i < _smplPerSeg; i++) {
outputData[i] = micData[i];
}
return;
}
_amplDelayIndexOut++;
_delayLineAmplify[_amplDelayIndexIn++] = amplify;
......
......@@ -32,7 +32,7 @@
#define SEGMENT_LENGTH 10
// Length of the echo tail in ms
#define ECHO_LENGTH 100
#define ECHO_LENGTH 50
// Voice level threashold
#define MIN_SIG_LEVEL 100
......@@ -41,7 +41,7 @@
#define DELAY_AMPLIFY 60
// maximum in segment size (segment are SEGMENT_LENGTH long)
#define MAX_DELAY_LINE_AMPL 100
#define MAX_DELAY_LINE_AMPL 100 // 1 sec
// Internal buffer size
#define BUFF_SIZE 10000
......@@ -50,8 +50,8 @@
#define DEFAULT_FRAME_LENGTH 20
#define MIC_ADAPT_SIZE 100
#define SPKR_ADAPT_SIZE 50
#define MIC_ADAPT_SIZE 100 // 1 sec
#define SPKR_ADAPT_SIZE 20 // 200 ms
class EchoCancel : public Algorithm {
......@@ -280,6 +280,9 @@ class EchoCancel : public Algorithm {
ofstream *echoFile;
*/
ofstream *micLearningData;
ofstream *spkrLearningData;
/**
* Noise reduction processing state
*/
......
......@@ -204,6 +204,7 @@ AudioStream::createStream (pa_context* c, std::string *deviceName)
else
pa_stream_connect_playback (s , NULL, attributes, (pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL);
pa_threaded_mainloop_unlock(_mainloop);
} else if (_streamType == CAPTURE_STREAM) {
......@@ -218,6 +219,7 @@ AudioStream::createStream (pa_context* c, std::string *deviceName)
else
pa_stream_connect_record (s, NULL, attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE));
pa_threaded_mainloop_unlock(_mainloop);
} else if (_streamType == RINGTONE_STREAM) {
......
......@@ -64,6 +64,24 @@ static void pa_success_callback(pa_context *c, int success, void *userdata) {
_debug("Audio: Success callback");
}
static void latency_update_callback(pa_stream *p, void *userdata) {
pa_usec_t r_usec;
pa_buffer_attr *buffattr;
pa_stream_get_latency (p, &r_usec, NULL);
// buffattr = pa_stream_get_buffer_attr(p);
_debug("Audio: Stream letency update %0.0f ms for device %s", (float)r_usec/1000, pa_stream_get_device_name(p));
// _debug("Audio: maxlength %d", buffattr->maxlength);
// _debug("Audio: tlength %d", buffattr->tlength);
// _debug("Audio: prebug %d", buffattr->prebuf);
// _debug("Audio: minreq %d", buffattr->minreq);
// _debug("Audio: fragsize %d", buffattr->fragsize);
}
static void sink_input_info_callback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
......@@ -517,6 +535,7 @@ bool PulseLayer::createStreams (pa_context* c)
pa_stream_set_underflow_callback (playback->pulseStream(), playback_underflow_callback, this);
// pa_stream_set_suspended_callback(playback->pulseStream(), stream_suspended_callback, this);
pa_stream_set_moved_callback(playback->pulseStream(), stream_moved_callback, this);
pa_stream_set_latency_update_callback(playback->pulseStream(), latency_update_callback, this);
delete playbackParam;
PulseLayerType * recordParam = new PulseLayerType();
......@@ -536,6 +555,7 @@ bool PulseLayer::createStreams (pa_context* c)
pa_stream_set_read_callback (record->pulseStream() , capture_callback, this);
// pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this);
pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this);
pa_stream_set_latency_update_callback(record->pulseStream(), latency_update_callback, this);
delete recordParam;
PulseLayerType * ringtoneParam = new PulseLayerType();
......@@ -896,8 +916,6 @@ void PulseLayer::readFromMic (void)
_warn("Audio: Error capture stream peek failed: %s" , pa_strerror (pa_context_errno (context)));
}
_debug("*********************** Read from mic: %d **************************", readableSize);
if (data != 0) {
int _mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate();
......@@ -925,8 +943,6 @@ void PulseLayer::readFromMic (void)
// echo cancellation processing
int sampleready = _echoCanceller->processAudio(rsmpl_out, echoCancelledMic, nbSample*sizeof(SFLDataFormat));
_debug("Read from mic: sampleReady %d", sampleready);
// getMainBuffer()->putData ( (void*) rsmpl_out, nbSample*sizeof (SFLDataFormat), 100);
if(sampleready)
getMainBuffer()->putData ( echoCancelledMic, sampleready*sizeof (SFLDataFormat), 100);
......@@ -960,8 +976,6 @@ void PulseLayer::ringtoneToSpeaker(void)
int writableSize = pa_stream_writable_size(ringtone->pulseStream());
_debug("writable size: %d", writableSize);
if (file_tone) {
if(ringtone->getStreamState() == PA_STREAM_READY) {
......
Supports Markdown
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