Skip to content

Commit

Permalink
* implemented threshold filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
prixt committed Mar 5, 2020
1 parent 9ea6139 commit ad1b886
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 23 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Example:
```
(.+) cancels (.+): (.*)(Water|water)(.*)\.
```
This pattern will make soundsense-rs ignore any cancallations related to water.
This pattern will make soundsense-rs ignore any cancellations related to water.

The regex pattern uses the [regex crate](https://docs.rs/regex/) syntax.

Expand Down
5 changes: 4 additions & 1 deletion src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ pub enum SoundMessage {
/// Reload the ignore list with this path.
ChangeIgnoreList(std::path::PathBuf),
/// Change the volume of a channel.
/// "all" is total volume, other values are specific channels.
/// "total" is total volume, other values are specific channels.
VolumeChange(Box<str>, f32),
/// Change the threshold of a channel.
/// "total" is total threshold, other values are specific channels.
ThresholdChange(Box<str>, u8),
/// Skip sound currently played by loop_player
SkipCurrentSound(Box<str>),
/// Play/Pause channel
Expand Down
11 changes: 11 additions & 0 deletions src/sound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,15 @@ pub struct SoundFile {
#[derive(Clone)]
pub struct VolumeLock(Arc<ShardedLock<f32>>);
impl VolumeLock {
#[inline]
pub fn new() -> Self {
Self(Arc::new(ShardedLock::new(1.0)))
}
#[inline]
pub fn get(&self) -> f32 {
*self.0.read().unwrap()
}
#[inline]
pub fn set(&self, volume: f32) {
*self.0.write().unwrap() = volume;
}
Expand All @@ -80,14 +83,17 @@ impl VolumeLock {
#[derive(Clone)]
pub struct IsPausedLock(Arc<AtomicBool>);
impl IsPausedLock {
#[inline]
pub fn new() -> Self {
Self(Arc::new(AtomicBool::new(false)))
}

#[inline]
pub fn get(&self) -> bool {
self.0.load(Ordering::Relaxed)
}

#[inline]
pub fn flip(&self) -> bool {
self.0.fetch_nand(true, Ordering::SeqCst)
}
Expand Down Expand Up @@ -195,6 +201,11 @@ pub fn run(sound_rx: Receiver<SoundMessage>, ui_tx: Sender<UIMessage>) {
manager.set_volume(&channel, volume * 0.01)?;
}

ThresholdChange(channel,threshold) => {
trace!("Set channel {} threshold to {}", channel, threshold);
manager.set_threshold(&channel, threshold)?;
}

SkipCurrentSound(channel) => {
trace!("Skip Current Sound in {}", channel);
manager.skip(&channel)?;
Expand Down
11 changes: 11 additions & 0 deletions src/sound/sound_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct SoundChannel {
local_volume: VolumeLock,
delay: usize,
local_is_paused: IsPausedLock,
threshold: u8,
pub play_type: ChannelPlayType,
}

Expand Down Expand Up @@ -49,6 +50,7 @@ impl SoundChannel {
}
},
local_is_paused,
threshold: 4,
}
}

Expand Down Expand Up @@ -152,6 +154,15 @@ impl SoundChannel {
self.local_volume.get()
}

#[inline]
pub fn set_threshold(&mut self, threshold: u8) {
self.threshold = threshold;
}
#[inline]
pub fn get_threshold(&mut self) -> u8 {
self.threshold
}

#[inline]
pub fn len(&self) -> usize {
self.one_shots.len() + self.looping.len()
Expand Down
67 changes: 49 additions & 18 deletions src/sound/sound_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub struct SoundManager {
total_volume: VolumeLock,
/// Total is_paused.
total_is_paused: IsPausedLock,
/// Total playback_treshold
total_threshold: u8,
/// Sender for UIMessage sent to the UI.
ui_sender: Sender<UIMessage>,
/// RNG for probability and randomly choosing a soundfile from many.
Expand Down Expand Up @@ -96,7 +98,7 @@ impl SoundManager {
let mut halt_on_match: bool = false;
let mut random_balance: bool = false;
#[allow(unused_mut)]
let mut playback_threshold: u8 = 5;
let mut playback_threshold: u8 = 4;
let files = Vec::new();
let weights = Vec::new();

Expand Down Expand Up @@ -288,7 +290,7 @@ impl SoundManager {
match attr_value {
"singleEager" => play_type = ChannelPlayType::SingleEager,
"singleLazy" => play_type = ChannelPlayType::SingleLazy,
"all" => (),
"total" => (),
other => {
warn!("Unknown Channel PlayType: {}", other);
warn!("Will ignore this value.");
Expand Down Expand Up @@ -338,9 +340,9 @@ impl SoundManager {

visit_dir(sound_dir, &mut func)?; // Run the DFS!

// Add the default channels "all" and "music"
// Add the default channels "total" and "music"
let mut channel_names: Vec<Box<str>> = vec![
"all".into(),
"total".into(),
"music".into(),
];
for channel_name in channels.keys() {
Expand All @@ -362,6 +364,7 @@ impl SoundManager {
channels,
total_volume,
total_is_paused,
total_threshold: 4,
ui_sender,
rng: thread_rng(),
};
Expand Down Expand Up @@ -413,7 +416,7 @@ impl SoundManager {

/// Set the volume of all, or specific channels.
pub fn set_volume(&mut self, channel_name: &str, volume: f32) -> Result<()> {
if channel_name == "all" {
if channel_name == "total" {
self.total_volume.set(volume);
}
else if let Some(channel) = self.channels.get_mut(channel_name) {
Expand All @@ -422,8 +425,18 @@ impl SoundManager {
Ok(())
}

pub fn set_threshold(&mut self, channel_name: &str, threshold: u8) -> Result<()> {
if channel_name == "total" {
self.total_threshold = threshold;
}
else if let Some(channel) = self.channels.get_mut(channel_name) {
channel.set_threshold(threshold);
}
Ok(())
}

pub fn skip(&mut self, channel_name: &str) -> Result<()> {
if channel_name == "all" {
if channel_name == "total" {
for (_, channel) in self.channels.iter_mut() {
channel.skip();
}
Expand All @@ -435,7 +448,7 @@ impl SoundManager {
}

pub fn play_pause(&mut self, channel_name: &str) -> Result<()> {
if channel_name == "all" {
if channel_name == "total" {
let is_paused = !self.total_is_paused.flip();
self.ui_sender.send(
UIMessage::ChannelWasPlayPaused(
Expand Down Expand Up @@ -512,6 +525,13 @@ impl SoundManager {
trace!(" can't play: failed probability roll");
}
}
can_play &= self.total_threshold > sound.playback_threshold;
if !can_play {
trace!(
" can't play: at threshold limit - sound.playback_threshold: {}, total_threshold: {}",
sound.playback_threshold, self.total_threshold
);
}
} else {
trace!(" can't play: current_timeout: {}", sound.current_timeout);
}
Expand Down Expand Up @@ -544,8 +564,18 @@ impl SoundManager {
continue;
};
let chn_len = channel.len();
let chn_threshold = channel.get_threshold();
// Check if there are too many sounds playing on this channel (concurrency).
if chn_len < sound.concurency.unwrap_or(std::usize::MAX) {
if chn_len >= sound.concurency.unwrap_or(std::usize::MAX) {
trace!(" can't play: at concurency limit: limit {}, channel {}",
sound.concurency.unwrap(), chn_len);
}
// Check if the playback_threshold is higher than the channel threshold.
else if chn_threshold <= sound.playback_threshold {
trace!(" can't play: at threshold limit - sound.playback_threshold: {}, channel_threshold: {}",
sound.playback_threshold, chn_threshold);
}
else {
// Set current_timeout if the sound has a timeout value.
if let Some(timeout) = sound.timeout {
sound.current_timeout = timeout;
Expand All @@ -571,25 +601,26 @@ impl SoundManager {
channel.add_oneshot(device, &files[idx], sound.delay.unwrap_or(0), rng);
}
}
else {
trace!(" can't play: at concurency limit: limit {}, channel {}",
sound.concurency.unwrap(), chn_len);
}
}
else if !sound.files.is_empty() {
trace!(" channel: misc");
let channel = self.channels.get_mut("misc").unwrap();
let chn_len = channel.len();
if channel.len() < sound.concurency.unwrap_or(std::usize::MAX) {
let chn_threshold = channel.get_threshold();
if chn_len >= sound.concurency.unwrap_or(std::usize::MAX) {
trace!(" can't play: at concurency limit - limit {}, channel {}",
sound.concurency.unwrap(), chn_len);
}
else if chn_threshold <= sound.playback_threshold {
trace!(" can't play: at threshold limit - sound.playback_threshold: {}, channel_threshold: {}",
sound.playback_threshold, chn_threshold);
}
else {
if let Some(timeout) = sound.timeout {
sound.current_timeout = timeout;
}
channel.add_oneshot(&self.device, &files[idx], sound.delay.unwrap_or(0), rng);
}
else {
trace!(" can't play: at concurency limit: limit {}, channel {}",
sound.concurency.unwrap(), chn_len);
}
}
}

Expand Down Expand Up @@ -628,7 +659,7 @@ impl SoundManager {
.ok_or("Failed to parse .ini file.")?
.as_str()
.parse()?;
if name == "all" {
if name == "total" {
self.total_volume.set(volume / 100.0);
}
else if let Some(chn) = self.channels.get_mut(name) {
Expand Down
9 changes: 8 additions & 1 deletion src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ r"A sound-engine utility for Dwarf Fortress, written in Rust
SoundMessage::VolumeChange(channel_name, channel_volume)
).unwrap();
}
"change_threshold" => {
let channel_name: Box<str> = parts[1].into();
let channel_threshold: u8 = parts[2].parse().unwrap();
sound_tx.send(
SoundMessage::ThresholdChange(channel_name, channel_threshold)
).unwrap();
}
"skip_current_sound" => {
let channel_name: Box<str> = parts[1].into();
sound_tx.send(
Expand All @@ -191,7 +198,7 @@ r"A sound-engine utility for Dwarf Fortress, written in Rust
).unwrap();
}
"test_message" => {
trace!("UI test message: {}", parts[1]);
info!("UI test message: {}", parts[1]);
}
_ => {
add_error(
Expand Down
16 changes: 15 additions & 1 deletion web/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,18 @@ function createSlider(channel_name) {
slider.className="w3-cell-row w3-border-bottom";
slider.insertAdjacentHTML(
'afterbegin',
"<div class='w3-cell w3-cell-middle w3-center w3-padding-small' style='width:10%;min-width:90px'"+
"<div class='w3-cell w3-cell-middle w3-center w3-padding-small overlay-container' style='width:10%;min-width:90px'"+
"id='"+channel_name+"_head'>"+
"<div class='overlay-content w3-container w3-padding-small w3-animate-opacity w3-grey w3-center'>"+
"<span>Threshold</span><br>"+
"<select id='"+channel_name+"_selector' onchange='thresholdSelect(\""+channel_name+"\",this.value)'>"+
"<option value='4'>Evertyhing</option>"+
"<option value='3'>Fluff</option>"+
"<option value='2'>Important</option>"+
"<option value='1'>Critical</option>"+
"<option value='0'>Nothing</option>"+
"</select>"+
"</div>"+
"<h4>"+channel_name+"</h4>"+
"</div>"+
"<div class='w3-cell w3-cell-middle w3-rest w3-container w3-padding-small'>"+
Expand Down Expand Up @@ -140,6 +150,10 @@ function createError(name, text) {
return error;
}

function thresholdSelect(channel_name, value) {
external.invoke("change_threshold:"+channel_name+":"+value);
}

function main() {
channels = document.getElementById('channels');
is_windows = /MSIE|Trident|Edge/.test(window.navigator.userAgent);
Expand Down
6 changes: 5 additions & 1 deletion web/w3.css
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,8 @@ hr{border:0;border-top:1px solid #eee;margin:20px 0}
.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}

.w3-closebtn{margin-left:15px;color:white;font-weight:bold;float:right;font-size:22px;line-height:20px;cursor:pointer;}
.w3-closebtn:hover{color:black;}
.w3-closebtn:hover{color:black;}

.overlay-container{position:relative;}
.overlay-content{position:absolute;left:0;top:0;display:none;min-width:100%}
.overlay-container:hover .overlay-content{display:inline-block;}

0 comments on commit ad1b886

Please sign in to comment.