You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将Rodio的Sink包装进结构体时,如何避免其被自动析构?

问题分析与解决方案

核心问题根源

你当前遇到的音频意外停止,并非是Sink被析构导致的,而是函数中创建的OutputStream(即原代码里的_stream变量)在try_new_from_haudio返回时被自动析构了。根据Rodio的设计,OutputStreamHandle的有效性完全依赖于对应的OutputStream实例存活,一旦OutputStream被销毁,整个音频输出通道会关闭,所有关联的Sink播放都会终止。

你之前误以为是Sink被析构,是因为把sleep_until_end放在返回前时,_stream还未被析构,音频能正常播放;返回后_stream被销毁,播放就停止了。

正确解决方案:保存OutputStream到HAudioSink

修改HAudioSink结构体,将OutputStream和Sink一起保存,确保OutputStream在HAudioSink的生命周期内始终存活:

struct HAudioSink {
    stream: OutputStream, // 新增:保存OutputStream实例
    sink: Sink,
}

impl HAudioSink {
    pub fn try_new_from_haudio<T>(haudio: HAudio<T>) -> HResult<Self>
    where
        T: NativeType + Float + ToPrimitive,
    {
        let (stream, stream_handle) = OutputStream::try_default()?; // 去掉变量名前的下划线
        let sink = Sink::try_new(&stream_handle).unwrap();
        
        // 后续音频数据处理逻辑保持不变
        let nchannels = haudio.nchannels();
        let nframes = haudio.nframes();
        let sr = haudio.sr();
        let mut data_interleaved: Vec<f32> = Vec::with_capacity(nchannels * nframes);
        let values = haudio
            .inner()
            .inner()
            .values()
            .as_any()
            .downcast_ref::<PrimitiveArray<T>>()
            .unwrap();

        for f in 0..nframes {
            for ch in 0..nchannels {
                data_interleaved.push(values.value(f + ch * nframes).to_f32().unwrap());
            }
        }

        let source = SamplesBuffer::new(u16::try_from(nchannels).unwrap(), sr, data_interleaved);

        sink.append(source);

        Ok(HAudioSink { stream, sink }) // 将stream和sink一起封装返回
    }

    // Sleeps the current thread until the sound ends.
    pub fn sleep_until_end(&self) {
        self.sink.sleep_until_end();
    }
}

这样,当HAudioSink实例存活时,OutputStream和Sink都会保持有效,音频播放不会被意外终止。

关于ManuallyDrop的疑问

ManuallyDrop在这里不是正确的解决方案。它的作用是手动控制值的析构时机,而你的问题本质是需要让依赖对象(OutputStream)存活,而非阻止Sink的正常析构。滥用ManuallyDrop反而会引入内存安全风险,比如忘记手动销毁导致资源泄漏。

内容的提问来源于stack exchange,提问作者daniellga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 01:20:18