LCOV - code coverage report
Current view: top level - src/media/audio/audio-processing - webrtc.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 0 77 0.0 %
Date: 2024-12-21 08:56:24 Functions: 0 43 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "webrtc.h"
      19             : #include "logger.h"
      20             : 
      21             : #include <webrtc/modules/audio_processing/include/audio_processing.h>
      22             : 
      23             : namespace jami {
      24             : 
      25             : inline size_t
      26           0 : webrtcFrameSize(AudioFormat format)
      27             : {
      28           0 :     return (size_t) (webrtc::AudioProcessing::kChunkSizeMs * format.sample_rate / 1000);
      29             : }
      30             : 
      31             : constexpr int webrtcNoError = webrtc::AudioProcessing::kNoError;
      32             : 
      33           0 : WebRTCAudioProcessor::WebRTCAudioProcessor(AudioFormat format, unsigned /* frameSize */)
      34           0 :     : AudioProcessor(format.withSampleFormat(AV_SAMPLE_FMT_FLTP), webrtcFrameSize(format))
      35             : {
      36           0 :     JAMI_LOG("[webrtc-ap] WebRTCAudioProcessor, frame size = {:d} (={:d} ms), channels = {:d}",
      37             :              frameSize_,
      38             :              frameDurationMs_,
      39             :              format_.nb_channels);
      40           0 :     webrtc::Config config;
      41           0 :     config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(true));
      42           0 :     config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(true));
      43             : 
      44           0 :     apm.reset(webrtc::AudioProcessing::Create(config));
      45             : 
      46           0 :     webrtc::StreamConfig streamConfig((int) format_.sample_rate, (int) format_.nb_channels);
      47             :     webrtc::ProcessingConfig pconfig = {
      48             :         streamConfig, /* input stream */
      49             :         streamConfig, /* output stream */
      50             :         streamConfig, /* reverse input stream */
      51             :         streamConfig, /* reverse output stream */
      52           0 :     };
      53             : 
      54           0 :     if (apm->Initialize(pconfig) != webrtcNoError) {
      55           0 :         JAMI_ERROR("[webrtc-ap] Error initialising audio processing module");
      56             :     }
      57           0 : }
      58             : 
      59             : void
      60           0 : WebRTCAudioProcessor::enableNoiseSuppression(bool enabled)
      61             : {
      62           0 :     JAMI_LOG("[webrtc-ap] enableNoiseSuppression {}", enabled);
      63           0 :     if (apm->noise_suppression()->Enable(enabled) != webrtcNoError) {
      64           0 :         JAMI_ERROR("[webrtc-ap] Error enabling noise suppression");
      65             :     }
      66           0 :     if (apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kVeryHigh) != webrtcNoError) {
      67           0 :         JAMI_ERROR("[webrtc-ap] Error setting noise suppression level");
      68             :     }
      69           0 :     if (apm->high_pass_filter()->Enable(enabled) != webrtcNoError) {
      70           0 :         JAMI_ERROR("[webrtc-ap] Error enabling high pass filter");
      71             :     }
      72           0 : }
      73             : 
      74             : void
      75           0 : WebRTCAudioProcessor::enableAutomaticGainControl(bool enabled)
      76             : {
      77           0 :     JAMI_LOG("[webrtc-ap] enableAutomaticGainControl {}", enabled);
      78           0 :     if (apm->gain_control()->Enable(enabled) != webrtcNoError) {
      79           0 :         JAMI_ERROR("[webrtc-ap] Error enabling automatic gain control");
      80             :     }
      81           0 :     if (apm->gain_control()->set_analog_level_limits(0, 255) != webrtcNoError) {
      82           0 :         JAMI_ERROR("[webrtc-ap] Error setting automatic gain control analog level limits");
      83             :     }
      84           0 :     if (apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveAnalog) != webrtcNoError) {
      85           0 :         JAMI_ERROR("[webrtc-ap] Error setting automatic gain control mode");
      86             :     }
      87           0 : }
      88             : 
      89             : void
      90           0 : WebRTCAudioProcessor::enableEchoCancel(bool enabled)
      91             : {
      92           0 :     JAMI_LOG("[webrtc-ap] enableEchoCancel {}", enabled);
      93             : 
      94           0 :     if (apm->echo_cancellation()->Enable(enabled) != webrtcNoError) {
      95           0 :         JAMI_ERROR("[webrtc-ap] Error enabling echo cancellation");
      96             :     }
      97           0 :     if (apm->echo_cancellation()->set_suppression_level(
      98             :             webrtc::EchoCancellation::SuppressionLevel::kHighSuppression)
      99           0 :         != webrtcNoError) {
     100           0 :         JAMI_ERROR("[webrtc-ap] Error setting echo cancellation level");
     101             :     }
     102           0 :     if (apm->echo_cancellation()->enable_drift_compensation(true) != webrtcNoError) {
     103           0 :         JAMI_ERROR("[webrtc-ap] Error enabling echo cancellation drift compensation");
     104             :     }
     105           0 : }
     106             : 
     107             : void
     108           0 : WebRTCAudioProcessor::enableVoiceActivityDetection(bool enabled)
     109             : {
     110           0 :     JAMI_LOG("[webrtc-ap] enableVoiceActivityDetection {}", enabled);
     111           0 :     if (apm->voice_detection()->Enable(enabled) != webrtcNoError) {
     112           0 :         JAMI_ERROR("[webrtc-ap] Error enabling voice activation detection");
     113             :     }
     114           0 :     if (apm->voice_detection()->set_likelihood(webrtc::VoiceDetection::kVeryLowLikelihood)
     115           0 :         != webrtcNoError) {
     116           0 :         JAMI_ERROR("[webrtc-ap] Error setting voice detection likelihood");
     117             :     }
     118             :     // asserted to be 10 in voice_detection_impl.cc
     119           0 :     if (apm->voice_detection()->set_frame_size_ms(10) != webrtcNoError) {
     120           0 :         JAMI_ERROR("[webrtc-ap] Error setting voice detection frame size");
     121             :     }
     122           0 : }
     123             : 
     124             : std::shared_ptr<AudioFrame>
     125           0 : WebRTCAudioProcessor::getProcessed()
     126             : {
     127           0 :     if (tidyQueues()) {
     128           0 :         return {};
     129             :     }
     130             : 
     131           0 :     int driftSamples = playbackQueue_.samples() - recordQueue_.samples();
     132             : 
     133           0 :     auto playback = playbackQueue_.dequeue();
     134           0 :     auto record = recordQueue_.dequeue();
     135           0 :     if (!playback || !record) {
     136           0 :         return {};
     137             :     }
     138           0 :     webrtc::StreamConfig sc((int) format_.sample_rate, (int) format_.nb_channels);
     139             : 
     140             :     // process reverse in place
     141           0 :     float** playData = (float**) playback->pointer()->extended_data;
     142           0 :     if (apm->ProcessReverseStream(playData, sc, sc, playData) != webrtcNoError) {
     143           0 :         JAMI_ERR("[webrtc-ap] ProcessReverseStream failed");
     144             :     }
     145             : 
     146             :     // process deinterleaved float recorded data
     147             :     // TODO: maybe implement this to see if it's better than automatic drift compensation
     148             :     // (it MUST be called prior to ProcessStream)
     149             :     // delay = (t_render - t_analyze) + (t_process - t_capture)
     150           0 :     if (apm->set_stream_delay_ms(0) != webrtcNoError) {
     151           0 :         JAMI_ERR("[webrtc-ap] set_stream_delay_ms failed");
     152             :     }
     153             : 
     154           0 :     if (apm->gain_control()->set_stream_analog_level(analogLevel_) != webrtcNoError) {
     155           0 :         JAMI_ERR("[webrtc-ap] set_stream_analog_level failed");
     156             :     }
     157           0 :     apm->echo_cancellation()->set_stream_drift_samples(driftSamples);
     158             : 
     159             :     // process in place
     160           0 :     float** recData = (float**) record->pointer()->extended_data;
     161           0 :     if (apm->ProcessStream(recData, sc, sc, recData) != webrtcNoError) {
     162           0 :         JAMI_ERR("[webrtc-ap] ProcessStream failed");
     163             :     }
     164             : 
     165           0 :     analogLevel_ = apm->gain_control()->stream_analog_level();
     166           0 :     record->has_voice = apm->voice_detection()->is_enabled()
     167           0 :                            && getStabilizedVoiceActivity(apm->voice_detection()->stream_has_voice());
     168           0 :     return record;
     169           0 : }
     170             : 
     171             : } // namespace jami

Generated by: LCOV version 1.14