Fix benchmarks for latest glium/glutin API
[mandelwow.git] / sound.rs
1 use libxm::XMContext;
2 use sdl2;
3 use sdl2::audio::{AudioCallback, AudioDevice, AudioSpecDesired};
4 use std::fs::File;
5 use std::io::Read;
6
7
8 const SAMPLE_RATE: i32 = 48000;
9
10 struct XmCallback {
11     xm: XMContext,
12 }
13
14 impl AudioCallback for XmCallback {
15     type Channel = f32;
16
17     fn callback(&mut self, out: &mut [f32]) {
18         self.xm.generate_samples(out);
19     }
20 }
21
22 pub struct SoundPlayer {
23     device: Option<AudioDevice<XmCallback>>,
24 }
25
26 fn play_xm(raw_xm: &[u8]) -> SoundPlayer {
27     let sdl_context = sdl2::init().unwrap();
28     let sdl_audio = sdl_context.audio().unwrap();
29
30     let desired_spec = AudioSpecDesired {
31         freq: Some(SAMPLE_RATE),
32         channels: Some(2),
33         samples: Some(4096),  // 85ms
34     };
35     let device = sdl_audio.open_playback(None, &desired_spec, |actual_spec| {
36         let xm = XMContext::new(raw_xm, actual_spec.freq as u32).unwrap();
37
38         XmCallback {
39             xm: xm,
40         }
41     }).unwrap();
42
43     device.resume();
44
45     SoundPlayer {
46         device: Some(device),
47     }
48 }
49
50 pub fn start() -> SoundPlayer {
51     let filename = "flora.xm";
52     match File::open(filename) {
53         Result::Ok(mut f) => {
54             let mut xm = Vec::new();
55             f.read_to_end(&mut xm).unwrap();
56             return play_xm(&xm);
57         },
58         Result::Err(err) => {
59             println!("Couldn't open module {}: {:?}", filename, err);
60         },
61     }
62     SoundPlayer { device: None }
63 }
64
65 pub fn hit_event(player: &mut SoundPlayer) -> f32 {
66     use std::ops::Deref;
67     let audio_device_lock = player.device.as_mut().unwrap().lock();
68     let xm_callback = audio_device_lock.deref();
69     let xm = &xm_callback.xm;
70     let n_samples = xm.latest_trigger_of_instrument(0x1D);
71     n_samples as f32 / SAMPLE_RATE as f32
72 }