desktop: Better event sounds

This commit is contained in:
Mike Welsh 2019-05-09 17:43:53 -07:00
parent 61189cfb84
commit af33b8538e
5 changed files with 26 additions and 14 deletions

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
gc = "0.3.3" gc = "0.3.3"
gc_derive = "0.3.2" gc_derive = "0.3.2"
generational-arena = "0.1" generational-arena = "0.2.2"
log = "0.4" log = "0.4"
rand = "0.6.5" rand = "0.6.5"
swf = { git = "https://github.com/Herschel/swf-rs", branch = "ruffle" } swf = { git = "https://github.com/Herschel/swf-rs", branch = "ruffle" }

View File

@ -15,8 +15,11 @@ pub trait AudioBackend {
fn play_sound(&mut self, sound: SoundHandle); fn play_sound(&mut self, sound: SoundHandle);
fn preload_stream_samples(&mut self, handle: AudioStreamHandle, samples: &[u8]) {} fn preload_stream_samples(&mut self, handle: AudioStreamHandle, samples: &[u8]) {}
fn preload_stream_finalize(&mut self, handle: AudioStreamHandle) {} fn preload_stream_finalize(&mut self, handle: AudioStreamHandle) {}
fn start_stream(&mut self, handle: AudioStreamHandle) -> bool { false } fn start_stream(&mut self, handle: AudioStreamHandle) -> bool {
false
}
fn queue_stream_samples(&mut self, handle: AudioStreamHandle, samples: &[u8]); fn queue_stream_samples(&mut self, handle: AudioStreamHandle, samples: &[u8]);
fn tick(&mut self) {}
} }
pub struct NullAudioBackend { pub struct NullAudioBackend {

View File

@ -9,7 +9,7 @@ ruffle_core = { path = "../core" }
glium = "0.24" glium = "0.24"
glutin = "0.20" glutin = "0.20"
env_logger = "0.6.1" env_logger = "0.6.1"
generational-arena = "0.1" generational-arena = "0.2.2"
image = "0.21.1" image = "0.21.1"
log = "0.4" log = "0.4"
lyon = "0.13.1" lyon = "0.13.1"

View File

@ -6,6 +6,7 @@ use std::sync::{Arc, Mutex};
pub struct RodioAudioBackend { pub struct RodioAudioBackend {
sounds: Arena<Sound>, sounds: Arena<Sound>,
active_sounds: Arena<Sink>,
streams: Arena<AudioStream>, streams: Arena<AudioStream>,
device: rodio::Device, device: rodio::Device,
} }
@ -26,6 +27,7 @@ impl RodioAudioBackend {
Ok(Self { Ok(Self {
sounds: Arena::new(), sounds: Arena::new(),
streams: Arena::new(), streams: Arena::new(),
active_sounds: Arena::new(),
device: rodio::default_output_device().ok_or("Unable to create output device")?, device: rodio::default_output_device().ok_or("Unable to create output device")?,
}) })
} }
@ -67,7 +69,6 @@ impl AudioBackend for RodioAudioBackend {
let sound = &self.sounds[sound]; let sound = &self.sounds[sound];
use swf::AudioCompression; use swf::AudioCompression;
log::info!("{:?}", sound.format.compression);
match sound.format.compression { match sound.format.compression {
AudioCompression::Uncompressed => { AudioCompression::Uncompressed => {
let mut data = Vec::with_capacity(sound.data.len() / 2); let mut data = Vec::with_capacity(sound.data.len() / 2);
@ -83,13 +84,13 @@ impl AudioBackend for RodioAudioBackend {
); );
let sink = Sink::new(&self.device); let sink = Sink::new(&self.device);
sink.append(buffer); sink.append(buffer);
sink.detach(); self.active_sounds.insert(sink);
} }
AudioCompression::Mp3 => { AudioCompression::Mp3 => {
let decoder = Mp3EventDecoder::new(Cursor::new(sound.data.clone())).unwrap(); let decoder = Mp3EventDecoder::new(Cursor::new(sound.data.clone())).unwrap();
let sink = Sink::new(&self.device); let sink = Sink::new(&self.device);
sink.append(decoder); sink.append(decoder);
sink.detach(); self.active_sounds.insert(sink);
} }
_ => unimplemented!(), _ => unimplemented!(),
} }
@ -108,6 +109,10 @@ impl AudioBackend for RodioAudioBackend {
buffer.get_mut().extend_from_slice(&samples); buffer.get_mut().extend_from_slice(&samples);
} }
} }
fn tick(&mut self) {
self.active_sounds.retain(|_, sink| !sink.empty());
}
} }
use std::io::{self, Read, Seek}; use std::io::{self, Read, Seek};
@ -121,10 +126,11 @@ impl Read for ThreadRead {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut buffer = self.0.lock().unwrap(); let mut buffer = self.0.lock().unwrap();
let result = buffer.read(buf); let result = buffer.read(buf);
if buffer.position() == buffer.get_ref().len() as u64 { let len_remaining = buffer.get_ref().len() - buffer.position() as usize;
buffer.get_mut().clear(); let tmp = buffer.get_ref()[buffer.position() as usize..].to_vec();
buffer.set_position(0); buffer.get_mut().resize(len_remaining, 0);
} *buffer.get_mut() = tmp;
buffer.set_position(0);
result result
} }
} }
@ -141,6 +147,7 @@ pub struct Mp3Decoder {
num_channels: u16, num_channels: u16,
current_frame: Frame, current_frame: Frame,
current_frame_offset: usize, current_frame_offset: usize,
playing: bool,
} }
impl Mp3Decoder { impl Mp3Decoder {
@ -160,6 +167,7 @@ impl Mp3Decoder {
sample_rate, sample_rate,
current_frame, current_frame,
current_frame_offset: 0, current_frame_offset: 0,
playing: false,
}) })
} }
} }
@ -191,19 +199,20 @@ impl Iterator for Mp3Decoder {
#[inline] #[inline]
fn next(&mut self) -> Option<i16> { fn next(&mut self) -> Option<i16> {
{ if !self.playing {
let buffer = self.decoder.reader().0.lock().unwrap(); let buffer = self.decoder.reader().0.lock().unwrap();
if buffer.get_ref().len() < 1000 { if buffer.get_ref().len() < 44100 / 60 {
return Some(0); return Some(0);
} }
self.playing = true;
} }
if self.current_frame_offset == self.current_frame.data.len() { if self.current_frame_offset == self.current_frame.data.len() {
self.current_frame_offset = 0;
match self.decoder.next_frame() { match self.decoder.next_frame() {
Ok(frame) => self.current_frame = frame, Ok(frame) => self.current_frame = frame,
_ => return Some(0), _ => return Some(0),
} }
self.current_frame_offset = 0;
} }
let v = self.current_frame.data[self.current_frame_offset]; let v = self.current_frame.data[self.current_frame_offset];

View File

@ -16,7 +16,7 @@ byteorder = "1.3.1"
console_error_panic_hook = { version = "0.1.1", optional = true } console_error_panic_hook = { version = "0.1.1", optional = true }
console_log = { version = "0.1", optional = true } console_log = { version = "0.1", optional = true }
ruffle_core = { path = "../core" } ruffle_core = { path = "../core" }
generational-arena = "0.1" generational-arena = "0.2.2"
inflate = "0.4.5" inflate = "0.4.5"
jpeg-decoder = "0.1.15" jpeg-decoder = "0.1.15"
js-sys = "0.3.19" js-sys = "0.3.19"