无法在QT中记录从麦克风到Qfile的音频
Unable to record audio from microphone to QFile in Qt
我正在尝试从桌面中存在的默认麦克风中录制音频,并将其存储在qfile中。最后,我想使用Windows Media Player播放录制的文件。问题是Qaudiostut具有一个方法Bytesready(),在我的情况下总是返回0。即使音频状态为qaudio ::激活字节不管()显示0个字节,这意味着没有音频字节可以从麦克风中读取。该系统麦克风正常工作。我的代码完美地编译了,我还将在具有80kb大小的指定位置中获得一个文件,但是即使保存为.Wav,该文件也不会使用Windows Media Player播放,它会返回错误。在我的情况下,输出窗口将字节准备就绪为0。我怀疑Qaudioutput无法读取麦克风的音频数据。
您能帮我在代码中找到错误吗?
`class mikeDemoClass : public QWidget
{
Q_OBJECT
public:
mikeDemoClass(QWidget *parent = 0, Qt::WFlags flags = 0);
~mikeDemoClass();
public slots:
void startRecording();
void browseFiles();
void stopRecording();
void handleAudioInputState(QAudio::State);
void notified();
private:
Ui::mikeDemoWidget ui;
QAudioInput *audioInput;
QFile *recordFile;
QTimer *testTimer;
int audio_state;
};
// cpp file starts here
#include <QIODevice>
#include "mic_demo.h"
mikeDemoClass::mikeDemoClass(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
ui.setupUi(this);
audioInput = NULL;
recordFile = NULL;
audio_state = -1;
connect(ui.browseButton,SIGNAL(clicked()),this,SLOT(browseFiles()));
connect(ui.recordingButton,SIGNAL(clicked()), this,SLOT(startRecording()));
}
mikeDemoClass::~mikeDemoClass()
{
if(recordFile)
{
delete recordFile;
recordFile = NULL;
}
}
void mikeDemoClass::browseFiles()
{
QString FileName = QFileDialog::getSaveFileName(this, tr("Browse Files"), "D:/", tr("Media Files (*.raw)"));
if(!FileName.isEmpty())
{
recordFile = new QFile(FileName);
QTextDocument *textDoc = new QTextDocument(FileName);
ui.textEdit->setDocument(textDoc);
}
}
void mikeDemoClass::startRecording()
{
bool status = recordFile->open(QIODevice::WriteOnly);
if(!status)
{
qDebug() <<"Error opening the file";
}
QString default_deviceName = "";
QAudioFormat preferred_format;
QList<QAudioDeviceInfo> device_list = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
int count = device_list.count();
if(device_list.empty())
{
qDebug() <<"The Audio Input Devices is empty";
}
else
{
foreach(QAudioDeviceInfo device_info, device_list)
{
QString device_name = device_info.deviceName();
qDebug() << "device_name:" << device_name.toLatin1();
}
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
default_deviceName = info.deviceName();
if(!default_deviceName.isEmpty())
{
preferred_format = info.preferredFormat();
QString codec = preferred_format.codec();
int sampleRate = preferred_format.sampleRate();
int sampleSize = preferred_format.sampleSize();
int channelCount = preferred_format.channelCount();
int sampleType = preferred_format.sampleType();
int byteOrder = preferred_format.byteOrder();
qDebug() << "codec:" << codec.toLatin1() << "sampleRate :" << sampleRate << "sampleSize:" << sampleSize << "channel Count:" << channelCount << "sample type:" <<sampleType
<< "byteOrder:" << byteOrder;
}
}
QAudioFormat format;
format.setSampleRate(8000);
format.setChannels(1);
format.setSampleSize(8);
format.setCodec("audio/PCM");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if(!info.isFormatSupported(format))
{
qDebug() <<"Default format not supported, try to use nearest format";
format = info.nearestFormat(format);
}
audioInput = new QAudioInput(info, format, this);
connect(audioInput, SIGNAL(notify()), this, SLOT(notified()));
connect(audioInput,SIGNAL(stateChanged(QAudio::State)),this, SLOT(handleAudioInputState(QAudio::State)));
QTimer::singleShot(10000, this, SLOT(stopRecording()));
//audioInput->setBufferSize(4096);
qDebug() << "platform buffer size:" << audioInput->bufferSize();
audioInput->start(recordFile);
}
void mikeDemoClass::stopRecording()
{
testTimer->stop();
audioInput->stop();
recordFile->close();
delete audioInput;
}
void mikeDemoClass::handleAudioInputState(QAudio::State state)
{
qDebug() << "Audio State:" << state;
audio_state = state;
if(state == QAudio::StoppedState)
{
qDebug() << "Error State:" << audioInput->error();
if(audioInput->error() != QAudio::NoError)
{
qDebug() << "QAudioInput error:" << audioInput->error();
}
}
}
void mikeDemoClass::notified()
{
if(audio_state == QAudio::ActiveState)
{
qDebug() << "Error State:" << audioInput->error();
qDebug() << "platform buffer size after calling QAudioInput start():" << audioInput->bufferSize();
qDebug() << "bytesReady = " << audioInput->bytesReady()
<< ", " << "elapsedUSecs = " <<audioInput->elapsedUSecs()
<< ", " << "processedUSecs = "<<audioInput->processedUSecs();
}
}`
输出显示如下:
device_name: "Microphone (High Definition Aud"
device_name: "default"
codec: "audio/pcm" sampleRate : 11025 sampleSize: 8 channel Count: 1 sample type: 1 byteOrder: 1
Default format not supported, try to use nearest format
platform buffer size: 0
Audio State: 0
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 1003000 , processedUSecs = 1000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 1998000 , processedUSecs = 2000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 3003000 , processedUSecs = 3000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 4000000 , processedUSecs = 4000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 5006000 , processedUSecs = 5000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 6001000 , processedUSecs = 6000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 7005000 , processedUSecs = 7000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 8002000 , processedUSecs = 8000000
Error State: 0
platform buffer size after called QAudioInput start(): 1600
bytesReady = 0 , elapsedUSecs = 8997000 , processedUSecs = 9000000
Audio State: 2
Error State: 0
已将您的代码与QT文档中的示例进行了比较,您正在使用通知信号来处理qaudio :: activestate,而示例代码将插槽连接到statechanged Signal: -
void AudioInputExample::handleStateChanged(QAudio::State newState)
{
switch (newState) {
case QAudio::StoppedState:
if (audio->error() != QAudio::NoError) {
// Error handling
} else {
// Finished recording
}
break;
case QAudio::ActiveState:
// Started recording - read from IO device
break;
default:
// ... other cases as appropriate
break;
}
}
as notify()状态: -
当音频数据的x ms处理通过setNotifyInterval
处理间隔时,发出了此信号。
间隔可以为零吗?
但是,我建议按照文档中所示的示例代码遵循示例代码,并使用statechanged信号,而不是通知。
将phdebug或phdbg视为qdebug(),请参见以下内容(我认为您的缺失点是QIODevice
,它是一个缓冲区。):
reader.cpp:
#include "PhLtcReader.h"
PhLtcReader::PhLtcReader(QObject *parent) :
QObject(parent),
_input(NULL),
_position(0),
_buffer(NULL)
{
_decoder = ltc_decoder_create(1920, 3840);
PHDEBUG << "LTC Reader created";
}
bool PhLtcReader::init(QString input)
{
QList<QAudioDeviceInfo> list = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
if(list.isEmpty())
{
PHDEBUG << "No audio input device";
return false;
}
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
foreach(QAudioDeviceInfo device, list)
{
if(device.deviceName() == input)
info = device;
}
PHDEBUG << "LTC input device :" << info.deviceName();
QAudioFormat format;
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleRate(48000);
format.setChannelCount(1);
format.setSampleSize(8);
format.setSampleType(QAudioFormat::SignedInt);
if(!info.isFormatSupported(format))
{
PHDEBUG << "Unsupported audio format";
return false;
}
_position = 0;
_input = new QAudioInput(info, format);
connect(_input, SIGNAL(notify()), this, SLOT(onNotify()));
_buffer = _input->start();
_input->setNotifyInterval(10);
_pauseDetector.start();
return true;
}
void PhLtcReader::close()
{
if(_input)
{
_input->stop();
delete _buffer;
_buffer = NULL;
delete _input;
_input = NULL;
}
}
QList<QString> PhLtcReader::inputList()
{
QList<QString> names;
QList<QAudioDeviceInfo> list = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
foreach(QAudioDeviceInfo device, list)
names.append(device.deviceName());
return names;
}
void PhLtcReader::onNotify()
{
QByteArray array = _buffer->readAll();
char max = 0;
for(int i = 0; i < array.count(); i++)
{
if(array.at(i) > max)
max = array.at(i);
}
ltc_decoder_write(_decoder, (ltcsnd_sample_t*)array.data(), array.count(), _position);
LTCFrameExt frame;
unsigned int *hhmmssff = new unsigned int[4];
while(ltc_decoder_read(_decoder, &frame))
{
PhFrame oldFrame = _clock.frame();
hhmmssff[0] = frame.ltc.hours_tens * 10 + frame.ltc.hours_units;
hhmmssff[1] = frame.ltc.mins_tens * 10 + frame.ltc.mins_units;
hhmmssff[2] = frame.ltc.secs_tens * 10 + frame.ltc.secs_units;
hhmmssff[3] = frame.ltc.frame_tens * 10 + frame.ltc.frame_units;
}
delete hhmmssff;
_position += array.count();
}
reader.h
class PhLtcReader : public QObject
{
Q_OBJECT
public:
explicit PhLtcReader(QObject *parent = 0);
bool init(QString _input="");
void close();
static QList<QString> inputList();
private slots:
void onNotify();
private:
QAudioInput *_input;
qint64 _position;
QIODevice * _buffer;
};
#endif // PHLTCREADER_H
您的问题的答案可以在输出中找到。
有一条线说
Default format not supported, try to use nearest format
这是问题所在。您使用的格式不受平台的支持。尝试其他方法或安装编解码器/驱动程序以支持该格式。
- 如何从QFile阅读?它显示该文件不可访问
- QDial:如何将 int 值传递给需要常量字符*的 Qfile?
- QDataStream 读取和写入的字节数比 QFile::length() 报告要多
- Qt 写入 xml: QIODevice::write (QFile, "D:/logs.xml" ): 设备未打开
- 适用于 macOS 的 Xcode 应用程序。这就是我设置从USB麦克风输入获取音频的方式。一年前工作,现在没有了。为什么
- Qt中的QFile::copy(source,dest)的实现有时是错误的吗?
- 使用 QFile::write 的正确方法?
- 在 Windows QDir::mkpath 和 QFile::rename 上报告成功,尽管失败了
- qfile qtextStream仅读取文件的一部分
- 使用自动初始化 QFile
- 如何从 qml webgl 获取麦克风到 c++?
- 如何使用口袋狮身人面像通过代码中的麦克风进行语音识别
- 如何使用 QFile、c++ 从文件创建整数数组
- 无法创建QFILE(仅使用MSVC2017 UWP)
- QFILE INIT/分配OP问题当对象是类成员时
- 如何捕获麦克风缓冲区原始数据
- 如何使用Android的双簧管/ AAudio从多个麦克风读取数据
- 如何确保QFile写入相同的物理地址?
- 如何以编程方式启用侧音/麦克风直通
- 无法在QT中记录从麦克风到Qfile的音频