Skip to content
This repository was archived by the owner on Feb 2, 2019. It is now read-only.

Commit 2bc3724

Browse files
committed
engine: 0.2.1 - add master volume, fix memory safety issues
- Consumers of the sqa-engine library should upgrade. - Bugfix: we now use Acquire & Release atomic orderings to ensure we don't deallocate a volume parameter in the middle of it being used. - We now support a 'master volume' that is independent of a Sender's volume. Useful for multi-channel streams! - We now clip audio properly.
1 parent 142b70c commit 2bc3724

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed

sqa-engine/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ repository = "https://github.com/eeeeeta/sqa-engine"
66
readme = "README.md"
77
keywords = ["audio", "sqa"]
88
license = "GPLv3"
9-
version = "0.2.0"
9+
version = "0.2.1"
1010
authors = ["eeeeeta <eeeeeta@users.noreply.github.com>"]
1111

1212
[dependencies]

sqa-engine/src/lib.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ pub struct Sender<T> {
7070
output_patch: Arc<AtomicUsize>,
7171
/// The playback volume (rw)
7272
volume: Arc<AtomicPtr<Parameter<f32>>>,
73+
/// The master playback volume (rw)
74+
master_vol: Arc<AtomicPtr<Parameter<f32>>>,
7375
/// The buffer to write to (or not) - will be a `bounded_spsc_queue::Producer<f32>` or `()`.
7476
pub buf: T,
7577
/// The sample rate of this sender. Can differ from the output sample rate.
@@ -104,20 +106,39 @@ impl<T> Sender<T> {
104106
self.set_start_time(time);
105107
self.set_active(true);
106108
}
109+
pub fn set_master_volume(&mut self, vol: Box<Parameter<f32>>) {
110+
let val = Box::into_raw(vol);
111+
let old_ptr = self.master_vol.swap(val, AcqRel);
112+
unsafe {
113+
let _: Box<Parameter<f32>> = Box::from_raw(old_ptr);
114+
}
115+
}
116+
pub fn master_volume(&self) -> Parameter<f32> {
117+
let ret;
118+
unsafe {
119+
let val = self.master_vol.load(Acquire);
120+
ret = (*val).clone();
121+
self.master_vol.store(val, Release);
122+
}
123+
ret
124+
}
107125
/// Set the volume of this stream.
108126
pub fn set_volume(&mut self, vol: Box<Parameter<f32>>) {
109127
let val = Box::into_raw(vol);
110-
let old_ptr = self.volume.swap(val, Relaxed);
128+
let old_ptr = self.volume.swap(val, AcqRel);
111129
unsafe {
112130
let _: Box<Parameter<f32>> = Box::from_raw(old_ptr);
113131
}
114132
}
115133
/// Get the volume of this stream.
116-
pub fn volume(&self) -> &Parameter<f32> {
117-
let val = self.volume.load(Relaxed);
134+
pub fn volume(&self) -> Parameter<f32> {
135+
let ret;
118136
unsafe {
119-
&*val
137+
let val = self.volume.load(Acquire);
138+
ret = (*val).clone();
139+
self.volume.store(val, Release);
120140
}
141+
ret
121142
}
122143
/// Get whether this stream will play samples or not.
123144
pub fn active(&self) -> bool {
@@ -174,6 +195,7 @@ impl<T> Sender<T> {
174195
start_time: self.start_time.clone(),
175196
output_patch: self.output_patch.clone(),
176197
volume: self.volume.clone(),
198+
master_vol: self.master_vol.clone(),
177199
buf: (),
178200
sample_rate: self.sample_rate,
179201
original: false,
@@ -289,7 +311,9 @@ impl EngineContext {
289311
let position = Arc::new(AtomicU64::new(0));
290312
let start_time = Arc::new(AtomicU64::new(0));
291313
let default_volume = Box::new(Parameter::Raw(1.0));
314+
let default_master_vol = default_volume.clone();
292315
let volume = Arc::new(AtomicPtr::new(Box::into_raw(default_volume)));
316+
let master_vol = Arc::new(AtomicPtr::new(Box::into_raw(default_master_vol)));
293317
let output_patch = Arc::new(AtomicUsize::new(::std::usize::MAX));
294318
let uu = Uuid::new_v4();
295319

@@ -302,6 +326,7 @@ impl EngineContext {
302326
alive: alive.clone(),
303327
output_patch: output_patch.clone(),
304328
volume: volume.clone(),
329+
master_vol: master_vol.clone(),
305330
uuid: uu,
306331
half_sent: false,
307332
empty_sent: false
@@ -316,6 +341,7 @@ impl EngineContext {
316341
start_time: start_time,
317342
sample_rate: sample_rate,
318343
volume: volume.clone(),
344+
master_vol: master_vol.clone(),
319345
original: true,
320346
uuid: uu
321347
}

sqa-engine/src/param.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub struct FadeDetails<T> where T: Mul<f32, Output=T> + Sub<T, Output=T> + Add<T
1414
duration: Arc<AtomicU64>,
1515
active: Arc<AtomicBool>
1616
}
17-
#[derive(Debug)]
17+
#[derive(Clone, Debug)]
1818
pub enum Parameter<T> where T: Mul<f32, Output=T> + Sub<T, Output=T> + Add<T, Output=T> + Copy + Display {
1919
Raw(T),
2020
LinearFade(FadeDetails<T>)

sqa-engine/src/thread.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub struct Player {
2323
pub alive: Arc<AtomicBool>,
2424
pub output_patch: Arc<AtomicUsize>,
2525
pub volume: Arc<AtomicPtr<Parameter<f32>>>,
26+
pub master_vol: Arc<AtomicPtr<Parameter<f32>>>,
2627
pub uuid: Uuid,
2728
pub half_sent: bool,
2829
pub empty_sent: bool
@@ -151,10 +152,16 @@ impl JackHandler for DeviceContext {
151152
player.active.store(false, Relaxed);
152153
continue;
153154
}
154-
let vol = player.volume.load(Relaxed);
155+
let volp = player.volume.load(Acquire);
156+
let master_volp = player.master_vol.load(Acquire);
155157
let vol = unsafe {
156-
(*vol).get(time)
158+
(*volp).get(time)
157159
};
160+
let master_vol = unsafe {
161+
(*master_volp).get(time)
162+
};
163+
player.volume.store(volp, Release);
164+
player.master_vol.store(master_volp, Release);
158165
let ch = self.chans[outpatch].as_mut().unwrap();
159166
if let Some(buf) = out.get_port_buffer(&ch.port) {
160167
let written = time == ch.written_t;
@@ -164,11 +171,13 @@ impl JackHandler for DeviceContext {
164171
for x in buf.iter_mut() {
165172
if let Some(data) = player.buf.try_pop() {
166173
if written {
167-
*x += data * vol;
174+
*x += data * vol * master_vol;
168175
}
169176
else {
170-
*x = data * vol;
177+
*x = data * vol * master_vol;
171178
}
179+
if *x > 1.0 { *x = 1.0; }
180+
if *x < -1.0 { *x = -1.0; }
172181
pos += 1;
173182
}
174183
}

0 commit comments

Comments
 (0)