[sosten] add direction
This commit is contained in:
parent
43605dfa87
commit
350e6d1bde
2 changed files with 55 additions and 6 deletions
17
README.md
17
README.md
|
@ -83,13 +83,14 @@ it's useful when you want to play a note super fast (over 1/64 tempo) but don't
|
||||||
|
|
||||||
### sosten
|
### sosten
|
||||||
|
|
||||||
sustains a sound by replaying a grain of sound on loop
|
sustains a sound by replaying a grain of sound on loop. small but versatile
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
- `enable`: will enable the sustain if it's over 0.5
|
- `enable`: will enable the sustain if it's over 0.5
|
||||||
- `length`: length of the grain in samples. maximum is 48000 cause i said so
|
- `length`: length of the grain in samples. maximum is 48000 cause i said so
|
||||||
- `manual/pitch detection`: whether to use the manually set length (if under 0.5) or use the detected pitch (over 0.5)
|
- `manual/pitch detection`: whether to use the manually set length (if under 0.5) or use the detected pitch (over 0.5)
|
||||||
- `dissipation`: amount of dissipation of the input
|
- `dissipation`: amount of dissipation of the input
|
||||||
|
- `direction`: direction in which the grain is played
|
||||||
|
|
||||||
to use this plugin, add an automation for `enable` and set the value to `1.0` wherever you want the sustain to happen. as soon as that happens, it'll start looping the last `length` samples
|
to use this plugin, add an automation for `enable` and set the value to `1.0` wherever you want the sustain to happen. as soon as that happens, it'll start looping the last `length` samples
|
||||||
|
|
||||||
|
@ -97,13 +98,23 @@ if set to manual, it uses the provided length for the looped grain. if pitch det
|
||||||
|
|
||||||
dissipation is a weird thingy. it smooths out the sound, and i think it's a lowpass filter? not sure. makes cool sounds though. what it does is roughly `x[n] = dissipation * x[n] + (1 - dissipation) * x[n + 1]` after each time it plays a sample, so `dissipation = 1` will leave the audio untouched, and setting it to `0.5` provides the greatest effect
|
dissipation is a weird thingy. it smooths out the sound, and i think it's a lowpass filter? not sure. makes cool sounds though. what it does is roughly `x[n] = dissipation * x[n] + (1 - dissipation) * x[n + 1]` after each time it plays a sample, so `dissipation = 1` will leave the audio untouched, and setting it to `0.5` provides the greatest effect
|
||||||
|
|
||||||
low lengths will almost produce a tone of frequency `1 / length`, which makes for interesting sounds
|
direction is a selector, with three ranges:
|
||||||
|
- `[0, 0.4)`: the grain will be played backwards
|
||||||
|
- `[0.4, 0.6)`: the grain will cycle through forwards and backwards
|
||||||
|
- `[0.6, 1.0]`: the grain will play forwards
|
||||||
|
|
||||||
|
my three main uses are:
|
||||||
|
- sustaining a note, which you can do with `manual/pitch detection = 1`, `direction = 1`, and any amount of dissipation
|
||||||
|
- wavetable-ish kinda thing, by setting `manual = 0` and a really low length, you can play notes of frequency `1 / length`
|
||||||
|
- glitch repetition effect, by setting `manual = 0`, any direction (but usually forward), any dissipation, and a medium length. enable at the end of a bar or smth
|
||||||
|
|
||||||
|
but you can probably use it for more stuff! idk! this are just my suggestions
|
||||||
|
|
||||||
### quinoa [WIP]
|
### quinoa [WIP]
|
||||||
|
|
||||||
nothing implemented yet, but it's supposed to be a granular synthesis plugin that does stuff with an audio file
|
nothing implemented yet, but it's supposed to be a granular synthesis plugin that does stuff with an audio file
|
||||||
|
|
||||||
since this needs a ui so we can select a file to play, and i still don't know how to do that, it's kinda stuck
|
since this needs a ui so we can select a file to play, and i still don't know how to do that, progress is kinda stuck
|
||||||
|
|
||||||
### XLowpass
|
### XLowpass
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ baseplug::model! {
|
||||||
#[model(min = 0.0, max = 1.0)]
|
#[model(min = 0.0, max = 1.0)]
|
||||||
#[parameter(name = "dissipation")]
|
#[parameter(name = "dissipation")]
|
||||||
dissipation: f32,
|
dissipation: f32,
|
||||||
|
#[model(min = 0.0, max = 1.0)]
|
||||||
|
#[parameter(name = "direction")]
|
||||||
|
direction: f32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +40,7 @@ impl Default for SostenModel {
|
||||||
length: 1000.0,
|
length: 1000.0,
|
||||||
manual: 0.0,
|
manual: 0.0,
|
||||||
dissipation: 1.0,
|
dissipation: 1.0,
|
||||||
|
direction: 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,9 @@ struct Sosten {
|
||||||
/// Period of the processed input
|
/// Period of the processed input
|
||||||
/// We keep both so we can instantly switch
|
/// We keep both so we can instantly switch
|
||||||
period: Option<usize>,
|
period: Option<usize>,
|
||||||
|
|
||||||
|
/// Keeps track of whether we are going forward while in cycle mode
|
||||||
|
forwards_in_cycle_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin for Sosten {
|
impl Plugin for Sosten {
|
||||||
|
@ -76,6 +83,8 @@ impl Plugin for Sosten {
|
||||||
detector_thread: pitch_detection::PitchDetectorThread::<PITCH_LEN>::new(),
|
detector_thread: pitch_detection::PitchDetectorThread::<PITCH_LEN>::new(),
|
||||||
used_period: None,
|
used_period: None,
|
||||||
period: None,
|
period: None,
|
||||||
|
|
||||||
|
forwards_in_cycle_mode: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,9 +155,38 @@ impl Plugin for Sosten {
|
||||||
self.buffers.r[a] += (1.0 - diss) * self.buffers.r[(a + 1) % LEN];
|
self.buffers.r[a] += (1.0 - diss) * self.buffers.r[(a + 1) % LEN];
|
||||||
|
|
||||||
// Loop index after we finish playing a section
|
// Loop index after we finish playing a section
|
||||||
self.buffers.idx += 1;
|
if model.direction[i] > 0.6 {
|
||||||
if self.buffers.idx >= len {
|
// we are going forwards, so increase the idx
|
||||||
self.buffers.idx = 0;
|
self.buffers.idx += 1;
|
||||||
|
// and loop at the end
|
||||||
|
if self.buffers.idx >= len {
|
||||||
|
self.buffers.idx = 0;
|
||||||
|
}
|
||||||
|
} else if model.direction[i] > 0.4 {
|
||||||
|
// we're in cycle mode
|
||||||
|
|
||||||
|
// alternate directions at the end
|
||||||
|
if self.buffers.idx == 0 {
|
||||||
|
self.forwards_in_cycle_mode = true;
|
||||||
|
}
|
||||||
|
if self.buffers.idx >= len {
|
||||||
|
self.forwards_in_cycle_mode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increase/decrease index
|
||||||
|
if self.forwards_in_cycle_mode {
|
||||||
|
self.buffers.idx += 1;
|
||||||
|
} else {
|
||||||
|
self.buffers.idx -= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we are going backwards, so loop first
|
||||||
|
// this ensures we don't do 0 - 1
|
||||||
|
if self.buffers.idx == 0 {
|
||||||
|
self.buffers.idx = len + 1;
|
||||||
|
}
|
||||||
|
// then decrease index
|
||||||
|
self.buffers.idx -= 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it's not on a repeat section, pass all the audio fully
|
// If it's not on a repeat section, pass all the audio fully
|
||||||
|
|
Loading…
Reference in a new issue