libASPL
Loading...
Searching...
No Matches
VolumeControl.hpp
Go to the documentation of this file.
1// Copyright (c) libASPL authors
2// Licensed under MIT
3
4//! @file aspl/VolumeControl.hpp
5//! @brief Volume control object.
6
7#pragma once
8
9#include <aspl/Direction.hpp>
10#include <aspl/Object.hpp>
11
12#include <CoreAudio/AudioServerPlugIn.h>
13
14#include <atomic>
15#include <memory>
16#include <mutex>
17
18namespace aspl {
19
20class VolumeCurve;
21
22//! Volume control parameters.
24{
25 //! Define whether this is input or output control.
26 //! Used by default implementation of VolumeControl::GetScope().
27 AudioObjectPropertyScope Scope = kAudioObjectPropertyScopeOutput;
28
29 //! Minimum volume value in raw units.
30 SInt32 MinRawVolume = 0;
31
32 //! Maximum volume value in raw units.
33 SInt32 MaxRawVolume = 96;
34
35 //! Minimum volume value in decibel units.
36 Float32 MinDecibelVolume = -96.0f;
37
38 //! Maximum volume value in decibel units.
39 Float32 MaxDecibelVolume = 0.0f;
40};
41
42//! Volume control object.
43//!
44//! Volumes can be represented using three scales:
45//! - raw - integer amplitude amplifier, custom range
46//! - decibels - floating point logarithmic scale, custom range
47//! - scalar - floating point logarithmic scale, range [0; 1]
48//!
49//! Decibels and raw scales are linearly related.
50//!
51//! The raw scale is intended for computations. The scalar scale is used by macOS
52//! for volume sliders.
53//!
54//! Default implementation of VolumeControl stores volumes in the raw scale and
55//! convert it on fly to/from other scales when requested.
56//!
57//! Volume control does not affect I/O by its own. It just stores the volume and
58//! provides ApplyProcessing() method which modifies given samples according to
59//! the volume.
60//!
61//! You can attach VolumeControl to Stream using Stream::AttachVolumeControl()
62//! method, and then stream will use it to process samples passed to stream.
63//! Alternatively, you can invoke VolumeControls manually the way you need.
64class VolumeControl : public Object
65{
66public:
67 //! Construct stream.
68 explicit VolumeControl(std::shared_ptr<const Context> context,
69 const VolumeControlParameters& params = {});
70
71 //! @name Getters and setters
72 //! @{
73
74 //! Get the scope that the control is attached to.
75 //! Can return kAudioObjectPropertyScopeInput or kAudioObjectPropertyScopeOutput.
76 //! By default returns VolumeControlParameters::Scope.
77 //! @note
78 //! Backs @c kAudioControlPropertyScope property.
79 virtual AudioObjectPropertyScope GetScope() const;
80
81 //! Get the element that the control is attached to.
82 //! Typically should return kAudioObjectPropertyElementMain.
83 //! By default returns kAudioObjectPropertyElementMain.
84 //! @note
85 //! Backs @c kAudioControlPropertyElement property.
86 virtual AudioObjectPropertyElement GetElement() const;
87
88 //! Get current volume, in raw units.
89 //! Values are in range GetRawRange().
90 virtual SInt32 GetRawValue() const;
91
92 //! Set current volume, in raw units.
93 //! Values are in range GetRawRange().
94 //! Invokes by SetRawValueImpl() and NotifyPropertiesChanged().
95 OSStatus SetRawValue(SInt32 value);
96
97 //! Get current volume, in decibel units.
98 //! Values are in range GetDecibelRange().
99 //! @note
100 //! Backs @c kAudioLevelControlPropertyDecibelValue property.
101 virtual Float32 GetDecibelValue() const;
102
103 //! Get current volume, in decibel units.
104 //! Values are in range GetDecibelRange().
105 //! Invokes by SetRawValue().
106 //! @note
107 //! Backs @c kAudioLevelControlPropertyDecibelValue property.
108 virtual OSStatus SetDecibelValue(Float32 value);
109
110 //! Get current volume, in scalar units.
111 //! Values are in range [0; 1].
112 //! @note
113 //! Backs @c kAudioLevelControlPropertyScalarValue property.
114 virtual Float32 GetScalarValue() const;
115
116 //! Set current volume, in scalar units.
117 //! Values are in range [0; 1].
118 //! Invokes by SetRawValue().
119 //! @note
120 //! Backs @c kAudioLevelControlPropertyScalarValue property.
121 virtual OSStatus SetScalarValue(Float32 value);
122
123 //! Get minimum and maximum volume values, in raw units.
124 //! Default implementation returns range based on VolumeControlParameters.
125 virtual AudioValueRange GetRawRange() const;
126
127 //! Get minimum and maximum volume values, in decibel units.
128 //! Default implementation returns range based on VolumeControlParameters.
129 //! @note
130 //! Backs @c kAudioLevelControlPropertyDecibelRange property.
131 virtual AudioValueRange GetDecibelRange() const;
132
133 //! Convert volume from scalar scale to decibel scale.
134 //! Default implementation performs conversion based on VolumeControlParameters.
135 //! @note
136 //! Backs @c kAudioLevelControlPropertyConvertScalarToDecibels property.
137 virtual Float32 ConvertScalarToDecibels(Float32 value) const;
138
139 //! Convert volume from decibel scale to scalar scale.
140 //! Default implementation performs conversion based on VolumeControlParameters.
141 //! @note
142 //! Backs @c kAudioLevelControlPropertyConvertDecibelsToScalar property.
143 virtual Float32 ConvertDecibelsToScalar(Float32 value) const;
144
145 //! @}
146
147 //! @name Processing
148 //! @{
149
150 //! Apply processing to given buffer.
151 //! The provided buffer contains exactly @p frameCount * @p channelCount samples.
152 //! The provides samples are scalled according to the current GetScalarValue().
153 //! @note
154 //! Invoked by Stream::ApplyProcessing() on realtime thread.
155 virtual void ApplyProcessing(Float32* frames,
156 UInt32 frameCount,
157 UInt32 channelCount) const;
158
159 //! @}
160
161 //! @name Property dispath
162 //! @{
163
164 //! Get class ID.
165 AudioClassID GetClass() const override;
166
167 //! Get base class ID.
168 AudioClassID GetBaseClass() const override;
169
170 //! Check if this object is instance of given base class.
171 bool IsInstance(AudioClassID classID) const override;
172
173 //! Check whether given property is present.
174 Boolean HasProperty(AudioObjectID objectID,
175 pid_t clientPID,
176 const AudioObjectPropertyAddress* address) const override;
177
178 //! Check whether given property can be changed.
179 OSStatus IsPropertySettable(AudioObjectID objectID,
180 pid_t clientPID,
181 const AudioObjectPropertyAddress* address,
182 Boolean* outIsSettable) const override;
183
184 //! Get size of property value in bytes.
185 OSStatus GetPropertyDataSize(AudioObjectID objectID,
186 pid_t clientPID,
187 const AudioObjectPropertyAddress* address,
188 UInt32 qualifierDataSize,
189 const void* qualifierData,
190 UInt32* outDataSize) const override;
191
192 //! Get property value.
193 OSStatus GetPropertyData(AudioObjectID objectID,
194 pid_t clientPID,
195 const AudioObjectPropertyAddress* address,
196 UInt32 qualifierDataSize,
197 const void* qualifierData,
198 UInt32 inDataSize,
199 UInt32* outDataSize,
200 void* outData) const override;
201
202 //! Change property value.
203 OSStatus SetPropertyData(AudioObjectID objectID,
204 pid_t clientPID,
205 const AudioObjectPropertyAddress* address,
206 UInt32 qualifierDataSize,
207 const void* qualifierData,
208 UInt32 inDataSize,
209 const void* inData) override;
210
211 //! @}
212
213protected:
214 //! @name Setters implementation
215 //! @{
216
217 //! Set current volume, in raw units.
218 //! Values are in range GetRawRange().
219 //! Invoked by SetRawValue().
220 virtual OSStatus SetRawValueImpl(SInt32 value);
221
222 //! @}
223
224private:
225 const VolumeControlParameters params_;
226 const std::unique_ptr<VolumeCurve> volumeCurve_;
227
228 std::mutex writeMutex_;
229 std::atomic<SInt32> rawVolume_ = 0;
230};
231
232} // namespace aspl
I/O direction.
Basic audio object.
Base class for audio objects.
Definition Object.hpp:55
Volume control object.
Boolean HasProperty(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address) const override
Check whether given property is present.
virtual AudioValueRange GetDecibelRange() const
Get minimum and maximum volume values, in decibel units. Default implementation returns range based o...
OSStatus IsPropertySettable(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, Boolean *outIsSettable) const override
Check whether given property can be changed.
VolumeControl(std::shared_ptr< const Context > context, const VolumeControlParameters &params={})
Construct stream.
virtual Float32 ConvertScalarToDecibels(Float32 value) const
Convert volume from scalar scale to decibel scale. Default implementation performs conversion based o...
virtual AudioObjectPropertyScope GetScope() const
Get the scope that the control is attached to. Can return kAudioObjectPropertyScopeInput or kAudioObj...
virtual Float32 GetDecibelValue() const
Get current volume, in decibel units. Values are in range GetDecibelRange().
OSStatus GetPropertyDataSize(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, UInt32 qualifierDataSize, const void *qualifierData, UInt32 *outDataSize) const override
Get size of property value in bytes.
AudioClassID GetClass() const override
Get class ID.
virtual Float32 GetScalarValue() const
Get current volume, in scalar units. Values are in range [0; 1].
virtual OSStatus SetScalarValue(Float32 value)
Set current volume, in scalar units. Values are in range [0; 1]. Invokes by SetRawValue().
OSStatus SetRawValue(SInt32 value)
Set current volume, in raw units. Values are in range GetRawRange(). Invokes by SetRawValueImpl() and...
virtual OSStatus SetDecibelValue(Float32 value)
Get current volume, in decibel units. Values are in range GetDecibelRange(). Invokes by SetRawValue()...
virtual AudioObjectPropertyElement GetElement() const
Get the element that the control is attached to. Typically should return kAudioObjectPropertyElementM...
AudioClassID GetBaseClass() const override
Get base class ID.
OSStatus SetPropertyData(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, UInt32 qualifierDataSize, const void *qualifierData, UInt32 inDataSize, const void *inData) override
Change property value.
virtual OSStatus SetRawValueImpl(SInt32 value)
Set current volume, in raw units. Values are in range GetRawRange(). Invoked by SetRawValue().
virtual SInt32 GetRawValue() const
Get current volume, in raw units. Values are in range GetRawRange().
virtual Float32 ConvertDecibelsToScalar(Float32 value) const
Convert volume from decibel scale to scalar scale. Default implementation performs conversion based o...
virtual AudioValueRange GetRawRange() const
Get minimum and maximum volume values, in raw units. Default implementation returns range based on Vo...
OSStatus GetPropertyData(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, UInt32 qualifierDataSize, const void *qualifierData, UInt32 inDataSize, UInt32 *outDataSize, void *outData) const override
Get property value.
virtual void ApplyProcessing(Float32 *frames, UInt32 frameCount, UInt32 channelCount) const
Apply processing to given buffer. The provided buffer contains exactly frameCount * channelCount samp...
bool IsInstance(AudioClassID classID) const override
Check if this object is instance of given base class.
Volume control parameters.
AudioObjectPropertyScope Scope
Define whether this is input or output control. Used by default implementation of VolumeControl::GetS...
Float32 MinDecibelVolume
Minimum volume value in decibel units.
SInt32 MinRawVolume
Minimum volume value in raw units.
Float32 MaxDecibelVolume
Maximum volume value in decibel units.
SInt32 MaxRawVolume
Maximum volume value in raw units.