finish the song + make the instrument act like a xylophone or somethiung

master
Ondřej Hruška 4 years ago
parent 03ea8cef87
commit 5e7af6ef47
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 48
      src/beep/instrument.rs
  2. 118
      src/beep/mod.rs

@ -17,6 +17,10 @@ pub struct Instrument {
pub(crate) ratio_right : f32, pub(crate) ratio_right : f32,
/// Master gain /// Master gain
gain: Tween, gain: Tween,
/// Master gain 2 (the two may be used for fade in & out)
gain2: Tween,
/// Gain always applied to the instrument on top of master gain
intrinsic_gain: f32,
} }
impl Instrument { impl Instrument {
@ -45,17 +49,30 @@ impl Instrument {
min: 0.0, min: 0.0,
max: 1.0, max: 1.0,
sample_rate sample_rate
} },
gain2: Tween {
actual: 0.0,
target: 0.0,
step: None,
min: 0.0,
max: 1.0,
sample_rate
},
intrinsic_gain: 1.0
}; };
o.update_side_ratios(); o.update_side_ratios();
o o
} }
pub fn set_intrinsic_gain(&mut self, gain : f32) {
self.intrinsic_gain = gain;
}
/// Update the pre-computed channel gain variables /// Update the pre-computed channel gain variables
pub fn update_side_ratios(&mut self) { pub fn update_side_ratios(&mut self) {
let angle = ((1.0 + self.balance.actual) / 2.0) * std::f32::consts::FRAC_PI_2; let angle = ((1.0 + self.balance.actual) / 2.0) * std::f32::consts::FRAC_PI_2;
self.ratio_left = angle.sin(); self.ratio_left = angle.cos();
self.ratio_right = angle.cos(); self.ratio_right = angle.sin();
} }
/// Get amplitude /// Get amplitude
@ -78,6 +95,27 @@ impl Instrument {
self.gain.fade(amp, time); self.gain.fade(amp, time);
} }
/// Get amplitude
pub fn get_amp2(&self) -> f32 {
self.gain.actual()
}
/// Set amplitude (0..1), change at the end of the current waveform to reduce popping
pub fn set_amp2(&mut self, amp : f32) {
self.gain2.set_at_crossover(amp);
}
/// Set amplitude (0..1) immediate
pub fn set_amp2_imm(&mut self, amp : f32) {
self.gain2.set_immediate(amp);
}
/// Fade amplitude over a given time
pub fn fade_amp2(&mut self, amp : f32, time: Duration) {
self.gain2.fade(amp, time);
}
/// Get balance value (-1..1) /// Get balance value (-1..1)
pub fn get_balance(&self) -> f32 { pub fn get_balance(&self) -> f32 {
self.balance.actual self.balance.actual
@ -101,6 +139,7 @@ impl Instrument {
pub fn get_peak_amplitude(&self) -> f32 { pub fn get_peak_amplitude(&self) -> f32 {
self.waveforms.iter() self.waveforms.iter()
.fold((0.0), |acc, item| acc + item.gain.actual) .fold((0.0), |acc, item| acc + item.gain.actual)
* self.intrinsic_gain // ???
} }
/// Get base frequency value (1..22050) /// Get base frequency value (1..22050)
@ -136,10 +175,11 @@ impl Instrument {
pub fn sample(&mut self) -> f32 { pub fn sample(&mut self) -> f32 {
self.balance.tick(); self.balance.tick();
self.gain.tick(); self.gain.tick();
self.gain2.tick();
self.waveforms.iter_mut() self.waveforms.iter_mut()
.fold(0.0, |mut acc, item| { .fold(0.0, |mut acc, item| {
acc + item.sample() acc + item.sample()
}) * self.gain.actual }) * self.gain.actual * self.gain2.actual * self.intrinsic_gain
} }
} }

@ -63,17 +63,20 @@ fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyh
// Produce a sinusoid of maximum amplitude. // Produce a sinusoid of maximum amplitude.
let ins1 = Instrument::new(vec![ let mut alt_synth = Instrument::new(vec![
HarmonicOscillator::new(1.0, 1.0), HarmonicOscillator::new(1.0, 1.0),
HarmonicOscillator::new(0.5, 5.0), HarmonicOscillator::new(0.5, 5.0),
], sr); ], sr);
alt_synth.set_balance_imm(0.3);
let ins2 = Instrument::new(vec![ let mut bas_synth = Instrument::new(vec![
HarmonicOscillator::new(1.0, 1.0), HarmonicOscillator::new(1.0, 1.0),
HarmonicOscillator::new(0.5, 5.0), HarmonicOscillator::new(0.5, 5.0),
], sr); ], sr);
bas_synth.set_intrinsic_gain(0.5);
bas_synth.set_baance_imm(-0.3);
let mut orch = Orchestra::new(vec![ins1, ins2], sr); let mut orch = Orchestra::new(vec![alt_synth, bas_synth], sr);
orch.normalize(true); orch.normalize(true);
let handle = Arc::new(parking_lot::RwLock::new(orch)); let handle = Arc::new(parking_lot::RwLock::new(orch));
@ -265,6 +268,50 @@ fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyh
(4, B4), (4, B4),
(2, G4X), (2, G4X),
(4, E4), (4, E4),
(2, A4),// end of 1st line
(4, C5),
(2, D5),
(3, E5), (1, F5X), (2, E5),
(4, D5),
(2, B4),
(3, G4), (1, A4), (2, B4),
(3, C5), (1, B4), (2, A4),
(3, G4X), (1, F4X), (2, G4X),
(6, A4),
(6, A4),// end of 2nd line
(6, G5),
(3, G5), (1, F5X), (2, E5),
(4, D5),
(2, B4),
(3, G4), (1, A4), (2, B4),
(4, C5),
(2, A4),
(3, A4), (1, G4X), (2, A4),
(4, B4),
(2, G4X),
(6, E4),// end of 3rd line
(6, G5),
(3, G5), (1, F5X), (2, E5),
(4, D5),
(2, B4),
(3, G4), (1, A4), (2, B4),
(3, C5), (1, B4), (2, A4),
(2, G4X), (2, F4X), (2, G4X),
(6, A4),
(4, A4),// end of 4th line
(2, -1),
]; ];
// Bass line, must be kept in sync with alt. Insert -1 notes for padding where needed. // Bass line, must be kept in sync with alt. Insert -1 notes for padding where needed.
@ -275,13 +322,50 @@ fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyh
(6, C4), (6, C4),
(6, G3), (6, G3),
(6, G4), (6, G3),
(6, A3), (6, A3),
(6, A4), (6, A3),
(6, E3), (6, E3),
(6, E4), (6, E3),// end of 1st line
(6, A3),
(6, C4),
(6, G3),
(6, E3),
(6, A3),
(6, E3),
(6, A3),
(6, A3),// end of 2nd line
(6, C4),
(6, C4),
(6, G3),
(6, G3),
(6, A3),
(6, A3),
(6, E3),
(6, E3), // end of line 3
(6, C4),
(6, C4),
(6, G3),
(6, E3),
(6, A3),
(6, E3),
(6, A3),
(4, A3), // end of line 4
(2, -1),
]; ];
const D_ONOFF: Duration = Duration::from_millis(10); const D_ONOFF: Duration = Duration::from_millis(10);
@ -300,22 +384,38 @@ fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyh
ticks_alt = *len; ticks_alt = *len;
if *key >= 0 { if *key >= 0 {
let f = key2freq(*key); let f = key2freq(*key);
wg.instruments[0].fade_amp(1.0, D_ONOFF); //wg.instruments[0].fade_amp(1.0, D_ONOFF);
wg.instruments[0].set_amp2_imm(0.0);
wg.instruments[0].fade_amp2(1.0, D_ONOFF);
wg.instruments[0].set_amp_imm(1.0);
wg.instruments[0].set_freq_imm(f); wg.instruments[0].set_freq_imm(f);
wg.instruments[0].fade_amp(0.0, Duration::from_secs_f32((60.0/bpm) / 16.0) * *len);
} else { } else {
wg.instruments[0].fade_amp(0.0, D_ONOFF); wg.instruments[0].fade_amp(0.0, D_ONOFF);
wg.instruments[0].fade_amp2(0.0, D_ONOFF);
} }
} }
} }
if ticks_bass == 0 { if ticks_bass == 0 {
if let Some((len, key)) = bass_iter.next() { if let Some((len, key)) = bass_iter.next() {
ticks_bass = len - 1; ticks_bass = *len;
if *key >= 0 { if *key >= 0 {
let f = key2freq(*key); let f = key2freq(*key);
wg.instruments[1].fade_amp(0.5, D_ONOFF); //wg.instruments[1].fade_amp(1.0, D_ONOFF);
// wg.instruments[1].set_amp_imm(1.0);
// wg.instruments[1].fade_amp(0.0, Duration::from_secs_f32((60.0/bpm) / 16.0) * *len);
// wg.instruments[1].set_freq_imm(f);
wg.instruments[1].set_amp2_imm(0.0);
wg.instruments[1].fade_amp2(1.0, D_ONOFF);
wg.instruments[1].set_amp_imm(1.0);
wg.instruments[1].set_freq_imm(f); wg.instruments[1].set_freq_imm(f);
wg.instruments[1].fade_amp(0.0, Duration::from_secs_f32((60.0/bpm) / 16.0) * *len);
} else { } else {
wg.instruments[1].fade_amp(0.0, D_ONOFF); wg.instruments[1].fade_amp(0.0, D_ONOFF);
wg.instruments[1].fade_amp2(0.0, D_ONOFF);
} }
} }
} }

Loading…
Cancel
Save