synth sine with an exponentially swept frequency doesn't start at zero #647

Open
opened 2025-10-10 13:06:07 +00:00 by martinwguy · 0 comments
martinwguy commented 2025-10-10 13:06:07 +00:00 (Migrated from codeberg.org)

synth sine with a exponentially swept frequency doesn't start at zero

Description

If you run synth sine at a fixed frequency, the generated wave starts
at sample value zero. However, if you use a exponential swept frequency range
like 440/441, it starts at an apparently random offset into the wave,
creating a delayed initial click with chorus, flanger and phaser.

The other sweep operators, : for linear, + for time squared,
and - for the stepped exponential starting at phase 0, all seem
to start at the zero-valued start of a cycle.

Analysis

For sweep type Exp, it does

start()
{
    chan->mult = samples_to_do
      ? log(chan->freq2 / chan->freq) / p->samples_to_do * effp->in_signal.rate
      : 1;  /* samples_to_do is 0 if the audio length is unknown */
    chan->freq /= chan->mult;
}

flow()
{
    phase = chan->freq * exp(chan->mult * elapsed_time_s);
    [...]
    phase = fmod(phase + chan->phase, 1.0);
}

and when elapsed_time_s is zero, exp() of it is 1 so phase ends up as
fmod(chan->freq, 1.0).
For the other three wave types, in flow phase is 0 when elapsed_time_s
is zero, but for / it is 1.9382e+06 which, fmod 1.0, is 0.167612

Why it divides chan->freq by chan->mult is unclear

The existence of -, "a stepped exponential sweep type that starts at phase 0",
suggests that the developers were aware of this anomaly.

Conclusion

See if the code can be reworked to give the same exponential frequency sweep
but with the output starting at phase 0.

# synth sine with a exponentially swept frequency doesn't start at zero ## Description If you run `synth sine` at a fixed frequency, the generated wave starts at sample value zero. However, if you use a exponential swept frequency range like `440/441`, it starts at an apparently random offset into the wave, creating a delayed initial click with `chorus`, `flanger` and `phaser`. The other sweep operators, `:` for linear, `+` for time squared, and `-` for the stepped exponential starting at phase 0, all seem to start at the zero-valued start of a cycle. ## Analysis For sweep type Exp, it does ``` start() { chan->mult = samples_to_do ? log(chan->freq2 / chan->freq) / p->samples_to_do * effp->in_signal.rate : 1; /* samples_to_do is 0 if the audio length is unknown */ chan->freq /= chan->mult; } flow() { phase = chan->freq * exp(chan->mult * elapsed_time_s); [...] phase = fmod(phase + chan->phase, 1.0); } ``` and when `elapsed_time_s` is zero, `exp()` of it is 1 so phase ends up as `fmod(chan->freq, 1.0)`. For the other three wave types, in flow `phase` is 0 when `elapsed_time_s` is zero, but for `/` it is `1.9382e+06` which, `fmod 1.0`, is 0.167612 Why it divides `chan->freq` by `chan->mult` is unclear The existence of `-`, "a stepped exponential sweep type that starts at phase 0", suggests that the developers were aware of this anomaly. ## Conclusion See if the code can be reworked to give the same exponential frequency sweep but with the output starting at phase 0.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
martinwguy/sox_ng#647
No description provided.