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>
|
2021-05-29 17:59:45 +00:00
|
|
|
#include <QtMath>
|
2021-06-04 07:24:26 +00:00
|
|
|
|
|
|
|
#if defined(RTAUDIO)
|
2021-06-06 16:56:48 +00:00
|
|
|
#include "rtaudio/RtAudio.h"
|
2021-06-04 07:24:26 +00:00
|
|
|
#elif defined (PORTAUDIO)
|
|
|
|
#include "portaudio.h"
|
2021-06-06 16:56:48 +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
|
|
|
|
|
|
|
typedef signed short MY_TYPE;
|
|
|
|
#define FORMAT RTAUDIO_SINT16
|
|
|
|
#define SCALE 32767.0
|
|
|
|
|
2021-05-27 17:34:44 +00:00
|
|
|
#define LOG100 4.60517018599
|
2021-05-16 12:34:04 +00:00
|
|
|
|
2021-02-11 19:18:35 +00:00
|
|
|
#include <QThread>
|
2021-02-12 20:42:56 +00:00
|
|
|
#include <QTimer>
|
2021-02-27 00:37:00 +00:00
|
|
|
#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"
|
2021-05-27 10:41:08 +00:00
|
|
|
#include "ring/ring.h"
|
2021-07-06 19:02:09 +00:00
|
|
|
#include "audiotaper.h"
|
2021-05-16 12:34:04 +00:00
|
|
|
|
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-02-27 00:37:00 +00:00
|
|
|
|
2021-05-16 20:16:59 +00:00
|
|
|
#define MULAW_BIAS 33
|
|
|
|
#define MULAW_MAX 0x1fff
|
|
|
|
|
2021-03-01 19:53:12 +00:00
|
|
|
struct audioPacket {
|
2021-03-14 08:44:30 +00:00
|
|
|
quint32 seq;
|
2021-02-27 00:37:00 +00:00
|
|
|
QTime time;
|
|
|
|
quint16 sent;
|
2021-05-27 10:41:08 +00:00
|
|
|
QByteArray data;
|
2021-02-27 00:37:00 +00:00
|
|
|
};
|
|
|
|
|
2021-06-04 07:24:26 +00:00
|
|
|
struct audioSetup {
|
|
|
|
QString name;
|
|
|
|
quint8 bits;
|
|
|
|
quint8 radioChan;
|
|
|
|
quint16 samplerate;
|
|
|
|
quint16 latency;
|
|
|
|
quint8 codec;
|
|
|
|
bool ulaw;
|
|
|
|
bool isinput;
|
|
|
|
#if defined(RTAUDIO)
|
|
|
|
int port;
|
|
|
|
#elif defined(PORTAUDIO)
|
|
|
|
#else
|
|
|
|
QAudioDeviceInfo port;
|
|
|
|
#endif
|
|
|
|
quint8 resampleQuality;
|
2021-07-05 23:45:19 +00:00
|
|
|
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);
|
2021-05-23 15:09:41 +00:00
|
|
|
|
2021-06-04 07:24:26 +00:00
|
|
|
public slots:
|
|
|
|
bool init(audioSetup setup);
|
2021-02-27 00:37:00 +00:00
|
|
|
void changeLatency(const quint16 newSize);
|
2021-03-22 18:53:34 +00:00
|
|
|
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);
|
2021-02-27 00:37:00 +00:00
|
|
|
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-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();
|
2021-06-03 11:05:28 +00:00
|
|
|
bool isInitialized=false;
|
2021-07-06 09:04:35 +00:00
|
|
|
bool isReady = false;
|
2021-06-04 07:24:26 +00:00
|
|
|
|
|
|
|
#if defined(RTAUDIO)
|
2021-06-02 17:35:04 +00:00
|
|
|
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)
|
|
|
|
#else
|
|
|
|
QAudioOutput* audioOutput=Q_NULLPTR;
|
|
|
|
QAudioInput* audioInput=Q_NULLPTR;
|
|
|
|
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
|
|
|
|
2021-02-11 19:18:35 +00:00
|
|
|
bool isUlaw;
|
2021-05-16 20:16:59 +00:00
|
|
|
quint16 audioLatency;
|
2021-02-11 19:18:35 +00:00
|
|
|
bool isInput; // Used to determine whether input or output audio
|
2021-05-23 15:09:41 +00:00
|
|
|
unsigned int chunkSize;
|
2021-03-03 09:49:49 +00:00
|
|
|
bool chunkAvailable;
|
|
|
|
|
2021-06-04 07:24:26 +00:00
|
|
|
quint32 lastSeq;
|
2021-02-11 19:18:35 +00:00
|
|
|
|
2021-06-04 07:24:26 +00:00
|
|
|
quint16 radioSampleRate;
|
|
|
|
quint16 nativeSampleRate=0;
|
|
|
|
quint8 radioSampleBits;
|
2021-03-09 17:22:16 +00:00
|
|
|
quint8 radioChannels;
|
|
|
|
|
2021-05-23 21:45:10 +00:00
|
|
|
QMap<quint32, audioPacket>audioBuffer;
|
2021-03-09 17:22:16 +00:00
|
|
|
|
|
|
|
unsigned int ratioNum;
|
|
|
|
unsigned int ratioDen;
|
2021-05-27 10:41:08 +00:00
|
|
|
|
|
|
|
wilt::Ring<audioPacket> *ringBuf=Q_NULLPTR;
|
2021-06-04 07:24:26 +00:00
|
|
|
|
2021-05-27 10:41:08 +00:00
|
|
|
volatile bool ready = false;
|
|
|
|
audioPacket tempBuf;
|
|
|
|
quint16 currentLatency;
|
2021-05-27 12:54:52 +00:00
|
|
|
qreal volume=1.0;
|
2021-05-29 19:13:52 +00:00
|
|
|
int devChannels;
|
2021-06-04 07:24:26 +00:00
|
|
|
audioSetup setup;
|
2021-02-11 19:18:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // AUDIOHANDLER_H
|