Audio 如何使用Rust SDL2播放WAV文件?

Audio 如何使用Rust SDL2播放WAV文件?,audio,rust,wav,sdl-2,Audio,Rust,Wav,Sdl 2,我正在尝试使用播放WAV文件 我发现了,但是没有一种音频初始化方法将其视为一种类型,并且它没有实现AudioCallback。我尝试自己用自己的回调实现这一点,如下所示: struct MyWav { wav: AudioSpecWAV, volume: f32, pos: usize, } impl AudioCallback for MyWav { type Channel = f32; fn callback(&mut self, out

我正在尝试使用播放WAV文件

我发现了,但是没有一种音频初始化方法将其视为一种类型,并且它没有实现
AudioCallback
。我尝试自己用自己的回调实现这一点,如下所示:

struct MyWav {
    wav: AudioSpecWAV,
    volume: f32,
    pos: usize,
}

impl AudioCallback for MyWav {
    type Channel = f32;

    fn callback(&mut self, out: &mut [f32]) {
        for x in out.iter_mut() {
            *x = match self.wav.buffer().get(self.pos) {
                Some(v) => { self.pos += 1; v as f32 },
                None => { 0.0 }
            }
        }
    }
}
。。。但我不知道如何解决我遇到的以下错误:

traitcore::marker::Sync没有为*mut u8类型实现

这似乎是
AudioSpecWAV
audio\u buf
字段,但如果这不是
Sync
我应该如何向回调传递缓冲区


(作为参考,)

AudioCallback
要求实现者是
Send
。您可以通过在结构中包装
AudioSpecWAV
并在该结构上执行
Send
unsafe impl
来实现,也可以复制数据。因为除非你知道你正在做的事情实际上是安全的,否则你通常不应该使用不安全的方法,你可能想看看复制方法

以下是两种方法的示例:

extern crate sdl2;

use std::thread::{self};

use sdl2::{Sdl};
use sdl2::audio::{self, AudioSpecDesired, AudioSpecWAV, AudioCallback, AudioDevice};

//----------------------------------------------------------------------------//

struct CopiedData {
    bytes: Vec<u8>,
    position: usize
}

impl AudioCallback for CopiedData {
    type Channel = u8;

    fn callback(&mut self, data: &mut [u8]) {
        let (start, end) = (self.position, self.position + data.len());
        self.position += data.len();

        let audio_data = &self.bytes[start..end];
        for (src, dst) in audio_data.iter().zip(data.iter_mut()) {
            *dst = *src;
        }
    }
}

//----------------------------------------------------------------------------//

struct WrappedData {
    audio: AudioSpecWAV,
    position: usize
}

impl AudioCallback for WrappedData {
    type Channel = u8;

    fn callback(&mut self, data: &mut [u8]) {
        let (start, end) = (self.position, self.position + data.len());
        self.position += data.len();

        let audio_data = &self.audio.buffer()[start..end];
        for (src, dst) in audio_data.iter().zip(data.iter_mut()) {
            *dst = *src;
        }
    }
}

unsafe impl Send for WrappedData { }

//----------------------------------------------------------------------------//

pub fn main() {
    let sdl_context = sdl2::init().unwrap();
    let audio_system = sdl_context.audio().unwrap();

    let audio_spec = AudioSpecDesired{ freq: None, channels: None, samples: None };
    let audio_wav = AudioSpecWAV::load_wav("test.wav").unwrap();

    let copied_data = CopiedData{ bytes: audio_wav.buffer().to_vec(), position: 0 };
    //let wrapped_data = WrappedData{ audio: audio_wav, position: 0 };

    let audio_device = audio_system.open_playback(None, audio_spec, move |spec| {
        copied_data
    }).unwrap();

    audio_device.resume();

    thread::sleep_ms(5000);
}
外部板条箱sdl2;
使用std::thread::{self};
使用sdl2::{Sdl};
使用sdl2::audio::{self,AudioSpecDesired,AudioSpecWAV,AudioCallback,AudioDevice};
//----------------------------------------------------------------------------//
结构复制数据{
字节:Vec,
职位:usize
}
复制数据的impl AudioCallback{
通道类型=u8;
fn回调(&mut self,数据:&mut[u8]){
let(start,end)=(self.position,self.position+data.len());
self.position+=data.len();
让audio_data=&self.bytes[start..end];
for audio_data.iter().zip(data.iter_mut()中的(src,dst){
*dst=*src;
}
}
}
//----------------------------------------------------------------------------//
结构WrappedData{
音频:AudioSpecWAV,
职位:usize
}
WrappedData的impl AudioCallback{
通道类型=u8;
fn回调(&mut self,数据:&mut[u8]){
let(start,end)=(self.position,self.position+data.len());
self.position+=data.len();
让audio_data=&self.audio.buffer()[start..end];
for audio_data.iter().zip(data.iter_mut()中的(src,dst){
*dst=*src;
}
}
}
WrappedData{}的不安全impl发送
//----------------------------------------------------------------------------//
pub fn main(){
让sdl_context=sdl2::init().unwrap();
让audio_system=sdl_context.audio().unwrap();
让audio_spec=AudioSpecDesired{freq:None,channels:None,samples:None};
让audio_wav=AudioSpecWAV::load_wav(“test.wav”).unwrap();
将复制的_data=CopiedData{bytes:audio_wav.buffer().复制到_vec(),位置:0};
//让WrappedData=WrappedData{audio:audio\u wav,位置:0};
让音频设备=音频系统。打开播放(无,音频规格,移动规格){
复制的数据
}).unwrap();
音频设备。恢复();
线程:sleep_ms(5000);
}

注意:我播放的WAV声音很大(甚至听起来有点失真),我不是一个声音专家,所以我不确定这是否与我的代码或我通常使用的WAV文件有关。

我尝试将
AudioSpecWAV
包装在
rBlock
中,以实现
同步,但新的问题是它没有实现
Send
。失真可能来自于频率/通道/采样未对齐。您可以使用
AudioCVT
修复:
sdl2::audio::AudioCVT::new(wav.format,wav.channels,wav.freq,spec.format,spec.channels,spec.freq)。unwrap()。转换(wav.buffer()。to_vec())