Loading game/src/lib.rs +8 −3 Original line number Diff line number Diff line use kea::renderer::{Color, Size, Surface, Target, Texture}; use kea::renderer::{Surface, Target}; use audio::Clip; use kea::*; use std::time::Instant; const ASSETS: assets::Assets = asset_pack!("assets.keapack"); pub fn game<P, R, I, A>(mut api: EngineApi<P, R, I, A>) Loading @@ -18,8 +16,15 @@ where let mut clip = api.audio.from_vorbis(ASSETS.assets("audio").unwrap().binary("audio.ogg").unwrap()); clip.play(); while !api.platform.exit() { api.poll(); if api.input.controller(&api.input.default().unwrap()).unwrap().start.active() { clip.stop(); clip.play(); } api.renderer.surface().set(&[0.65, 0.87, 0.91, 1.0]); api.renderer.surface().present(true); } Loading target-desktop/src/main.rs +25 −26 Original line number Diff line number Diff line extern crate audio_ears; extern crate game; extern crate gilrs; extern crate kea; extern crate kea_dev; extern crate audio_ears; use kea::input; use kea_dev::glutin; Loading Loading @@ -98,7 +98,7 @@ impl kea::Input for Input { } } if self.2.lock().unwrap().0 >= latest.0 { return Some(!0) return Some(!0); } latest.1.map(|x| *x) Loading Loading @@ -154,7 +154,7 @@ impl kea::Input for Input { bumper: state.rb.into(), trigger: state.rt.into(), }, }) }); } self.1.lock().unwrap().get(id).map(|id| { Loading Loading @@ -226,7 +226,10 @@ fn main() { should_close: false, })); let platform = Api(platform_state.clone()); let keyboard = Arc::new(Mutex::new((std::time::SystemTime::UNIX_EPOCH, KeyState::default()))); let keyboard = Arc::new(Mutex::new(( std::time::SystemTime::UNIX_EPOCH, KeyState::default(), ))); let input = Input( Mutex::new(gilrs::Gilrs::new().unwrap()), Loading @@ -237,12 +240,7 @@ fn main() { let poll = Box::new(move || { events.poll_events(|e| { use glutin::{ Event, WindowEvent, DeviceEvent, KeyboardInput, VirtualKeyCode, ElementState ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent, }; match e { Event::WindowEvent { Loading @@ -255,8 +253,10 @@ fn main() { .should_close = true; } Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { event: WindowEvent::KeyboardInput { input: KeyboardInput { state, virtual_keycode: Some(key), .. Loading Loading @@ -293,22 +293,21 @@ fn main() { VirtualKeyCode::LShift => keyboard.lock().unwrap().1.lt = s, VirtualKeyCode::RShift => keyboard.lock().unwrap().1.rt = s, VirtualKeyCode::LControl | VirtualKeyCode::LWin | VirtualKeyCode::LAlt => keyboard.lock().unwrap().1.lb = s, VirtualKeyCode::RControl | VirtualKeyCode::RWin | VirtualKeyCode::RAlt => keyboard.lock().unwrap().1.rb = s, VirtualKeyCode::LControl | VirtualKeyCode::LWin | VirtualKeyCode::LAlt => { keyboard.lock().unwrap().1.lb = s } VirtualKeyCode::RControl | VirtualKeyCode::RWin | VirtualKeyCode::RAlt => { keyboard.lock().unwrap().1.rb = s } VirtualKeyCode::R => keyboard.lock().unwrap().1.start = s, VirtualKeyCode::T => keyboard.lock().unwrap().1.select = s, _ => () _ => (), } keyboard.lock().unwrap().0 = std::time::SystemTime::now(); } _ => () _ => (), } }) }); Loading util/audio-ears/src/lib.rs +121 −65 Original line number Diff line number Diff line use kea::audio; use cpal; use kea::audio; use std::sync::mpsc::{channel, Sender}; use std::io::Cursor; use std::sync::{Arc, Mutex}; use cpal::{StreamData, UnknownTypeOutputBuffer}; use lewton::inside_ogg::OggStreamReader; pub struct Audio { tx: Sender<u8>, map: Map, } impl Audio { pub fn new() -> Self { let (tx, rx) = channel(); let events = cpal::EventLoop::new(); // TODO: Audio switching let device = cpal::default_output_device().expect("No audio device"); let mut supported_formats_range = device.supported_output_formats() let mut supported_formats_range = device .supported_output_formats() .expect("error while querying formats"); let format = supported_formats_range.next() let format = supported_formats_range .next() .expect("no supported format?!") .with_max_sample_rate(); let stream_id = events.build_output_stream(&device, &format).unwrap(); events.play_stream(stream_id); println!("Playing, format {:#?}", format); let map: Map = Arc::new(Mutex::new(vec![])); let my_map = map.clone(); std::thread::spawn(move || { use cpal::{StreamData, UnknownTypeOutputBuffer}; let mut i = 0usize; events.run(move |id, data| { match data { StreamData::Output { buffer: UnknownTypeOutputBuffer::U16(mut buffer) } => { for elem in buffer.iter_mut() { let t = i as f64 / format.sample_rate.0 as f64 * 400.0; *elem = u16::max_value() / 2 + (t.sin() * u16::max_value() as f64 / 2.0) as u16; i += 1; } }, StreamData::Output { buffer: UnknownTypeOutputBuffer::I16(mut buffer) } => { for elem in buffer.iter_mut() { let t = i as f64 / format.sample_rate.0 as f64 * 400.0; *elem = (t.sin() * u16::max_value() as f64 / 2.0) as i16; i += 1; } }, StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => { for (channel, elem) in buffer.iter_mut().enumerate() { let t = [ i as f64 / format.sample_rate.0 as f64 * 200.0, i as f64 / format.sample_rate.0 as f64 * 400.0 ]; *elem = t[channel % t.len()].sin() as f32; i += 1; } }, _ => (), events.run(move |_id, data| match data { StreamData::Output { mut buffer } => { for data in &*map.lock().unwrap() { data.lock().unwrap().render(&mut buffer, format.sample_rate.0); } } _ => (), }) }); Audio { tx } Audio { map: my_map } } } impl audio::Audio for Audio { type Clip = Clip; fn from_vorbis(&self, bytes: &[u8]) -> Clip { let bytes = Arc::new(bytes.to_vec()); Clip::new(bytes, self.map.clone()) } } type Map = Arc<Mutex<Vec<Arc<Mutex<Data>>>>>; let mut bytes = std::io::Cursor::new(bytes); let start = std::time::Instant::now(); let mut buf = vec![]; let mut reader = lewton::inside_ogg::OggStreamReader::new(bytes).expect("Couldn't start reading OGG"); while let Ok(Some(mut data)) = reader.read_dec_packet_itl() { buf.append(&mut data); pub struct Clip { map: Map, data: Arc<Mutex<Data>>, } println!("Loaded all data {:?}, {} samples", start.elapsed(), buf.len()); struct Data { playing: bool, time: f32, dropped: bool, bytes: Arc<Vec<u8>>, ogg: OggStreamReader<Cursor<Vec<u8>>>, buffer_rate: u32, buffer: Vec<i16>, } Clip::new(Arc::new(buf)) impl Data { fn render(&mut self, buffer: &mut UnknownTypeOutputBuffer, rate: u32) { if !self.playing { return } let chan_count = self.ogg.ident_hdr.audio_channels; let mut channel = 0; match buffer { UnknownTypeOutputBuffer::I16(ref mut buffer) => { for e in buffer.iter_mut() { if channel % chan_count == 0 { self.time += 1.0 / rate as f32; channel = 0; } pub struct Clip { data: Arc<Vec<i16>>, // our time as sample index let t = self.time as f64 * self.buffer_rate as f64 * chan_count as f64; let sli = t.floor() as usize * chan_count as usize + channel as usize; let shi = t.ceil() as usize * chan_count as usize + channel as usize; // make sure we always have some (128) samples just in case while shi >= self.buffer.len() { if let Some(mut read) = self.ogg.read_dec_packet_itl().expect("Vorbis decoder error") { self.buffer.append(&mut read); } } impl Clip { fn new(data: Arc<Vec<i16>>) -> Clip { let sl = self.buffer[sli]; let sh = self.buffer[shi]; let i = t.fract(); *e = (sl as f64 * i + sh as f64 * (1.0 - i)) as i16; channel += 1; } } _ => (), } } } Clip { data, impl Drop for Clip { fn drop(&mut self) { self.data.lock().unwrap().dropped = true; } } impl Clip { fn new(bytes: Arc<Vec<u8>>, map: Map) -> Clip { let ogg = OggStreamReader::new(Cursor::new((*bytes).clone())).expect("couldnt not make reader"); let rate = ogg.ident_hdr.audio_sample_rate; let data = Arc::new(Mutex::new(Data { playing: false, time: 0.0, dropped: false, bytes, ogg, buffer_rate: rate, buffer: vec![], })); map.lock().unwrap().push(data.clone()); Clip { map, data } } } impl Clone for Clip { fn clone(&self) -> Clip { Clip::new(self.data.clone()) Clip::new(self.data.lock().unwrap().bytes.clone(), self.map.clone()) } } impl audio::Clip for Clip { fn play(&mut self) {} fn pause(&mut self) {} fn repeat(&mut self, repeat: bool) {} fn seek(&mut self, secs: f32) {} fn length(&self) -> f32 { unimplemented!() } fn time(&self) -> f32 { unimplemented!() } fn done(&self) -> bool { unimplemented!() } fn play(&mut self) { self.data.lock().unwrap().playing = true; } fn pause(&mut self) { self.data.lock().unwrap().playing = false; } fn repeat(&mut self, repeat: bool) { unimplemented!() } fn seek(&mut self, secs: f32) { self.data.lock().unwrap().time = secs; } fn length(&self) -> f32 { unimplemented!() } fn time(&self) -> f32 { self.data.lock().unwrap().time } fn done(&self) -> bool { unimplemented!() } } Loading
game/src/lib.rs +8 −3 Original line number Diff line number Diff line use kea::renderer::{Color, Size, Surface, Target, Texture}; use kea::renderer::{Surface, Target}; use audio::Clip; use kea::*; use std::time::Instant; const ASSETS: assets::Assets = asset_pack!("assets.keapack"); pub fn game<P, R, I, A>(mut api: EngineApi<P, R, I, A>) Loading @@ -18,8 +16,15 @@ where let mut clip = api.audio.from_vorbis(ASSETS.assets("audio").unwrap().binary("audio.ogg").unwrap()); clip.play(); while !api.platform.exit() { api.poll(); if api.input.controller(&api.input.default().unwrap()).unwrap().start.active() { clip.stop(); clip.play(); } api.renderer.surface().set(&[0.65, 0.87, 0.91, 1.0]); api.renderer.surface().present(true); } Loading
target-desktop/src/main.rs +25 −26 Original line number Diff line number Diff line extern crate audio_ears; extern crate game; extern crate gilrs; extern crate kea; extern crate kea_dev; extern crate audio_ears; use kea::input; use kea_dev::glutin; Loading Loading @@ -98,7 +98,7 @@ impl kea::Input for Input { } } if self.2.lock().unwrap().0 >= latest.0 { return Some(!0) return Some(!0); } latest.1.map(|x| *x) Loading Loading @@ -154,7 +154,7 @@ impl kea::Input for Input { bumper: state.rb.into(), trigger: state.rt.into(), }, }) }); } self.1.lock().unwrap().get(id).map(|id| { Loading Loading @@ -226,7 +226,10 @@ fn main() { should_close: false, })); let platform = Api(platform_state.clone()); let keyboard = Arc::new(Mutex::new((std::time::SystemTime::UNIX_EPOCH, KeyState::default()))); let keyboard = Arc::new(Mutex::new(( std::time::SystemTime::UNIX_EPOCH, KeyState::default(), ))); let input = Input( Mutex::new(gilrs::Gilrs::new().unwrap()), Loading @@ -237,12 +240,7 @@ fn main() { let poll = Box::new(move || { events.poll_events(|e| { use glutin::{ Event, WindowEvent, DeviceEvent, KeyboardInput, VirtualKeyCode, ElementState ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent, }; match e { Event::WindowEvent { Loading @@ -255,8 +253,10 @@ fn main() { .should_close = true; } Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { event: WindowEvent::KeyboardInput { input: KeyboardInput { state, virtual_keycode: Some(key), .. Loading Loading @@ -293,22 +293,21 @@ fn main() { VirtualKeyCode::LShift => keyboard.lock().unwrap().1.lt = s, VirtualKeyCode::RShift => keyboard.lock().unwrap().1.rt = s, VirtualKeyCode::LControl | VirtualKeyCode::LWin | VirtualKeyCode::LAlt => keyboard.lock().unwrap().1.lb = s, VirtualKeyCode::RControl | VirtualKeyCode::RWin | VirtualKeyCode::RAlt => keyboard.lock().unwrap().1.rb = s, VirtualKeyCode::LControl | VirtualKeyCode::LWin | VirtualKeyCode::LAlt => { keyboard.lock().unwrap().1.lb = s } VirtualKeyCode::RControl | VirtualKeyCode::RWin | VirtualKeyCode::RAlt => { keyboard.lock().unwrap().1.rb = s } VirtualKeyCode::R => keyboard.lock().unwrap().1.start = s, VirtualKeyCode::T => keyboard.lock().unwrap().1.select = s, _ => () _ => (), } keyboard.lock().unwrap().0 = std::time::SystemTime::now(); } _ => () _ => (), } }) }); Loading
util/audio-ears/src/lib.rs +121 −65 Original line number Diff line number Diff line use kea::audio; use cpal; use kea::audio; use std::sync::mpsc::{channel, Sender}; use std::io::Cursor; use std::sync::{Arc, Mutex}; use cpal::{StreamData, UnknownTypeOutputBuffer}; use lewton::inside_ogg::OggStreamReader; pub struct Audio { tx: Sender<u8>, map: Map, } impl Audio { pub fn new() -> Self { let (tx, rx) = channel(); let events = cpal::EventLoop::new(); // TODO: Audio switching let device = cpal::default_output_device().expect("No audio device"); let mut supported_formats_range = device.supported_output_formats() let mut supported_formats_range = device .supported_output_formats() .expect("error while querying formats"); let format = supported_formats_range.next() let format = supported_formats_range .next() .expect("no supported format?!") .with_max_sample_rate(); let stream_id = events.build_output_stream(&device, &format).unwrap(); events.play_stream(stream_id); println!("Playing, format {:#?}", format); let map: Map = Arc::new(Mutex::new(vec![])); let my_map = map.clone(); std::thread::spawn(move || { use cpal::{StreamData, UnknownTypeOutputBuffer}; let mut i = 0usize; events.run(move |id, data| { match data { StreamData::Output { buffer: UnknownTypeOutputBuffer::U16(mut buffer) } => { for elem in buffer.iter_mut() { let t = i as f64 / format.sample_rate.0 as f64 * 400.0; *elem = u16::max_value() / 2 + (t.sin() * u16::max_value() as f64 / 2.0) as u16; i += 1; } }, StreamData::Output { buffer: UnknownTypeOutputBuffer::I16(mut buffer) } => { for elem in buffer.iter_mut() { let t = i as f64 / format.sample_rate.0 as f64 * 400.0; *elem = (t.sin() * u16::max_value() as f64 / 2.0) as i16; i += 1; } }, StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => { for (channel, elem) in buffer.iter_mut().enumerate() { let t = [ i as f64 / format.sample_rate.0 as f64 * 200.0, i as f64 / format.sample_rate.0 as f64 * 400.0 ]; *elem = t[channel % t.len()].sin() as f32; i += 1; } }, _ => (), events.run(move |_id, data| match data { StreamData::Output { mut buffer } => { for data in &*map.lock().unwrap() { data.lock().unwrap().render(&mut buffer, format.sample_rate.0); } } _ => (), }) }); Audio { tx } Audio { map: my_map } } } impl audio::Audio for Audio { type Clip = Clip; fn from_vorbis(&self, bytes: &[u8]) -> Clip { let bytes = Arc::new(bytes.to_vec()); Clip::new(bytes, self.map.clone()) } } type Map = Arc<Mutex<Vec<Arc<Mutex<Data>>>>>; let mut bytes = std::io::Cursor::new(bytes); let start = std::time::Instant::now(); let mut buf = vec![]; let mut reader = lewton::inside_ogg::OggStreamReader::new(bytes).expect("Couldn't start reading OGG"); while let Ok(Some(mut data)) = reader.read_dec_packet_itl() { buf.append(&mut data); pub struct Clip { map: Map, data: Arc<Mutex<Data>>, } println!("Loaded all data {:?}, {} samples", start.elapsed(), buf.len()); struct Data { playing: bool, time: f32, dropped: bool, bytes: Arc<Vec<u8>>, ogg: OggStreamReader<Cursor<Vec<u8>>>, buffer_rate: u32, buffer: Vec<i16>, } Clip::new(Arc::new(buf)) impl Data { fn render(&mut self, buffer: &mut UnknownTypeOutputBuffer, rate: u32) { if !self.playing { return } let chan_count = self.ogg.ident_hdr.audio_channels; let mut channel = 0; match buffer { UnknownTypeOutputBuffer::I16(ref mut buffer) => { for e in buffer.iter_mut() { if channel % chan_count == 0 { self.time += 1.0 / rate as f32; channel = 0; } pub struct Clip { data: Arc<Vec<i16>>, // our time as sample index let t = self.time as f64 * self.buffer_rate as f64 * chan_count as f64; let sli = t.floor() as usize * chan_count as usize + channel as usize; let shi = t.ceil() as usize * chan_count as usize + channel as usize; // make sure we always have some (128) samples just in case while shi >= self.buffer.len() { if let Some(mut read) = self.ogg.read_dec_packet_itl().expect("Vorbis decoder error") { self.buffer.append(&mut read); } } impl Clip { fn new(data: Arc<Vec<i16>>) -> Clip { let sl = self.buffer[sli]; let sh = self.buffer[shi]; let i = t.fract(); *e = (sl as f64 * i + sh as f64 * (1.0 - i)) as i16; channel += 1; } } _ => (), } } } Clip { data, impl Drop for Clip { fn drop(&mut self) { self.data.lock().unwrap().dropped = true; } } impl Clip { fn new(bytes: Arc<Vec<u8>>, map: Map) -> Clip { let ogg = OggStreamReader::new(Cursor::new((*bytes).clone())).expect("couldnt not make reader"); let rate = ogg.ident_hdr.audio_sample_rate; let data = Arc::new(Mutex::new(Data { playing: false, time: 0.0, dropped: false, bytes, ogg, buffer_rate: rate, buffer: vec![], })); map.lock().unwrap().push(data.clone()); Clip { map, data } } } impl Clone for Clip { fn clone(&self) -> Clip { Clip::new(self.data.clone()) Clip::new(self.data.lock().unwrap().bytes.clone(), self.map.clone()) } } impl audio::Clip for Clip { fn play(&mut self) {} fn pause(&mut self) {} fn repeat(&mut self, repeat: bool) {} fn seek(&mut self, secs: f32) {} fn length(&self) -> f32 { unimplemented!() } fn time(&self) -> f32 { unimplemented!() } fn done(&self) -> bool { unimplemented!() } fn play(&mut self) { self.data.lock().unwrap().playing = true; } fn pause(&mut self) { self.data.lock().unwrap().playing = false; } fn repeat(&mut self, repeat: bool) { unimplemented!() } fn seek(&mut self, secs: f32) { self.data.lock().unwrap().time = secs; } fn length(&self) -> f32 { unimplemented!() } fn time(&self) -> f32 { self.data.lock().unwrap().time } fn done(&self) -> bool { unimplemented!() } }