Skip to content

Commit

Permalink
Added gain control and multiple simultaneous sounds.
Browse files Browse the repository at this point in the history
  • Loading branch information
facundo-villa committed Dec 24, 2023
1 parent ffe0e99 commit 6e9d0c7
Showing 1 changed file with 42 additions and 14 deletions.
56 changes: 42 additions & 14 deletions src/audio/audio_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@ pub struct DefaultAudioSystem {
resource_manager: EntityHandle<ResourceManager>,
ahi: Box<dyn AudioHardwareInterface>,
audio_resources: HashMap<String, (audio_resource_handler::Audio, Vec<i16>)>,
playing_audios: Vec<(String, u32)>,
audio_buffer: Box<[i16]>,
playing_audios: Vec<PlayingSound>,
channels: HashMap<String, Channel>,
}

impl DefaultAudioSystem {
pub fn new(resource_manager: EntityHandle<ResourceManager>) -> Self {
let mut channels = HashMap::with_capacity(16);

channels.insert("master".to_string(), Channel { samples: vec![0; 48000 / 60].into_boxed_slice(), gain: 0.25f32 });

Self {
resource_manager,
ahi: Box::new(ahi::audio_hardware_interface::create_ahi()),
audio_resources: HashMap::with_capacity(1024),
playing_audios: Vec::with_capacity(32),
audio_buffer: vec![0; 48000 / 60].into_boxed_slice(),
channels,
}
}

Expand Down Expand Up @@ -67,35 +71,59 @@ impl AudioSystem for DefaultAudioSystem {
};

if let Some((_, audio_data)) = data {
self.playing_audios.push((audio_asset_url.to_string(), 0));
self.playing_audios.push(PlayingSound { audio_asset_url: audio_asset_url.to_string(), current_sample: 0 });
}
}

fn render(&mut self) {
let master_channel = self.channels.get_mut("master").expect("No master channel was found.");

master_channel.samples.iter_mut().for_each(|sample| *sample = 0);

// let non_master_channels = self.channels.iter_mut().filter(|(name, _)| name.as_str() != "master");

{
let audio_buffer = self.audio_buffer.as_mut();
let audio_buffer = master_channel.samples.as_mut();
let channel_gain = master_channel.gain;

for playing_sound in &self.playing_audios {
let audio_asset_url = &playing_sound.audio_asset_url;
let current_sample = &playing_sound.current_sample;

for (audio_asset_url, current_sample) in &self.playing_audios {
let (audio_resource, audio_data) = self.audio_resources.get(audio_asset_url).unwrap();

let audio_data = &audio_data[*current_sample as usize..];

if audio_data.len() > audio_buffer.len() {
audio_buffer.copy_from_slice(&audio_data[..audio_buffer.len()]);
let audio_data = if audio_data.len() > audio_buffer.len() {
&audio_data[..audio_buffer.len()]
} else {
audio_buffer[..audio_data.len()].copy_from_slice(audio_data);
audio_data
};

for (i, sample) in audio_data.iter().enumerate() {
audio_buffer[i] += ((((*sample as f32) / (65535f32 / 2f32)) * channel_gain) * (65535f32 / 2f32)) as i16;
}
}
}

let audio_buffer = &self.audio_buffer;
let audio_buffer = master_channel.samples.as_mut();

self.ahi.play(&self.audio_buffer[..]);
self.ahi.play(&audio_buffer[..]);

for (_, index) in &mut self.playing_audios {
*index += audio_buffer.len() as u32;
for playing_sound in &mut self.playing_audios {
playing_sound.current_sample += audio_buffer.len() as u32;
}

self.playing_audios.retain(|(audio, index)| *index < self.audio_resources.get(audio).unwrap().0.sample_count as u32);
self.playing_audios.retain(|playing_sound| playing_sound.current_sample < self.audio_resources.get(&playing_sound.audio_asset_url).unwrap().0.sample_count as u32);
}
}

struct Channel {
samples: Box<[i16]>,
gain: f32,
}

struct PlayingSound {
audio_asset_url: String,
current_sample: u32,
}

0 comments on commit 6e9d0c7

Please sign in to comment.