本页内容

音频概述

声波

音频功能

Qt Multimedia 提供了一系列音频类,涵盖了音频输入、输出和处理的低级和高级实现方法。

音频实现细节

播放压缩音频

若要播放非简单未压缩音频的媒体或音频文件,您可以使用QMediaPlayer C++类,或MediaPlayer QML类型。如有需要,QMediaPlayer 类及其关联的QML类型还支持播放视频。

更多详细信息,请参阅“支持的媒体格式”。

媒体播放器需要连接到一个QAudioOutput 对象(或QML中的AudioOutput 元素)才能播放音频。

以下是使用 C++ 播放本地文件的方法:

player = new QMediaPlayer;
audioOutput = new QAudioOutput;
player->setAudioOutput(audioOutput);
// ...
player->setSource(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));
audioOutput->setVolume(0.5);
player->play();

QML中的相同功能如下:

MediaPlayer {
    audioOutput: AudioOutput {}
    source: "file:///path/to/my/music.mp3"
    Component.onCompleted: { play() }
}

将音频录制到文件中

要将音频录制到文件中,您需要创建一个捕获会话,并将其与音频输入和录音机连接起来。这些组件通过QMediaCaptureSession 、QAudioInput 和QMediaRecorder 类实现。默认构造的QAudioInput 会选择系统默认的音频输入。 录音器通过简单的 record() 和 stop() 函数控制录音过程。此外,您还可以使用它来选择输出位置、音频编码器或文件容器格式。

在 C++ 中,从默认麦克风录制音频的会话代码如下所示:

QMediaCaptureSession session;
QAudioInput audioInput;
session.setAudioInput(&audioInput);
QMediaRecorder recorder;
session.setRecorder(&recorder);
recorder.setQuality(QMediaRecorder::HighQuality);
recorder.setOutputLocation(QUrl::fromLocalFile("test.mp3"));
recorder.record();

在 QML 中,可以通过以下方式实现相同的功能:

CaptureSession {
    audioInput: AudioInput {}
    mediaRecorder: MediaRecorder {
        id: recorder
        outputLocation: "file:///path/to/test.mp3"
    }
    Component.onCompleted: { recorder.record() }
}

QMediaCaptureSession 还支持更复杂的用例,例如图像捕捉或视频录制。

低延迟音效

除了对声音设备的直接访问外,QSoundEffect 类(以及SoundEffect QML类型)还提供了一种更抽象的声音播放方式。该类允许您指定一个WAV格式的文件,并在需要时以低延迟的方式播放该文件。

您可以调整:

低级音频输入与输出

Qt Multimedia 的 C++ API 提供了用于直接访问音频输入和输出功能的类,允许应用程序从麦克风等设备接收原始数据,并将原始数据写入扬声器或其他设备。通常,这些类不会进行任何音频解码或其他处理,但它们可以支持不同类型的原始音频数据。

QAudioSink 类提供原始音频数据输出,而QAudioSource 类提供原始音频数据输入。可用的音频输入和输出接口取决于具体硬件配置。

使用 QIODevice 进行推送和拉取

低级音频类可运行于两种模式——push 和pull 。在pull 模式下,通过向音频设备提供QIODevice 来启动该设备。对于输出设备,当需要更多音频数据时,QAudioSink 类将从QIODevice 中拉取数据(使用QIODevice::read())。相反,在pull 模式下(使用QAudioSource ),当有音频数据可用时,数据将直接写入QIODevice 。

在push 模式下,音频设备会提供一个QIODevice 实例,可根据需要对其进行读写操作。

注意: QIODevice 不会立即访问音频设备,而是会在内部对数据进行缓冲。这意味着可以随时从应用程序线程使用QIODevice 进行数据读写,同时会增加通常为 250 毫秒的缓冲时间。 如果应用程序向QIODevice 传输音频数据的速度不够快(针对QAudioSink ),或者读取QIODevice 的速度不够快,就会发生音频中断。

基于回调的接口

除了基于QIODevice 的接口外,低级音频类还提供了一个基于回调的接口,允许用户注册一个回调函数,该回调会在音频设备需要或发送更多数据时,在音频线程上被调用。这使得音频处理的延迟大大降低,因为应用程序可以直接在音频线程上处理数据。

{
    QAudioFormat format;
    // 配置格式,例如:
    format.setSampleRate(44100);
    format.setChannelCount(2);
    format.setSampleFormat(QAudioFormat::Float);

    QAudioDevice info(QMediaDevices::defaultAudioOutput());
    if(!info.isFormatSupported(format)) {
        qWarning() << "Raw audio format not supported by backend, cannot play audio.";
       return;
    }

    audio= newQAudioSink(format, this);
    floatphaseIncrement= 2 *M_PI* 220.0 /format.sampleRate();// 220 Hz 正弦波
    audio->start([&phase,phaseIncrement](QSpan<float>交错音频缓冲区) {
        // 音频回调不应调用任何可能导致阻塞的函数

        // 用正弦波填充音频缓冲区
        const int采样数=交错音频缓冲区.size()/ 2;// 立体声,因此除以 2
        for(inti= 0; i<sampleCount;++i) {
            floatsample=std::sin(phase);
            interleavedAudioBuffer[i* 2] =sample;    // 左声道
            interleavedAudioBuffer[i* 2 + 1] =sample;// 右声道
            phase+=phaseIncrement;                    // 增加相位以处理下一个采样
        }
    });

    if(!audio->error()==QtAudio::Error::NoError) {
        // 除了其他 start() 签名外,如果出现以下情况,启动音频回调将失败:
        // * 后端未实现基于回调的 I/O(该 API 在所有主要
        //   平台上均 可用 )
       // * 音频回调的签名与 format.sampleFormat() 不匹配

        qWarning() << "Error starting audio output:" << audio->errorString();
    }
}

注意:此 API 仅在支持回调 API 的平台上可用:Apple 的 CoreAudio(macOS、iOS 等)、Windows、Linux(使用 PulseAudio 或 PipeWire 后端)以及 Android。

注意:回调 将在软实时音频线程上被调用。务必确保回调不会阻塞,否则可能会导致音频卡顿或中断。这包括执行阻塞式 I/O、锁定互斥量、分配内存或任何其他可能导致阻塞的操作。 有关最佳实践,请参阅 Ross Bencina 的文章《实时音频编程入门:时间不等人》。此外,建议使用 clang的实时验证器(Realtime sanitizer)来验证音频回调函数。

将压缩音频解码到内存中

在某些情况下,您可能需要解码压缩音频文件并自行进行进一步处理。例如,混合多个采样或使用自定义的数字信号处理算法。QAudioDecoder 支持解码本地文件或来自QIODevice 实例的数据流。

以下是一个解码本地文件的示例:

QAudioFormat desiredFormat;
desiredFormat.setChannelCount(2);
desiredFormat.setSampleFormat(QAudioFormat::Int16);
desiredFormat.setSampleRate(48000);

QAudioDecoder *decoder = new QAudioDecoder(this);
decoder->setAudioFormat(desiredFormat);
decoder->setSource("level1.mp3");

connect(decoder, &QAudioDecoder::bufferReady, this, &AudioDecodingExample::readBuffer);
decoder->start();

// Now wait for bufferReady() signal and call decoder->read()

空间音频

该 Qt Spatial Audio 模块提供了一个用于在三维空间中实现声场的 API。

参考文档

C++ 类

QAmbientSound

立体声叠加音频

QAudioBuffer

表示一组具有特定格式和采样率的音频样本

QAudioBufferInput

用于通过 QMediaCaptureSession 向 QMediaRecorder 提供自定义音频缓冲区

QAudioBufferOutput

用于捕获由 QMediaPlayer 提供的音频数据

QAudioDecoder

实现音频解码

QAudioDevice

有关音频设备及其功能的信息

QAudioEngine

管理三维声场

QAudioFormat

用于存储音频流参数信息

QAudioInput

表示音频的输入通道

QAudioListener

定义聆听由 QAudioEngine 定义的声场的人的位置和方向

QAudioOutput

表示音频的输出通道

QAudioRoom

QAudioSink

用于将音频数据发送至音频输出设备的接口

QAudioSource

用于从音频输入设备接收音频数据的接口

QMediaCaptureSession

允许捕获音频和视频内容

QMediaRecorder

用于对捕获会话进行编码和录制

QSoundEffect

播放低延迟音效的方法

QSpatialSound

3D 空间中的声音对象

QtAudio

包含音频类所使用的枚举

QML 类型

AmbientSound

立体声叠加音频

AudioEngine

管理 3D 场景中的声音对象

AudioInput

用于在捕获会话中捕获音频的音频输入

AudioListener

定义了聆听由 AudioEngine 定义的声音场的人的位置和方向

AudioOutput

用于回放或监听采集会话的音频输出

AudioRoom

CaptureSession

允许捕获音频和视频内容

MediaPlayer

向场景中添加媒体播放功能

MediaRecorder

用于对 CaptureSession 中生成的媒体进行编码和录制

PlaybackOptions

低级媒体播放选项

SoundEffect

该类型提供了一种在 QML 中播放音效的方法

SpatialSound

3D 空间中的声音对象

audioDevice

描述音频设备

mediaMetaData

为媒体文件提供元数据

示例

Audio Devices Example

列出可用的音频设备及其配置。

Audio Output Example

使用 QAudioSink 类启用音频播放。

Audio Recorder Example

检测可用设备及支持的编解码器。

Audio Source Example

使用 QAudioSource 类录制音频。

Spatial Audio Panning Example

展示 Qt Spatial Audio 中空间音频引擎的部分功能

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.