kopia lustrzana https://gitlab.com/eliggett/wfview
More TX audio fixes...
rodzic
9cbd572d4a
commit
3ac1c004e3
|
@ -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 {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Ładowanie…
Reference in New Issue