Arduino A2DP
A2DPVolumeControl.h
1 #pragma once
2 
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Copyright 2020 Phil Schatzmann
16 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
17 
18 #include "esp_log.h"
19 
26 struct __attribute__((packed)) Frame {
27  int16_t channel1;
28  int16_t channel2;
29 
30  Frame(int v = 0) { channel1 = channel2 = v; }
31 
32  Frame(int ch1, int ch2) {
33  channel1 = ch1;
34  channel2 = ch2;
35  }
36 };
37 
46  public:
47  A2DPVolumeControl() { volumeFactorMax = 0x1000; }
48 
49  virtual void update_audio_data(uint8_t* data, uint16_t byteCount) {
50  update_audio_data((Frame*)data, byteCount / 4);
51  }
52 
53  virtual void update_audio_data(Frame* data, uint16_t frameCount) {
54  if (data != nullptr && frameCount > 0 && (mono_downmix || is_volume_used)) {
55  ESP_LOGD("VolumeControl", "update_audio_data");
56  for (int i = 0; i < frameCount; i++) {
57  int32_t pcmLeft = data[i].channel1;
58  int32_t pcmRight = data[i].channel2;
59  // if mono -> we provide the same output on both channels
60  if (mono_downmix) {
61  pcmRight = pcmLeft = (pcmLeft + pcmRight) / 2;
62  }
63  // adjust the volume
64  if (is_volume_used) {
65  pcmLeft = clip(pcmLeft * volumeFactor / volumeFactorMax);
66  pcmRight = clip(pcmRight * volumeFactor / volumeFactorMax);
67  }
68  data[i].channel1 = pcmLeft;
69  data[i].channel2 = pcmRight;
70  }
71  }
72  }
73 
74  // provides a factor in the range of 0 to 4096
75  int32_t get_volume_factor() { return volumeFactor; }
76 
77  // provides the max factor value 4096
78  int32_t get_volume_factor_max() { return volumeFactorMax; }
79 
80  void set_enabled(bool enabled) { is_volume_used = enabled; }
81 
82  void set_mono_downmix(bool enabled) { mono_downmix = enabled; }
83 
84  virtual void set_volume(uint8_t volume) = 0;
85 
86  protected:
87  bool is_volume_used = false;
88  bool mono_downmix = false;
89  int32_t volumeFactor;
90  int32_t volumeFactorMax;
91 
92  int32_t clip(int32_t value) {
93  int32_t result = value;
94  if (value < -32768) result = -32768;
95  if (value > 32767) result = 32767;
96  return result;
97  }
98 };
99 
106  protected:
107  void set_volume(uint8_t volume) override {
108  constexpr float base = 1.4f;
109  constexpr float bits = 12.0f;
110  constexpr float zero_ofs = pow(base, -bits);
111  constexpr float scale = pow(2.0f, bits);
112  float volumeFactorFloat =
113  (pow(base, volume * bits / 127.0f - bits) - zero_ofs) * scale /
114  (1.0f - zero_ofs);
115  volumeFactor = volumeFactorFloat;
116  if (volumeFactor > 0xfff) {
117  volumeFactor = 0xfff;
118  }
119  }
120 };
121 
127  protected:
128  void set_volume(uint8_t volume) override {
129  float volumeFactorFloat = volume;
130  volumeFactorFloat = pow(2.0f, volumeFactorFloat * 12.0f / 127.0f);
131  volumeFactor = volumeFactorFloat - 1.0f;
132  if (volumeFactor > 0xfff) {
133  volumeFactor = 0xfff;
134  }
135  }
136 };
137 
144  public:
145  A2DPLinearVolumeControl() { volumeFactorMax = 128; }
146 
147  protected:
148  void set_volume(uint8_t volume) override { volumeFactor = volume; }
149 };
150 
157  public:
158  void update_audio_data(Frame* data, uint16_t frameCount) override {}
159  void set_volume(uint8_t volume) override {}
160 };
Default implementation for handling of the volume of the audio data.
Definition: A2DPVolumeControl.h:105
The simplest possible implementation of a VolumeControl.
Definition: A2DPVolumeControl.h:143
Keeps the audio data as is -> no volume control!
Definition: A2DPVolumeControl.h:156
Exponentional volume control.
Definition: A2DPVolumeControl.h:126
Abstract class for handling of the volume of the audio data.
Definition: A2DPVolumeControl.h:45