Ring Daemon
Loading...
Searching...
No Matches
audiolayer.h
Go to the documentation of this file.
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#pragma once
18
19#include "ringbuffer.h"
20#include "noncopyable.h"
21#include "audio_frame_resizer.h"
23
24#include <chrono>
25#include <mutex>
26#include <vector>
27#include <atomic>
28#include <condition_variable>
29
30extern "C" {
31struct SpeexEchoState_;
32typedef struct SpeexEchoState_ SpeexEchoState;
33}
34
40// Define the audio api
41#define AAUDIO_API_STR "aaudio"
42#define PULSEAUDIO_API_STR "pulseaudio"
43#define ALSA_API_STR "alsa"
44#define JACK_API_STR "jack"
45#define COREAUDIO_API_STR "coreaudio"
46#define PORTAUDIO_API_STR "portaudio"
47
48#define PCM_DEFAULT "default" // Default ALSA plugin
49#define PCM_DSNOOP "plug:dsnoop" // Alsa plugin for microphone sharing
50#define PCM_DMIX_DSNOOP "dmix/dsnoop" // Audio profile using Alsa dmix/dsnoop
51
52namespace jami {
53
54class AudioPreference;
55class Resampler;
56
57enum class AudioDeviceType : int8_t { ALL = -1, PLAYBACK = 0, CAPTURE, RINGTONE };
58
60{
61private:
63
64protected:
65 enum class Status : uint8_t { Idle, Starting, Started };
66
67public:
69 virtual ~AudioLayer();
70
75 virtual void startStream(AudioDeviceType stream) = 0;
76
82 virtual void startCaptureStream(const std::string& id) { (void) id; };
83
89 virtual void stopCaptureStream(const std::string& id) { (void) id; };
90
96
97 virtual std::vector<std::string> getCaptureDeviceList() const = 0;
98 virtual std::vector<std::string> getPlaybackDeviceList() const = 0;
99
100 virtual int getAudioDeviceIndex(const std::string& name, AudioDeviceType type) const = 0;
101 virtual std::string getAudioDeviceName(int index, AudioDeviceType type) const = 0;
102 virtual int getIndexCapture() const = 0;
103 virtual int getIndexPlayback() const = 0;
104 virtual int getIndexRingtone() const = 0;
105
109 inline bool isStarted() const { return status_ == Status::Started; }
110
111 template<class Rep, class Period>
112 bool waitForStart(const std::chrono::duration<Rep, Period>& rel_time) const
113 {
114 std::unique_lock lk(mutex_);
115 startedCv_.wait_for(lk, rel_time, [this] { return isStarted(); });
116 return isStarted();
117 }
118
124 void putUrgent(std::shared_ptr<AudioFrame> buffer);
125
130 void playIncomingCallNotification(bool play) { playIncomingCallBeep_.exchange(play); }
131
135 void flushMain();
136
140 void flushUrgent();
141
142 bool isCaptureMuted() const { return isCaptureMuted_; }
143
148
149 bool isPlaybackMuted() const { return isPlaybackMuted_; }
150
155
156 bool isRingtoneMuted() const { return isRingtoneMuted_; }
158
164
168 double getCaptureGain() const { return captureGain_; }
169
175
179 double getPlaybackGain() const { return playbackGain_; }
180
186 unsigned int getSampleRate() const { return audioFormat_.sample_rate; }
187
192
196 void notifyIncomingCall();
197
198 virtual void updatePreference(AudioPreference& pref, int index, AudioDeviceType type) = 0;
199
200protected:
204 void hardwareFormatAvailable(AudioFormat playback, size_t bufSize = 0);
205
210
211 void devicesChanged();
212
213 void playbackChanged(bool started);
214 void recordChanged(bool started);
215 void setHasNativeAEC(bool hasEAC);
216 void setHasNativeNS(bool hasNS);
217
218 std::shared_ptr<AudioFrame> getToPlay(AudioFormat format, size_t writableSamples);
219 std::shared_ptr<AudioFrame> getToRing(AudioFormat format, size_t writableSamples);
220 std::shared_ptr<AudioFrame> getPlayback(AudioFormat format, size_t samples)
221 {
222 const auto& ringBuff = getToRing(format, samples);
223 const auto& playBuff = getToPlay(format, samples);
224 return ringBuff ? ringBuff : playBuff;
225 }
226
227 void putRecorded(std::shared_ptr<AudioFrame>&& frame);
228
229 void flush();
230
235
240
244 bool isRingtoneMuted_ {false};
245
246 bool playbackStarted_ {false};
247 bool recordStarted_ {false};
248 bool hasNativeAEC_ {true};
249 bool hasNativeNS_ {false};
250
255
260
261 // audio processor preferences
263
267 std::shared_ptr<RingBuffer> mainRingBuffer_;
268 std::unique_ptr<AudioFrameResizer> playbackQueue_;
269
273 std::atomic<Status> status_ {Status::Idle};
274 mutable std::condition_variable startedCv_;
275
280
285
287
292
296 mutable std::mutex mutex_ {};
297
301 std::unique_ptr<Resampler> resampler_;
302
303private:
304 std::mutex audioProcessorMutex {};
305 std::unique_ptr<AudioProcessor> audioProcessor;
306
307 void createAudioProcessor();
308 void destroyAudioProcessor();
309
310 // Set to "true" to play the incoming call notification (beep)
311 // when the playback is on (typically when there is already an
312 // active call).
313 std::atomic_bool playIncomingCallBeep_ {false};
317 std::chrono::system_clock::time_point lastNotificationTime_ {std::chrono::system_clock::time_point::min()};
318};
319
320} // namespace jami
bool isCaptureMuted_
True if capture is not to be used.
Definition audiolayer.h:234
void mutePlayback(bool muted)
Mute playback.
Definition audiolayer.h:154
std::shared_ptr< RingBuffer > mainRingBuffer_
Buffers for audio processing.
Definition audiolayer.h:267
std::mutex mutex_
Lock for the entire audio layer.
Definition audiolayer.h:296
std::unique_ptr< Resampler > resampler_
Manage sampling rate conversion.
Definition audiolayer.h:301
virtual int getIndexRingtone() const =0
bool isRingtoneMuted() const
Definition audiolayer.h:156
virtual int getIndexCapture() const =0
virtual void updatePreference(AudioPreference &pref, int index, AudioDeviceType type)=0
double getPlaybackGain() const
Get playback stream gain (speaker)
Definition audiolayer.h:179
std::atomic< Status > status_
Whether or not the audio layer's playback stream is started.
Definition audiolayer.h:273
std::shared_ptr< AudioFrame > getPlayback(AudioFormat format, size_t samples)
Definition audiolayer.h:220
virtual std::vector< std::string > getPlaybackDeviceList() const =0
RingBuffer urgentRingBuffer_
Urgent ring buffer used for ringtones.
Definition audiolayer.h:291
bool waitForStart(const std::chrono::duration< Rep, Period > &rel_time) const
Definition audiolayer.h:112
virtual ~AudioLayer()
void playbackChanged(bool started)
virtual void stopCaptureStream(const std::string &id)
Stop an ongoing capture stream on the given device.
Definition audiolayer.h:89
void notifyIncomingCall()
Emit an audio notification (beep) on incoming calls.
virtual int getIndexPlayback() const =0
double getCaptureGain() const
Get capture stream gain (microphone)
Definition audiolayer.h:168
void muteRingtone(bool muted)
Definition audiolayer.h:157
void setHasNativeNS(bool hasNS)
bool isPlaybackMuted_
True if playback is not to be used.
Definition audiolayer.h:239
virtual int getAudioDeviceIndex(const std::string &name, AudioDeviceType type) const =0
void hardwareFormatAvailable(AudioFormat playback, size_t bufSize=0)
Callback to be called by derived classes when the audio output is opened.
std::shared_ptr< AudioFrame > getToRing(AudioFormat format, size_t writableSamples)
bool isCaptureMuted() const
Definition audiolayer.h:142
virtual void startCaptureStream(const std::string &id)
Start a capture stream on the given device (eg.
Definition audiolayer.h:82
void flushUrgent()
Flush urgent buffer.
void hardwareInputFormatAvailable(AudioFormat capture)
Set the input format on necessary objects.
virtual void startStream(AudioDeviceType stream)=0
Start the capture stream and prepare the playback stream.
std::unique_ptr< AudioFrameResizer > playbackQueue_
Definition audiolayer.h:268
void muteCapture(bool muted)
Mute capture (microphone)
Definition audiolayer.h:147
double captureGain_
Gain applied to mic signal.
Definition audiolayer.h:254
void playIncomingCallNotification(bool play)
Start/Stop playing the incoming call notification sound (beep) while playing back audio (typically du...
Definition audiolayer.h:130
void setHasNativeAEC(bool hasEAC)
std::shared_ptr< AudioFrame > getToPlay(AudioFormat format, size_t writableSamples)
size_t nativeFrameSize_
Definition audiolayer.h:286
bool isPlaybackMuted() const
Definition audiolayer.h:149
virtual std::string getAudioDeviceName(int index, AudioDeviceType type) const =0
virtual void stopStream(AudioDeviceType stream=AudioDeviceType::ALL)=0
Stop the playback and capture streams.
double playbackGain_
Gain applied to playback signal.
Definition audiolayer.h:259
bool isRingtoneMuted_
True if ringtone should be muted.
Definition audiolayer.h:244
void recordChanged(bool started)
AudioFormat audioFormat_
Sample Rate that should be sent to the sound card.
Definition audiolayer.h:279
bool isStarted() const
Determine whether or not the audio layer is active (i.e.
Definition audiolayer.h:109
void flushMain()
Flush main buffer.
unsigned int getSampleRate() const
Get the sample rate of the audio layer.
Definition audiolayer.h:186
const AudioPreference & pref_
Definition audiolayer.h:262
AudioFormat audioInputFormat_
Sample Rate for input.
Definition audiolayer.h:284
std::condition_variable startedCv_
Definition audiolayer.h:274
virtual std::vector< std::string > getCaptureDeviceList() const =0
void setCaptureGain(double gain)
Set capture stream gain (microphone) Range should be [-1.0, 1.0].
Definition audiolayer.h:163
void putRecorded(std::shared_ptr< AudioFrame > &&frame)
void setPlaybackGain(double gain)
Set playback stream gain (speaker) Range should be [-1.0, 1.0].
Definition audiolayer.h:174
AudioFormat getFormat() const
Get the audio format of the layer (sample rate & channel number).
Definition audiolayer.h:191
void putUrgent(std::shared_ptr< AudioFrame > buffer)
Send a chunk of data to the hardware buffer to start the playback Copy data in the urgent buffer.
A ring buffer for mutichannel audio samples.
Definition ringbuffer.h:37
void emitSignal(Args... args)
Definition jami_signal.h:64
AudioDeviceType
Definition audiolayer.h:57
Simple macro to hide class' copy constructor and assignment operator.
#define NON_COPYABLE(ClassName)
Definition noncopyable.h:30
struct SpeexEchoState_ SpeexEchoState
Definition speex.h:24
Structure to hold sample rate and channel number associated with audio data.