More TX audio fixes...

merge-requests/2/head
Phil Taylor 2021-02-13 00:45:59 +00:00
rodzic 9cbd572d4a
commit 3ac1c004e3
2 zmienionych plików z 42 dodań i 31 usunięć

Wyświetl plik

@ -4,14 +4,15 @@
*/ */
#include "audiohandler.h" #include "audiohandler.h"
static int8_t uLawEncode(int16_t number) #define MULAW_BIAS 33
#define MULAW_MAX 0x1fff
qint8 uLawEncode(qint16 number)
{ {
const uint16_t MULAW_MAX = 0x1FFF; quint16 mask = 0x1000;
const uint16_t MULAW_BIAS = 33; quint8 sign = 0;
uint16_t mask = 0x1000; quint8 position = 12;
uint8_t sign = 0; quint8 lsb = 0;
uint8_t position = 12;
uint8_t lsb = 0;
if (number < 0) if (number < 0)
{ {
number = -number; number = -number;
@ -28,8 +29,25 @@ static int8_t uLawEncode(int16_t number)
return (~(sign | ((position - 5) << 4) | lsb)); return (~(sign | ((position - 5) << 4) | lsb));
} }
/*
qint16 uLawDecode(qint8 number)
{
quint8 sign = 0, position = 0;
qint16 decoded = 0;
number = ~number;
if (number & 0x80)
{
number &= ~(1 << 7);
sign = -1;
}
position = ((number & 0xF0) >> 4) + 5;
decoded = ((1 << position) | ((number & 0x0F) << (position - 4))
| (1 << (position - 5))) - MULAW_BIAS;
return (sign == 0) ? (decoded) : (-(decoded));
}
*/
static qint16 uLawDecode(quint8 in) qint16 uLawDecode(quint8 in)
{ {
static const qint16 ulaw_decode[256] = { static const qint16 ulaw_decode[256] = {
-32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
@ -69,7 +87,6 @@ static qint16 uLawDecode(quint8 in)
return ulaw_decode[in]; return ulaw_decode[in];
} }
audioHandler::audioHandler(QObject* parent) : audioHandler::audioHandler(QObject* parent) :
QIODevice(parent), QIODevice(parent),
isInitialized(false), isInitialized(false),
@ -172,8 +189,8 @@ void audioHandler::reinit()
if (this->isInput) if (this->isInput)
{ {
// (Re)initialize audio input // (Re)initialize audio input
delete audioInput; if (audioInput != Q_NULLPTR)
audioInput = Q_NULLPTR; delete audioInput;
audioInput = new QAudioInput(deviceInfo, format, this); audioInput = new QAudioInput(deviceInfo, format, this);
audioInput->setBufferSize(audioBuffer); audioInput->setBufferSize(audioBuffer);
audioInput->setNotifyInterval(20); audioInput->setNotifyInterval(20);
@ -184,7 +201,8 @@ void audioHandler::reinit()
} }
else { else {
// (Re)initialize audio output // (Re)initialize audio output
delete audioOutput; if (audioOutput != Q_NULLPTR)
delete audioOutput;
audioOutput = Q_NULLPTR; audioOutput = Q_NULLPTR;
audioOutput = new QAudioOutput(deviceInfo, format, this); audioOutput = new QAudioOutput(deviceInfo, format, this);
audioOutput->setBufferSize(audioBuffer); audioOutput->setBufferSize(audioBuffer);
@ -214,7 +232,6 @@ void audioHandler::start()
else { else {
this->open(QIODevice::ReadOnly); this->open(QIODevice::ReadOnly);
} }
buffer.clear(); // No buffer used on audioinput. buffer.clear(); // No buffer used on audioinput.
if (isInput) { if (isInput) {
@ -248,9 +265,12 @@ void audioHandler::flush()
void audioHandler::stop() void audioHandler::stop()
{ {
QMutexLocker locker(&mutex);
if (audioOutput && audioOutput->state() != QAudio::StoppedState) { if (audioOutput && audioOutput->state() != QAudio::StoppedState) {
// Stop audio output // Stop audio output
audioOutput->stop(); audioOutput->stop();
QByteArray ret;
buffer.clear(); buffer.clear();
this->close(); this->close();
} }
@ -267,6 +287,7 @@ qint64 audioHandler::readData(char* data, qint64 maxlen)
{ {
// Calculate output length, always full samples // Calculate output length, always full samples
int outlen = 0; int outlen = 0;
QMutexLocker locker(&mutex);
if (isUlaw) if (isUlaw)
{ {
// Need to process uLaw. // Need to process uLaw.
@ -274,7 +295,7 @@ qint64 audioHandler::readData(char* data, qint64 maxlen)
outlen = qMin(buffer.length(), (int)maxlen / 2); outlen = qMin(buffer.length(), (int)maxlen / 2);
for (int f = 0; f < outlen; f++) for (int f = 0; f < outlen; f++)
{ {
qToLittleEndian<qint16>(uLawDecode(buffer.at(f)), data + f * 2); qToLittleEndian<qint16>(uLawDecode(buffer.at(f)),data + f * 2);
} }
buffer.remove(0, outlen); buffer.remove(0, outlen);
outlen = outlen * 2; outlen = outlen * 2;
@ -285,7 +306,7 @@ qint64 audioHandler::readData(char* data, qint64 maxlen)
outlen = qMin(buffer.length(), (int)maxlen/2); outlen = qMin(buffer.length(), (int)maxlen/2);
for (int f = 0; f < outlen; f++) for (int f = 0; f < outlen; f++)
{ {
qToLittleEndian<qint16>((qint16)(buffer[f]<<8) - 32640, data + f * 2); qToLittleEndian<qint16>((qint16)(buffer[f]<<8) - 32640,data + f * 2);
} }
buffer.remove(0, outlen); buffer.remove(0, outlen);
outlen = outlen * 2; outlen = outlen * 2;
@ -305,19 +326,18 @@ qint64 audioHandler::readData(char* data, qint64 maxlen)
qint64 audioHandler::writeData(const char* data, qint64 len) qint64 audioHandler::writeData(const char* data, qint64 len)
{ {
QMutexLocker locker(&mutex);
QMutexLocker locker(&mutex);
if (buffer.length() > bufferSize * 4) if (buffer.length() > bufferSize * 4)
{ {
qWarning() << "writeData() Buffer overflow"; qWarning() << "writeData() Buffer overflow";
buffer.clear(); buffer.clear();
} }
//int chunkSize = 960; // Assume 8bit or uLaw.
if (isUlaw) { if (isUlaw) {
for (int f = 0; f < len / 2; f++) for (int f = 0; f < len / 2; f++)
{ {
buffer.append(uLawEncode(qFromLittleEndian<qint16>(data + f * 2))); buffer.append((quint8)uLawEncode(qFromLittleEndian<qint16>(data + f * 2)));
} }
} }
else if (radioSampleBits == 8) { else if (radioSampleBits == 8) {
@ -328,7 +348,6 @@ qint64 audioHandler::writeData(const char* data, qint64 len)
} }
else if (radioSampleBits == 16) { else if (radioSampleBits == 16) {
buffer.append(QByteArray::fromRawData(data, len)); buffer.append(QByteArray::fromRawData(data, len));
//chunkSize = 1920;
} }
else { else {
qWarning() << "Unsupported number of bits! :" << radioSampleBits; qWarning() << "Unsupported number of bits! :" << radioSampleBits;
@ -370,21 +389,13 @@ void audioHandler::stateChanged(QAudio::State state)
void audioHandler::incomingAudio(const QByteArray& data) void audioHandler::incomingAudio(const QByteArray& data)
{ {
//qDebug() << "Got " << data.length() << " samples"; //qDebug() << "Got " << data.length() << " samples";
QMutexLocker locker(&mutex);
if (audioOutput != Q_NULLPTR && audioOutput->state() != QAudio::StoppedState) { if (audioOutput != Q_NULLPTR && audioOutput->state() != QAudio::StoppedState) {
// Append input data to the end of buffer QMutexLocker locker(&mutex);
buffer.append(data); buffer.append(data);
//if (buffer.length() > bufferSize*2) {
// this->flush();
//}
// If audio is suspended and buffer is full, resume
if (audioOutput->state() == QAudio::SuspendedState) { if (audioOutput->state() == QAudio::SuspendedState) {
if (buffer.length() >= bufferSize) { qDebug() << "RX Audio Suspended, Resuming...";
qDebug() << this->metaObject()->className() << ": Resuming..."; audioOutput->resume();
audioOutput->resume();
}
} }
} }
else { else {

Wyświetl plik

@ -40,11 +40,11 @@ public:
qint64 writeData(const char* data, qint64 len); qint64 writeData(const char* data, qint64 len);
qint64 bytesAvailable() const; qint64 bytesAvailable() const;
bool isSequential() const; bool isSequential() const;
void incomingAudio(const QByteArray& data);
QByteArray getNextAudioChunk(void); QByteArray getNextAudioChunk(void);
public slots: public slots:
bool init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 bufferSize, const bool isulaw, const bool isinput); bool init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 bufferSize, const bool isulaw, const bool isinput);
void incomingAudio(const QByteArray& data);
void changeBufferSize(const quint16 newSize); void changeBufferSize(const quint16 newSize);
private slots: private slots: