Commit 8c2eb952 authored by Noxim's avatar Noxim
Browse files

[sfx] CPAL backend is partially working

audio resampling and OGG live decode is functional, but most functions in Clip don't work

repeat/length/done are all broken and i don't even know what happens when track plays past its buffer
parent db1a3c97
Loading
Loading
Loading
Loading
Loading
+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>)
@@ -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);
    }
+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;
@@ -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)
@@ -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| {
@@ -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()),
@@ -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 {
@@ -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),
                                    ..
@@ -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();
                }
                _ => ()
                _ => (),
            }
        })
    });
+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!()
    }
}