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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user