switch to software volume scaling (it's bad tho i need daniel to do maths for me please)

custom
jacqueline 1 year ago
parent b319b3f07f
commit ade0094595
  1. 27
      src/audio/bt_audio_output.cpp
  2. 3
      src/audio/include/bt_audio_output.hpp
  3. 31
      src/drivers/bluetooth.cpp
  4. 7
      src/drivers/include/bluetooth.hpp

@ -7,9 +7,9 @@
#include "bt_audio_output.hpp"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cmath>
#include <memory>
#include <variant>
@ -32,7 +32,7 @@ namespace audio {
BluetoothAudioOutput::BluetoothAudioOutput(StreamBufferHandle_t s,
drivers::Bluetooth& bt,
tasks::WorkerPool& p)
: IAudioOutput(s), bluetooth_(bt), bg_worker_(p), volume_(10) {}
: IAudioOutput(s), bluetooth_(bt), bg_worker_(p), volume_() {}
BluetoothAudioOutput::~BluetoothAudioOutput() {}
@ -44,10 +44,16 @@ auto BluetoothAudioOutput::changeMode(Modes mode) -> void {
}
}
auto BluetoothAudioOutput::SetVolumeImbalance(int_fast8_t balance) -> void {}
auto BluetoothAudioOutput::SetVolumeImbalance(int_fast8_t balance) -> void {
// FIXME: Support two separate scaling factors in the bluetooth driver.
}
auto BluetoothAudioOutput::SetVolume(uint16_t v) -> void {
volume_ = std::clamp<uint16_t>(v, 0, 0x7f);
volume_ = std::clamp<uint16_t>(v, 0, 100);
bg_worker_.Dispatch<void>([&]() {
float factor = volume_ / 100.;
bluetooth_.SetVolumeFactor(factor);
});
}
auto BluetoothAudioOutput::GetVolume() -> uint16_t {
@ -55,20 +61,19 @@ auto BluetoothAudioOutput::GetVolume() -> uint16_t {
}
auto BluetoothAudioOutput::GetVolumePct() -> uint_fast8_t {
return static_cast<uint_fast8_t>(round(static_cast<int>(volume_) * 100.0 / 0x7f));
return static_cast<uint_fast8_t>(round(static_cast<int>(volume_)));
}
auto BluetoothAudioOutput::SetVolumePct(uint_fast8_t val) -> bool {
if (val > 100) {
return false;
}
uint16_t vol = (val * (0x7f))/100;
SetVolume(vol);
SetVolume(val);
return true;
}
auto BluetoothAudioOutput::GetVolumeDb() -> int_fast16_t {
double pct = GetVolumePct()/100.0;
double pct = GetVolumePct() / 100.0;
if (pct <= 0) {
pct = 0.01;
}
@ -82,11 +87,11 @@ auto BluetoothAudioOutput::SetVolumeDb(int_fast16_t val) -> bool {
}
auto BluetoothAudioOutput::AdjustVolumeUp() -> bool {
if (volume_ == 0x7f) {
if (volume_ == 100) {
return false;
}
volume_++;
bg_worker_.Dispatch<void>([&]() { bluetooth_.SetVolume(volume_); });
SetVolume(volume_);
return true;
}
@ -95,7 +100,7 @@ auto BluetoothAudioOutput::AdjustVolumeDown() -> bool {
return false;
}
volume_--;
bg_worker_.Dispatch<void>([&]() { bluetooth_.SetVolume(volume_); });
SetVolume(volume_);
return true;
}

@ -54,7 +54,8 @@ class BluetoothAudioOutput : public IAudioOutput {
private:
drivers::Bluetooth& bluetooth_;
tasks::WorkerPool& bg_worker_;
uint8_t volume_;
uint16_t volume_;
};
} // namespace audio

@ -25,6 +25,7 @@
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"
#include "freertos/timers.h"
#include "sample.hpp"
#include "tinyfsm/include/tinyfsm.hpp"
#include "bluetooth_types.hpp"
@ -37,6 +38,8 @@ namespace drivers {
[[maybe_unused]] static constexpr char kTag[] = "bluetooth";
DRAM_ATTR static StreamBufferHandle_t sStream = nullptr;
DRAM_ATTR static std::atomic<float> sVolumeFactor = 1.f;
static tasks::WorkerPool* sBgWorker;
auto gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t* param) -> void {
@ -69,7 +72,16 @@ IRAM_ATTR auto a2dp_data_cb(uint8_t* buf, int32_t buf_size) -> int32_t {
if (stream == nullptr) {
return 0;
}
return xStreamBufferReceive(stream, buf, buf_size, 0);
size_t bytes_received = xStreamBufferReceive(stream, buf, buf_size, 0);
// Apply software volume scaling.
int16_t* samples = reinterpret_cast<int16_t*>(buf);
float factor = sVolumeFactor.load();
for (size_t i = 0; i < bytes_received / 2; i++) {
samples[i] *= factor;
}
return bytes_received;
}
Bluetooth::Bluetooth(NvsStorage& storage, tasks::WorkerPool& bg_worker) {
@ -150,10 +162,8 @@ auto Bluetooth::SetSource(StreamBufferHandle_t src) -> void {
bluetooth::events::SourceChanged{});
}
auto Bluetooth::SetVolume(uint8_t vol) -> void {
auto lock = bluetooth::BluetoothState::lock();
tinyfsm::FsmList<bluetooth::BluetoothState>::dispatch(
bluetooth::events::ChangeVolume{.volume = vol});
auto Bluetooth::SetVolumeFactor(float f) -> void {
sVolumeFactor = f;
}
auto Bluetooth::SetEventHandler(std::function<void(bluetooth::Event)> cb)
@ -654,17 +664,6 @@ void Connected::react(const events::SourceChanged& ev) {
}
}
void Connected::react(const events::ChangeVolume& ev) {
esp_err_t err = esp_avrc_ct_send_set_absolute_volume_cmd(
transaction_num_++, std::clamp<uint8_t>(ev.volume, 0, 0x7f));
if (err != ESP_OK) {
ESP_LOGW(kTag, "send vol failed %u", err);
}
if (transaction_num_ > ESP_AVRC_TRANS_LABEL_MAX) {
transaction_num_ = 0;
}
}
void Connected::react(const events::internal::Gap& ev) {
sScanner_->HandleGapEvent(ev);
switch (ev.type) {

@ -43,7 +43,7 @@ class Bluetooth {
auto PreferredDevice() -> std::optional<bluetooth::MacAndName>;
auto SetSource(StreamBufferHandle_t) -> void;
auto SetVolume(uint8_t) -> void;
auto SetVolumeFactor(float) -> void;
auto SetEventHandler(std::function<void(bluetooth::Event)> cb) -> void;
};
@ -60,9 +60,6 @@ struct SourceChanged : public tinyfsm::Event {};
struct DeviceDiscovered : public tinyfsm::Event {
const Device& device;
};
struct ChangeVolume : public tinyfsm::Event {
const uint8_t volume;
};
namespace internal {
struct Gap : public tinyfsm::Event {
@ -131,7 +128,6 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
virtual void react(const events::ConnectTimedOut& ev){};
virtual void react(const events::PreferredDeviceChanged& ev){};
virtual void react(const events::SourceChanged& ev){};
virtual void react(const events::ChangeVolume&) {}
virtual void react(const events::DeviceDiscovered&);
@ -204,7 +200,6 @@ class Connected : public BluetoothState {
void react(const events::PreferredDeviceChanged& ev) override;
void react(const events::SourceChanged& ev) override;
void react(const events::ChangeVolume&) override;
void react(const events::Disable& ev) override;
void react(const events::internal::Gap& ev) override;

Loading…
Cancel
Save