mirror of
https://gitee.com/Zhaoxin59/my-chat_-client.git
synced 2026-02-13 16:41:48 +08:00
132 lines
4.2 KiB
C++
132 lines
4.2 KiB
C++
#include "soundrecorder.h"
|
|
#include <QDir>
|
|
#include <QMediaDevices>
|
|
|
|
#include "model/data.h"
|
|
#include "toast.h"
|
|
|
|
/////////////////////////////////////////////
|
|
/// 单例模式
|
|
/////////////////////////////////////////////
|
|
SoundRecorder* SoundRecorder::instance = nullptr;
|
|
|
|
SoundRecorder *SoundRecorder::getInstance()
|
|
{
|
|
if (instance == nullptr) {
|
|
instance = new SoundRecorder();
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
// 播放参考 https://www.cnblogs.com/tony-yang-flutter/p/16477212.html
|
|
// 录制参考 https://doc.qt.io/qt-6/qaudiosource.html
|
|
SoundRecorder::SoundRecorder(QObject *parent)
|
|
: QObject{parent}
|
|
{
|
|
// 1. 创建目录
|
|
QDir soundRootPath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
|
soundRootPath.mkdir("sound");
|
|
|
|
// 2. 初始化录制模块
|
|
soundFile.setFileName(RECORD_PATH);
|
|
|
|
QAudioFormat inputFormat;
|
|
inputFormat.setSampleRate(16000);
|
|
inputFormat.setChannelCount(1);
|
|
inputFormat.setSampleFormat(QAudioFormat::Int16);
|
|
|
|
QAudioDevice info = QMediaDevices::defaultAudioInput();
|
|
if (!info.isFormatSupported(inputFormat)) {
|
|
//LOG() << "录制设备, 格式不支持!";
|
|
LOG() << "指定格式不支持,尝试使用设备的最佳格式进行录音";
|
|
inputFormat = info.preferredFormat();
|
|
|
|
QAudioFormat preferredFormat = inputFormat;
|
|
// 打印查看详细的格式信息
|
|
//LOG() << "设备首选格式详情:";
|
|
//LOG() << " 采样率 (SampleRate):" << preferredFormat.sampleRate() << "Hz";48000hz
|
|
//LOG() << " 声道数 (ChannelCount):" << preferredFormat.channelCount(); 2
|
|
//LOG() << " 样本格式 (SampleFormat):" << preferredFormat.sampleFormat(); FLOAT
|
|
|
|
// 确保至少是单声道
|
|
/*if (inputFormat.channelCount() > 1) {
|
|
inputFormat.setChannelCount(1);
|
|
}*/
|
|
//return;
|
|
}
|
|
|
|
audioSource = new QAudioSource(inputFormat, this);
|
|
connect(audioSource, &QAudioSource::stateChanged, this, [=](QtAudio::State state) {
|
|
if (state == QtAudio::StoppedState) {
|
|
// 录制完毕
|
|
if (audioSource->error() != QAudio::NoError) {
|
|
LOG() << audioSource->error();
|
|
}
|
|
}
|
|
});
|
|
|
|
// 3. 初始化播放模块
|
|
outputDevices = new QMediaDevices(this);
|
|
outputDevice = outputDevices->defaultAudioOutput();
|
|
QAudioFormat outputFormat;
|
|
outputFormat.setSampleRate(16000);
|
|
outputFormat.setChannelCount(1);
|
|
outputFormat.setSampleFormat(QAudioFormat::Int16);
|
|
if (!outputDevice.isFormatSupported(outputFormat)) {
|
|
//LOG() << "播放设备, 格式不支持";
|
|
LOG() << "指定格式不支持,尝试使用设备的最佳格式进行播放";
|
|
outputFormat = outputDevice.preferredFormat();
|
|
// 确保至少是单声道
|
|
/*if (outputFormat.channelCount() > 1) {
|
|
outputFormat.setChannelCount(1);
|
|
}*/
|
|
//return;
|
|
}
|
|
audioSink = new QAudioSink(outputDevice, outputFormat);
|
|
|
|
connect(audioSink, &QAudioSink::stateChanged, this, [=](QtAudio::State state) {
|
|
if (state == QtAudio::IdleState) {
|
|
LOG() << "IdleState";
|
|
this->stopPlay();
|
|
emit this->soundPlayDone();
|
|
} else if (state == QAudio::ActiveState) {
|
|
LOG() << "ActiveState";
|
|
} else if (state == QAudio::StoppedState) {
|
|
LOG() << "StoppedState";
|
|
if (audioSink->error() != QtAudio::NoError) {
|
|
LOG() << audioSink->error();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void SoundRecorder::startRecord() {
|
|
soundFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
|
|
audioSource->start(&soundFile);
|
|
}
|
|
|
|
void SoundRecorder::stopRecord() {
|
|
audioSource->stop();
|
|
soundFile.close();
|
|
emit this->soundRecordDone(RECORD_PATH);
|
|
}
|
|
|
|
void SoundRecorder::startPlay(const QByteArray& content) {
|
|
if (content.isEmpty()) {
|
|
Toast::showMessage("数据加载中, 请稍后播放");
|
|
return;
|
|
}
|
|
// 1. 把数据写入到临时文件
|
|
model::writeByteArrayToFile(PLAY_PATH, content);
|
|
|
|
// 2. 播放语音
|
|
inputFile.setFileName(PLAY_PATH);
|
|
inputFile.open(QIODevice::ReadOnly);
|
|
audioSink->start(&inputFile);
|
|
}
|
|
|
|
void SoundRecorder::stopPlay() {
|
|
audioSink->stop();
|
|
inputFile.close();
|
|
}
|