Derive playback devices from common AudioOutputBase (#2703)

The audio output objects all have the same general necessary configuration
calls.  Abstract them out to a generic AudioOutputBase interface class that
they will inherit from.  Simplifies letting applications use different
output channels.

Should be backwards compatible with existing code.
This commit was merged in pull request #2703.
This commit is contained in:
Earle F. Philhower, III
2024-12-18 12:19:40 -08:00
committed by GitHub
parent f1b965f704
commit eecbcdf59a
7 changed files with 77 additions and 22 deletions
+21
View File
@@ -0,0 +1,21 @@
// Abstract class for audio output devices to allow easy swapping between output devices
#pragma once
#include <Print.h>
class AudioOutputBase : public Print {
public:
virtual ~AudioOutputBase() { }
virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) = 0;
virtual bool setBitsPerSample(int bps) = 0;
virtual bool setFrequency(int freq) = 0;
virtual bool setStereo(bool stereo = true) = 0;
virtual bool begin() = 0;
virtual bool end() = 0;
virtual bool getUnderflow() = 0;
virtual void onTransmit(void(*)(void *), void *) = 0;
// From Print
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual int availableForWrite() = 0;
};
@@ -220,6 +220,8 @@ void A2DPSource::clearPairing() {
size_t A2DPSource::write(const uint8_t *buffer, size_t size) {
BluetoothLock b;
size = std::min((size_t)availableForWrite(), size);
size_t count = 0;
size /= 2;
@@ -260,6 +262,7 @@ int A2DPSource::availableForWrite() {
} else {
avail = _pcmBufferSize - _pcmWriter + _pcmReader - 1;
}
avail /= sizeof(uint32_t); // availableForWrite always 32b sample pairs in this core...
return avail;
}
+22 -5
View File
@@ -24,17 +24,20 @@
#include <BluetoothHCI.h>
#include <BluetoothLock.h>
#include "BluetoothMediaConfigurationSBC.h"
#include <AudioOutputBase.h>
#include <functional>
#include <list>
#include <memory>
class A2DPSource : public Stream {
class A2DPSource : public Stream, public AudioOutputBase {
public:
A2DPSource() {
}
bool setFrequency(uint32_t rate) {
virtual ~A2DPSource() { }
virtual bool setFrequency(int rate) override {
if (_running || ((rate != 44100) && (rate != 48000))) {
return false;
}
@@ -51,7 +54,14 @@ public:
return true;
}
void onTransmit(void (*cb)(void *), void *cbData = nullptr) {
virtual bool setBitsPerSample(int bps) override {
return bps == 16;
}
virtual bool setStereo(bool stereo = true) override {
return stereo;
}
virtual void onTransmit(void (*cb)(void *), void *cbData = nullptr) override {
_transmitCB = cb;
_transmitData = cbData;
}
@@ -84,7 +94,11 @@ public:
return true;
}
bool getUnderflow() {
virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override {
return setBufferSize(buffers * bufferWords * sizeof(int32_t));
}
virtual bool getUnderflow() override {
BluetoothLock b;
if (!_running) {
return false;
@@ -102,7 +116,10 @@ public:
}
}
bool begin();
virtual bool begin() override;
virtual bool end() override {
return false; // We can't actually stop bluetooth on this device
}
std::vector<BTDeviceInfo> scan(uint32_t mask = BluetoothHCI::speaker_cod, int scanTimeSec = 5, bool async = false) {
return _hci.scan(mask, scanTimeSec, async);
+2 -1
View File
@@ -287,7 +287,7 @@ bool I2S::begin() {
return true;
}
void I2S::end() {
bool I2S::end() {
if (_running) {
if (_MCLKenabled) {
pio_sm_set_enabled(_pioMCLK, _smMCLK, false);
@@ -301,6 +301,7 @@ void I2S::end() {
delete _i2s;
_i2s = nullptr;
}
return true;
}
int I2S::available() {
+14 -7
View File
@@ -21,9 +21,10 @@
#pragma once
#include <Arduino.h>
#include "AudioBufferManager.h"
#include <AudioBufferManager.h>
#include <AudioOutputBase.h>
class I2S : public Stream {
class I2S : public Stream, public AudioOutputBase {
public:
I2S(PinMode direction = OUTPUT, pin_size_t bclk = 26, pin_size_t data = 28, pin_size_t mclk = 25);
virtual ~I2S();
@@ -31,9 +32,12 @@ public:
bool setBCLK(pin_size_t pin);
bool setDATA(pin_size_t pin);
bool setMCLK(pin_size_t pin);
bool setBitsPerSample(int bps);
bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0);
bool setFrequency(int newFreq);
virtual bool setBitsPerSample(int bps) override;
virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override;
virtual bool setFrequency(int newFreq) override;
virtual bool setStereo(bool stereo = true) override {
return stereo;
}
bool setLSBJFormat();
bool setTDMFormat();
bool setTDMChannels(int channels);
@@ -46,8 +50,11 @@ public:
return begin();
}
bool begin();
void end();
virtual bool begin() override;
virtual bool end() override;
virtual bool getUnderflow() override {
return getOverUnderflow();
}
// from Stream
virtual int available() override;
+4 -2
View File
@@ -40,7 +40,8 @@ PWMAudio::~PWMAudio() {
end();
}
bool PWMAudio::setBuffers(size_t buffers, size_t bufferWords) {
bool PWMAudio::setBuffers(size_t buffers, size_t bufferWords, int32_t silence) {
(void) silence;
if (_running || (buffers < 3) || (bufferWords < 8)) {
return false;
}
@@ -176,7 +177,7 @@ bool PWMAudio::begin() {
return true;
}
void PWMAudio::end() {
bool PWMAudio::end() {
if (_running) {
_running = false;
pinMode(_pin, OUTPUT);
@@ -189,6 +190,7 @@ void PWMAudio::end() {
dma_timer_unclaim(_pacer);
_pacer = -1;
}
return true;
}
int PWMAudio::available() {
+11 -7
View File
@@ -21,20 +21,24 @@
#pragma once
#include <Arduino.h>
#include "AudioBufferManager.h"
#include <AudioOutputBase.h>
#include <AudioBufferManager.h>
class PWMAudio : public Stream {
class PWMAudio : public Stream, public AudioOutputBase {
public:
PWMAudio(pin_size_t pin = 0, bool stereo = false);
virtual ~PWMAudio();
bool setBuffers(size_t buffers, size_t bufferWords);
virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override;
/*Sets the frequency of the PWM in hz*/
bool setPWMFrequency(int newFreq);
/*Sets the sample rate frequency in hz*/
bool setFrequency(int frequency);
virtual bool setFrequency(int frequency) override;
bool setPin(pin_size_t pin);
bool setStereo(bool stereo = true);
virtual bool setStereo(bool stereo = true) override;
virtual bool setBitsPerSample(int bits) override {
return bits == 16;
}
bool begin(long sampleRate) {
_sampleRate = sampleRate;
@@ -47,8 +51,8 @@ public:
return begin();
}
bool begin();
void end();
virtual bool begin() override;
virtual bool end() override;
// from Stream
virtual int available() override;