Joined: Jan 18, 2005 Posts: 4145 Location: Sweden
Audio files: 373
G2 patch files: 100
Posted: Sat Mar 15, 2008 9:48 am Post subject:
Weird artifacts when using SawOsc with high frequencies
I've been meaning to post this for a while, thinking it's just in my head or something. Finally got my act together to make a simple exploring patch.
Here's a ChucK program that loops some frequencies on SawOsc. As it gets higher, I think I hear some artifacts that shouldn't be there - subfrequencies that sound like they used to do on my old Amiga when I played samples with higher frequencies than the soundchip could take. It would be interesting to hear if any of you experience the same result. I'm attaching a sound sample (outputs looped back into an output on my Ultralite sound interface - slightly different version of the program but the sound is the same). I've also tried with the internal sound card on my MacBook Pro, same result.
I've tried adding --srate44100 and --bufsize1024 on the ChucK command line, no difference.
Code:
SawOsc c => dac;
0.5 => c.gain;
while (true) {
for (0 => int y; y < 8; y++) {
Std.mtof(y*16 + 8) => c.freq;
500::ms => now;
}
}
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
Posted: Sat Mar 15, 2008 10:13 am Post subject:
Yeah. It's actually supposed to do that.
It's called frequency warping.
Here's a little background:
A sawtooth wave like any periodic waveform is in a mathematical sense composed of harmonics. Sine waves playing at a base frequency and it's integer multiples.
The thing with sawtooth and square wave especially is that they are very sharp and it means that their harmonics stay strong well beyond the limits of human hearing.
The problem arises because you cannot produce those high frequencies with the samplerates we use. The harmonics climb to nyquist (frequency of half the sampling rate) and then start descending back towards zero. This sounds awful. You can verify the effect yourself by playing a sinewave sweep that goes up in frequency endlessly. After getting really high it will start comming back down, reaches zero and starts going up again.
What we need to do is cut the harmonics off at nyquist. Luckily ChucK comes with BlitSaw (bandlimited sawtooth wave) that does this.
Code:
BlitSaw c => dac;
0.5 => c.gain;
while (true) {
for (0 => int y; y < 8; y++) {
Std.mtof(y*16 + 8) => c.freq;
0 => c.harmonics; //Let ChucK calculate how many harmonics we need
500::ms => now;
}
}
Try BlitSquare too! _________________ To boldly go where no man has bothered to go before.
Joined: Jan 18, 2005 Posts: 4145 Location: Sweden
Audio files: 373
G2 patch files: 100
Posted: Sat Mar 15, 2008 10:44 am Post subject:
Aha - thanks a lot for that very fast and informative reply! I even see that I delved into stuff mentioned in your signature! A new topic that I didn't know about.
I'm actually not completely in the clear because I was running into this when I was messing about with CurveTable. I've always been intrigued by "drawing your own waveform" kind of synthesis, and was hoping that I could make some interesting timbres with this. Maybe you're not really supposed to work with waveforms this way... drawing curves with sharp edges will always get you into these frequency warping issues maybe?
If you really need the sound but at the same time want to lower the warping,
you may want to work with a higher sample rate..
so if your soundcard / audio interface support that, you can try and hear out.
drawing curves with sharp edges will always get you into these frequency warping issues maybe?
Typically, yes. Unless the module is anti-aliased, I fear.
So, the way to go would be a higher sample rate, then filtering and down sampling. Of course this means calculating what sample-rate would be sufficient for a given curve... which may be hard...
I tend to go by ear for stuff like that. _________________ Kassen
SuperCollider has them (Saw, Pulse etc.) and they rock. They're a bit more cpu-hungry than the non-band-limited versions (LFSaw, LFPulse) but sound great over the whole frequency range.
I've also used wavetable synthesis where you interpolate between adjacent buffers. In pseudocode:
for(i = 0; i < numberOfBuffers; i++) {
base = (i + lowMidi) * 12;
numHarmonics = int (20000 / midiToCps(base));
for(j = 0; j < numHarmonics; j++) {
add harmonic to buffers[i] with amplitude 1/(j+1)
}
}
Then, you can map the frequency onto the right fractional buffer number -- log2(freq / basefreq) / log2(topfreq / basefreq) * (numberOfBuffers-1) -- or, to remove a division, (log2(freq) - log2(basefreq)) / (log2(topfreq) - log2(basefreq)).
Then interpolate:
float b = (log2(freq) - log2(basefreq)) / (log2(topfreq) - log2(basefreq));
int bInt = (int) trunc(b);
WavetableOscillator(bInt) * (bInt - b + 1)
+ WaveTableOscillator(bInt+1) * (b - bInt)
Hope that's not too unclear... I'm trying to extract the basic idea from SuperCollider code I've been using for years.
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
Posted: Sat Mar 15, 2008 2:24 pm Post subject:
Antimon wrote:
Another newbie question: what, exactly, does Blit do?
Blit is short for band limited oscillator. It produces a set of harmonics with equal gains.
The two patches bellow sound the same but if you look at the waveforms they're completely different!
Human hearing isn't phase aware so it doesn't matter how the harmonics are related to each other in phase as long as their relative gains are the same.
Blit is useful when you want to do timbre manipulation with filters. Blit is what is called spectrally flat so it doesn't impinge any additional characteristic to the sound.
Code:
220.0 => float freq;
//Try the Blit:
Blit b => dac;
freq => b.freq;
10 => b.harmonics;
second => now;
b =< dac;
second => now;
//Let's make a Blit ourselves:
SinOsc harmonic[10];
float k;
for(0 => int i; i < harmonic.cap(); i++){
harmonic[i] => dac;
i+1 => k; //This is the index of the harmonic
freq*k => harmonic[i].freq;
0.1 => harmonic[i].gain;
}
second => now;
Quote:
What's the difference between it and BlitSaw?
The difference is that Blit produces harmonics with equal gains and BlitSaw weights them according to the alternating harmonic series. That is the kth partial is weighted ( -(-1)^k )/k.
So the first sinewave has a weight 1.0.
the second -0.5
the third 0.33333...
the fourth -0.25
and so on....
BlitSquare skips over every even harmonic. It's odd in spectrum. _________________ To boldly go where no man has bothered to go before.
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
Posted: Sat Mar 15, 2008 2:39 pm Post subject:
dewdrop_world wrote:
I've also used wavetable synthesis where you interpolate between adjacent buffers...
Funny you mention that. Because it's exactly what I did with my FourierPool. It can be found in the Instrument library I just posted on the other thread.
It's based on IFFT (Inverse Fast Fourier Transform) that is an UAna (Unit Analyser) in chuck.
The basic idea is to place sinewave partials in to the discrete frequency bins using linear interpolation for fractional bin values.
It almost has it all. It's perfectly band limited by definition (assuming you use the best settings to eliminate artifacts), allows precise control over the timbre (assuming you are a float function wizard), but it's not especially fast. _________________ To boldly go where no man has bothered to go before.
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 270
Posted: Sat Mar 15, 2008 3:08 pm Post subject:
Quote:
Human hearing isn't phase aware so it doesn't matter how the harmonics are related to each other in phase as long as their relative gains are the same.
That's a great thing to know, Frostburn, I always thought the phase mattered. Looking forward to hearing some additive synthesis tunes.
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
Posted: Sun Mar 16, 2008 1:03 pm Post subject:
Inventor wrote:
That's a great thing to know, Frostburn, I always thought the phase mattered. Looking forward to hearing some additive synthesis tunes.
For a single sound source it's harmonic phase relations aren't audible. (well maybe a little but it's not much)
They still make a difference when you mix different sources together, especially if distortion is involved. _________________ To boldly go where no man has bothered to go before.
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum