parent
a2fb735bbc
commit
11c207d7ee
@ -0,0 +1,211 @@ |
||||
#include "UBMicrophoneInput.h" |
||||
|
||||
UBMicrophoneInput::UBMicrophoneInput() |
||||
: mAudioInput(NULL) |
||||
, mIODevice(NULL) |
||||
, mSeekPos(0) |
||||
{ |
||||
} |
||||
|
||||
UBMicrophoneInput::~UBMicrophoneInput() |
||||
{ |
||||
if (mAudioInput) |
||||
delete mAudioInput; |
||||
} |
||||
|
||||
int UBMicrophoneInput::channelCount() |
||||
{ |
||||
return mAudioFormat.channelCount(); |
||||
} |
||||
|
||||
int UBMicrophoneInput::sampleRate() |
||||
{ |
||||
return mAudioFormat.sampleRate(); |
||||
} |
||||
|
||||
/* Return the sample size in bits */ |
||||
int UBMicrophoneInput::sampleSize() |
||||
{ |
||||
return mAudioFormat.sampleSize(); |
||||
} |
||||
|
||||
/** Return the sample format in FFMpeg style (AVSampleFormat enum) */ |
||||
int UBMicrophoneInput::sampleFormat() |
||||
{ |
||||
enum AVSampleFormat { |
||||
AV_SAMPLE_FMT_NONE = -1, |
||||
AV_SAMPLE_FMT_U8, |
||||
AV_SAMPLE_FMT_S16, |
||||
AV_SAMPLE_FMT_S32, |
||||
AV_SAMPLE_FMT_FLT, |
||||
AV_SAMPLE_FMT_DBL, |
||||
AV_SAMPLE_FMT_U8P, |
||||
AV_SAMPLE_FMT_S16P, |
||||
AV_SAMPLE_FMT_S32P, |
||||
AV_SAMPLE_FMT_FLTP, |
||||
AV_SAMPLE_FMT_DBLP, |
||||
AV_SAMPLE_FMT_NB |
||||
}; |
||||
|
||||
int sampleSize = mAudioFormat.sampleSize(); |
||||
QAudioFormat::SampleType sampleType = mAudioFormat.sampleType(); |
||||
|
||||
// qDebug() << "Input sample format: " << sampleSize << "bits " << sampleType;
|
||||
|
||||
switch (sampleType) { |
||||
case QAudioFormat::Unknown: |
||||
return AV_SAMPLE_FMT_NONE; |
||||
|
||||
case QAudioFormat::SignedInt: |
||||
if (sampleSize == 16) |
||||
return AV_SAMPLE_FMT_S16; |
||||
if (sampleSize == 32) |
||||
return AV_SAMPLE_FMT_S32; |
||||
|
||||
case QAudioFormat::UnSignedInt: |
||||
if (sampleSize == 8) |
||||
return AV_SAMPLE_FMT_U8; |
||||
|
||||
case QAudioFormat::Float: |
||||
return AV_SAMPLE_FMT_FLT; |
||||
|
||||
default: |
||||
return AV_SAMPLE_FMT_NONE; |
||||
} |
||||
} |
||||
|
||||
QString UBMicrophoneInput::codec() |
||||
{ |
||||
return mAudioFormat.codec(); |
||||
} |
||||
|
||||
qint64 UBMicrophoneInput::processUSecs() const |
||||
{ |
||||
return mAudioInput->processedUSecs(); |
||||
} |
||||
|
||||
bool UBMicrophoneInput::init() |
||||
{ |
||||
if (mAudioDeviceInfo.isNull()) { |
||||
qWarning("No audio input device selected; using default"); |
||||
mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); |
||||
} |
||||
|
||||
qDebug() << "Input device name: " << mAudioDeviceInfo.deviceName(); |
||||
|
||||
mAudioFormat = mAudioDeviceInfo.preferredFormat(); |
||||
|
||||
mAudioInput = new QAudioInput(mAudioDeviceInfo, mAudioFormat, NULL); |
||||
//mAudioInput->setNotifyInterval(100);
|
||||
|
||||
connect(mAudioInput, SIGNAL(stateChanged(QAudio::State)), |
||||
this, SLOT(onAudioInputStateChanged(QAudio::State))); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
void UBMicrophoneInput::start() |
||||
{ |
||||
qDebug() << "starting audio input"; |
||||
|
||||
mIODevice = mAudioInput->start(); |
||||
|
||||
connect(mIODevice, SIGNAL(readyRead()), |
||||
this, SLOT(onDataReady())); |
||||
|
||||
if (mAudioInput->error() == QAudio::OpenError) |
||||
qWarning() << "Error opening audio input"; |
||||
} |
||||
|
||||
void UBMicrophoneInput::stop() |
||||
{ |
||||
mAudioInput->stop(); |
||||
} |
||||
|
||||
QStringList UBMicrophoneInput::availableDevicesNames() |
||||
{ |
||||
QStringList names; |
||||
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); |
||||
|
||||
foreach (QAudioDeviceInfo device, devices) { |
||||
names.push_back(device.deviceName()); |
||||
} |
||||
|
||||
return names; |
||||
} |
||||
|
||||
void UBMicrophoneInput::setInputDevice(QString name) |
||||
{ |
||||
if (name.isEmpty()) { |
||||
mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); |
||||
return; |
||||
} |
||||
|
||||
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); |
||||
bool found = false; |
||||
|
||||
foreach (QAudioDeviceInfo device, devices) { |
||||
if (device.deviceName() == name) { |
||||
mAudioDeviceInfo = device; |
||||
found = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!found) { |
||||
qWarning() << "Audio input device not found; using default instead"; |
||||
mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); |
||||
} |
||||
|
||||
} |
||||
|
||||
void UBMicrophoneInput::onDataReady() |
||||
{ |
||||
int numBytes = mAudioInput->bytesReady(); |
||||
|
||||
if (numBytes > 0) |
||||
emit dataAvailable(mIODevice->read(numBytes)); |
||||
} |
||||
|
||||
void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state) |
||||
{ |
||||
qDebug() << "Audio input state changed to " << state; |
||||
switch (state) { |
||||
case QAudio::StoppedState: |
||||
if (mAudioInput->error() != QAudio::NoError) { |
||||
emit error(getErrorString(mAudioInput->error())); |
||||
} |
||||
break; |
||||
|
||||
// handle other states?
|
||||
|
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* @brief Return a meaningful error string based on QAudio error codes |
||||
*/ |
||||
QString UBMicrophoneInput::getErrorString(QAudio::Error errorCode) |
||||
{ |
||||
switch (errorCode) { |
||||
case QAudio::NoError : |
||||
return ""; |
||||
|
||||
case QAudio::OpenError : |
||||
return "Couldn't open the audio device"; |
||||
|
||||
case QAudio::IOError : |
||||
return "Error reading from audio device"; |
||||
|
||||
case QAudio::UnderrunError : |
||||
return "Underrun error"; |
||||
|
||||
case QAudio::FatalError : |
||||
return "Fatal error; audio device unusable"; |
||||
|
||||
} |
||||
return ""; |
||||
} |
@ -0,0 +1,57 @@ |
||||
#ifndef UBMICROPHONEINPUT_H |
||||
#define UBMICROPHONEINPUT_H |
||||
|
||||
#include <QtCore> |
||||
#include <QAudioInput> |
||||
|
||||
/**
|
||||
* @brief The UBMicrophoneInput class captures uncompressed sound from a microphone |
||||
*/ |
||||
class UBMicrophoneInput : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
UBMicrophoneInput(); |
||||
virtual ~UBMicrophoneInput(); |
||||
|
||||
bool init(); |
||||
void start(); |
||||
void stop(); |
||||
|
||||
static QStringList availableDevicesNames(); |
||||
void setInputDevice(QString name = ""); |
||||
|
||||
int channelCount(); |
||||
int sampleRate(); |
||||
int sampleSize(); |
||||
int sampleFormat(); |
||||
QString codec(); |
||||
|
||||
qint64 processUSecs() const; |
||||
|
||||
signals: |
||||
/// Send the new volume, between 0 and 255
|
||||
void audioLevelChanged(quint8 level); |
||||
|
||||
/// Emitted when new audio data is available
|
||||
void dataAvailable(QByteArray data); |
||||
|
||||
void error(QString message); |
||||
|
||||
private slots: |
||||
void onAudioInputStateChanged(QAudio::State state); |
||||
void onDataReady(); |
||||
|
||||
private: |
||||
QString getErrorString(QAudio::Error errorCode); |
||||
|
||||
QAudioInput* mAudioInput; |
||||
QIODevice * mIODevice; |
||||
QAudioDeviceInfo mAudioDeviceInfo; |
||||
QAudioFormat mAudioFormat; |
||||
|
||||
qint64 mSeekPos; |
||||
}; |
||||
|
||||
#endif // UBMICROPHONEINPUT_H
|
Loading…
Reference in new issue