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-04-19 19:18:04 Functions: 6 16 37.5 %

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

Generated by: LCOV version 1.14