wfview/audiohandler.h

425 wiersze
12 KiB
C
Czysty Zwykły widok Historia

2021-02-11 19:18:35 +00:00
#ifndef AUDIOHANDLER_H
#define AUDIOHANDLER_H
#include <QObject>
#include <QByteArray>
2021-05-24 08:27:18 +00:00
#include <QMutex>
2021-05-27 12:54:52 +00:00
#include <QtEndian>
#include <QtMath>
2021-06-04 07:24:26 +00:00
#if defined(RTAUDIO)
2021-11-01 20:27:33 +00:00
#ifdef Q_OS_WIN
#include "RtAudio.h"
#else
2021-06-06 16:56:48 +00:00
#include "rtaudio/RtAudio.h"
2021-11-01 20:27:33 +00:00
#endif
2021-06-04 07:24:26 +00:00
#elif defined (PORTAUDIO)
#include "portaudio.h"
2021-11-01 20:27:33 +00:00
//#error "PORTAUDIO is not currently supported"
2021-06-04 07:24:26 +00:00
#else
#include <QAudioOutput>
#include <QAudioFormat>
#include <QAudioDeviceInfo>
#include <QAudioInput>
#include <QIODevice>
#endif
2021-05-16 20:16:59 +00:00
2022-01-29 22:50:58 +00:00
#include "packettypes.h"
2021-05-16 20:16:59 +00:00
typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16
2022-03-23 17:27:47 +00:00
2021-02-11 19:18:35 +00:00
#include <QThread>
2021-02-12 20:42:56 +00:00
#include <QTimer>
#include <QTime>
2021-05-17 15:19:36 +00:00
#include <QMap>
2021-03-09 17:22:16 +00:00
#include "resampler/speex_resampler.h"
#include "ring/ring.h"
2021-07-29 15:18:59 +00:00
2021-06-16 08:52:47 +00:00
#ifdef Q_OS_WIN
2021-06-16 08:49:38 +00:00
#include "opus.h"
2021-06-16 08:52:47 +00:00
#else
#include "opus/opus.h"
#endif
#include "audiotaper.h"
2022-04-03 19:16:52 +00:00
#include <Eigen/Eigen>
//#include <r8bbase.h>
//#include <CDSPResampler.h>
2021-02-11 19:18:35 +00:00
#include <QDebug>
//#define BUFFER_SIZE (32*1024)
2021-03-09 17:22:16 +00:00
#define INTERNAL_SAMPLE_RATE 48000
2021-05-16 20:16:59 +00:00
#define MULAW_BIAS 33
#define MULAW_MAX 0x1fff
struct audioPacket {
2021-03-14 08:44:30 +00:00
quint32 seq;
QTime time;
quint16 sent;
QByteArray data;
2022-01-29 22:50:58 +00:00
quint8 guid[GUIDLEN];
};
2021-06-04 07:24:26 +00:00
struct audioSetup {
QString name;
2022-04-03 19:16:52 +00:00
// quint8 bits;
// quint8 radioChan;
// quint16 samplerate;
2021-06-04 07:24:26 +00:00
quint16 latency;
quint8 codec;
2022-04-03 19:16:52 +00:00
bool ulaw = false;
2021-06-04 07:24:26 +00:00
bool isinput;
2022-04-03 19:16:52 +00:00
QAudioFormat format; // Use this for all audio APIs
2021-11-01 20:27:33 +00:00
#if defined(RTAUDIO) || defined(PORTAUDIO)
2021-06-04 07:24:26 +00:00
int port;
#else
QAudioDeviceInfo port;
#endif
quint8 resampleQuality;
unsigned char localAFgain;
2021-06-04 07:24:26 +00:00
};
// For QtMultimedia, use a native QIODevice
#if !defined(PORTAUDIO) && !defined(RTAUDIO)
class audioHandler : public QIODevice
#else
2021-05-23 15:09:41 +00:00
class audioHandler : public QObject
2021-06-04 07:24:26 +00:00
#endif
2021-02-11 19:18:35 +00:00
{
Q_OBJECT
public:
audioHandler(QObject* parent = 0);
~audioHandler();
2021-05-27 17:34:44 +00:00
int getLatency();
2021-02-11 19:18:35 +00:00
2021-06-06 16:56:48 +00:00
#if !defined (RTAUDIO) && !defined(PORTAUDIO)
2021-06-04 07:24:26 +00:00
bool setDevice(QAudioDeviceInfo deviceInfo);
void start();
void flush();
void stop();
qint64 bytesAvailable() const;
bool isSequential() const;
2021-06-06 16:56:48 +00:00
#endif
2021-06-04 07:24:26 +00:00
2021-02-13 11:04:26 +00:00
void getNextAudioChunk(QByteArray &data);
quint16 getAmplitude();
2021-05-23 15:09:41 +00:00
2021-06-04 07:24:26 +00:00
public slots:
bool init(audioSetup setup);
void changeLatency(const quint16 newSize);
void setVolume(unsigned char volume);
2021-05-27 17:34:44 +00:00
void incomingAudio(const audioPacket data);
2021-02-11 19:18:35 +00:00
2021-06-04 07:24:26 +00:00
private slots:
2021-06-06 16:56:48 +00:00
#if !defined (RTAUDIO) && !defined(PORTAUDIO)
2021-06-04 07:24:26 +00:00
void notified();
void stateChanged(QAudio::State state);
2021-06-06 16:56:48 +00:00
#endif
2021-06-04 07:24:26 +00:00
2021-02-11 19:18:35 +00:00
signals:
void audioMessage(QString message);
void sendLatency(quint16 newSize);
2021-02-11 19:18:35 +00:00
void haveAudioData(const QByteArray& data);
2021-02-12 20:42:56 +00:00
2021-02-11 19:18:35 +00:00
private:
2021-06-04 07:24:26 +00:00
#if defined(RTAUDIO)
2021-05-24 17:00:38 +00:00
int readData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status);
static int staticRead(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void* userData) {
return static_cast<audioHandler*>(userData)->readData(outputBuffer, inputBuffer, nFrames, streamTime, status);
}
int writeData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status);
static int staticWrite(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void* userData) {
return static_cast<audioHandler*>(userData)->writeData(outputBuffer, inputBuffer, nFrames, streamTime, status);
}
2021-06-04 07:24:26 +00:00
#elif defined(PORTAUDIO)
2021-11-01 20:27:33 +00:00
int readData(const void* inputBuffer, void* outputBuffer,
unsigned long nFrames,
const PaStreamCallbackTimeInfo* streamTime,
PaStreamCallbackFlags status);
static int staticRead(const void* inputBuffer, void* outputBuffer, unsigned long nFrames, const PaStreamCallbackTimeInfo* streamTime, PaStreamCallbackFlags status, void* userData) {
return ((audioHandler*)userData)->readData(inputBuffer, outputBuffer, nFrames, streamTime, status);
}
int writeData(const void* inputBuffer, void* outputBuffer,
unsigned long nFrames,
const PaStreamCallbackTimeInfo* streamTime,
PaStreamCallbackFlags status);
static int staticWrite(const void* inputBuffer, void* outputBuffer, unsigned long nFrames, const PaStreamCallbackTimeInfo* streamTime, PaStreamCallbackFlags status, void* userData) {
return ((audioHandler*)userData)->writeData(inputBuffer, outputBuffer, nFrames, streamTime, status);
}
2021-05-24 17:00:38 +00:00
2021-06-04 07:24:26 +00:00
#else
qint64 readData(char* data, qint64 nBytes);
qint64 writeData(const char* data, qint64 nBytes);
#endif
2021-02-11 19:18:35 +00:00
2021-06-04 07:24:26 +00:00
void reinit();
bool isInitialized=false;
2021-07-06 09:04:35 +00:00
bool isReady = false;
bool audioBuffered = false;
2021-06-04 07:24:26 +00:00
#if defined(RTAUDIO)
RtAudio* audio = Q_NULLPTR;
2021-05-16 20:16:59 +00:00
int audioDevice = 0;
RtAudio::StreamParameters aParams;
2021-06-02 11:48:35 +00:00
RtAudio::StreamOptions options;
2021-05-16 20:16:59 +00:00
RtAudio::DeviceInfo info;
2021-06-04 07:24:26 +00:00
#elif defined(PORTAUDIO)
2021-11-01 20:27:33 +00:00
PaStream* audio = Q_NULLPTR;
PaStreamParameters aParams;
const PaDeviceInfo *info;
2021-06-04 07:24:26 +00:00
#else
QAudioOutput* audioOutput=Q_NULLPTR;
QAudioInput* audioInput=Q_NULLPTR;
2022-04-03 19:16:52 +00:00
QIODevice* audioDevice=Q_NULLPTR;
2021-06-04 07:24:26 +00:00
QAudioFormat format;
QAudioDeviceInfo deviceInfo;
#endif
2021-05-23 15:09:41 +00:00
SpeexResamplerState* resampler = Q_NULLPTR;
2021-05-16 20:16:59 +00:00
2022-04-03 19:16:52 +00:00
//r8b::CFixedBuffer<double>* resampBufs;
//r8b::CPtrKeeper<r8b::CDSPResampler24*>* resamps;
2021-05-16 20:16:59 +00:00
quint16 audioLatency;
2021-05-23 15:09:41 +00:00
unsigned int chunkSize;
bool chunkAvailable;
2021-06-04 07:24:26 +00:00
quint32 lastSeq;
2021-06-17 08:55:09 +00:00
quint32 lastSentSeq=0;
2022-04-03 19:16:52 +00:00
qint64 elapsedMs = 0;
2021-06-17 08:55:09 +00:00
2021-06-04 07:24:26 +00:00
quint16 nativeSampleRate=0;
quint8 radioSampleBits;
2021-03-09 17:22:16 +00:00
quint8 radioChannels;
int delayedPackets=0;
2021-05-23 21:45:10 +00:00
QMap<quint32, audioPacket>audioBuffer;
2021-03-09 17:22:16 +00:00
2021-11-07 13:27:52 +00:00
double resampleRatio;
wilt::Ring<audioPacket> *ringBuf=Q_NULLPTR;
2021-06-04 07:24:26 +00:00
volatile bool ready = false;
audioPacket tempBuf;
quint16 currentLatency;
2022-04-03 19:16:52 +00:00
float amplitude;
2021-05-27 12:54:52 +00:00
qreal volume=1.0;
int devChannels;
2021-06-04 07:24:26 +00:00
audioSetup setup;
2021-06-16 08:49:38 +00:00
OpusEncoder* encoder=Q_NULLPTR;
OpusDecoder* decoder=Q_NULLPTR;
2021-02-11 19:18:35 +00:00
};
2022-04-03 19:16:52 +00:00
// Various audio handling functions declared inline
static inline qint64 getAudioSize(qint64 timeInMs, const QAudioFormat& format)
{
qint64 value = qint64(qCeil(format.channelCount() * (format.sampleSize() / 8) * format.sampleRate() / qreal(10000) * timeInMs));
if (value % (format.channelCount() * (format.sampleSize() / 8)) != 0)
value += (format.channelCount() * (format.sampleSize() / 8) - value % (format.channelCount() * (format.sampleSize() / 8)));
return value;
}
static inline qint64 getAudioDuration(qint64 bytes, const QAudioFormat& format)
{
return qint64(qFloor(bytes / (format.channelCount() * (format.sampleSize() / 8) * format.sampleRate() / qreal(1000))));
}
typedef Eigen::Matrix<quint8, Eigen::Dynamic, 1> VectorXuint8;
typedef Eigen::Matrix<qint8, Eigen::Dynamic, 1> VectorXint8;
typedef Eigen::Matrix<qint16, Eigen::Dynamic, 1> VectorXint16;
typedef Eigen::Matrix<qint32, Eigen::Dynamic, 1> VectorXint32;
static inline QByteArray samplesToInt(const QByteArray& data, const QAudioFormat& supported_format)
{
QByteArray input = data;
switch (supported_format.sampleSize())
{
case 8:
{
switch (supported_format.sampleType())
{
case QAudioFormat::UnSignedInt:
{
Eigen::Ref<Eigen::VectorXf> samples_float = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(input.data()), input.size() / int(sizeof(float)));
Eigen::VectorXf samples_int_tmp = samples_float * float(std::numeric_limits<quint8>::max());
VectorXuint8 samples_int = samples_int_tmp.cast<quint8>();
QByteArray raw = QByteArray(reinterpret_cast<char*>(samples_int.data()), int(samples_int.size()) * int(sizeof(quint8)));
return raw;
}
case QAudioFormat::SignedInt:
{
Eigen::Ref<Eigen::VectorXf> samples_float = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(input.data()), input.size() / int(sizeof(float)));
Eigen::VectorXf samples_int_tmp = samples_float * float(std::numeric_limits<qint8>::max());
VectorXint8 samples_int = samples_int_tmp.cast<qint8>();
QByteArray raw = QByteArray(reinterpret_cast<char*>(samples_int.data()), int(samples_int.size()) * int(sizeof(qint8)));
return raw;
}
default:
break;
}
break;
}
case 16:
{
switch (supported_format.sampleType())
{
case QAudioFormat::SignedInt:
{
Eigen::Ref<Eigen::VectorXf> samples_float = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(input.data()), input.size() / int(sizeof(float)));
Eigen::VectorXf samples_int_tmp = samples_float * float(std::numeric_limits<qint16>::max());
VectorXint16 samples_int = samples_int_tmp.cast<qint16>();
QByteArray raw = QByteArray(reinterpret_cast<char*>(samples_int.data()), int(samples_int.size()) * int(sizeof(qint16)));
return raw;
}
default:
break;
}
break;
}
case 32:
{
switch (supported_format.sampleType())
{
case QAudioFormat::SignedInt:
{
Eigen::Ref<Eigen::VectorXf> samples_float = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(input.data()), input.size() / int(sizeof(float)));
Eigen::VectorXf samples_int_tmp = samples_float * float(std::numeric_limits<qint32>::max());
VectorXint32 samples_int = samples_int_tmp.cast<qint32>();
QByteArray raw = QByteArray(reinterpret_cast<char*>(samples_int.data()), int(samples_int.size()) * int(sizeof(qint32)));
return raw;
}
default:
break;
}
break;
}
default:
break;
}
return QByteArray();
}
static inline QByteArray samplesToFloat(const QByteArray& data, const QAudioFormat& supported_format)
{
QByteArray input = data;
switch (supported_format.sampleSize())
{
case 8:
{
switch (supported_format.sampleType())
{
case QAudioFormat::UnSignedInt:
{
QByteArray raw = input;
Eigen::Ref<VectorXuint8> samples_int = Eigen::Map<VectorXuint8>(reinterpret_cast<quint8*>(raw.data()), raw.size() / int(sizeof(quint8)));
Eigen::VectorXf samples_float = samples_int.cast<float>() / float(std::numeric_limits<quint8>::max());
return QByteArray(reinterpret_cast<char*>(samples_float.data()), int(samples_float.size()) * int(sizeof(float)));
}
case QAudioFormat::SignedInt:
{
QByteArray raw = input;
Eigen::Ref<VectorXint8> samples_int = Eigen::Map<VectorXint8>(reinterpret_cast<qint8*>(raw.data()), raw.size() / int(sizeof(qint8)));
Eigen::VectorXf samples_float = samples_int.cast<float>() / float(std::numeric_limits<qint8>::max());
return QByteArray(reinterpret_cast<char*>(samples_float.data()), int(samples_float.size()) * int(sizeof(float)));
}
default:
break;
}
break;
}
case 16:
{
switch (supported_format.sampleType())
{
case QAudioFormat::SignedInt:
{
QByteArray raw = input;
Eigen::Ref<VectorXint16> samples_int = Eigen::Map<VectorXint16>(reinterpret_cast<qint16*>(raw.data()), raw.size() / int(sizeof(qint16)));
Eigen::VectorXf samples_float = samples_int.cast<float>() / float(std::numeric_limits<qint16>::max());
return QByteArray(reinterpret_cast<char*>(samples_float.data()), int(samples_float.size()) * int(sizeof(float)));
}
default:
break;
}
break;
}
case 32:
{
switch (supported_format.sampleType())
{
case QAudioFormat::SignedInt:
{
QByteArray raw = input;
Eigen::Ref<VectorXint32> samples_int = Eigen::Map<VectorXint32>(reinterpret_cast<qint32*>(raw.data()), raw.size() / int(sizeof(qint32)));
Eigen::VectorXf samples_float = samples_int.cast<float>() / float(std::numeric_limits<qint32>::max());
return QByteArray(reinterpret_cast<char*>(samples_float.data()), int(samples_float.size()) * int(sizeof(float)));
}
default:
break;
}
break;
}
default:
break;
}
return QByteArray();
}
2021-02-11 19:18:35 +00:00
#endif // AUDIOHANDLER_H