#include "audiorecorder.h"
#include "QDebug"
#include "qdatastream.h"
#include "QTime"
#include <QFileInfo>
static quint16 targetPort = 12345;
static QHostAddress targetAddress("192.168.1.1");
AudioRecorder::AudioRecorder(QObject *parent) : QObject(parent)
{
readAudioFile.setFileName("output.wav");
thread = new QThread(this);
udpSocket = new QUdpSocket(this);
// 设置音频格式
format.setSampleRate(8000); // 8000 12000 16000
format.setChannelCount(1);
format.setSampleSize(8); // 16 8
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
// 检查格式是否被支持
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(format)) {
qWarning() << "Default format not supported - trying to use nearest";
format = info.nearestFormat(format);
}
audioFile = new QFile("output.wav");
timer = new QTimer(this);
// 每秒更新一次时间和数据大小
connect(timer, &QTimer::timeout, this, [&]() {
m_recordTime += 1000;
emit recordTimeChanged();
emit dataSizeChanged();
});
sendTimer = new QTimer(this);
connect(sendTimer, &QTimer::timeout, this, [&]() {
m_recordTime++;
_sendData.append(m_recordTime);
qDebug() << "_sendData:" << _sendData;
sendData();
//thread->start();
});
//sendTimer->start(1000);
}
AudioRecorder::~AudioRecorder()
{
if (audioInput)
delete audioInput;
if (audioFile)
delete audioFile;
}
void AudioRecorder::startRecording()
{
audioInput = new QAudioInput(format, this);
if(!audioFile->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "Open failed";
}
audioInput->start(audioFile);
// 连接信号槽来监控数据
QObject::connect(audioInput, &QAudioInput::notify, [&]() {
m_dataSize = audioFile->size();
qDebug() << "Record data" << m_dataSize << "byte";
});
// 设置通知间隔
audioInput->setNotifyInterval(1000); // 每秒更新一次
emit recordingStarted();
}
void AudioRecorder::stopRecording()
{
if (audioInput) {
audioInput->stop();
audioFile->seek(0);
writeWavHeader();
QFileInfo fileInfo(*audioFile);
QString fullPath = fileInfo.absoluteFilePath();
qDebug() << "Finish record, size:" << audioFile->size() << fullPath;
setFilePath(fullPath);
audioFile->close();
delete audioInput;
audioInput = nullptr;
emit recordingStopped();
}
}
void AudioRecorder::play()
{
mediaPlayer = new QMediaPlayer;
connect(mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
// 连接信号和槽以处理媒体状态变化
QObject::connect(mediaPlayer, &QMediaPlayer::mediaStatusChanged, [=](QMediaPlayer::MediaStatus status) {
if (status == QMediaPlayer::LoadedMedia) {
qint64 duration = mediaPlayer->duration(); // 获取时长(毫秒)
qDebug() << "Duration:" << duration << "ms";
}
});
// 连接 durationChanged 信号
QObject::connect(mediaPlayer, &QMediaPlayer::durationChanged, [=](qint64 duration) {
if (duration > 0) {
qDebug() << "Duration:" << duration << "ms";
}
});
// 连接 stateChanged 信号
QObject::connect(mediaPlayer, &QMediaPlayer::stateChanged, [=](QMediaPlayer::State state) {
if (state == QMediaPlayer::StoppedState) {
// 播放完成,执行清理
qDebug() << "delete";
mediaPlayer->deleteLater(); // 安全删除对象
}
});
mediaPlayer->setVolume(50); // 设置音量
mediaPlayer->setMedia(QUrl::fromLocalFile("output.wav"));
mediaPlayer->play();
}
void AudioRecorder::writeWavHeader()
{
// WAV 文件的头部信息
audioFile->seek(0);
QDataStream out(audioFile);
out.setByteOrder(QDataStream::LittleEndian);
// RIFF 头部
out.writeRawData("RIFF", 4);
out << quint32(audioFile->size() - 8); // 文件大小减去 RIFF 头部和文件大小字段
out.writeRawData("WAVE", 4);
// fmt 子块
out.writeRawData("fmt ", 4);
out << quint32(16); // PCM 的 fmt 子块的大小
out << quint16(1); // PCM 格式
out << quint16(format.channelCount());
out << quint32(format.sampleRate());
out << quint32(format.sampleRate() * format.channelCount() * format.sampleSize() / 8);
out << quint16(format.channelCount() * format.sampleSize() / 8);
out << quint16(format.sampleSize());
// data 子块
out.writeRawData("data", 4);
out << quint32(audioFile->size() - 44); // 音频数据的大小
}
void AudioRecorder::sendData_UDP()
{
if (!readAudioFile.open(QIODevice::ReadOnly)) {
qDebug() << "Open file error";
return;
}
const int bufferSize = 32;
QByteArray buffer(bufferSize, 0);
static int sendCounts = 0;
static int sendByteAll = 0;
while (!readAudioFile.atEnd()) {
int bytesRead = readAudioFile.read(buffer.data(), bufferSize);
sendByteAll += bytesRead;
qDebug() << "Send " << sendByteAll << QTime::currentTime().toString("hh:mm:ss:zzz");
if (bytesRead > 0) {
udpSocket->writeDatagram(buffer, targetAddress, targetPort);
}
sendCounts++;
QThread::msleep(20);
}
readAudioFile.close();
qDebug() << "sendCounts:" << sendCounts;
}
void AudioRecorder::sendData()
{
udpSocket->writeDatagram(_sendData, targetAddress, targetPort);
}
void AudioRecorder::positionChanged(qint64 pos)
{
qDebug() << "pos:" << pos;
}
const QString &AudioRecorder::filePath() const
{
return m_filePath;
}
void AudioRecorder::setFilePath(const QString &newFilePath)
{
if (m_filePath == newFilePath)
return;
m_filePath = newFilePath;
emit filePathChanged();
}