1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md
#pragma once
#include <Audio/Endpoint.hpp>
#include <Audio/AudioDevice.hpp>
#include <Audio/AudioFormat.hpp>
#include <Audio/Stream.hpp>
#include <interface/profiles/A2DP/MediaContext.hpp>
#include <interface/profiles/AudioProfile.hpp>
extern "C"
{
#include "classic/btstack_cvsd_plc.h"
}
namespace bluetooth
{
class BluetoothAudioDevice : public audio::AudioDevice
{
public:
explicit BluetoothAudioDevice(AudioProfile audioProfile);
virtual ~BluetoothAudioDevice();
virtual auto getProfileType() const -> AudioProfile;
auto setInputGain(float gain) -> audio::AudioDevice::RetCode override;
// Endpoint control methods
void enableInput() override;
void enableOutput() override;
void disableInput() override;
void disableOutput() override;
protected:
[[nodiscard]] auto isInputEnabled() const -> bool;
[[nodiscard]] auto isOutputEnabled() const -> bool;
auto fillSbcAudioBuffer() -> int;
auto scaleVolume(audio::Stream::Span &dataSpan) const -> void;
float outputVolume;
private:
bool outputEnabled = false;
bool inputEnabled = false;
AudioProfile profile = AudioProfile::None;
};
class A2DPAudioDevice : public BluetoothAudioDevice
{
public:
explicit A2DPAudioDevice(const float volume) : BluetoothAudioDevice(AudioProfile::A2DP)
{
outputVolume = volume;
}
auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
void onDataSend() override;
void onDataReceive() override;
auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
[[nodiscard]] auto getTraits() const -> Traits override;
auto getSourceFormat() -> ::audio::AudioFormat override;
audio::AudioDevice::RetCode Start() override;
audio::AudioDevice::RetCode Stop() override;
audio::AudioDevice::RetCode Resume() override;
audio::AudioDevice::RetCode Pause() override;
private:
[[nodiscard]] audio::AudioDevice::RetCode waitUntilStreamPaused() const;
};
class CVSDAudioDevice : public BluetoothAudioDevice
{
public:
explicit CVSDAudioDevice(const float volume, const AudioProfile &profile) : BluetoothAudioDevice(profile)
{
outputVolume = volume;
btstack_cvsd_plc_init(&cvsdPlcState);
}
auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
void onDataSend() override;
void onDataSend(std::uint16_t scoHandle);
void onDataReceive() override;
auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
[[nodiscard]] auto getTraits() const -> Traits override;
auto getSourceFormat() -> ::audio::AudioFormat override;
void enableInput() override;
void setAclHandle(hci_con_handle_t handle);
void receiveCVSD(audio::AbstractStream::Span receivedData);
private:
static constexpr std::size_t scratchBufferSize = 128;
static constexpr auto packetHandleOffset = 0;
static constexpr auto packetStatusOffset = 1;
static constexpr auto packetLengthOffset = 2;
static constexpr auto packetDataOffset = 3;
static constexpr auto supportedBitWidth = 16U;
static constexpr auto supportedChannels = 1;
static constexpr auto allGoodMask = 0x30;
auto decodeCVSD(audio::AbstractStream::Span dataToDecode) -> audio::AbstractStream::Span;
std::unique_ptr<std::uint8_t[]> rxLeftovers;
std::unique_ptr<std::int16_t[]> decoderBuffer;
std::size_t leftoversSize = 0;
btstack_cvsd_plc_state_t cvsdPlcState;
hci_con_handle_t aclHandle;
};
} // namespace bluetooth