// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
fn duration_to_secs(duration : @moon_cpal.Duration) -> Double {
Double::from_int(duration.secs.to_int()) +
Double::from_int(duration.nanos) / 1_000_000_000.0
}
///|
fn agc_coeff(
duration : @moon_cpal.Duration,
sample_rate : SampleRate,
) -> Double {
let secs = duration_to_secs(duration)
if secs <= 0.0 || sample_rate <= 0 {
0.0
} else {
@math.exp(-1.0 / (secs * Double::from_int(sample_rate)))
}
}
///|
pub struct AutomaticGainControlSettings {
target_level : Sample
attack_time : @moon_cpal.Duration
release_time : @moon_cpal.Duration
absolute_max_gain : Sample
}
///|
pub fn AutomaticGainControlSettings::default() -> AutomaticGainControlSettings {
{
target_level: 1.0,
attack_time: @moon_cpal.Duration::from_secs((4 : UInt64)),
release_time: @moon_cpal.Duration::from_secs((0 : UInt64)),
absolute_max_gain: 7.0,
}
}
///|
pub fn AutomaticGainControlSettings::new() -> AutomaticGainControlSettings {
AutomaticGainControlSettings::default()
}
///|
pub fn AutomaticGainControlSettings::with_target_level(
self : AutomaticGainControlSettings,
target_level : Sample,
) -> AutomaticGainControlSettings {
{ ..self, target_level, }
}
///|
pub fn AutomaticGainControlSettings::with_attack(
self : AutomaticGainControlSettings,
attack_time : @moon_cpal.Duration,
) -> AutomaticGainControlSettings {
{ ..self, attack_time, }
}
///|
pub fn AutomaticGainControlSettings::with_release(
self : AutomaticGainControlSettings,
release_time : @moon_cpal.Duration,
) -> AutomaticGainControlSettings {
{ ..self, release_time, }
}
///|
pub fn AutomaticGainControlSettings::with_absolute_max_gain(
self : AutomaticGainControlSettings,
absolute_max_gain : Sample,
) -> AutomaticGainControlSettings {
{ ..self, absolute_max_gain, }
}
///|
pub struct AutomaticGainControl {
input : DynSource
target_level : Ref[Sample]
absolute_max_gain : Ref[Sample]
current_gain : Ref[Sample]
floor : Ref[Sample]
attack_coeff : Ref[Sample]
release_coeff : Ref[Sample]
agc_control : Ref[Bool]
}
///|
pub fn[S : Source] automatic_gain_control(
source : S,
settings : AutomaticGainControlSettings,
) -> AutomaticGainControl {
let src = to_dyn(source)
{
input: src,
target_level: @ref.new(settings.target_level),
absolute_max_gain: @ref.new(settings.absolute_max_gain),
current_gain: @ref.new(1.0),
floor: @ref.new(0.0),
attack_coeff: @ref.new(agc_coeff(settings.attack_time, src.sample_rate())),
release_coeff: @ref.new(agc_coeff(settings.release_time, src.sample_rate())),
agc_control: @ref.new(true),
}
}
///|
pub fn[S : Source] automatic_gain_control_with_params(
source : S,
target_level : Sample,
attack_time : @moon_cpal.Duration,
release_time : @moon_cpal.Duration,
absolute_max_gain : Sample,
) -> AutomaticGainControl {
automatic_gain_control(
source,
AutomaticGainControlSettings::new()
.with_target_level(target_level)
.with_attack(attack_time)
.with_release(release_time)
.with_absolute_max_gain(absolute_max_gain),
)
}
///|
pub fn[S : Source] AutomaticGainControl::new(
source : S,
settings : AutomaticGainControlSettings,
) -> AutomaticGainControl {
automatic_gain_control(source, settings)
}
///|
pub fn[S : Source] AutomaticGainControl::new_with_params(
source : S,
target_level : Sample,
attack_time : @moon_cpal.Duration,
release_time : @moon_cpal.Duration,
absolute_max_gain : Sample,
) -> AutomaticGainControl {
automatic_gain_control_with_params(
source, target_level, attack_time, release_time, absolute_max_gain,
)
}
///|
pub fn AutomaticGainControl::inner(self : AutomaticGainControl) -> DynSource {
self.input
}
///|
pub fn AutomaticGainControl::inner_mut(
self : AutomaticGainControl,
) -> DynSource {
self.input
}
///|
pub fn AutomaticGainControl::next(self : AutomaticGainControl) -> Sample? {
match self.input.next() {
None => None
Some(v) => {
if !self.agc_control.val {
return Some(v)
}
let abs_v = v.abs()
let raw_target_gain = if abs_v > 1.0e-12 {
self.target_level.val / abs_v
} else {
self.absolute_max_gain.val
}
let target_gain = if raw_target_gain < 0.0 {
0.0
} else if raw_target_gain > self.absolute_max_gain.val {
self.absolute_max_gain.val
} else {
raw_target_gain
}
let current = self.current_gain.val
let coeff = if target_gain < current {
self.attack_coeff.val
} else {
self.release_coeff.val
}
let gain = coeff * current + (1.0 - coeff) * target_gain
self.current_gain.val = if gain < self.floor.val {
self.floor.val
} else {
gain
}
Some(v * self.current_gain.val)
}
}
}
///|
pub fn AutomaticGainControl::get_target_level(
self : AutomaticGainControl,
) -> Ref[Sample] {
self.target_level
}
///|
pub fn AutomaticGainControl::get_absolute_max_gain(
self : AutomaticGainControl,
) -> Ref[Sample] {
self.absolute_max_gain
}
///|
pub fn AutomaticGainControl::get_attack_coeff(
self : AutomaticGainControl,
) -> Ref[Sample] {
self.attack_coeff
}
///|
pub fn AutomaticGainControl::get_release_coeff(
self : AutomaticGainControl,
) -> Ref[Sample] {
self.release_coeff
}
///|
pub fn AutomaticGainControl::get_agc_control(
self : AutomaticGainControl,
) -> Ref[Bool] {
self.agc_control
}
///|
pub fn AutomaticGainControl::set_enabled(
self : AutomaticGainControl,
enabled : Bool,
) -> Unit {
self.agc_control.val = enabled
}
///|
pub fn AutomaticGainControl::set_floor(
self : AutomaticGainControl,
floor : Sample?,
) -> Unit {
match floor {
None => self.floor.val = 0.0
Some(v) => self.floor.val = if v < 0.0 { 0.0 } else { v }
}
}
///|
pub fn AutomaticGainControl::channels(
self : AutomaticGainControl,
) -> ChannelCount {
self.input.channels()
}
///|
pub fn AutomaticGainControl::sample_rate(
self : AutomaticGainControl,
) -> SampleRate {
self.input.sample_rate()
}
///|
pub impl Source for AutomaticGainControl with fn next(
self : AutomaticGainControl,
) {
self.next()
}
///|
pub impl Source for AutomaticGainControl with fn channels(
self : AutomaticGainControl,
) {
self.channels()
}
///|
pub impl Source for AutomaticGainControl with fn sample_rate(
self : AutomaticGainControl,
) {
self.sample_rate()
}
///|
pub enum BltMode {
LowPass
HighPass
} derive(Debug, Eq)
///|
pub impl Show for BltMode with fn output(self, logger) {
match self {
LowPass => logger.write_string("BltMode::LowPass")
HighPass => logger.write_string("BltMode::HighPass")
}
}
///|
pub struct BltFilter {
input : DynSource
mode : Ref[BltMode]
freq : Ref[Int]
q : Ref[Sample]
b0 : Ref[Sample]
b1 : Ref[Sample]
b2 : Ref[Sample]
a1 : Ref[Sample]
a2 : Ref[Sample]
x1 : Ref[Sample]
x2 : Ref[Sample]
y1 : Ref[Sample]
y2 : Ref[Sample]
}
///|
fn compute_blt_coeffs(
mode : BltMode,
sample_rate : SampleRate,
freq : Int,
q : Sample,
) -> (Sample, Sample, Sample, Sample, Sample) {
let sr = if sample_rate <= 0 { 1 } else { sample_rate }
let qq = if q <= 1.0e-9 { 0.5 } else { q }
let w0 = 2.0 * @math.PI * Double::from_int(freq) / Double::from_int(sr)
let cos_w0 = @math.cos(w0)
let sin_w0 = @math.sin(w0)
let alpha = sin_w0 / (2.0 * qq)
match mode {
LowPass => {
let bb1 = 1.0 - cos_w0
let bb0 = bb1 / 2.0
let bb2 = bb0
let aa0 = 1.0 + alpha
let aa1 = -2.0 * cos_w0
let aa2 = 1.0 - alpha
(bb0 / aa0, bb1 / aa0, bb2 / aa0, aa1 / aa0, aa2 / aa0)
}
HighPass => {
let bb0 = (1.0 + cos_w0) / 2.0
let bb1 = -1.0 - cos_w0
let bb2 = bb0
let aa0 = 1.0 + alpha
let aa1 = -2.0 * cos_w0
let aa2 = 1.0 - alpha
(bb0 / aa0, bb1 / aa0, bb2 / aa0, aa1 / aa0, aa2 / aa0)
}
}
}
///|
fn[S : Source] blt_new(
source : S,
mode : BltMode,
freq : Int,
q : Sample,
) -> BltFilter {
let src = to_dyn(source)
let (b0, b1, b2, a1, a2) = compute_blt_coeffs(
mode,
src.sample_rate(),
freq,
q,
)
{
input: src,
mode: @ref.new(mode),
freq: @ref.new(freq),
q: @ref.new(q),
b0: @ref.new(b0),
b1: @ref.new(b1),
b2: @ref.new(b2),
a1: @ref.new(a1),
a2: @ref.new(a2),
x1: @ref.new(0.0),
x2: @ref.new(0.0),
y1: @ref.new(0.0),
y2: @ref.new(0.0),
}
}
///|
pub fn BltFilter::inner(self : BltFilter) -> DynSource {
self.input
}
///|
pub fn BltFilter::inner_mut(self : BltFilter) -> DynSource {
self.input
}
///|
pub fn BltFilter::into_inner(self : BltFilter) -> DynSource {
self.input
}
///|
pub fn[S : Source] low_pass(source : S, freq : Int) -> BltFilter {
blt_new(source, LowPass, freq, 0.5)
}
///|
pub fn[S : Source] high_pass(source : S, freq : Int) -> BltFilter {
blt_new(source, HighPass, freq, 0.5)
}
///|
pub fn[S : Source] low_pass_with_q(
source : S,
freq : Int,
q : Sample,
) -> BltFilter {
blt_new(source, LowPass, freq, q)
}
///|
pub fn[S : Source] high_pass_with_q(
source : S,
freq : Int,
q : Sample,
) -> BltFilter {
blt_new(source, HighPass, freq, q)
}
///|
fn BltFilter::set_formula(
self : BltFilter,
mode : BltMode,
freq : Int,
q : Sample,
) -> Unit {
self.mode.val = mode
self.freq.val = freq
self.q.val = q
let (b0, b1, b2, a1, a2) = compute_blt_coeffs(
mode,
self.input.sample_rate(),
freq,
q,
)
self.b0.val = b0
self.b1.val = b1
self.b2.val = b2
self.a1.val = a1
self.a2.val = a2
}
///|
pub fn BltFilter::to_low_pass(self : BltFilter, freq : Int) -> Unit {
self.set_formula(LowPass, freq, 0.5)
}
///|
pub fn BltFilter::to_high_pass(self : BltFilter, freq : Int) -> Unit {
self.set_formula(HighPass, freq, 0.5)
}
///|
pub fn BltFilter::to_low_pass_with_q(
self : BltFilter,
freq : Int,
q : Sample,
) -> Unit {
self.set_formula(LowPass, freq, q)
}
///|
pub fn BltFilter::to_high_pass_with_q(
self : BltFilter,
freq : Int,
q : Sample,
) -> Unit {
self.set_formula(HighPass, freq, q)
}
///|
pub fn BltFilter::next(self : BltFilter) -> Sample? {
match self.input.next() {
None => None
Some(x0) => {
let y0 = self.b0.val * x0 +
self.b1.val * self.x1.val +
self.b2.val * self.x2.val -
self.a1.val * self.y1.val -
self.a2.val * self.y2.val
self.x2.val = self.x1.val
self.x1.val = x0
self.y2.val = self.y1.val
self.y1.val = y0
Some(y0)
}
}
}
///|
pub fn BltFilter::channels(self : BltFilter) -> ChannelCount {
self.input.channels()
}
///|
pub fn BltFilter::sample_rate(self : BltFilter) -> SampleRate {
self.input.sample_rate()
}
///|
pub impl Source for BltFilter with fn next(self : BltFilter) {
self.next()
}
///|
pub impl Source for BltFilter with fn channels(self : BltFilter) {
self.channels()
}
///|
pub impl Source for BltFilter with fn sample_rate(self : BltFilter) {
self.sample_rate()
}
///|
fn lcg_next(state : Ref[UInt64]) -> UInt64 {
state.val = state.val * (6364136223846793005 : UInt64) +
(1442695040888963407 : UInt64)
state.val
}
///|
fn seed_or_default(seed : UInt64) -> UInt64 {
if seed == (0 : UInt64) {
(0x9E3779B97F4A7C15 : UInt64)
} else {
seed
}
}
///|
pub(open) trait NoiseRng {
fn next_u64(Self) -> UInt64
}
///|
pub struct LcgNoiseRng {
state : Ref[UInt64]
}
///|
pub fn LcgNoiseRng::new(seed : UInt64) -> LcgNoiseRng {
{ state: @ref.new(seed_or_default(seed)) }
}
///|
pub fn LcgNoiseRng::next_u64(self : LcgNoiseRng) -> UInt64 {
lcg_next(self.state)
}
///|
pub impl NoiseRng for LcgNoiseRng with fn next_u64(self : LcgNoiseRng) {
self.next_u64()
}
///|
pub struct NoiseRngState {
next_fn : () -> UInt64
}
///|
fn seeded_rng_state(seed : UInt64) -> NoiseRngState {
let rng = LcgNoiseRng::new(seed)
{ next_fn: fn() { rng.next_u64() } }
}
///|
fn[R : NoiseRng] custom_rng_state(rng : R) -> NoiseRngState {
{ next_fn: fn() { rng.next_u64() } }
}
///|
fn NoiseRngState::next_u64(self : NoiseRngState) -> UInt64 {
(self.next_fn)()
}
///|
fn rand_unit(rng : NoiseRngState) -> Sample {
let x = rng.next_u64()
Double::from_int((x & (0x7fff_ffff : UInt64)).to_int()) / 2147483647.0
}
///|
fn rand_signed(rng : NoiseRngState) -> Sample {
rand_unit(rng) * 2.0 - 1.0
}
///|
pub struct WhiteUniform {
sample_rate : SampleRate
rng : NoiseRngState
}
///|
pub fn WhiteUniform::new(sample_rate : SampleRate) -> WhiteUniform {
WhiteUniform::new_with_seed(sample_rate, (0x9E3779B97F4A7C15 : UInt64))
}
///|
pub fn WhiteUniform::new_with_seed(
sample_rate : SampleRate,
seed : UInt64,
) -> WhiteUniform {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: seeded_rng_state(seed) }
}
///|
pub fn[R : NoiseRng] WhiteUniform::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> WhiteUniform {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: custom_rng_state(rng) }
}
///|
pub fn WhiteUniform::next(self : WhiteUniform) -> Sample? {
Some(rand_signed(self.rng))
}
///|
pub fn WhiteUniform::std_dev(_self : WhiteUniform) -> Sample {
@math.pow(1.0 / 3.0, 0.5)
}
///|
pub fn WhiteUniform::channels(_self : WhiteUniform) -> ChannelCount {
1
}
///|
pub fn WhiteUniform::sample_rate(self : WhiteUniform) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for WhiteUniform with fn next(self : WhiteUniform) {
self.next()
}
///|
pub impl Source for WhiteUniform with fn channels(self : WhiteUniform) {
self.channels()
}
///|
pub impl Source for WhiteUniform with fn sample_rate(self : WhiteUniform) {
self.sample_rate()
}
///|
pub fn white(sample_rate : SampleRate) -> WhiteUniform {
WhiteUniform::new(sample_rate)
}
///|
pub struct Pink {
sample_rate : SampleRate
rng : NoiseRngState
prev : Ref[Sample]
}
///|
pub fn Pink::new(sample_rate : SampleRate) -> Pink {
Pink::new_with_seed(sample_rate, (0xD1B54A32D192ED03 : UInt64))
}
///|
pub fn Pink::new_with_seed(sample_rate : SampleRate, seed : UInt64) -> Pink {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: seeded_rng_state(seed), prev: @ref.new(0.0) }
}
///|
pub fn[R : NoiseRng] Pink::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> Pink {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: custom_rng_state(rng), prev: @ref.new(0.0) }
}
///|
pub fn Pink::next(self : Pink) -> Sample? {
let white = rand_signed(self.rng)
self.prev.val = 0.98 * self.prev.val + 0.02 * white
Some(self.prev.val * 5.0)
}
///|
pub fn Pink::channels(_self : Pink) -> ChannelCount {
1
}
///|
pub fn Pink::sample_rate(self : Pink) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for Pink with fn next(self : Pink) {
self.next()
}
///|
pub impl Source for Pink with fn channels(self : Pink) {
self.channels()
}
///|
pub impl Source for Pink with fn sample_rate(self : Pink) {
self.sample_rate()
}
///|
pub fn pink(sample_rate : SampleRate) -> Pink {
Pink::new(sample_rate)
}
///|
pub struct WhiteTriangular {
sample_rate : SampleRate
rng : NoiseRngState
}
///|
pub fn WhiteTriangular::new(sample_rate : SampleRate) -> WhiteTriangular {
WhiteTriangular::new_with_seed(sample_rate, (0x94D049BB133111EB : UInt64))
}
///|
pub fn WhiteTriangular::new_with_seed(
sample_rate : SampleRate,
seed : UInt64,
) -> WhiteTriangular {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: seeded_rng_state(seed) }
}
///|
pub fn[R : NoiseRng] WhiteTriangular::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> WhiteTriangular {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: custom_rng_state(rng) }
}
///|
pub fn WhiteTriangular::next(self : WhiteTriangular) -> Sample? {
Some((rand_signed(self.rng) + rand_signed(self.rng)) / 2.0)
}
///|
pub fn WhiteTriangular::std_dev(_self : WhiteTriangular) -> Sample {
2.0 / @math.pow(6.0, 0.5)
}
///|
pub fn WhiteTriangular::channels(_self : WhiteTriangular) -> ChannelCount {
1
}
///|
pub fn WhiteTriangular::sample_rate(self : WhiteTriangular) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for WhiteTriangular with fn next(self : WhiteTriangular) {
self.next()
}
///|
pub impl Source for WhiteTriangular with fn channels(self : WhiteTriangular) {
self.channels()
}
///|
pub impl Source for WhiteTriangular with fn sample_rate(self : WhiteTriangular) {
self.sample_rate()
}
///|
pub struct WhiteGaussian {
sample_rate : SampleRate
rng : NoiseRngState
}
///|
pub fn WhiteGaussian::new(sample_rate : SampleRate) -> WhiteGaussian {
WhiteGaussian::new_with_seed(sample_rate, (0x369DEA0F31A53F85 : UInt64))
}
///|
pub fn WhiteGaussian::new_with_seed(
sample_rate : SampleRate,
seed : UInt64,
) -> WhiteGaussian {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: seeded_rng_state(seed) }
}
///|
pub fn[R : NoiseRng] WhiteGaussian::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> WhiteGaussian {
guard sample_rate > 0 else { panic() }
{ sample_rate, rng: custom_rng_state(rng) }
}
///|
pub fn WhiteGaussian::mean(_self : WhiteGaussian) -> Sample {
0.0
}
///|
pub fn WhiteGaussian::std_dev(_self : WhiteGaussian) -> Sample {
0.6
}
///|
pub fn WhiteGaussian::next(self : WhiteGaussian) -> Sample? {
// Irwin-Hall approximation of a normal distribution.
let mut sum = 0.0
for _ in 0..<12 {
sum += rand_unit(self.rng)
}
Some((sum - 6.0) * 0.6)
}
///|
pub fn WhiteGaussian::channels(_self : WhiteGaussian) -> ChannelCount {
1
}
///|
pub fn WhiteGaussian::sample_rate(self : WhiteGaussian) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for WhiteGaussian with fn next(self : WhiteGaussian) {
self.next()
}
///|
pub impl Source for WhiteGaussian with fn channels(self : WhiteGaussian) {
self.channels()
}
///|
pub impl Source for WhiteGaussian with fn sample_rate(self : WhiteGaussian) {
self.sample_rate()
}
///|
let velvet_default_density : Sample = 2_000.0
///|
pub struct Velvet {
sample_rate : SampleRate
rng : NoiseRngState
grid_size : Ref[Sample]
grid_pos : Ref[Sample]
impulse_pos : Ref[Sample]
}
///|
pub fn Velvet::new(sample_rate : SampleRate) -> Velvet {
Velvet::new_with_seed(sample_rate, (0x2545F4914F6CDD1D : UInt64))
}
///|
pub fn Velvet::new_with_seed(sample_rate : SampleRate, seed : UInt64) -> Velvet {
Velvet::new_with_density_and_seed(sample_rate, velvet_default_density, seed)
}
///|
pub fn[R : NoiseRng] Velvet::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> Velvet {
Velvet::new_with_density_and_rng(sample_rate, velvet_default_density, rng)
}
///|
pub fn Velvet::new_with_density(
sample_rate : SampleRate,
density : Sample,
) -> Velvet {
Velvet::new_with_density_and_seed(
sample_rate,
density,
(0x2545F4914F6CDD1D : UInt64),
)
}
///|
pub fn[R : NoiseRng] Velvet::new_with_density_and_rng(
sample_rate : SampleRate,
density : Sample,
rng : R,
) -> Velvet {
guard sample_rate > 0 else { panic() }
let density = if density <= 1.0e-9 { velvet_default_density } else { density }
let grid_size = Double::from_int(sample_rate) / density
let state = custom_rng_state(rng)
let impulse_pos = rand_unit(state) * grid_size
{
sample_rate,
rng: state,
grid_size: @ref.new(grid_size),
grid_pos: @ref.new(0.0),
impulse_pos: @ref.new(impulse_pos),
}
}
///|
pub fn Velvet::new_with_density_and_seed(
sample_rate : SampleRate,
density : Sample,
seed : UInt64,
) -> Velvet {
guard sample_rate > 0 else { panic() }
let density = if density <= 1.0e-9 { velvet_default_density } else { density }
let grid_size = Double::from_int(sample_rate) / density
let state = seeded_rng_state(seed)
let impulse_pos = rand_unit(state) * grid_size
{
sample_rate,
rng: state,
grid_size: @ref.new(grid_size),
grid_pos: @ref.new(0.0),
impulse_pos: @ref.new(impulse_pos),
}
}
///|
pub fn Velvet::next(self : Velvet) -> Sample? {
let out = if self.grid_pos.val.to_int() == self.impulse_pos.val.to_int() {
if rand_unit(self.rng) > 0.5 {
1.0
} else {
-1.0
}
} else {
0.0
}
self.grid_pos.val += 1.0
if self.grid_pos.val >= self.grid_size.val {
self.grid_pos.val = 0.0
self.impulse_pos.val = rand_unit(self.rng) * self.grid_size.val
}
Some(out)
}
///|
pub fn Velvet::channels(_self : Velvet) -> ChannelCount {
1
}
///|
pub fn Velvet::sample_rate(self : Velvet) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for Velvet with fn next(self : Velvet) {
self.next()
}
///|
pub impl Source for Velvet with fn channels(self : Velvet) {
self.channels()
}
///|
pub impl Source for Velvet with fn sample_rate(self : Velvet) {
self.sample_rate()
}
///|
pub struct Blue {
sample_rate : SampleRate
white_noise : WhiteUniform
prev_white : Ref[Sample]
}
///|
pub fn Blue::new(sample_rate : SampleRate) -> Blue {
Blue::new_with_seed(sample_rate, (0x9E3779B97F4A7C15 : UInt64))
}
///|
pub fn Blue::new_with_seed(sample_rate : SampleRate, seed : UInt64) -> Blue {
guard sample_rate > 0 else { panic() }
{
sample_rate,
white_noise: WhiteUniform::new_with_seed(sample_rate, seed),
prev_white: @ref.new(0.0),
}
}
///|
pub fn[R : NoiseRng] Blue::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> Blue {
guard sample_rate > 0 else { panic() }
{
sample_rate,
white_noise: WhiteUniform::new_with_rng(sample_rate, rng),
prev_white: @ref.new(0.0),
}
}
///|
pub fn Blue::next(self : Blue) -> Sample? {
let white = self.white_noise.next().unwrap()
let blue = white - self.prev_white.val
self.prev_white.val = white
Some(blue)
}
///|
pub fn Blue::channels(_self : Blue) -> ChannelCount {
1
}
///|
pub fn Blue::sample_rate(self : Blue) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for Blue with fn next(self : Blue) {
self.next()
}
///|
pub impl Source for Blue with fn channels(self : Blue) {
self.channels()
}
///|
pub impl Source for Blue with fn sample_rate(self : Blue) {
self.sample_rate()
}
///|
pub struct Violet {
sample_rate : SampleRate
blue_noise : Blue
prev : Ref[Sample]
}
///|
pub fn Violet::new(sample_rate : SampleRate) -> Violet {
Violet::new_with_seed(sample_rate, (0x9E3779B97F4A7C15 : UInt64))
}
///|
pub fn Violet::new_with_seed(sample_rate : SampleRate, seed : UInt64) -> Violet {
guard sample_rate > 0 else { panic() }
{
sample_rate,
blue_noise: Blue::new_with_seed(sample_rate, seed),
prev: @ref.new(0.0),
}
}
///|
pub fn[R : NoiseRng] Violet::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> Violet {
guard sample_rate > 0 else { panic() }
{
sample_rate,
blue_noise: Blue::new_with_rng(sample_rate, rng),
prev: @ref.new(0.0),
}
}
///|
pub fn Violet::next(self : Violet) -> Sample? {
let blue = self.blue_noise.next().unwrap()
let violet = blue - self.prev.val
self.prev.val = blue
Some(violet)
}
///|
pub fn Violet::channels(_self : Violet) -> ChannelCount {
1
}
///|
pub fn Violet::sample_rate(self : Violet) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for Violet with fn next(self : Violet) {
self.next()
}
///|
pub impl Source for Violet with fn channels(self : Violet) {
self.channels()
}
///|
pub impl Source for Violet with fn sample_rate(self : Violet) {
self.sample_rate()
}
///|
pub struct Brownian {
sample_rate : SampleRate
white_noise : WhiteGaussian
accumulator : Ref[Sample]
leak_factor : Ref[Sample]
scale : Ref[Sample]
}
///|
pub fn Brownian::new(sample_rate : SampleRate) -> Brownian {
Brownian::new_with_seed(sample_rate, (0x369DEA0F31A53F85 : UInt64))
}
///|
pub fn Brownian::new_with_seed(
sample_rate : SampleRate,
seed : UInt64,
) -> Brownian {
guard sample_rate > 0 else { panic() }
let white_noise = WhiteGaussian::new_with_seed(sample_rate, seed)
let center_freq_hz = 5.0
let mut leak = 1.0 -
2.0 * @math.PI * center_freq_hz / Double::from_int(sample_rate)
if leak < 0.0 {
leak = 0.0
}
let stddev = white_noise.std_dev()
let variance = stddev * stddev / (1.0 - leak * leak + 1.0e-12)
let scale = 1.0 / @math.pow(variance, 0.5)
{
sample_rate,
white_noise,
accumulator: @ref.new(0.0),
leak_factor: @ref.new(leak),
scale: @ref.new(scale),
}
}
///|
pub fn[R : NoiseRng] Brownian::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> Brownian {
guard sample_rate > 0 else { panic() }
let white_noise = WhiteGaussian::new_with_rng(sample_rate, rng)
let center_freq_hz = 5.0
let mut leak = 1.0 -
2.0 * @math.PI * center_freq_hz / Double::from_int(sample_rate)
if leak < 0.0 {
leak = 0.0
}
let stddev = white_noise.std_dev()
let variance = stddev * stddev / (1.0 - leak * leak + 1.0e-12)
let scale = 1.0 / @math.pow(variance, 0.5)
{
sample_rate,
white_noise,
accumulator: @ref.new(0.0),
leak_factor: @ref.new(leak),
scale: @ref.new(scale),
}
}
///|
pub fn Brownian::next(self : Brownian) -> Sample? {
let white = self.white_noise.next().unwrap()
self.accumulator.val = self.accumulator.val * self.leak_factor.val + white
Some(self.accumulator.val * self.scale.val)
}
///|
pub fn Brownian::channels(_self : Brownian) -> ChannelCount {
1
}
///|
pub fn Brownian::sample_rate(self : Brownian) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for Brownian with fn next(self : Brownian) {
self.next()
}
///|
pub impl Source for Brownian with fn channels(self : Brownian) {
self.channels()
}
///|
pub impl Source for Brownian with fn sample_rate(self : Brownian) {
self.sample_rate()
}
///|
pub struct Red {
sample_rate : SampleRate
white_noise : WhiteUniform
accumulator : Ref[Sample]
leak_factor : Ref[Sample]
scale : Ref[Sample]
}
///|
pub fn Red::new(sample_rate : SampleRate) -> Red {
Red::new_with_seed(sample_rate, (0x9E3779B97F4A7C15 : UInt64))
}
///|
pub fn Red::new_with_seed(sample_rate : SampleRate, seed : UInt64) -> Red {
guard sample_rate > 0 else { panic() }
let white_noise = WhiteUniform::new_with_seed(sample_rate, seed)
let center_freq_hz = 5.0
let mut leak = 1.0 -
2.0 * @math.PI * center_freq_hz / Double::from_int(sample_rate)
if leak < 0.0 {
leak = 0.0
}
let stddev = @math.pow(1.0 / 3.0, 0.5)
let variance = stddev * stddev / (1.0 - leak * leak + 1.0e-12)
let scale = 1.0 / @math.pow(variance, 0.5)
{
sample_rate,
white_noise,
accumulator: @ref.new(0.0),
leak_factor: @ref.new(leak),
scale: @ref.new(scale),
}
}
///|
pub fn[R : NoiseRng] Red::new_with_rng(
sample_rate : SampleRate,
rng : R,
) -> Red {
guard sample_rate > 0 else { panic() }
let white_noise = WhiteUniform::new_with_rng(sample_rate, rng)
let center_freq_hz = 5.0
let mut leak = 1.0 -
2.0 * @math.PI * center_freq_hz / Double::from_int(sample_rate)
if leak < 0.0 {
leak = 0.0
}
let stddev = @math.pow(1.0 / 3.0, 0.5)
let variance = stddev * stddev / (1.0 - leak * leak + 1.0e-12)
let scale = 1.0 / @math.pow(variance, 0.5)
{
sample_rate,
white_noise,
accumulator: @ref.new(0.0),
leak_factor: @ref.new(leak),
scale: @ref.new(scale),
}
}
///|
pub fn Red::next(self : Red) -> Sample? {
let white = self.white_noise.next().unwrap()
self.accumulator.val = self.accumulator.val * self.leak_factor.val + white
Some(self.accumulator.val * self.scale.val)
}
///|
pub fn Red::channels(_self : Red) -> ChannelCount {
1
}
///|
pub fn Red::sample_rate(self : Red) -> SampleRate {
self.sample_rate
}
///|
pub impl Source for Red with fn next(self : Red) {
self.next()
}
///|
pub impl Source for Red with fn channels(self : Red) {
self.channels()
}
///|
pub impl Source for Red with fn sample_rate(self : Red) {
self.sample_rate()
}
///|
pub impl Source for AutomaticGainControl with fn current_span_len(
_self : AutomaticGainControl,
) {
_self.input.current_span_len()
}
///|
pub impl Source for AutomaticGainControl with fn total_duration(
_self : AutomaticGainControl,
) {
_self.input.total_duration()
}
///|
pub impl Source for AutomaticGainControl with fn try_seek(
_self : AutomaticGainControl,
pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
_self.input.try_seek(pos)
}
///|
pub impl Source for BltFilter with fn current_span_len(_self : BltFilter) {
_self.input.current_span_len()
}
///|
pub impl Source for BltFilter with fn total_duration(_self : BltFilter) {
_self.input.total_duration()
}
///|
pub impl Source for BltFilter with fn try_seek(
_self : BltFilter,
pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
_self.input.try_seek(pos)
}
///|
pub impl Source for WhiteUniform with fn current_span_len(_self : WhiteUniform) {
source_default_current_span_len()
}
///|
pub impl Source for WhiteUniform with fn total_duration(_self : WhiteUniform) {
source_default_total_duration()
}
///|
pub impl Source for WhiteUniform with fn try_seek(
_self : WhiteUniform,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}
///|
pub impl Source for Pink with fn current_span_len(_self : Pink) {
source_default_current_span_len()
}
///|
pub impl Source for Pink with fn total_duration(_self : Pink) {
source_default_total_duration()
}
///|
pub impl Source for Pink with fn try_seek(
_self : Pink,
pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
ignore(pos)
}
///|
pub impl Source for WhiteTriangular with fn current_span_len(
_self : WhiteTriangular,
) {
source_default_current_span_len()
}
///|
pub impl Source for WhiteTriangular with fn total_duration(
_self : WhiteTriangular,
) {
source_default_total_duration()
}
///|
pub impl Source for WhiteTriangular with fn try_seek(
_self : WhiteTriangular,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}
///|
pub impl Source for WhiteGaussian with fn current_span_len(
_self : WhiteGaussian,
) {
source_default_current_span_len()
}
///|
pub impl Source for WhiteGaussian with fn total_duration(_self : WhiteGaussian) {
source_default_total_duration()
}
///|
pub impl Source for WhiteGaussian with fn try_seek(
_self : WhiteGaussian,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}
///|
pub impl Source for Velvet with fn current_span_len(_self : Velvet) {
source_default_current_span_len()
}
///|
pub impl Source for Velvet with fn total_duration(_self : Velvet) {
source_default_total_duration()
}
///|
pub impl Source for Velvet with fn try_seek(
_self : Velvet,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}
///|
pub impl Source for Blue with fn current_span_len(_self : Blue) {
source_default_current_span_len()
}
///|
pub impl Source for Blue with fn total_duration(_self : Blue) {
source_default_total_duration()
}
///|
pub impl Source for Blue with fn try_seek(
_self : Blue,
pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
ignore(pos)
}
///|
pub impl Source for Violet with fn current_span_len(_self : Violet) {
source_default_current_span_len()
}
///|
pub impl Source for Violet with fn total_duration(_self : Violet) {
source_default_total_duration()
}
///|
pub impl Source for Violet with fn try_seek(
_self : Violet,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}
///|
pub impl Source for Brownian with fn current_span_len(_self : Brownian) {
source_default_current_span_len()
}
///|
pub impl Source for Brownian with fn total_duration(_self : Brownian) {
source_default_total_duration()
}
///|
pub impl Source for Brownian with fn try_seek(
_self : Brownian,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}
///|
pub impl Source for Red with fn current_span_len(_self : Red) {
source_default_current_span_len()
}
///|
pub impl Source for Red with fn total_duration(_self : Red) {
source_default_total_duration()
}
///|
pub impl Source for Red with fn try_seek(
_self : Red,
_pos : @moon_cpal.Duration,
) -> Unit raise SeekError {
()
}