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);
193 if ((vol > 1.0f && !info.allow_boost) || vol < 0.0f) {
194 LOGE(
"Invalid volume: %f", vol);
199 float volume_value = volumeValue(vol);
200 if (volume_values[channel] != volume_value){
201 LOGI(
"setVolume: %f at %d", volume_value, channel);
203 volume_values[channel]=volume_value;
204 #if PREFER_FIXEDPOINT
207 if(factor > 4.0) factor = 4.0;
208 uint8_t factorF2P6 = (uint8_t) (factor*(1<<6));
209 factor_for_channel[channel] = factorF2P6;
211 factor_for_channel[channel]=factor;
216 LOGE(
"Invalid channel %d - max: %d", channel, info.
channels-1);
224 if (volume_values.size()==0)
return 0;
227 int cnt = volume_values.size();
228 for (
int j=0; j<cnt; j++){
229 total += volume_values[j];
231 return total /
static_cast<float>(cnt);
236 return channel>=info.
channels? 0 : volume_values[channel];
240 Print *p_out=
nullptr;
244 SimulatedAudioPot pot_vc;
245 CachedVolumeControl cached_volume{pot_vc};
246 Vector<float> volume_values;
247 #if PREFER_FIXEDPOINT
248 Vector<uint8_t> factor_for_channel;
250 Vector<float> factor_for_channel;
252 bool is_started =
false;
253 float max_value = 32767;
256 bool isVolumeUpdate(){
257 if (!is_started)
return false;
258 if (isAllChannelsFullVolume())
return false;
262 bool isAllChannelsFullVolume(){
263 int channels = MIN(info.
channels, volume_values.size());
264 for (
int ch=0;ch < channels;ch++){
265 if (volume_values[ch]!=1.0)
return false;
272 factor_for_channel.resize(info.
channels);
273 volume_values.resize(info.
channels);
283 cfg1.volume = info.volume;
284 cfg1.allow_boost = info.allow_boost;
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 if (factor_for_channel.size()==0)
return 1.0;
314 if (channel >= factor_for_channel.size())
return 1.0;
315 return factor_for_channel[channel];
318 void applyVolume(
const uint8_t *buffer,
size_t size){
321 applyVolume16((int16_t*)buffer, size/2);
324 applyVolume24((int24_t*)buffer, size/
sizeof(int24_t));
327 applyVolume32((int32_t*)buffer, size/4);
334 void applyVolume16(int16_t* data,
size_t size){
335 for (
size_t j=0;j<size;j++){
336 #if PREFER_FIXEDPOINT
337 int32_t result = (data[j] * factorForChannel(j%info.
channels)) >> 6;
339 float result = factorForChannel(j%info.
channels) * data[j];
341 if (!info.allow_boost){
342 if (result>max_value) result = max_value;
343 if (result<-max_value) result = -max_value;
345 data[j]=
static_cast<int16_t
>(result);
349 void applyVolume24(int24_t* data,
size_t size) {
350 for (
size_t j=0;j<size;j++){
351 #if PREFER_FIXEDPOINT
352 int32_t result = (data[j] * factorForChannel(j%info.
channels)) >> 6;
354 float result = factorForChannel(j%info.
channels) * data[j];
356 if (!info.allow_boost){
357 if (result>max_value) result = max_value;
358 if (result<-max_value) result = -max_value;
360 int32_t result1 = result;
361 data[j]=
static_cast<int24_t
>(result1);
365 void applyVolume32(int32_t* data,
size_t size) {
366 for (
size_t j=0;j<size;j++){
367 #if PREFER_FIXEDPOINT
368 int64_t result = (
static_cast<int64_t
>(data[j]) *
static_cast<int64_t
>(factorForChannel(j%info.
channels))) >> 6;
370 float result = factorForChannel(j%info.
channels) * data[j];
372 if (!info.allow_boost){
373 if (result>max_value) result = max_value;
374 if (result<-max_value) result = -max_value;
376 data[j]=
static_cast<int32_t
>(result);