qt6 多媒体开发代码分析(二、录音)

常见的音频编码格式包括MP3、AAC、OGG、WMA、FLAC等,它们之间具有以下区别:

  1. 编码方式不同:这些编码格式采用的编码算法不同,例如MP3和AAC使用有损压缩算法,而FLAC使用无损压缩算法。

  2. 压缩率和文件大小不同:由于采用的编码算法不同,不同格式的音频文件压缩率和文件大小也不同。有损压缩格式如MP3通常能够将文件压缩至原始文件大小的10%左右,相对较小,但以牺牲一定的音质为代价。无损压缩格式如FLAC虽然压缩率不如有损压缩格式高,但保持了接近原始音频文件的质量,文件大小也比有损格式大。

  3. 支持性和兼容性不同:不同的音频编码格式在各种设备和软件上的兼容性和支持性也不同。例如,MP3格式是最为普及的音频格式之一,几乎所有主流的音频设备和软件都支持;而FLAC格式虽然有着高保真的特点,但并不是所有设备和平台都支持,特别是在移动设备上的使用较局限。

  4. 音质表现不同:由于采用的编码算法、参数和设置不同,不同格式的音频文件在音质表现上也会有所区别。例如,有些编码格式对高音区的表现可能更优秀,而有些编码格式则可能更擅长处理低音区。

综上所述,选择哪种音频编码格式应根据实际需求和设备支持情况来判断。如果需要在多平台或多设备上播放音频文件,一般建议选择通用性较高、支持性广泛的格式,如MP3、AAC等;如果注重音质,则可以考虑使用无损压缩格式,如FLAC等。

MP3和AAC是两种常见的音频编码格式,它们之间有以下区别:

  1. 编码方式:MP3采用MPEG Audio Layer-3的编码方式,而AAC采用Advanced Audio Coding的编码方式。

  2. 压缩效率:AAC相对于MP3具有更高的压缩效率,即在相同的比特率下能够提供更好的音质。这意味着使用相同文件大小或比特率,AAC编码的音频文件往往会更清晰、更接近原始音频。

  3. 音质表现:由于采用不同的编码算法,AAC在相同比特率下通常具有更好的音质表现。尤其在低比特率下,AAC能够保持相对较好的音质,而MP3在低比特率下可能出现更明显的失真和质量损失。

  4. 文件大小:由于AAC更高的压缩效率,相同音质下的AAC文件大小通常会比MP3文件小一些。这对于存储容量有限的设备和带宽有限的网络传输来说,可以节省空间和提升传输速度。

  5. 广泛支持:MP3是最为广泛支持的音频格式之一,几乎所有音频设备和软件都能播放MP3文件。而AAC作为较新的编码格式,在一些旧版设备和软件上可能不如MP3普及,但在现代设备和流媒体平台上得到了广泛支持。

总的来说,AAC相对于MP3具有更高的压缩效率和更好的音质表现,而MP3则具有更广泛的支持。选择使用哪种格式应根据具体需求和设备的兼容性来决定。若追求更好的音质或者希望节省空间和带宽,AAC可能是更好的选择;若需要在各种设备和软件上保证兼容性,则MP3是一个较为安全的选择。

        音频通道数是指音频信号中包含的独立声音通道的数量。每个通道都可以携带单独的音频信息,例如左声道、右声道或者中央声道等。

常见的音频通道数有以下几种:

  1. 单声道(Mono):只有一个声道,音频信号通过一个单独的通道进行传输。适用于部分语音、广播和低成本音频设备。

  2. 双声道(Stereo):包含左声道(Left Channel)和右声道(Right Channel),分别用于传输不同的音频信息。大部分音乐、影视作品以及普通耳机、扬声器都支持双声道。

  3. 立体声(Joint Stereo):在双声道的基础上,通过对左声道和右声道进行编码,利用共享信息实现更高的压缩效率。立体声通常会保留左右声道的独立性,但一些低比特率的编码方式可能会牺牲一定的声音分离度。

  4. 多声道(Multi-channel):除了左声道和右声道外,还包含额外的声道,如中央声道(Center Channel)、环绕声道(Surround Channels)等。多声道通常用于影院、家庭影院系统,以及专业音频领域,以提供更真实、沉浸式的音频体验。

音频通道数决定了音频信号可以携带的声音分离度和立体感。选择适合的音频通道数取决于音频内容的特性以及播放设备的支持能力。例如,音乐作品通常会采用双声道或多声道以提供立体声效果,而语音录音或电话通话可能只需要单声道即可。

录音时固定品质和固定比特率是两种不同的录音设置方法,它们有以下区别:

  1. 固定品质:该设置方式的目的是保持录制音频的固定品质,通常以VBR(可变比特率)的方式实现。在固定品质的设置下,编码器会根据音频信号的复杂程度动态调整比特率,使得音频能够达到相对稳定并且高质量的压缩比率。因此,使用固定品质设置可以获得更好的音质体验,但文件大小可能会随着音频信号复杂程度的变化而发生变化。

  2. 固定比特率:该设置方式的目的是保持录制音频的固定比特率,通常以CBR(恒定比特率)的方式实现。在固定比特率的设置下,编码器会始终以相同的比特率对音频数据进行编码,即使音频信号复杂度发生变化,也不会改变编码率。因此,使用固定比特率设置可以确保录制的音频文件大小、比特率的稳定性,但音质可能会受到影响,特别是在音频信号复杂度变化较大的情况下。

总的来说,选择固定品质或固定比特率设置需要根据具体情况进行选择。如果追求更好的音质体验,可以使用固定品质设置;如果追求稳定的文件大小和比特率,可以使用固定比特率设置。但需要注意的是,使用VBR设置时,音频文件的大小可能会随着信号复杂度的变化而产生变化,因此在一些容量受限或者网络带宽受限的场景下,需要权衡考虑。

qt6  开发录音主要是2个类:

  • QMediaCaptureSession对象,用于采集音频和视频。
  • recorder:QMediaRecorder对象,用于录制音频和视频

QAudioInput 类   访问连接到系统上的输入设备 如麦克风等

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>
#include    <QtMultimedia>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE


class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QMediaCaptureSession *session;
    QMediaRecorder  *recorder;

    void closeEvent(QCloseEvent *event);
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
//自定义槽函数
    void do_stateChanged(QMediaRecorder::RecorderState state);

    void do_durationChanged(qint64 duration);

    void on_actRecord_triggered();

    void on_btnGetFile_clicked();

    void on_actPause_triggered();

    void on_actStop_triggered();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

这段代码是一个使用Qt框架实现的主窗口类MainWindow的头文件。下面对其进行解释:

  1. 包含了必要的头文件:

    • <QMainWindow>:用于定义主窗口类的头文件。
    • <QtMultimedia>:包含了多媒体相关的类和函数。
  2. 命名空间声明:

    • QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE:用于将后续内容置于Qt命名空间中,防止命名冲突。
    • namespace Ui:定义了一个名为Ui的命名空间。
  3. 类定义:

    • MainWindow:继承自QMainWindow,表示主窗口类。
    • private部分:包含了私有的成员变量和函数,不可以直接访问。
      • session:用于存储多媒体捕捉会话对象的指针。
      • recorder:用于存储多媒体录制对象的指针。
      • closeEvent:处理关闭事件的函数,通过重写该函数可以自定义在窗口关闭时执行的操作。
    • public部分:包含了公共的成员函数,可以从外部访问。
      • 构造函数MainWindow:用于创建MainWindow类的对象。
      • 析构函数~MainWindow:用于销毁MainWindow类的对象。
    • private slots部分:包含了一些私有槽函数,用于处理信号和事件。
      • do_stateChanged:处理录音状态改变的槽函数。
      • do_durationChanged:处理录音时长改变的槽函数。
      • on_actRecord_triggered:响应录制触发动作的槽函数。
      • on_btnGetFile_clicked:响应获取文件按钮点击事件的槽函数。
      • on_actPause_triggered:响应暂停触发动作的槽函数。
      • on_actStop_triggered:响应停止触发动作的槽函数。
    • private部分:定义了一个私有成员变量ui,用于存储MainWindow窗口的用户界面对象。
  4. 宏定义:

    • #ifndef MAINWINDOW_H 和 #define MAINWINDOW_H:用于避免头文件的重复包含。

总体来说,这段代码定义了一个主窗口类MainWindow,其中包含了一些私有成员变量、公共成员函数和私有槽函数,用于实现多媒体录音功能的控制和操作。

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include    <QFileDialog>
#include    <QMessageBox>
#include    <QFileInfo>

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (recorder->recorderState() != QMediaRecorder::StoppedState)
    {
        QMessageBox::information(this,"提示","正在录音,不能退出");
        event->ignore();
    }
    else
        event->accept();
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    session = new QMediaCaptureSession(this);  //QMediaCaptureSession是采集音频、视频的类

    QAudioInput *audioInput= new QAudioInput(this);
    session->setAudioInput(audioInput);     // session 需要设置音频输入

    recorder= new QMediaRecorder(this);
    session->setRecorder(recorder);         //为session 设置 recorder

    connect(recorder,&QMediaRecorder::recorderStateChanged,
            this,&MainWindow::do_stateChanged);

    connect(recorder, &QMediaRecorder::durationChanged,
            this, &MainWindow::do_durationChanged);

    if (QMediaDevices::defaultAudioInput().isNull())    //如果没有默认的音频输入设备
    {
        ui->groupBoxDevice->setTitle("录音设置(无设备)");
        ui->actRecord->setEnabled(false);
        QMessageBox::information(this,"提示", "无音频输入设备");
        return;  //无音频录入设备
    }

     //音频录入设备列表
    foreach (QAudioDevice device, QMediaDevices::audioInputs())
        ui->comboDevices->addItem(device.description(), QVariant::fromValue(device));

    QMediaFormat format;        //默认的格式对象
    //支持的编码格式
    foreach (QMediaFormat::AudioCodec encoder, format.supportedAudioCodecs(QMediaFormat::Encode))
        ui->comboCodec->addItem(QMediaFormat::audioCodecDescription(encoder),
                                QVariant::fromValue(encoder));
    //支持的文件格式
    foreach (QMediaFormat::FileFormat fileFormat, format.supportedFileFormats(QMediaFormat::Encode))
        ui->comboFileFormat->addItem(QMediaFormat::fileFormatDescription(fileFormat),
                                     QVariant::fromValue(fileFormat));
    //采样频率
    int minSampRate=audioInput->device().minimumSampleRate();   //输入设备支持的最低采样率
    ui->comboSampleRate->addItem(QString("Minimum %1").arg(minSampRate), minSampRate);
    int maxSampRate=audioInput->device().maximumSampleRate();   //输入设备支持的最高采样率
    ui->comboSampleRate->addItem(QString("Maximum %1").arg(maxSampRate), maxSampRate);
    ui->comboSampleRate->addItem("16000", 16000);   //添加了用户数据
    ui->comboSampleRate->addItem("44100", 44100);
    ui->comboSampleRate->addItem("48000", 48000);
    ui->comboSampleRate->addItem("88200", 88200);

    //通道数
    int minChan=audioInput->device().minimumChannelCount();  //最少通道数
    ui->comboChannels->addItem(QString("Minimum %1").arg(minChan), minChan);
    int maxChan=audioInput->device().maximumChannelCount();  //最多通道数
    ui->comboChannels->addItem(QString("Maximum %1").arg(maxChan), maxChan);
    ui->comboChannels->addItem("1", 1);
    ui->comboChannels->addItem("2", 2);

    //固定品质
    ui->sliderQuality->setRange(0, int(QImageCapture::VeryHighQuality));
    ui->sliderQuality->setValue(int(QImageCapture::NormalQuality));

    //固定比特率
    ui->comboBitrate->addItem("32000");
    ui->comboBitrate->addItem("64000");
    ui->comboBitrate->addItem("96000");
    ui->comboBitrate->addItem("128000");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::do_stateChanged(QMediaRecorder::RecorderState state)
{ //录音状态变化
    bool isRecording = state==QMediaRecorder::RecordingState;   //正在录制
    ui->actRecord->setEnabled(!isRecording);
    ui->actPause->setEnabled(isRecording);
    ui->actStop->setEnabled(isRecording);

    ui->btnGetFile->setEnabled(state==QMediaRecorder::StoppedState);
}

void MainWindow::do_durationChanged(qint64 duration)
{//录音持续时间变化
    ui->labPassTime->setText(QString("已录制 %1 秒").arg(duration / 1000));
}

//void MainWindow::processBuffer(const QAudioBuffer &buffer)
//{ //处理探测到的缓冲区
//    ui->spin_byteCount->setValue(buffer.byteCount());//缓冲区字节数
//    ui->spin_duration->setValue(buffer.duration()/1000);//缓冲区时长
//    ui->spin_frameCount->setValue(buffer.frameCount());//缓冲区帧数
//    ui->spin_sampleCount->setValue(buffer.sampleCount());//缓冲区采样数

//    QAudioFormat audioFormat=buffer.format();//缓冲区格式
//    ui->spin_channelCount->setValue(audioFormat.channelCount()); //通道数
//    ui->spin_sampleSize->setValue(audioFormat.sampleSize());//采样大小
//    ui->spin_sampleRate->setValue(audioFormat.sampleRate());//采样率
//    ui->spin_bytesPerFrame->setValue(audioFormat.bytesPerFrame());//每帧字节数

//    if (audioFormat.byteOrder()==QAudioFormat::LittleEndian)
//        ui->edit_byteOrder->setText("LittleEndian");//字节序
//    else
//        ui->edit_byteOrder->setText("BigEndian");

//    ui->edit_codec->setText(audioFormat.codec());//编码格式

//    if (audioFormat.sampleType()==QAudioFormat::SignedInt)//采样点类型
//        ui->edit_sampleType->setText("SignedInt");
//    else if(audioFormat.sampleType()==QAudioFormat::UnSignedInt)
//        ui->edit_sampleType->setText("UnSignedInt");
//    else if(audioFormat.sampleType()==QAudioFormat::Float)
//        ui->edit_sampleType->setText("Float");
//    else
//        ui->edit_sampleType->setText("Unknown");

//}

void MainWindow::on_actRecord_triggered()
{ //开始录音
    if (recorder->recorderState() == QMediaRecorder::PausedState)
    {//若是暂停状态,就继续录音
        recorder->record();
        return;
    }

    QString selectedFile=ui->editOutputFile->text().trimmed();
    if (selectedFile.isEmpty())
    {
        QMessageBox::critical(this,"错误","请先设置录音输出文件");
        return;
    }
    if (QFile::exists(selectedFile))
        QFile::remove(selectedFile);
    recorder->setOutputLocation(QUrl::fromLocalFile(selectedFile)); //设置输出文件

//设置session的输入设备
//    QVariant var =ui->comboDevices->itemData(ui->comboDevices->currentIndex());
//    QAudioDevice audioDevice= var.value<QAudioDevice>();
//    session->audioInput()->setDevice(audioDevice);
    session->audioInput()->setDevice(QMediaDevices::defaultAudioInput());

//设置 recorder 的 mediaFormat 参数,包括文件格式和编码格式
    QMediaFormat mediaFormat;
    QVariant var=ui->comboCodec->itemData(ui->comboCodec->currentIndex());
    QMediaFormat::FileFormat fileFormat= var.value<QMediaFormat::FileFormat>();
    mediaFormat.setFileFormat(fileFormat);  //设置文件格式

    var=ui->comboFileFormat->itemData(ui->comboFileFormat->currentIndex());
    QMediaFormat::AudioCodec audioCodec =var.value<QMediaFormat::AudioCodec>();
    mediaFormat.setAudioCodec(audioCodec);  //设置编码格式

    recorder->setMediaFormat(mediaFormat);  //设置mediaFormat

//设置 recorder 的其他参数
    var=ui->comboSampleRate->itemData(ui->comboSampleRate->currentIndex());
    recorder->setAudioSampleRate(var.toInt());      //设置采样率
    var=ui->comboChannels->itemData(ui->comboChannels->currentIndex());
    recorder->setAudioChannelCount(var.toInt());    //设置通道数
    recorder->setAudioBitRate(ui->comboBitrate->currentText().toInt());         //设置比特率
    recorder->setQuality(QMediaRecorder::Quality(ui->sliderQuality->value()));  //设置品质
    if (ui->radioQuality->isChecked())              //设置编码模式
        recorder->setEncodingMode(QMediaRecorder::ConstantQualityEncoding);     //固定品质
    else
        recorder->setEncodingMode(QMediaRecorder::ConstantBitRateEncoding);     //固定比特率

    recorder->record();
}

void MainWindow::on_btnGetFile_clicked()
{ //设置保存文件
    QString curPath=QDir::currentPath();//获取系统当前目录
    QString dlgTitle="选择输出文件"; //对话框标题
    QString filter="所有文件(*.*);;MP3文件(*.mp3);;WMA文件(*.wma);;MP4文件(*.mp4)"; //文件过滤器
    QString selectedFile=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);

    if (!selectedFile.isEmpty())
    {
        ui->editOutputFile->setText(selectedFile);
        QFileInfo  fileInfo(selectedFile);
        QDir::setCurrent(fileInfo.absolutePath());
    }
}

void MainWindow::on_actPause_triggered()
{ //暂停
    recorder->pause();
}

void MainWindow::on_actStop_triggered()
{//停止
    recorder->stop();
}

这段代码是一个录音应用的主窗口类的实现。它使用Qt框架提供的多媒体模块来实现录音功能。

主要的成员变量包括:

  • session:QMediaCaptureSession对象,用于采集音频和视频。
  • recorder:QMediaRecorder对象,用于录制音频和视频。

主要的成员函数包括:

  • closeEvent():重写了窗口关闭事件,如果正在录音,则弹出提示框,阻止窗口关闭。
  • do_stateChanged():槽函数,处理录音状态变化的信号。根据录音状态,启用或禁用相关按钮。
  • do_durationChanged():槽函数,处理录音持续时间变化的信号。更新显示录音时长的标签。
  • on_actRecord_triggered():槽函数,处理开始录音按钮的点击事件。设置录音输出文件、音频输入设备、媒体格式等参数,并开始录音。
  • on_btnGetFile_clicked():槽函数,处理选择输出文件按钮的点击事件。打开文件对话框,选择保存录音文件的路径。
  • on_actPause_triggered():槽函数,处理暂停录音按钮的点击事件。暂停录音。
  • on_actStop_triggered():槽函数,处理停止录音按钮的点击事件。停止录音。

在构造函数中,通过获取音频输入设备列表,并分别添加到音频输入设备的下拉列表中。同时,还获取了支持的编码格式、文件格式、采样频率、通道数等信息,并将其分别添加到对应的下拉列表中。

        总体来说,这段代码实现了一个简单的录音应用的主窗口界面和录音功能的实现。用户可以选择音频输入设备、设置媒体格式参数,开始录音,并可以暂停、停止录音,并选择保存录音文件的路径。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值