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

这篇具有很好参考价值的文章主要介绍了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():槽函数,处理停止录音按钮的点击事件。停止录音。

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

        总体来说,这段代码实现了一个简单的录音应用的主窗口界面和录音功能的实现。用户可以选择音频输入设备、设置媒体格式参数,开始录音,并可以暂停、停止录音,并选择保存录音文件的路径。文章来源地址https://www.toymoban.com/news/detail-723874.html

到了这里,关于qt6 多媒体开发代码分析(二、录音)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 鸿蒙HarmonyOS开发实战—多媒体开发(音频开发 一)

    HarmonyOS音频模块支持音频业务的开发,提供音频相关的功能,主要包括音频播放、音频采集、音量管理和短音播放等。 基本概念 采样 采样是指将连续时域上的模拟信号按照一定的时间间隔采样,获取到离散时域上离散信号的过程。 采样率 采样率为每秒从连续信号中提取并

    2024年01月24日
    浏览(51)
  • Android多媒体功能开发(2)——FileProvider

    使用系统多媒体界面需要在我们的应用和其他应用之间通过Intent传递音频、图片、视频文件的信息。随着Android版本的升级,对应用数据安全性方面的限制越来越多。 Android 6以后不允许应用在外部存储随便创建目录,只能在Android规定的应用自己的文件目录下创建目录,该目录

    2024年02月14日
    浏览(48)
  • HarmonyOS学习路之开发篇—多媒体开发(相机开发 二)

    Camera操作类,包括相机预览、录像、拍照等功能接口。 接口名 描述 triggerSingleCapture​(FrameConfig frameConfig) 启动相机帧的单帧捕获。 triggerMultiCapture​(ListFrameConfig frameConfigs) 启动相机帧的多帧捕获。 configure​(CameraConfig config) 配置相机。 flushCaptures​() 停止并清除相机帧的捕获

    2024年02月11日
    浏览(56)
  • HarmonyOS学习路之开发篇—多媒体开发(图像开发 二)

    图像编码就是将PixelMap图像编码成不同存档格式图片,用于后续其他处理,比如保存、传输等。当前仅支持JPEG格式。 ImagePacker主要用于图像编码。 接口名 描述 create() 创建图像打包器实例。 initializePacking(byte[] data, PackingOptions opts) 初始化打包任务,将字节数组设置为打包后输

    2024年02月11日
    浏览(59)
  • HarmonyOS学习路之开发篇—多媒体开发(相机开发 一)

    HarmonyOS相机模块支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照、连拍和录像等。 相机静态能力 用于描述相机的固有能力的一系列参数,比如朝向、支持的分辨率等信息。 物理相机 物理相机就是独

    2024年02月10日
    浏览(68)
  • HarmonyOS学习路之开发篇—多媒体开发(图像开发 一)

    HarmonyOS图像模块支持图像业务的开发,常见功能如图像解码、图像编码、基本的位图操作、图像编辑等。当然,也支持通过接口组合来实现更复杂的图像处理逻辑。 图像解码 图像解码就是不同的存档格式图片(如JPEG、PNG等)解码为无压缩的位图格式,以方便在应用或者系统

    2024年02月11日
    浏览(50)
  • HarmonyOS学习路之开发篇—多媒体开发(音频开发 二(1)

    接口说明 接口名 描述 AudioCapturer(AudioCapturerInfo audioCapturerInfo) throws IllegalArgumentException 构造函数,设置录音相关音频参数,使用默认录音设备。 AudioCapturer(AudioCapturerInfo audioCapturerInfo, AudioDeviceDescriptor devInfo) throws IllegalArgumentException 构造函数,设置录音相关音频参数并指定录音

    2024年04月23日
    浏览(57)
  • Android多媒体功能开发(12)——使用Camera类拍照

    Android上用摄像头拍照、录视频有两套API可用,Android5.0(API21)之前使用android.hardware.Camera类,之后推荐使用android.hardware.camera2包。目前这两套API都可以使用,Camera类用起来比较简单易懂,但功能少灵活性差,所以现在降级使用;Camera2框架功能强大,对摄像头的控制灵活,但由于

    2023年04月13日
    浏览(43)
  • Android多媒体功能开发(11)——使用AudioRecord类录制音频

    AudioRecord类优点是能录制到缓冲区,能够实现边录边播(AudioRecord + AudioTrack)以及对音频的实时处理(如QQ电话)。缺点是输出是PCM格式的原始采集数据,如果直接保存成音频文件,不能够被播放器播放,所以必须用代码实现数据编码以及压缩。 使用AudioRecord录音的基本步骤是

    2023年04月09日
    浏览(45)
  • SDL库入门:掌握跨平台游戏开发和多媒体编程

    SDL (Simple DirectMedia Layer) 是一个跨平台的开源多媒体库,它提供了访问音频、键盘、鼠标、操纵杆以及图形硬件的底层接口。SDL 可用于开发游戏、仿真器、媒体播放器等多种类型的应用程序。 1.1 SDL 的背景与应用领域 SDL 由 Sam Lantinga 开发,最早发布于 1998 年。SDL 的设计目标是

    2024年02月02日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包