weirdness trying to create a siren (or pitchbend)
-
- KVRer
- Topic Starter
- 3 posts since 17 May, 2009
Hi, I'm running into a weird problem, and banging my head. I want to create something as simple as a siren VST that goes up and down in pitch, and much to my surprise, what I hear is not what I see and expect.
Here's my pseudo code:
Init()
{
basefreq=440;
freq=basefreq;
step=0;
direction=TRUE; // pitch going up or down
}
ProcessReplacing(input[], output[], samplecount)
{
for (i=0; i<samplecount; i++)
{
step=step+1;
if (freq<baseFreq/2) {direction=TRUE};
if (freq>baseFreq*2) {direction=FALSE};
if(direction==TRUE) {freq:=freq*1.001}
else {freq=freq/1.001;}
x=2*PI*step*freq/samplerate;
output=sin(x);
}
}
The pitch is supposed to go up and then down, but instead I can hear it go up when it's supposed to go down. I check the values of freq in the debugger, but what I'm hearing is very different from the frequencies I'm supposed to hear. Sometimes I even hear two voices.
If I put this line "if(direction==TRUE) {freq:=freq*1.001} else {freq=freq/1.001;}" out of the loop, so that the frequency changes only per buffer and not per sample, it does sound a bit like what's expected, but still with lots of artifacts and jitter.
Can somebody explain me what I am missing ? Can somebody point out what is the logic required to produce something as simple as a siren ?
Thanks.
Here's my pseudo code:
Init()
{
basefreq=440;
freq=basefreq;
step=0;
direction=TRUE; // pitch going up or down
}
ProcessReplacing(input[], output[], samplecount)
{
for (i=0; i<samplecount; i++)
{
step=step+1;
if (freq<baseFreq/2) {direction=TRUE};
if (freq>baseFreq*2) {direction=FALSE};
if(direction==TRUE) {freq:=freq*1.001}
else {freq=freq/1.001;}
x=2*PI*step*freq/samplerate;
output=sin(x);
}
}
The pitch is supposed to go up and then down, but instead I can hear it go up when it's supposed to go down. I check the values of freq in the debugger, but what I'm hearing is very different from the frequencies I'm supposed to hear. Sometimes I even hear two voices.
If I put this line "if(direction==TRUE) {freq:=freq*1.001} else {freq=freq/1.001;}" out of the loop, so that the frequency changes only per buffer and not per sample, it does sound a bit like what's expected, but still with lots of artifacts and jitter.
Can somebody explain me what I am missing ? Can somebody point out what is the logic required to produce something as simple as a siren ?
Thanks.
- KVRAF
- 7892 posts since 12 Feb, 2006 from Helsinki, Finland
pureveg wrote: x=2*PI*step*freq/samplerate;
output=sin(x);
Your problem is that you're calculating the phase from the frequency here as if it was constant. Instead of calculating the current phase as "time*frequency" you need to integrate the phase (ie. accumulate it into a variable, instead of accumulating the step value which is useless), such that the phase of the current sample is the phase of the previous sample plus the phase-change at the current frequency.
- KVRian
- 799 posts since 25 Apr, 2011
Try renaming step to phase, and then instead of:
try:
Further code rearrangements will then probably suggest themselves
Code: Select all
step=step+1
...
x=2*PI*step*freq/samplerate;
Code: Select all
phase=phase+freq/samplerate
if phase>=1 then phase=phase-1
...
x=2*PI*phase;