3 #include "AudioTools/CoreAudio/AudioStreams.h"
4 #include "AudioTools/CoreAudio/AudioOutput.h"
5 #include "AudioTools/CoreAudio/VolumeControl.h"
6 #include "AudioTools/CoreAudio/AudioTypes.h"
20 bool allow_boost =
false;
51 Print *p_print = &out;
90 bool begin()
override {
94 bool begin(AudioInfo cfg) {
104 if (cfg.allow_boost){
116 void end()
override {
123 cached_volume.setVolumeControl(vc);
128 cached_volume.setVolumeControl(pot_vc);
132 virtual size_t readBytes(uint8_t *data,
size_t len)
override {
134 if (data==
nullptr || p_in==
nullptr){
138 size_t result = p_in->readBytes(data, len);
139 if (isVolumeUpdate()) applyVolume(data, result);
144 virtual size_t write(
const uint8_t *data,
size_t len)
override {
145 LOGD(
"VolumeStream::write: %zu", len);
146 if (data==
nullptr || p_out==
nullptr){
150 if (isVolumeUpdate()) applyVolume(data,len);
151 return p_out->write(data, len);
156 return p_out==
nullptr? 0 : p_out->availableForWrite();
161 return p_in==
nullptr? 0 : p_in->available();
168 notifyAudioChange(cfg);
191 if ((vol > 1.0 && !info.allow_boost) || vol < 0) {
192 LOGE(
"Invalid volume: %f", vol);
197 float volume_value = volumeValue(vol);
198 if (volume_values[channel] != volume_value){
199 LOGI(
"setVolume: %f at %d", volume_value, channel);
201 volume_values[channel]=volume_value;
202 #if PREFER_FIXEDPOINT
205 if(factor > 4.0) factor = 4.0;
206 uint8_t factorF2P6 = (uint8_t) (factor*(1<<6));
207 factor_for_channel[channel] = factorF2P6;
209 factor_for_channel[channel]=factor;
214 LOGE(
"Invalid channel %d - max: %d", channel, info.
channels-1);
222 if (volume_values.size()==0)
return 0;
225 int cnt = volume_values.size();
226 for (
int j=0; j<cnt; j++){
227 total += volume_values[j];
229 return total /
static_cast<float>(cnt);
234 return channel>=info.
channels? 0 : volume_values[channel];
238 Print *p_out=
nullptr;
242 SimulatedAudioPot pot_vc;
243 CachedVolumeControl cached_volume{pot_vc};
244 Vector<float> volume_values;
245 #if PREFER_FIXEDPOINT
246 Vector<uint8_t> factor_for_channel;
248 Vector<float> factor_for_channel;
250 bool is_started =
false;
251 float max_value = 32767;
252 int max_channels = 0;
255 bool isVolumeUpdate(){
256 if (!is_started)
return false;
257 if (isAllChannelsFullVolume())
return false;
261 bool isAllChannelsFullVolume(){
262 for (
int ch=0;ch<info.
channels;ch++){
263 if (volume_values[ch]!=1.0)
return false;
270 factor_for_channel.resize(info.
channels);
271 volume_values.resize(info.
channels);
281 cfg1.volume = info.volume;
294 float volumeValue(
float vol){
295 if (!info.allow_boost && vol>1.0f) vol = 1.0;
296 if (vol<0.0f) vol = 0.0;
299 float value = (int)(vol * 100 + .5f);
300 float volume_value = (float)value / 100;
304 VolumeControl &volumeControl(){
305 return cached_volume;
308 #if PREFER_FIXEDPOINT
309 uint8_t factorForChannel(
int channel){
311 float factorForChannel(
int channel){
313 return factor_for_channel.size()==0? 1.0 : factor_for_channel[channel];
316 void applyVolume(
const uint8_t *buffer,
size_t size){
319 applyVolume16((int16_t*)buffer, size/2);
322 applyVolume24((int24_t*)buffer, size/
sizeof(int24_t));
325 applyVolume32((int32_t*)buffer, size/4);
332 void applyVolume16(int16_t* data,
size_t size){
333 for (
size_t j=0;j<size;j++){
334 #if PREFER_FIXEDPOINT
335 int32_t result = (data[j] * factorForChannel(j%info.
channels)) >> 6;
337 float result = factorForChannel(j%info.
channels) * data[j];
339 if (!info.allow_boost){
340 if (result>max_value) result = max_value;
341 if (result<-max_value) result = -max_value;
343 data[j]=
static_cast<int16_t
>(result);
347 void applyVolume24(int24_t* data,
size_t size) {
348 for (
size_t j=0;j<size;j++){
349 #if PREFER_FIXEDPOINT
350 int32_t result = (data[j] * factorForChannel(j%info.
channels)) >> 6;
352 float result = factorForChannel(j%info.
channels) * data[j];
354 if (!info.allow_boost){
355 if (result>max_value) result = max_value;
356 if (result<-max_value) result = -max_value;
358 int32_t result1 = result;
359 data[j]=
static_cast<int24_t
>(result1);
363 void applyVolume32(int32_t* data,
size_t size) {
364 for (
size_t j=0;j<size;j++){
365 #if PREFER_FIXEDPOINT
366 int64_t result = (
static_cast<int64_t
>(data[j]) *
static_cast<int64_t
>(factorForChannel(j%info.
channels))) >> 6;
368 float result = factorForChannel(j%info.
channels) * data[j];
370 if (!info.allow_boost){
371 if (result>max_value) result = max_value;
372 if (result<-max_value) result = -max_value;
374 data[j]=
static_cast<int32_t
>(result);