kopia lustrzana https://gitlab.com/eliggett/wfview
139 wiersze
3.2 KiB
C++
139 wiersze
3.2 KiB
C++
#ifndef AUDIOCONVERTER_H
|
|
#define AUDIOCONVERTER_H
|
|
#include <QObject>
|
|
#include <QByteArray>
|
|
#include <QTime>
|
|
#include <QMap>
|
|
#include <QDebug>
|
|
#include <QAudioFormat>
|
|
#include <QAudioDeviceInfo>
|
|
|
|
/* Opus and Eigen */
|
|
#ifdef Q_OS_WIN
|
|
#include "opus.h"
|
|
#include <Eigen/Eigen>
|
|
#else
|
|
#include "opus/opus.h"
|
|
#include <eigen3/Eigen/Eigen>
|
|
#endif
|
|
|
|
enum audioType {qtAudio,portAudio,rtAudio};
|
|
|
|
#include "resampler/speex_resampler.h"
|
|
|
|
#include "packettypes.h"
|
|
|
|
struct audioPacket {
|
|
quint32 seq;
|
|
QTime time;
|
|
quint16 sent;
|
|
QByteArray data;
|
|
quint8 guid[GUIDLEN];
|
|
float amplitudePeak;
|
|
float amplitudeRMS;
|
|
qreal volume = 1.0;
|
|
};
|
|
|
|
struct audioSetup {
|
|
audioType type;
|
|
QString name;
|
|
quint16 latency;
|
|
quint8 codec;
|
|
bool ulaw = false;
|
|
bool isinput;
|
|
quint32 sampleRate;
|
|
QAudioDeviceInfo port;
|
|
int portInt;
|
|
quint8 resampleQuality;
|
|
unsigned char localAFgain;
|
|
quint16 blockSize = 20; // Each 'block' of audio is 20ms long by default.
|
|
quint8 guid[GUIDLEN];
|
|
};
|
|
|
|
class audioConverter : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit audioConverter(QObject* parent = nullptr);;
|
|
~audioConverter();
|
|
|
|
public slots:
|
|
bool init(QAudioFormat inFormat, QAudioFormat outFormat, quint8 opusComplexity, quint8 resampleQuality);
|
|
bool convert(audioPacket audio);
|
|
|
|
signals:
|
|
void converted(audioPacket audio);
|
|
|
|
protected:
|
|
QAudioFormat inFormat;
|
|
QAudioFormat outFormat;
|
|
OpusEncoder* opusEncoder = Q_NULLPTR;
|
|
OpusDecoder* opusDecoder = Q_NULLPTR;
|
|
SpeexResamplerState* resampler = Q_NULLPTR;
|
|
quint8 opusComplexity;
|
|
quint8 resampleQuality = 4;
|
|
double resampleRatio=1.0; // Default resample ratio is 1:1
|
|
quint32 lastAudioSequence;
|
|
};
|
|
|
|
|
|
// Various audio handling functions declared inline
|
|
|
|
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 QAudioFormat toQAudioFormat(quint8 codec, quint32 sampleRate)
|
|
{
|
|
QAudioFormat format;
|
|
|
|
/*
|
|
0x01 uLaw 1ch 8bit
|
|
0x02 PCM 1ch 8bit
|
|
0x04 PCM 1ch 16bit
|
|
0x08 PCM 2ch 8bit
|
|
0x10 PCM 2ch 16bit
|
|
0x20 uLaw 2ch 8bit
|
|
0x40 Opus 1ch
|
|
0x80 Opus 2ch
|
|
*/
|
|
|
|
format.setByteOrder(QAudioFormat::LittleEndian);
|
|
format.setCodec("audio/pcm");
|
|
format.setSampleRate(sampleRate);
|
|
|
|
if (codec == 0x01 || codec == 0x20) {
|
|
/* Set sample to be what is expected by the encoder and the output of the decoder */
|
|
format.setSampleSize(16);
|
|
format.setSampleType(QAudioFormat::SignedInt);
|
|
format.setCodec("audio/PCMU");
|
|
}
|
|
|
|
if (codec == 0x02 || codec == 0x08) {
|
|
format.setSampleSize(8);
|
|
format.setSampleType(QAudioFormat::UnSignedInt);
|
|
}
|
|
if (codec == 0x08 || codec == 0x10 || codec == 0x20 || codec == 0x80) {
|
|
format.setChannelCount(2);
|
|
} else {
|
|
format.setChannelCount(1);
|
|
}
|
|
|
|
if (codec == 0x04 || codec == 0x10) {
|
|
format.setSampleSize(16);
|
|
format.setSampleType(QAudioFormat::SignedInt);
|
|
}
|
|
|
|
if (codec == 0x40 || codec == 0x80) {
|
|
format.setSampleSize(32);
|
|
format.setSampleType(QAudioFormat::Float);
|
|
format.setCodec("audio/opus");
|
|
}
|
|
|
|
return format;
|
|
}
|
|
|
|
#endif
|