diff --git a/river/io/Group.cpp b/river/io/Group.cpp index ac414b8..afeeca0 100644 --- a/river/io/Group.cpp +++ b/river/io/Group.cpp @@ -124,7 +124,7 @@ void river::io::Group::stop() { RIVER_ERROR(" have " << count << " interfaces ..."); if (count == 0) { RIVER_ERROR("GROUP :::::::::::: STOP() [START]"); - for (size_t iii=0; iii=0; --iii) { if (m_list[iii] != nullptr) { m_list[iii]->stop(); } diff --git a/test/testEchoDelay.h b/test/testEchoDelay.h index 99c4ebf..36feebb 100644 --- a/test/testEchoDelay.h +++ b/test/testEchoDelay.h @@ -27,6 +27,11 @@ namespace river_test_echo_delay { std11::chrono::system_clock::time_point m_currentTick; int32_t m_stateFB; int32_t m_stateMic; + std::vector m_delayListMic; + bool m_estimateVolumeInput; + int16_t m_volumeInputMax; + int16_t m_volumeInputMin; + float m_gain; public: TestClass(std11::shared_ptr _manager) : m_manager(_manager), @@ -35,7 +40,9 @@ namespace river_test_echo_delay { m_nextSampleCount(0), m_delayBetweenEvent(400), m_stateFB(3), - m_stateMic(3) { + m_stateMic(0), + m_estimateVolumeInput(true), + m_gain(-40) { //Set stereo output: std::vector channelMap; channelMap.push_back(audio::channel_frontLeft); @@ -55,6 +62,7 @@ namespace river_test_echo_delay { std11::placeholders::_5, std11::placeholders::_6)); m_interfaceOut->addVolumeGroup("FLOW"); + m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB"); m_interfaceIn = m_manager->createInput(48000, channelMap, @@ -96,54 +104,66 @@ namespace river_test_echo_delay { const std::vector& _map) { int16_t* data = static_cast(_data); double baseCycle = 2.0*M_PI/(double)48000 * m_freq; - if (_time == std11::chrono::system_clock::time_point()) { + if (m_estimateVolumeInput == true) { for (int32_t iii=0; iii<_nbChunk; iii++) { - for (int32_t jjj=0; jjj<_map.size(); jjj++) { - data[_map.size()*iii+jjj] = 0; - } - } - return; - } - if (m_nextTick == std11::chrono::system_clock::time_point()) { - m_nextTick = _time + m_delayBetweenEvent; - m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000; - m_phase = -1; - } - //APPL_INFO("sample : " << m_nextSampleCount); - for (int32_t iii=0; iii<_nbChunk; iii++) { - if (m_nextSampleCount > 0) { - m_nextSampleCount--; - } else { - m_phase = 0; - m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000; - m_currentTick = m_nextTick; - m_nextTick += m_delayBetweenEvent; - } - if (m_phase >= 0) { for (int32_t jjj=0; jjj<_map.size(); jjj++) { data[_map.size()*iii+jjj] = sin(m_phase) * 30000; } - double newPhase = m_phase+baseCycle; - if ( m_phase < M_PI - && newPhase >= M_PI) { - // the zero crossing position : - m_currentTick = getInterpolateTime(_time, iii, sin(m_phase) * 30000, sin(newPhase) * 30000, _frequency); - // start detection ... - m_stateFB = 0; - m_stateMic = 0; - APPL_WARNING("Time Pulse zero crossing: " << m_currentTick << " id=" << iii); - } - m_phase = newPhase; + m_phase += baseCycle; if (m_phase >= 2*M_PI) { - m_phase = -1; - //m_freq += 50.0; - if (m_freq>20000.0) { - m_freq = 400.0; + m_phase -= 2*M_PI; + } + } + } else { + if (_time == std11::chrono::system_clock::time_point()) { + for (int32_t iii=0; iii<_nbChunk; iii++) { + for (int32_t jjj=0; jjj<_map.size(); jjj++) { + data[_map.size()*iii+jjj] = 0; } } - } else { - for (int32_t jjj=0; jjj<_map.size(); jjj++) { - data[_map.size()*iii+jjj] = 0; + return; + } + if (m_nextTick == std11::chrono::system_clock::time_point()) { + m_nextTick = _time + m_delayBetweenEvent; + m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000; + m_phase = -1; + } + //APPL_INFO("sample : " << m_nextSampleCount); + for (int32_t iii=0; iii<_nbChunk; iii++) { + if (m_nextSampleCount > 0) { + m_nextSampleCount--; + } else { + m_phase = 0; + m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000; + m_currentTick = m_nextTick; + m_nextTick += m_delayBetweenEvent; + } + if (m_phase >= 0) { + for (int32_t jjj=0; jjj<_map.size(); jjj++) { + data[_map.size()*iii+jjj] = sin(m_phase) * 30000; + } + double newPhase = m_phase+baseCycle; + if ( m_phase < M_PI + && newPhase >= M_PI) { + // the zero crossing position : + m_currentTick = getInterpolateTime(_time, iii, sin(m_phase) * 30000, sin(newPhase) * 30000, _frequency); + // start detection ... + m_stateFB = 0; + m_stateMic = 0; + APPL_WARNING("Time Pulse zero crossing: " << m_currentTick << " id=" << iii); + } + m_phase = newPhase; + if (m_phase >= 2*M_PI) { + m_phase = -1; + //m_freq += 50.0; + if (m_freq>20000.0) { + m_freq = 400.0; + } + } + } else { + for (int32_t jjj=0; jjj<_map.size(); jjj++) { + data[_map.size()*iii+jjj] = 0; + } } } } @@ -169,42 +189,47 @@ namespace river_test_echo_delay { APPL_ERROR("call wrong type ... (need int16_t)"); } RIVER_SAVE_FILE_MACRO(int16_t, "REC_FeedBack.raw", _data, _nbChunk*_map.size()); - const int16_t* data = static_cast(_data); - // Detect Zero crossing after a max/min ... - for (size_t iii=0; iii<_nbChunk; ++iii) { - //for (size_t jjj=0; jjj<_map.size(); ++jjj) { - size_t jjj=0; { - if (m_stateFB == 0) { - if (data[iii*_map.size() + jjj] > INT16_MAX/5) { - m_stateFB = 1; - APPL_VERBOSE("FB: detect Normal " << iii); - } else if (data[iii*_map.size() + jjj] < -INT16_MAX/5) { - m_stateFB = 2; - APPL_VERBOSE("FB: detect inverse " << iii); + if (m_estimateVolumeInput == true) { + // nothing to do ... + } else { + const int16_t* data = static_cast(_data); + // Detect Zero crossing after a max/min ... + for (size_t iii=0; iii<_nbChunk; ++iii) { + //for (size_t jjj=0; jjj<_map.size(); ++jjj) { + size_t jjj=0; { + if (m_stateFB == 0) { + if (data[iii*_map.size() + jjj] > INT16_MAX/5) { + m_stateFB = 1; + APPL_VERBOSE("FB: detect Normal " << iii); + } else if (data[iii*_map.size() + jjj] < -INT16_MAX/5) { + m_stateFB = 2; + APPL_VERBOSE("FB: detect inverse " << iii); + } + } else if (m_stateFB == 1) { + // normale phase + if (data[iii*_map.size() + jjj] <= 0) { + // detect inversion of signe ... + m_stateFB = 3; + std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); + APPL_VERBOSE("FB: 1 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); + APPL_VERBOSE("FB: 1 position 0: " << iii << " " << data[iii*_map.size() + jjj]); + + APPL_WARNING("FB: 1 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs"); + } + } else if (m_stateFB == 2) { + // inverse phase + if (data[iii*_map.size() + jjj] >= 0) { + // detect inversion of signe ... + m_stateFB = 3; + std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); + APPL_VERBOSE("FB: 2 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); + APPL_VERBOSE("FB: 2 position 0: " << iii << " " << data[iii*_map.size() + jjj]); + APPL_WARNING("FB: 2 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs"); + } + } else if (m_stateFB == 3) { + // TODO : Detect the pic ... + // do nothing ... } - } else if (m_stateFB == 1) { - // normale phase - if (data[iii*_map.size() + jjj] <= 0) { - // detect inversion of signe ... - m_stateFB = 3; - std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); - APPL_VERBOSE("FB: 1 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); - APPL_VERBOSE("FB: 1 position 0: " << iii << " " << data[iii*_map.size() + jjj]); - APPL_WARNING("FB: 1 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs"); - } - } else if (m_stateFB == 2) { - // inverse phase - if (data[iii*_map.size() + jjj] >= 0) { - // detect inversion of signe ... - m_stateFB = 3; - std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); - APPL_VERBOSE("FB: 2 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); - APPL_VERBOSE("FB: 2 position 0: " << iii << " " << data[iii*_map.size() + jjj]); - APPL_WARNING("FB: 2 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs"); - } - } else if (m_stateFB == 3) { - // TODO : Detect the pic ... - // do nothing ... } } } @@ -220,62 +245,120 @@ namespace river_test_echo_delay { } RIVER_SAVE_FILE_MACRO(int16_t, "REC_Microphone.raw", _data, _nbChunk*_map.size()); const int16_t* data = static_cast(_data); - // Detect Zero crossing after a max/min ... - for (size_t iii=0; iii<_nbChunk; ++iii) { - //for (size_t jjj=0; jjj<_map.size(); ++jjj) { - size_t jjj=0; { - if (m_stateMic == 0) { - if (data[iii*_map.size() + jjj] > 400/*INT16_MAX/15*/) { - m_stateMic = 1; - APPL_VERBOSE("Mic: detect Normal " << iii); - } else if (data[iii*_map.size() + jjj] < -400/*INT16_MAX/15*/) { - m_stateMic = 2; - APPL_VERBOSE("Mic: detect inverse " << iii); + if (m_estimateVolumeInput == true) { + m_stateMic ++; + const int16_t* data = static_cast(_data); + if (m_stateMic <= 40) { + for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) { + //APPL_INFO("value=" << data[iii]); + m_volumeInputMax = std::max(int16_t(data[iii]), m_volumeInputMax); + m_volumeInputMin = std::min(int16_t(data[iii]), m_volumeInputMin); + } + if (m_stateMic == 40) { + m_volumeInputMax *= 2; + m_volumeInputMin *= 2; + } + } else if (m_stateMic <= 10000) { + int16_t valueMax = 0; + int16_t valueMin = 0; + for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) { + //APPL_INFO("value=" << data[iii]); + valueMax = std::max(int16_t(data[iii]), valueMax); + valueMin = std::min(int16_t(data[iii]), valueMin); + } + if ( valueMax > m_volumeInputMax + && valueMin < m_volumeInputMin + && ( m_gain == 0.0 + || ( valueMax > INT16_MAX/2 + && valueMin < INT16_MIN/2 + ) + ) + ) { + m_gain += 3.0f; + m_gain = std::min(m_gain, 0.0f); + m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB"); + APPL_INFO("Set detection volume : " << m_gain << " m_stateMic=" << m_stateMic); + m_stateMic = 3; + m_phase = -1; + m_estimateVolumeInput = false; + return; + } else { + if (m_stateMic%2 == 0) { + if (m_gain == 0.0f) { + APPL_CRITICAL("Can not find the basicVolume ..."); + } + // just update volume + m_gain += 1.0f; + m_gain = std::min(m_gain, 0.0f); + m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB"); } - } else if (m_stateMic == 1) { - // normale phase - if (data[iii*_map.size() + jjj] <= 0) { - // detect inversion of signe ... - m_stateFB = 3; - std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); - APPL_VERBOSE("MIC: 1 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); - APPL_VERBOSE("MIC: 1 position 0: " << iii << " " << data[iii*_map.size() + jjj]); - APPL_WARNING("MIC: 1 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs"); + } + } + } else { + // Detect Zero crossing after a max/min ... + for (size_t iii=0; iii<_nbChunk; ++iii) { + //for (size_t jjj=0; jjj<_map.size(); ++jjj) { + size_t jjj=0; { + if (m_stateMic == 0) { + if (data[iii*_map.size() + jjj] > 400/*INT16_MAX/15*/) { + m_stateMic = 1; + APPL_VERBOSE("Mic: detect Normal " << iii); + } else if (data[iii*_map.size() + jjj] < -400/*INT16_MAX/15*/) { + m_stateMic = 2; + APPL_VERBOSE("Mic: detect inverse " << iii); + } + } else if (m_stateMic == 1) { + // normale phase + if (data[iii*_map.size() + jjj] <= 0) { + // detect inversion of signe ... + m_stateMic = 3; + std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); + APPL_VERBOSE("MIC: 1 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); + APPL_VERBOSE("MIC: 1 position 0: " << iii << " " << data[iii*_map.size() + jjj]); + std11::chrono::nanoseconds delay = time-m_currentTick; + int32_t sampleDalay = (delay.count()*_frequency)/1000000000LL; + APPL_WARNING("MIC: 1 time detected: " << time << " delay = " << float(delay.count())/1000.0f << "µs samples=" << sampleDalay); + m_delayListMic.push_back(delay.count()); + } + } else if (m_stateMic == 2) { + // inverse phase + if (data[iii*_map.size() + jjj] >= 0) { + // detect inversion of signe ... + m_stateMic = 3; + std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); + APPL_VERBOSE("MIC: 2 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); + APPL_VERBOSE("MIC: 2 position 0: " << iii << " " << data[iii*_map.size() + jjj]); + std11::chrono::nanoseconds delay = time-m_currentTick; + int32_t sampleDalay = (delay.count()*_frequency)/1000000000LL; + APPL_WARNING("MIC: 2 time detected: " << time << " delay = " << float(delay.count())/1000.0f << "µs samples=" << sampleDalay); + m_delayListMic.push_back(delay.count()); + } + } else if (m_stateMic == 3) { + // TODO : Detect the pic ... + // do nothing ... } - } else if (m_stateMic == 2) { - // inverse phase - if (data[iii*_map.size() + jjj] >= 0) { - // detect inversion of signe ... - m_stateMic = 3; - std11::chrono::system_clock::time_point time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency); - APPL_VERBOSE("MIC: 2 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]); - APPL_VERBOSE("MIC: 2 position 0: " << iii << " " << data[iii*_map.size() + jjj]); - APPL_WARNING("MIC: 2 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs"); - } - } else if (m_stateMic == 3) { - // TODO : Detect the pic ... - // do nothing ... } } } - /* - const int16_t* data = static_cast(_data); - int16_t value = 0; - for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) { - //APPL_INFO("value=" << data[iii]); - value = std::max(int16_t(std::abs(data[iii])), value); - } - APPL_INFO("Get data ... max=" << value); - */ } void run() { m_interfaceOut->start(); m_interfaceIn->start(); - m_interfaceFB->start(); - usleep(30000000); - m_interfaceFB->stop(); + //m_interfaceFB->start(); + usleep(10000000); + //m_interfaceFB->stop(); m_interfaceIn->stop(); m_interfaceOut->stop(); + + int64_t delayAverage = 0; + if (m_delayListMic.size() > 0) { + for (size_t iii=0; iii