mirror of
https://gitee.com/Zhaoxin59/my-chat_-client.git
synced 2026-02-14 00:51:48 +08:00
refactor: 大规模调整项目目录结构,将ChatClient和ChatServer整合为Monorepo结构,并分为两个独立文件夹:chatclient/ 和 chatserver/。更新了ChatClient的CMakeLists.txt配置以适配新结构。
This commit is contained in:
131
ChatClient/src/soundrecorder.cpp
Normal file
131
ChatClient/src/soundrecorder.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#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();
|
||||
}
|
||||
Reference in New Issue
Block a user