本页内容

QAudioSink Class

QAudioSink 类提供了一个用于将音频数据发送至音频输出设备的接口。更多内容...

头文件: #include <QAudioSink>
CMake: find_package(Qt6 REQUIRED COMPONENTS Multimedia)
target_link_libraries(mytarget PRIVATE Qt6::Multimedia)
qmake: QT += multimedia
继承自: QObject

公共函数

QAudioSink(const QAudioFormat &format = QAudioFormat(), QObject *parent = nullptr)
QAudioSink(const QAudioDevice &audioDevice, const QAudioFormat &format = QAudioFormat(), QObject *parent = nullptr)
virtual ~QAudioSink() override
(since 6.10) qsizetype bufferFrameCount() const
qsizetype bufferSize() const
qsizetype bytesFree() const
qint64 elapsedUSecs() const
QtAudio::Error error() const
QAudioFormat format() const
(since 6.10) qsizetype framesFree() const
bool isNull() const
(since 6.12) qsizetype nativePeriodFrameCount() const
qint64 processedUSecs() const
void reset()
void resume()
(since 6.10) void setBufferFrameCount(qsizetype value)
void setBufferSize(qsizetype value)
(since 6.12) void setNativePeriodFrameCount(qsizetype frameCount)
void setVolume(qreal volume)
QIODevice *start()
(since 6.11) void start(Callback &&cb)
void start(QIODevice *device)
QtAudio::State state() const
void stop()
void suspend()
qreal volume() const

信号

void stateChanged(QtAudio::State state)

详细说明

您可以使用系统的默认音频输出设备构建音频输出。也可以通过指定QAudioDevice 来创建QAudioSink。在创建音频输出时,还应提供用于播放的QAudioFormat (详情请参阅QAudioFormat 类的描述)。

QAudioSink 支持两种不同的工作模式:

  • 从应用程序线程使用QIODevice
  • 从音频线程使用基于回调的接口

QIODevice 接口

要开始播放音频流,只需向 `start()` 传递一个 `QIODevice` 即可。随后,`QAudioSink` 将从 I/O 设备中获取所需的数据。因此,播放音频文件非常简单:

QFile sourceFile;  // 类成员变量。
QAudioSink*audio;// 类成员。
{
    sourceFile.setFileName("/tmp/test.raw");
    sourceFile.open(QIODevice::ReadOnly);

    QAudioFormat format;
    // 设置格式,例如:
    format.setSampleRate(44100);
    format.setChannelCount(1);
    format.setSampleFormat(QAudioFormat::Int16);

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

    audio= newQAudioSink(format, this);
    connect(audio,QAudioSink::stateChanged, this, &AudioInputExample::handleStateChanged);
    audio->start(&sourceFile);
}

只要音频系统和输出设备支持该文件,它就会开始播放。如果播放失败,请检查error() 函数是否存在问题。

文件播放完毕后,我们需要停止设备:

void AudioOutputExample::stopAudioOutput()
{
    audio->stop();
    sourceFile.close();
    delete audio;
}

在任何给定时刻,QAudioSink 都会处于以下四种状态之一:活动、暂停、停止或空闲。这些状态由QtAudio::State 枚举类型描述。

线程模型与缓冲机制

QIODevice 接口的设计初衷是供应用程序线程使用。它采用无等待环形缓冲区与音频线程进行通信。 该环形缓冲区的大小可通过 `setBufferSize()` 进行配置,默认值为 250 毫秒。可通过 `bytesFree()` 查询该缓冲区的状态。如果环形缓冲区中的数据耗尽,音频线程将向音频设备发送静音信号,状态将变为 `QtAudio::IdleState `;当从 `QIODevice` 获得更多数据时,状态将恢复为 `QtAudio::ActiveState `。

回调接口

实现低音频延迟的首选方法是使用基于回调的接口。它允许您将音频数据直接写入音频设备,而无需通过QIODevice 。具体操作是调用start(),并传入一个将由音频线程调用的回调函数。 每当音频后端需要数据时,该回调函数都会被调用,并传入一个QSpan<SampleType>对象。

QAudioSink*audio;// 类成员。
floatphase;       // 类成员。
{
    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>interleavedAudioBuffer) {
        // 音频回调不应调用任何可能导致阻塞的函数

        // 用正弦波填充音频缓冲区
        const intsampleCount=interleavedAudioBuffer.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();
    }
}

与基于QIODevice 的接口不同,QAudioSink 只能处于 active、suspended 和 stopped 三种状态。使用回调时,setBufferSize() API 不可用,回调参数的大小由音频后端决定。

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

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

状态与错误处理

状态变化通过stateChanged()信号进行报告。您可以利用此信号来更新应用程序的图形用户界面(GUI);一个常见的示例就是更改play/pause 按钮的状态。您可以通过suspend()、stop()、reset()、resume()和start()直接请求状态变化。

当遇到错误时,QAudioSink将进入StoppedState 状态。可通过error()函数获取error type 。有关可能报告的错误的描述,请参阅QtAudio::Error 枚举。调用stop()或reset()将把错误状态重置为NoError 。

您可以通过订阅stateChanged() 信号来检查是否存在错误:

void AudioOutputExample::handleStateChanged(QtAudio::State newState)
{
    switch (newState) {
        case QtAudio::IdleState:
            // Finished playing (no more data)
            AudioOutputExample::stopAudioOutput();
            break;

        case QtAudio::StoppedState:
            // Stopped for other reasons
            if (audio->error() != QtAudio::NoError) {
                // Error handling
            }
            break;

        default:
            // ... other cases as appropriate
            break;
    }
}

另请参阅 QAudioSource 和QAudioDevice 。

成员函数文档

[explicit] QAudioSink::QAudioSink(const QAudioFormat &format = QAudioFormat(), QObject *parent = nullptr)

创建一个新的音频输出,并将其连接到parent 。当输出参数设置为format 时,将使用默认音频输出设备。如果format 采用默认初始化,则格式将设置为该音频设备的首选格式。

[explicit] QAudioSink::QAudioSink(const QAudioDevice &audioDevice, const QAudioFormat &format = QAudioFormat(), QObject *parent = nullptr)

创建一个新的音频输出,并将其连接到parent 。由audioDevice 引用的设备将与输出参数format 配合使用。如果format 采用默认初始化,则格式将设置为audioDevice 的首选格式。

[override virtual noexcept] QAudioSink::~QAudioSink()

销毁此音频输出。

这将释放所占用的系统资源并清空所有缓冲区。

[since 6.10] qsizetype QAudioSink::bufferFrameCount() const

返回以帧为单位的音频缓冲区大小。

如果在调用start()之前调用此函数,则返回平台的默认值。如果在调用start() 之前调用此函数,但此前已调用setBufferSize()或setBufferFrameCount(),则返回由setBufferSize() 或setBufferFrameCount() 设置的值。如果在调用start() 之后调用此函数,则返回当前实际使用的缓冲区大小。该值可能与先前通过setBufferSize() 或setBufferFrameCount() 设置的值不一致。

该函数在 Qt 6.10 中引入。

另请参阅 setBufferFrameCount() 和bufferSize 。

qsizetype QAudioSink::bufferSize() const

返回音频缓冲区的大小(以字节为单位)。

如果在调用start()之前调用该函数,则返回平台的默认值。如果在调用start() 之前调用该函数,但此前已调用setBufferSize()或setBufferFrameCount(),则返回由setBufferSize() 或setBufferFrameCount() 设置的值。如果在调用start() 之后调用该函数,则返回当前实际使用的缓冲区大小。该值可能与先前通过setBufferSize() 或setBufferFrameCount() 设置的值不一致。

另请参阅 setBufferSize() 和bufferFrameCount 。

qsizetype QAudioSink::bytesFree() const

返回音频缓冲区中可用空闲字节的数量。

注意: 返回值 仅在处于QtAudio::ActiveState 或QtAudio::IdleState 状态时有效,否则返回零。

参见 framesFree 。

qint64 QAudioSink::elapsedUSecs() const

返回自调用start() 以来经过的微秒数,其中包括处于空闲和挂起状态的时间。

QtAudio::Error QAudioSink::error() const

返回错误状态。

QAudioFormat QAudioSink::format() const

返回当前正在使用的QAudioFormat 。

[since 6.10] qsizetype QAudioSink::framesFree() const

返回音频缓冲区中可用空帧的数量。

注意: 返回值 仅在处于“QtAudio::ActiveState ”或“QtAudio::IdleState ”状态时有效,否则返回零。

该函数在 Qt 6.10 中引入。

另请参阅 bytesFree 。

bool QAudioSink::isNull() const

true 如果QAudioSink 是 实例,则返回null ;否则返回false 。

[since 6.12] qsizetype QAudioSink::nativePeriodFrameCount() const

返回本机周期帧数。

若未设置,则返回 -1;否则返回先前通过 `setNativePeriodFrameCount()` 设置的值。

该函数在 Qt 6.12 中引入。

另请参阅 setNativePeriodFrameCount 。

qint64 QAudioSink::processedUSecs() const

返回自调用start()以来处理的音频数据量(以微秒为单位)。

void QAudioSink::reset()

立即停止音频输出,并丢弃缓冲区中当前的所有音频数据。所有已推送到QIODevice 的待处理音频数据均将被忽略。

另请参阅 stop()。

void QAudioSink::resume()

在调用suspend()之后,恢复处理音频数据。

将state()设置为调用suspend()时音频接收端所处的状态。如果音频接收端的状态不是QtAudio::SuspendedState ,则此函数不执行任何操作。

[since 6.10] void QAudioSink::setBufferFrameCount(qsizetype value)

将音频缓冲区大小设置为value 帧。

注意:此 函数可在调用start() 之前随时调用。在调用start() 之后,对该函数的调用将被忽略。不应假设所设置的缓冲区大小即为实际使用的缓冲区大小——请在调用start() 之后随时调用bufferFrameCount() 以获取当前实际使用的缓冲区大小。

bufferFrameCount() 和bufferSize() 属性表示在使用QIODevice API 时的环形缓冲区大小。原生周期大小通过setNativePeriodFrameCount() 进行控制。

该函数在 Qt 6.10 中引入。

另请参阅 bufferFrameCount() 和setBufferSize 。

void QAudioSink::setBufferSize(qsizetype value)

将音频缓冲区大小设置为value 字节。

注意:此 函数可在调用start() 之前随时调用。在调用start() 之后,对该函数的调用将被忽略。不应假设所设置的缓冲区大小即为实际使用的缓冲区大小——请在调用start() 之后随时调用bufferSize() 以获取当前实际使用的缓冲区大小。

bufferFrameCount() 和bufferSize() 属性表示使用QIODevice API 时的环形缓冲区大小。原生周期大小通过setNativePeriodFrameCount() 进行控制。

另请参阅 bufferSize() 和setBufferFrameCount 。

[since 6.12] void QAudioSink::setNativePeriodFrameCount(qsizetype frameCount)

将原生周期帧数设置为frameCount 。

调整操作系统和硬件使用的音频缓冲区大小。默认情况下(未设置时),系统使用一个与平台相关的值,通常为 1024 个帧(在 44100 Hz 时约为 23 毫秒)。

使用较小的值(64-256)可降低延迟,使用较大的值(2048-4096)可降低缓冲区不足(音频丢失)的风险。

有效值为32至4096(含)之间的2的幂,或-1以取消设置。仅可在音频接收端停止运行时调用。

映射到平台特定的设置:kAudioDevicePropertyBufferFrameSize (macOS)、IAudioClient::bufferDuration (Windows)、PW_KEY_NODE_FORCE_QUANTUM (PipeWire/Linux)和AAudioStreamBuilder_setBufferCapacityInFrames (Android)。

注意:这 与通过setBufferSize() 或setBufferFrameCount() 配置的环形缓冲区是分开的。

该函数在 Qt 6.12 中引入。

另请参阅 nativePeriodFrameCount 。

void QAudioSink::setVolume(qreal volume)

将输出音量设置为volume 。

音量从0.0 (静音)线性调整至1.0 (最大音量)。超出此范围的值将被限制。

默认音量为1.0 。

注意:调整 音量将改变该音频流的音量,而非全局音量。

UI 音量控件通常应采用非线性刻度。例如,使用对数刻度会产生感知响度的线性变化,这正是用户通常对音量控件的预期。更多详情请参阅QtAudio::convertVolume()。

另请参阅 volume()。

QIODevice *QAudioSink::start()

返回一个指向内部QIODevice 的指针,该指针用于将数据传输到系统的音频输出端。该设备此时已处于打开状态,write() 函数可直接向其写入数据。

注意: 在流停止后或您启动另一个流时,该 指针将失效。

如果QAudioSink 能够访问系统的音频设备,则state()将返回QtAudio::IdleState ,error()将返回QtAudio::NoError ,并触发stateChanged()信号。

如果在此过程中发生问题,error() 将返回QtAudio::OpenError ,state() 将返回QtAudio::StoppedState ,并发出stateChanged() 信号。

另请参阅 QIODevice 和QIODevice interface 。

[since 6.11] template <typename Callback> requires QtAudio::if_audio_sink_callback<Callback> void QAudioSink::start(Callback &&cb)

使用一个回调函数启动QAudioSink ,该回调函数将在软实时音频线程上被调用。该回调函数是一个可调用对象,其参数为QSpan<SampleType>,其中SampleType必须与QAudioSink 格式的QAudioFormat::SampleFormat 相匹配。该时间段内需填充交织的音频数据。

如果QAudioSink 能够成功启动,error()将返回QtAudio::NoError 。

如果在此过程中发生问题,error() 将返回QtAudio::OpenError ,state() 将返回QtAudio::StoppedState ,并触发stateChanged() 信号。

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

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

该函数于 Qt 6.11 中引入。

另请参阅 Callback interface 。

void QAudioSink::start(QIODevice *device)

开始将音频数据从device 传输到系统的音频输出端。device 必须已在ReadOnly 或ReadWrite 模式下被打开。

如果QAudioSink 能够成功输出音频数据,则state()将返回QtAudio::ActiveState ,error()将返回QtAudio::NoError ,并触发stateChanged()信号。

如果在此过程中发生问题,error() 将返回QtAudio::OpenError ,state() 将返回QtAudio::StoppedState ,并触发stateChanged() 信号。

另请参阅 QIODevice 和QIODevice interface 。

QtAudio::State QAudioSink::state() const

返回音频处理的状态。

[signal] void QAudioSink::stateChanged(QtAudio::State state)

当设备state 发生变化时,会触发此信号。这是音频输出的当前状态。

注意: 在 Qt 6.6 及更早版本中,QtAudio 命名空间名为 QAudio。与此信号建立基于字符串的连接时,必须使用QAudio::State 作为参数类型:connect(source, SIGNAL(stateChanged(QAudio::State)), ...);

void QAudioSink::stop()

停止音频输出,并从系统资源中断开连接。

将error()设置为QtAudio::NoError ,将state()设置为QtAudio::StoppedState ,并触发stateChanged()信号。

注意:在 Linux 和 Darwin系统上, 此操作会同步清空底层音频缓冲区,这可能会根据缓冲区负载大小导致相应的延迟。若需立即重置所有缓冲区,请改用reset 方法。

另请参阅 reset()。

void QAudioSink::suspend()

停止处理音频数据,同时保留缓冲的音频数据。

将state()设置为QtAudio::SuspendedState ,并触发stateChanged()信号。

qreal QAudioSink::volume() const

返回介于 0.0 到 1.0 之间的音量值(包含 0.0 和 1.0)。

另请参阅 setVolume()。

© 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.