避免在包装为结构体时丢弃该变量

huangapple go评论65阅读模式
英文:

Avoid dropping the variable when wrapped into a struct

问题

I have a Rodio's Sink wrapper in HAudioSink. I also implement a try_new_from_haudio function that, in short, creates a Sink instance, wrap it in HAudioSink and already starts playing the first audio.
In Sink's docs it states: "Dropping the Sink stops all sounds. You can use detach if you want the sounds to continue playing". So when try_new_from_haudio` is returning, it drops the original sink and the sound is stopping when it shouldn't.

So my question here is: what should I do to avoid it dropping when I create an instance of HAudioSink? Is ManuallyDrop the way to go?

struct HAudioSink {
    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 { sink })
    }

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

#[cfg(test)]
mod tests {
    use super::*;

    //this test doesn't work
    #[test]
    fn play_test() {
        let sink = HAudioSink::try_new_from_file("../testfiles/gs-16b-2c-44100hz.wav").unwrap();

        sink.append_from_file("../testfiles/gs-16b-2c-44100hz.wav")
            .unwrap();

        sink.sleep_until_end();
    }
}

If I put sink.sleep_until_end() inside try_new_from_haudio, just before returning Ok, it works.

check the following link for the reproducible example of this issue: https://github.com/RustAudio/rodio/issues/476

英文:

I have a Rodio's Sink wrapper in HAudioSink. I also implement a try_new_from_haudio function that, in short, creates a Sink instance, wrap it in HAudioSink and already starts playing the first audio.
In Sink's docs it states: "Dropping the Sink stops all sounds. You can use detach if you want the sounds to continue playing". So when try_new_from_haudiois returning, it drops the original sink and the sound is stopping when it shouldn't.

So my question here is: what should I do to avoid it dropping when I create an instance of HAudioSink? Is ManuallyDrop the way to go?

struct HAudioSink {
    sink: Sink,
}

impl HAudioSink {
    pub fn try_new_from_haudio&lt;T&gt;(haudio: HAudio&lt;T&gt;) -&gt; HResult&lt;Self&gt;
    where
        T: NativeType + Float + ToPrimitive,
    {
        let (_stream, stream_handle) = OutputStream::try_default()?;
        let sink = Sink::try_new(&amp;stream_handle).unwrap();
        let nchannels = haudio.nchannels();
        let nframes = haudio.nframes();
        let sr = haudio.sr();
        let mut data_interleaved: Vec&lt;f32&gt; = Vec::with_capacity(nchannels * nframes);
        let values = haudio
            .inner()
            .inner()
            .values()
            .as_any()
            .downcast_ref::&lt;PrimitiveArray&lt;T&gt;&gt;()
            .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 { sink })
    }

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

#[cfg(test)]
mod tests {
    use super::*;

    //this test doesn&#39;t work
    #[test]
    fn play_test() {
        let sink = HAudioSink::try_new_from_file(&quot;../testfiles/gs-16b-2c-44100hz.wav&quot;).unwrap();

        sink.append_from_file(&quot;../testfiles/gs-16b-2c-44100hz.wav&quot;)
            .unwrap();

        sink.sleep_until_end();
    }
}

If I put sink.sleep_until_end() inside try_new_from_haudio, just before returning Ok, it works.

check the following link for the reproducible example of this issue: https://github.com/RustAudio/rodio/issues/476

答案1

得分: 1

问题在于对于_stream来说太重要了,"如果它被丢弃,播放将结束,并且附加的OutputStreamHandles将不再起作用。"请参阅OutputStream文档。因此,您必须将它与您的Sink一起存储:```rust
pub struct SinkWrapper {
pub sink: Sink,
pub stream: OutputStream,
}

impl SinkWrapper {
pub fn new() -> Self {
let (stream, stream_handle) = OutputStream::try_default().unwrap();
let sink = Sink::try_new(&stream_handle).unwrap();

    // 为了示例,添加了一个虚拟的音频源。
    let source = SineWave::new(440.0)
        .take_duration(Duration::from_secs_f32(1.))
        .amplify(2.);
    sink.append(source);

    Self { sink, stream }
}

}


<details>
<summary>英文:</summary>

The problem is that for the `_stream` too &quot;If this is dropped playback will end &amp; attached OutputStreamHandles will no longer work.&quot;
see the docs on [`OutputStream`](https://docs.rs/rodio/0.16.0/rodio/struct.OutputStream.html). So you have to store it alongside your `Sink`:
```rust
pub struct SinkWrapper {
    pub sink: Sink,
    pub stream: OutputStream,
}

impl SinkWrapper {
    pub fn new() -&gt; Self {
        let (stream, stream_handle) = OutputStream::try_default().unwrap();
        let sink = Sink::try_new(&amp;stream_handle).unwrap();

        // Add a dummy source of the sake of the example.
        let source = SineWave::new(440.0)
            .take_duration(Duration::from_secs_f32(1.))
            .amplify(2.);
        sink.append(source);

        Self { sink, stream }
    }
}

huangapple
  • 本文由 发表于 2023年2月16日 19:16:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75471482.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定