LCOV - code coverage report
Current view: top level - src/media/audio - audiolayer.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 6 19 31.6 %
Date: 2024-12-21 08:56:24 Functions: 6 16 37.5 %

          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             : #pragma once
      18             : 
      19             : #include "ringbuffer.h"
      20             : #include "noncopyable.h"
      21             : #include "audio_frame_resizer.h"
      22             : #include "audio-processing/audio_processor.h"
      23             : 
      24             : #include <chrono>
      25             : #include <mutex>
      26             : #include <vector>
      27             : #include <atomic>
      28             : #include <condition_variable>
      29             : #include <array>
      30             : 
      31             : extern "C" {
      32             : struct SpeexEchoState_;
      33             : typedef struct SpeexEchoState_ SpeexEchoState;
      34             : }
      35             : 
      36             : /**
      37             :  * @file  audiolayer.h
      38             :  * @brief Main sound class. Manages the data transfers between the application and the hardware.
      39             :  */
      40             : 
      41             : // Define the audio api
      42             : #define OPENSL_API_STR     "opensl"
      43             : #define PULSEAUDIO_API_STR "pulseaudio"
      44             : #define ALSA_API_STR       "alsa"
      45             : #define JACK_API_STR       "jack"
      46             : #define COREAUDIO_API_STR  "coreaudio"
      47             : #define PORTAUDIO_API_STR  "portaudio"
      48             : 
      49             : #define PCM_DEFAULT     "default"     // Default ALSA plugin
      50             : #define PCM_DSNOOP      "plug:dsnoop" // Alsa plugin for microphone sharing
      51             : #define PCM_DMIX_DSNOOP "dmix/dsnoop" // Audio profile using Alsa dmix/dsnoop
      52             : 
      53             : namespace jami {
      54             : 
      55             : class AudioPreference;
      56             : class Resampler;
      57             : 
      58             : enum class AudioDeviceType { ALL = -1, PLAYBACK = 0, CAPTURE, RINGTONE };
      59             : 
      60             : class AudioLayer
      61             : {
      62             : private:
      63             :     NON_COPYABLE(AudioLayer);
      64             : 
      65             : protected:
      66             :     enum class Status { Idle, Starting, Started };
      67             : 
      68             : public:
      69             :     AudioLayer(const AudioPreference&);
      70             :     virtual ~AudioLayer();
      71             : 
      72             :     /**
      73             :      * Start the capture stream and prepare the playback stream.
      74             :      * The playback starts accordingly to its threshold
      75             :      */
      76             :     virtual void startStream(AudioDeviceType stream = AudioDeviceType::ALL) = 0;
      77             : 
      78             :     /**
      79             :      * Stop the playback and capture streams.
      80             :      * Drops the pending frames and put the capture and playback handles to PREPARED state
      81             :      */
      82             :     virtual void stopStream(AudioDeviceType stream = AudioDeviceType::ALL) = 0;
      83             : 
      84             :     virtual std::vector<std::string> getCaptureDeviceList() const = 0;
      85             :     virtual std::vector<std::string> getPlaybackDeviceList() const = 0;
      86             : 
      87             :     virtual int getAudioDeviceIndex(const std::string& name, AudioDeviceType type) const = 0;
      88             :     virtual std::string getAudioDeviceName(int index, AudioDeviceType type) const = 0;
      89             :     virtual int getIndexCapture() const = 0;
      90             :     virtual int getIndexPlayback() const = 0;
      91             :     virtual int getIndexRingtone() const = 0;
      92             : 
      93             :     /**
      94             :      * Determine whether or not the audio layer is active (i.e. playback opened)
      95             :      */
      96           0 :     inline bool isStarted() const { return status_ == Status::Started; }
      97             : 
      98             :     template<class Rep, class Period>
      99           0 :     bool waitForStart(const std::chrono::duration<Rep, Period>& rel_time) const
     100             :     {
     101           0 :         std::unique_lock lk(mutex_);
     102           0 :         startedCv_.wait_for(lk, rel_time, [this] { return isStarted(); });
     103           0 :         return isStarted();
     104           0 :     }
     105             : 
     106             :     /**
     107             :      * Send a chunk of data to the hardware buffer to start the playback
     108             :      * Copy data in the urgent buffer.
     109             :      * @param buffer The buffer containing the data to be played ( ringtones )
     110             :      */
     111             :     void putUrgent(std::shared_ptr<AudioFrame> buffer);
     112             : 
     113             :     /**
     114             :      * Start/Stop playing the incoming call notification sound (beep)
     115             :      * while playing back audio (typically during an ongoing call).
     116             :      */
     117         267 :     void playIncomingCallNotification(bool play) { playIncomingCallBeep_.exchange(play); }
     118             : 
     119             :     /**
     120             :      * Flush main buffer
     121             :      */
     122             :     void flushMain();
     123             : 
     124             :     /**
     125             :      * Flush urgent buffer
     126             :      */
     127             :     void flushUrgent();
     128             : 
     129        1733 :     bool isCaptureMuted() const { return isCaptureMuted_; }
     130             : 
     131             :     /**
     132             :      * Mute capture (microphone)
     133             :      */
     134           0 :     void muteCapture(bool muted) { isCaptureMuted_ = muted; }
     135             : 
     136        1733 :     bool isPlaybackMuted() const { return isPlaybackMuted_; }
     137             : 
     138             :     /**
     139             :      * Mute playback
     140             :      */
     141           0 :     void mutePlayback(bool muted) { isPlaybackMuted_ = muted; }
     142             : 
     143           0 :     bool isRingtoneMuted() const { return isRingtoneMuted_; }
     144           0 :     void muteRingtone(bool muted) { isRingtoneMuted_ = muted; }
     145             : 
     146             :     /**
     147             :      * Set capture stream gain (microphone)
     148             :      * Range should be [-1.0, 1.0]
     149             :      */
     150           0 :     void setCaptureGain(double gain) { captureGain_ = gain; }
     151             : 
     152             :     /**
     153             :      * Get capture stream gain (microphone)
     154             :      */
     155        1733 :     double getCaptureGain() const { return captureGain_; }
     156             : 
     157             :     /**
     158             :      * Set playback stream gain (speaker)
     159             :      * Range should be [-1.0, 1.0]
     160             :      */
     161           0 :     void setPlaybackGain(double gain) { playbackGain_ = gain; }
     162             : 
     163             :     /**
     164             :      * Get playback stream gain (speaker)
     165             :      */
     166        1733 :     double getPlaybackGain() const { return playbackGain_; }
     167             : 
     168             :     /**
     169             :      * Get the sample rate of the audio layer
     170             :      * @return unsigned int The sample rate
     171             :      *                      default: 44100 HZ
     172             :      */
     173           0 :     unsigned int getSampleRate() const { return audioFormat_.sample_rate; }
     174             : 
     175             :     /**
     176             :      * Get the audio format of the layer (sample rate & channel number).
     177             :      */
     178         206 :     AudioFormat getFormat() const { return audioFormat_; }
     179             : 
     180             :     /**
     181             :      * Emit an audio notification (beep) on incoming calls
     182             :      */
     183             :     void notifyIncomingCall();
     184             : 
     185             :     virtual void updatePreference(AudioPreference& pref, int index, AudioDeviceType type) = 0;
     186             : 
     187             : protected:
     188             :     /**
     189             :      * Callback to be called by derived classes when the audio output is opened.
     190             :      */
     191             :     void hardwareFormatAvailable(AudioFormat playback, size_t bufSize = 0);
     192             : 
     193             :     /**
     194             :      * Set the input format on necessary objects.
     195             :      */
     196             :     void hardwareInputFormatAvailable(AudioFormat capture);
     197             : 
     198             :     void devicesChanged();
     199             : 
     200             :     void playbackChanged(bool started);
     201             :     void recordChanged(bool started);
     202             :     void setHasNativeAEC(bool hasEAC);
     203             :     void setHasNativeNS(bool hasNS);
     204             : 
     205             :     std::shared_ptr<AudioFrame> getToPlay(AudioFormat format, size_t writableSamples);
     206             :     std::shared_ptr<AudioFrame> getToRing(AudioFormat format, size_t writableSamples);
     207             :     std::shared_ptr<AudioFrame> getPlayback(AudioFormat format, size_t samples)
     208             :     {
     209             :         const auto& ringBuff = getToRing(format, samples);
     210             :         const auto& playBuff = getToPlay(format, samples);
     211             :         return ringBuff ? ringBuff : playBuff;
     212             :     }
     213             : 
     214             :     void putRecorded(std::shared_ptr<AudioFrame>&& frame);
     215             : 
     216             :     void flush();
     217             : 
     218             :     /**
     219             :      * True if capture is not to be used
     220             :      */
     221             :     bool isCaptureMuted_;
     222             : 
     223             :     /**
     224             :      * True if playback is not to be used
     225             :      */
     226             :     bool isPlaybackMuted_;
     227             : 
     228             :     /**
     229             :      * True if ringtone should be muted
     230             :      */
     231             :     bool isRingtoneMuted_ {false};
     232             : 
     233             :     bool playbackStarted_ {false};
     234             :     bool recordStarted_ {false};
     235             :     bool hasNativeAEC_ {true};
     236             :     bool hasNativeNS_ {false};
     237             : 
     238             :     /**
     239             :      * Gain applied to mic signal
     240             :      */
     241             :     double captureGain_;
     242             : 
     243             :     /**
     244             :      * Gain applied to playback signal
     245             :      */
     246             :     double playbackGain_;
     247             : 
     248             :     // audio processor preferences
     249             :     const AudioPreference& pref_;
     250             : 
     251             :     /**
     252             :      * Buffers for audio processing
     253             :      */
     254             :     std::shared_ptr<RingBuffer> mainRingBuffer_;
     255             :     std::unique_ptr<AudioFrameResizer> playbackQueue_;
     256             : 
     257             :     /**
     258             :      * Whether or not the audio layer's playback stream is started
     259             :      */
     260             :     std::atomic<Status> status_ {Status::Idle};
     261             :     mutable std::condition_variable startedCv_;
     262             : 
     263             :     /**
     264             :      * Sample Rate that should be sent to the sound card
     265             :      */
     266             :     AudioFormat audioFormat_;
     267             : 
     268             :     /**
     269             :      * Sample Rate for input.
     270             :      */
     271             :     AudioFormat audioInputFormat_;
     272             : 
     273             :     size_t nativeFrameSize_ {0};
     274             : 
     275             :     /**
     276             :      * Urgent ring buffer used for ringtones
     277             :      */
     278             :     RingBuffer urgentRingBuffer_;
     279             : 
     280             :     /**
     281             :      * Lock for the entire audio layer
     282             :      */
     283             :     mutable std::mutex mutex_ {};
     284             : 
     285             :     /**
     286             :      * Manage sampling rate conversion
     287             :      */
     288             :     std::unique_ptr<Resampler> resampler_;
     289             : 
     290             : private:
     291             :     std::mutex audioProcessorMutex {};
     292             :     std::unique_ptr<AudioProcessor> audioProcessor;
     293             : 
     294             :     void createAudioProcessor();
     295             :     void destroyAudioProcessor();
     296             : 
     297             :     // Set to "true" to play the incoming call notification (beep)
     298             :     // when the playback is on (typically when there is already an
     299             :     // active call).
     300             :     std::atomic_bool playIncomingCallBeep_ {false};
     301             :     /**
     302             :      * Time of the last incoming call notification
     303             :      */
     304             :     std::chrono::system_clock::time_point lastNotificationTime_ {
     305             :         std::chrono::system_clock::time_point::min()};
     306             : };
     307             : 
     308             : } // namespace jami

Generated by: LCOV version 1.14