mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Get sound effects working
This commit is contained in:
parent
529cb40dc4
commit
2bca20cf69
@ -1,4 +1,4 @@
|
|||||||
use rodio::{SpatialSink, Decoder, Device};
|
use rodio::{SpatialSink, Decoder, Device, Source, Sample};
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use crate::audio::fader::Fader;
|
use crate::audio::fader::Fader;
|
||||||
@ -8,6 +8,7 @@ use vek::*;
|
|||||||
pub enum AudioType {
|
pub enum AudioType {
|
||||||
Sfx,
|
Sfx,
|
||||||
Music,
|
Music,
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
@ -27,10 +28,22 @@ pub struct Channel {
|
|||||||
state: ChannelState,
|
state: ChannelState,
|
||||||
fader: Fader,
|
fader: Fader,
|
||||||
pub pos: Vec3::<f32>,
|
pub pos: Vec3::<f32>,
|
||||||
// sound_cache: Option<&SoundCache>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement asynchronous loading
|
||||||
impl Channel {
|
impl Channel {
|
||||||
|
/// Create an empty channel for future use
|
||||||
|
pub fn new(device: &Device) -> Self {
|
||||||
|
Self {
|
||||||
|
id: 0,
|
||||||
|
sink: SpatialSink::new(device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]),
|
||||||
|
audio_type: AudioType::None,
|
||||||
|
state: ChannelState::Stopped,
|
||||||
|
fader: Fader::fade_in(0.0),
|
||||||
|
pos: Vec3::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn music(id: usize, device: &Device, bufr: BufReader<File>) -> Self {
|
pub fn music(id: usize, device: &Device, bufr: BufReader<File>) -> Self {
|
||||||
let sink = SpatialSink::new(device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]);
|
let sink = SpatialSink::new(device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]);
|
||||||
let sound = Decoder::new(bufr).unwrap();
|
let sound = Decoder::new(bufr).unwrap();
|
||||||
@ -44,7 +57,6 @@ impl Channel {
|
|||||||
state: ChannelState::Playing,
|
state: ChannelState::Playing,
|
||||||
fader: Fader::fade_in(0.0),
|
fader: Fader::fade_in(0.0),
|
||||||
pos: Vec3::zero(),
|
pos: Vec3::zero(),
|
||||||
// sound_cache: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,10 +68,20 @@ impl Channel {
|
|||||||
state: ChannelState::Playing,
|
state: ChannelState::Playing,
|
||||||
fader: Fader::fade_in(0.0),
|
fader: Fader::fade_in(0.0),
|
||||||
pos,
|
pos,
|
||||||
// sound_cache,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn play<S>(&mut self, source: S)
|
||||||
|
where
|
||||||
|
S: Source + Send + 'static,
|
||||||
|
S::Item: Sample,
|
||||||
|
S::Item: Send,
|
||||||
|
<S as std::iter::Iterator>::Item: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
self.state = ChannelState::Playing;
|
||||||
|
self.sink.append(source);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_done(&self) -> bool {
|
pub fn is_done(&self) -> bool {
|
||||||
self.sink.empty() || self.state == ChannelState::Stopped
|
self.sink.empty() || self.state == ChannelState::Stopped
|
||||||
}
|
}
|
||||||
@ -73,6 +95,10 @@ impl Channel {
|
|||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_id(&mut self, new_id: usize) {
|
||||||
|
self.id = new_id;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_audio_type(&self) -> AudioType {
|
pub fn get_audio_type(&self) -> AudioType {
|
||||||
self.audio_type
|
self.audio_type
|
||||||
}
|
}
|
||||||
@ -102,6 +128,7 @@ impl Channel {
|
|||||||
ChannelState::Stopping => {
|
ChannelState::Stopping => {
|
||||||
self.fader.update(dt);
|
self.fader.update(dt);
|
||||||
self.sink.set_volume(self.fader.get_volume());
|
self.sink.set_volume(self.fader.get_volume());
|
||||||
|
|
||||||
if self.fader.is_finished() {
|
if self.fader.is_finished() {
|
||||||
self.state = ChannelState::Stopped;
|
self.state = ChannelState::Stopped;
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,21 @@ pub struct AudioFrontend {
|
|||||||
|
|
||||||
impl AudioFrontend {
|
impl AudioFrontend {
|
||||||
/// Construct with given device
|
/// Construct with given device
|
||||||
pub fn new(device: String) -> Self {
|
pub fn new(device: String, channel_num: usize) -> Self {
|
||||||
|
let mut channels = Vec::with_capacity(channel_num);
|
||||||
|
let audio_device = get_device_raw(&device);
|
||||||
|
if let Some(audio_device) = &audio_device {
|
||||||
|
for i in (0..channel_num) {
|
||||||
|
channels.push(Channel::new(&audio_device));
|
||||||
|
}
|
||||||
|
}
|
||||||
Self {
|
Self {
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
device_list: list_devices(),
|
device_list: list_devices(),
|
||||||
audio_device: get_device_raw(device),
|
audio_device,
|
||||||
sound_cache: SoundCache::new(),
|
sound_cache: SoundCache::new(),
|
||||||
channels: Vec::new(),
|
channels: channels,
|
||||||
next_channel_id: 0,
|
next_channel_id: 1,
|
||||||
sfx_volume: 1.0,
|
sfx_volume: 1.0,
|
||||||
music_volume: 1.0,
|
music_volume: 1.0,
|
||||||
listener_pos: Vec3::zero(),
|
listener_pos: Vec3::zero(),
|
||||||
@ -58,7 +65,7 @@ impl AudioFrontend {
|
|||||||
audio_device: None,
|
audio_device: None,
|
||||||
sound_cache: SoundCache::new(),
|
sound_cache: SoundCache::new(),
|
||||||
channels: Vec::new(),
|
channels: Vec::new(),
|
||||||
next_channel_id: 0,
|
next_channel_id: 1,
|
||||||
sfx_volume: 1.0,
|
sfx_volume: 1.0,
|
||||||
music_volume: 1.0,
|
music_volume: 1.0,
|
||||||
listener_pos: Vec3::zero(),
|
listener_pos: Vec3::zero(),
|
||||||
@ -70,18 +77,15 @@ impl AudioFrontend {
|
|||||||
|
|
||||||
/// Maintain audio
|
/// Maintain audio
|
||||||
pub fn maintain(&mut self, dt: f32) {
|
pub fn maintain(&mut self, dt: f32) {
|
||||||
let mut stopped_channels = Vec::<usize>::new();
|
|
||||||
for (i, channel) in self.channels.iter_mut().enumerate() {
|
for (i, channel) in self.channels.iter_mut().enumerate() {
|
||||||
channel.update(dt);
|
channel.update(dt);
|
||||||
if channel.is_done() {
|
|
||||||
stopped_channels.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i in stopped_channels.iter().rev() {
|
|
||||||
self.channels.remove(*i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_channel(&mut self) -> Option<&mut Channel> {
|
||||||
|
self.channels.iter_mut().find(|c| c.is_done())
|
||||||
|
}
|
||||||
|
|
||||||
/// Play specfied sound file.
|
/// Play specfied sound file.
|
||||||
///```ignore
|
///```ignore
|
||||||
///audio.play_sound("voxygen.audio.sfx.step");
|
///audio.play_sound("voxygen.audio.sfx.step");
|
||||||
@ -96,15 +100,21 @@ impl AudioFrontend {
|
|||||||
(pos.y - self.listener_pos.y) * FALLOFF,
|
(pos.y - self.listener_pos.y) * FALLOFF,
|
||||||
(pos.z - self.listener_pos.z) * FALLOFF,
|
(pos.z - self.listener_pos.z) * FALLOFF,
|
||||||
];
|
];
|
||||||
let sink = SpatialSink::new(device, calc_pos,
|
|
||||||
self.listener_pos_left,
|
|
||||||
self.listener_pos_right);
|
|
||||||
|
|
||||||
let sound = self.sound_cache.load_sound(sound);
|
let sound = self.sound_cache.load_sound(sound);
|
||||||
|
|
||||||
sink.append(sound);
|
let left_ear = self.listener_pos_left;
|
||||||
|
let right_ear = self.listener_pos_right;
|
||||||
|
|
||||||
self.channels.push(Channel::sfx(id, sink, pos));
|
if let Some(channel) = self.get_channel() {
|
||||||
|
channel.set_id(id);
|
||||||
|
channel.set_emitter_position(calc_pos);
|
||||||
|
channel.set_left_ear_position(left_ear);
|
||||||
|
channel.set_right_ear_position(right_ear);
|
||||||
|
channel.play(sound);
|
||||||
|
} else {
|
||||||
|
println!("No available channels!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
@ -141,8 +151,12 @@ impl AudioFrontend {
|
|||||||
|
|
||||||
if let Some(device) = &self.audio_device {
|
if let Some(device) = &self.audio_device {
|
||||||
let file = assets::load_file(&sound, &["ogg"]).unwrap();
|
let file = assets::load_file(&sound, &["ogg"]).unwrap();
|
||||||
|
let sound = Decoder::new(file).unwrap();
|
||||||
|
|
||||||
self.channels.push(Channel::music(id, device, file));
|
if let Some(channel) = self.get_channel() {
|
||||||
|
channel.set_id(id);
|
||||||
|
channel.play(sound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
@ -186,7 +200,7 @@ impl AudioFrontend {
|
|||||||
// TODO: figure out how badly this will break things when it is called
|
// TODO: figure out how badly this will break things when it is called
|
||||||
pub fn set_device(&mut self, name: String) {
|
pub fn set_device(&mut self, name: String) {
|
||||||
self.device = name.clone();
|
self.device = name.clone();
|
||||||
self.audio_device = get_device_raw(name);
|
self.audio_device = get_device_raw(&name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +244,6 @@ fn list_devices_raw() -> Vec<Device> {
|
|||||||
rodio::output_devices().collect()
|
rodio::output_devices().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_device_raw(device: String) -> Option<Device> {
|
fn get_device_raw(device: &str) -> Option<Device> {
|
||||||
rodio::output_devices().find(|d| d.name() == device)
|
rodio::output_devices().find(|d| d.name() == device)
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ fn main() {
|
|||||||
None => audio::get_default_device(),
|
None => audio::get_default_device(),
|
||||||
};
|
};
|
||||||
let audio = if settings.audio.audio_on {
|
let audio = if settings.audio.audio_on {
|
||||||
AudioFrontend::new(audio_device)
|
AudioFrontend::new(audio_device, 16)
|
||||||
} else {
|
} else {
|
||||||
AudioFrontend::no_audio()
|
AudioFrontend::no_audio()
|
||||||
};
|
};
|
||||||
|
@ -34,8 +34,6 @@ impl PlayState for MainMenuState {
|
|||||||
// Used for client creation.
|
// Used for client creation.
|
||||||
let mut client_init: Option<ClientInit> = None;
|
let mut client_init: Option<ClientInit> = None;
|
||||||
|
|
||||||
let music = global_state.audio.play_music("voxygen.audio.soundtrack.veloren_title_tune-3".to_string());
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Handle window events.
|
// Handle window events.
|
||||||
for event in global_state.window.fetch_events() {
|
for event in global_state.window.fetch_events() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user