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