LCOV - code coverage report
Current view: top level - src/media/audio/audio-processing - webrtc.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 0.0 % 76 0
Test Date: 2026-06-13 09:18:46 Functions: 0.0 % 51 0

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 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(webrtc::EchoCancellation::SuppressionLevel::kHighSuppression)
      98            0 :         != webrtcNoError) {
      99            0 :         JAMI_ERROR("[webrtc-ap] Error setting echo cancellation level");
     100              :     }
     101            0 :     if (apm->echo_cancellation()->enable_drift_compensation(true) != webrtcNoError) {
     102            0 :         JAMI_ERROR("[webrtc-ap] Error enabling echo cancellation drift compensation");
     103              :     }
     104            0 : }
     105              : 
     106              : void
     107            0 : WebRTCAudioProcessor::enableVoiceActivityDetection(bool enabled)
     108              : {
     109            0 :     JAMI_LOG("[webrtc-ap] enableVoiceActivityDetection {}", enabled);
     110            0 :     if (apm->voice_detection()->Enable(enabled) != webrtcNoError) {
     111            0 :         JAMI_ERROR("[webrtc-ap] Error enabling voice activation detection");
     112              :     }
     113            0 :     if (apm->voice_detection()->set_likelihood(webrtc::VoiceDetection::kVeryLowLikelihood) != webrtcNoError) {
     114            0 :         JAMI_ERROR("[webrtc-ap] Error setting voice detection likelihood");
     115              :     }
     116              :     // asserted to be 10 in voice_detection_impl.cc
     117            0 :     if (apm->voice_detection()->set_frame_size_ms(10) != webrtcNoError) {
     118            0 :         JAMI_ERROR("[webrtc-ap] Error setting voice detection frame size");
     119              :     }
     120            0 : }
     121              : 
     122              : std::shared_ptr<AudioFrame>
     123            0 : WebRTCAudioProcessor::getProcessed()
     124              : {
     125            0 :     if (tidyQueues()) {
     126            0 :         return {};
     127              :     }
     128              : 
     129            0 :     int driftSamples = playbackQueue_.samples() - recordQueue_.samples();
     130              : 
     131            0 :     auto playback = playbackQueue_.dequeue();
     132            0 :     auto record = recordQueue_.dequeue();
     133            0 :     if (!playback || !record) {
     134            0 :         return {};
     135              :     }
     136            0 :     webrtc::StreamConfig sc((int) format_.sample_rate, (int) format_.nb_channels);
     137              : 
     138              :     // process reverse in place
     139            0 :     float** playData = (float**) playback->pointer()->extended_data;
     140            0 :     if (apm->ProcessReverseStream(playData, sc, sc, playData) != webrtcNoError) {
     141            0 :         JAMI_ERROR("[webrtc-ap] ProcessReverseStream failed");
     142              :     }
     143              : 
     144              :     // process deinterleaved float recorded data
     145              :     // TODO: maybe implement this to see if it's better than automatic drift compensation
     146              :     // (it MUST be called prior to ProcessStream)
     147              :     // delay = (t_render - t_analyze) + (t_process - t_capture)
     148            0 :     if (apm->set_stream_delay_ms(0) != webrtcNoError) {
     149            0 :         JAMI_ERROR("[webrtc-ap] set_stream_delay_ms failed");
     150              :     }
     151              : 
     152            0 :     if (apm->gain_control()->set_stream_analog_level(analogLevel_) != webrtcNoError) {
     153            0 :         JAMI_ERROR("[webrtc-ap] set_stream_analog_level failed");
     154              :     }
     155            0 :     apm->echo_cancellation()->set_stream_drift_samples(driftSamples);
     156              : 
     157              :     // process in place
     158            0 :     float** recData = (float**) record->pointer()->extended_data;
     159            0 :     if (apm->ProcessStream(recData, sc, sc, recData) != webrtcNoError) {
     160            0 :         JAMI_ERROR("[webrtc-ap] ProcessStream failed");
     161              :     }
     162              : 
     163            0 :     analogLevel_ = apm->gain_control()->stream_analog_level();
     164            0 :     record->has_voice = apm->voice_detection()->is_enabled()
     165            0 :                         && getStabilizedVoiceActivity(apm->voice_detection()->stream_has_voice());
     166            0 :     return record;
     167            0 : }
     168              : 
     169              : } // namespace jami
        

Generated by: LCOV version 2.0-1