Author |
Message |
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Jul 07, 2015 2:45 pm Post subject:
Chebyshev ... but now for triangle waves |
|
|
This started off a long time ago ... on the G2 I had discovered two 'formulas', one for doubling a sine wave's frequency and another for a triangular wave.
For the sake of the discussion let's say we have signals in a range [-1,1] and that the functions discussed here will give outputs in that same range.
Then for sine we have :
Code: | O2( t) = 2 * t * t - 1 |
And for Tri we have
Code: | O2( t) = 2 * abs( t) - 1 |
The O2 notation used stands for Order two. Higher orders where the order is a power of two are easy of course, like for example :
Code: | O4( t) = O2( O2( t)) |
For the sine wave there is a nicer generalization, the Chebyshev polynomials can be used. These are recursively defined as :
Code: |
O0( t) = 1
O1( t) = t
On( t) = 2 * On-1( t) - On-2( t)
|
And this indeed gives frequency multiplication for sine waves by 2, 3, 4, ..., n
Then the question arose .. could such a generalization be made for triangular wave forms as well. We were discussing this in the chatroom, and then Scott (JovianPyx) came up with a nice pattern for the odd order cases 3 and 5. He originally wrote them down a bit different, but we found a more regular form that lent itself to extension to higher orders better.
Code: |
O3( t) = abs( abs( 3t - 1) - 2) - 1
O5( t) = abs( abs( abs( abs( 5t - 1 ) - 2 ) - 2 ) - 2 ) - 1
|
And this can easily be extended for higher odd orders by pre-pending 'abs( abs( ' and adding an extra ' - 2 ) - 2 )'
The even cases though seem to behave quite different, order 4 would just be order 2 applied to order 2, or O4 = O2( O2). but O6 = O2( O3) = O3( O2) which does not look like a pattern really.
Sofar we found
Code: |
O0( t) = 1
O1( t) = t
O2( t) = abs( 2t) - 1
O3( t) = abs( abs( 3t - 1) - 2) - 1
O4( t) = abs( 2 * ( abs( 2t) - 1)) - 1 = abs( abs( 4t) - 2) - 1
O5( t) = abs( abs( abs( abs( 5t - 1 ) - 2 ) - 2 ) - 2 ) - 1
O6( t) = abs( abs( 3 * ( abs( 2t) - 1) - 1) - 2) - 1
O6( t) = abs( 2 * ( abs( abs( 3t - 1) - 2) - 1)) - 1
O7( t) = abs( abs( abs( abs( abs( abs( 7t - 1 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 1
O8( t) = abs( abs( abs( abs( 8t) - 1) - 1) - 1) - 1
O9( t) = abs( abs( abs( abs( abs( abs( abs( abs( 9t - 1 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 1
O10( t) = abs( abs( abs( abs( 5 * ( abs( 2t) - 1) - 1 ) - 2 ) - 2 ) - 2 ) - 1
O10( t) = abs( 2 * ( abs( abs( abs( abs( 5t - 1 ) - 2 ) - 2 ) - 2 ) - 1)) - 1
O11( t) = abs( abs( abs( abs( abs( abs( abs( abs( abs( abs( 11t - 1 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 1
O12( t) = abs( abs( 4 * ( abs( abs( 3t - 1) - 2) - 1)) - 1) - 1
O12( t) = abs( abs( 3 * ( abs( abs( 4t) - 1) - 1) - 1) - 2) - 1
O13( t) = abs( abs( abs( abs( abs( abs( abs( abs( abs( abs( abs( abs( 11t - 1 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 2 ) - 1
|
Where order zero is a bit of a speculation really, and order one seems to make sense like this.
We were not able to find a nice form for this, like the Chebyshev definition has, and apart from that the nested abs() calls are not too nice either ... but it works.
This is similar BTW to what a wave wrapper does, and I do have some code for that but found that to be too ugly to expore it any further .. but here it is:
Code: |
procedure TModWaveWrapper.DoSlowTick; // override;
var
Modulation : TSignal;
LoMirror : TSignal;
MirrorDelta : TSignal;
Amp : TSignal;
Mute : TSignal;
Signal : TSignal;
begin
Modulation := Normalize( FInputs[ i_mod] * FInputs[ i_modamt]); // Modulation amount
LoMirror := FInputs[ i_lowlevel ] - Modulation; // Get low mirror and subtract modulatio
MirrorDelta := 2.0 * ( FInputs[ i_Highlevel] + Modulation - LoMirror); // High mirror gets modulation added. calc mirror distance, times 2
Mute := SignalToMute( FInputs[ i_mute]); // Get Mute multiplier
if Abs( MirrorDelta) < 1e-6 // When mirrors are too close to each other
then FOutputs[ o_out] := 0 // make an exception ...
else begin
Amp := 4.0 / MirrorDelta; // Amplitude reduction factor due to wrapping - times two
Signal := MathFloatMod( FInputs[ i_in] + LoMirror, MirrorDelta); // Lift signal by LoMirror, and take signal modulo 2 * Delta
if Signal > 0.5 * MirrorDelta // Reflect bit above Delta back
then Signal := MirrorDelta - Signal;
FOutputs[ o_out] := Normalize(( Amp * Signal - 1.0) * Mute); // Bring signal into -1, 1 range and apply Mute signal
end;
end;
|
Anyway .. anyone fancy a nice puzzle? _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Tue Jul 07, 2015 3:23 pm Post subject:
|
|
|
Nice.
The only pattern I see with the even outputs is:
Code: |
Ow = On( Om( tri_input ) )
where w = n * m and where w is even and greater than zero, where m or n or both are even and both n and m are greater than zero.
|
I see a possible analog design in that. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
|
|
Back to top
|
|
|
CreatorLes
Joined: Oct 05, 2014 Posts: 84 Location: San Antonio TX USA
|
Posted: Tue Jul 07, 2015 3:28 pm Post subject:
|
|
|
you guys are hella dope wako taco!
Les |
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Jul 07, 2015 4:03 pm Post subject:
|
|
|
Here is an order five example ... in tri wave mode (fig 1) .. on square, saw, tri and sine wave inputs ... only the tri wave is interesting for the discussion above, but due to how the triangle is calculated (it has some built-in LPF as it is being integrated from the square wave) the image is not too good.
Edit: changed the oscillators for LFOs - those have naive waveforms, making the image look better.
Edit: added the order five Chebyshev mode (fig 2) on the same input signals.
fig 1, Tri mode.
fig 2, Chebyshev mode. _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Mon Apr 18, 2016 3:13 pm Post subject:
|
|
|
I later added a saw mode as well... that was not to hard actually ...
Code: |
SawMult( x, N) = MathFloatMod( N * ( x + 1), 2) - 1;
|
Where N is the frequency multiplication factor, x the input value and MathFloatMod defined as :
Code: |
FloatMod( x, y) = Frac( x / y) * y;
MathFloatMod( x, y) = FloatMod( FloatMod( x, y) + y, y);
|
Which is the 'mathematically correct' modulo operation for real numbers.
Frac returns the fractional bit of it's parameter, i.e. the part after the dot.
The image below is order five, like the others I posted before.
Too bad squares can not be done _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Mon Apr 18, 2016 3:57 pm Post subject:
|
|
|
Very interesting.
Looking at the waveforms as drawn, they look "naive" in nature. I understand that can be done as a waveshape demonstration image, but what about band limiting for audio use?
Do you band limit the output or somehow prevent alias artifacts another way in the algorithm that generates the waveforms you actually use? Or is band limiting a choice (switched limited vs not limited)?
Just curious how your code deals with transients in this case because they look like they're not always predictable. High sample rates can help reduce the effect, so just that? I know that's worked for me to use high sample rates and then the effect is such low amplitude that it can be ignored.
Nice work. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
|
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Apr 19, 2016 1:53 am Post subject:
|
|
|
They are naive as I use this for LFO rate multiplication almost exclusively. _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Apr 19, 2016 1:43 pm Post subject:
|
|
|
Although it is interesting to note that the algorithm in my pre-previous post will 'sort of work' for non-integer N values, resulting in a PWM like effect on saw tooth signals.
like this (red being the N modulator, N varies from 1 to 5 here):
And this sounds like a high Q filter sweep .. except aliased of course .. so for this you'd want some form of band limiting. Reading up on that now. _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Tue Apr 19, 2016 2:19 pm Post subject:
|
|
|
The green (output) waveform looks visually a bit like hard sync.
Hopefully there's a better way to band limit than a brick wall low pass filter (with upsample and downsample). I tried that with plain naive sawtooth and it worked mostly, but had amplitude change artifacts in the upper register (fade a bit for certain frequencies) as the oscillator frequency was swept. The biggest problem with it was computational load, I used a 256 tap FIR filter. Smaller filter kernels worked too, but let more alias artifacts through. I've always been curious if there's other methods for dealing with arbitrary naive waveforms with unpredictable transients. Might be possible to use IIR technique with a fixed cutoff, but say 4 or 8 poles. IIR will introduce some delay which doesn't always matter. Still have to upsample->filter->downsample, but IIR is a far less computational load than a huge FIR filter. Gotta wonder if that might fall into the "good enough" zone. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
|
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Tue Apr 19, 2016 3:55 pm Post subject:
|
|
|
The first one I'd not seen before. Interesting concepts along with the visual observations ("corners") with regard to waveform aspects that can contribute to alias artifacts. I'd been told by some DSP people it's improper to think that way... I do it anyway. It appeared to me that the method applied needs to identify problem portions of a waveform and replace them with band limited versions. That way of doing things sounds promising for high throughput.
The second one I have somewhere, read through it then, but found it a bit much at the time. Now I see what they're doing. That should also be more efficient than a brick wall filter. ... the basis of the idea comes from differentiate, then correct problems with the differentiated signal and finally restore the "original" signal from the corrected differentiated signal. However, this is done without differentiation at all.
Both seem to work with arbitrary waveforms, though I like the second approach better personally.
I also find it interesting how the output waveforms from the discussed methods don't look anything like the brickwall anti-aliased versions. The output of these methods seems to look more natural to me. It would be interesting to look at the spectral properties of both methods and see which suppresses artifacts best as well as passing as much high frequency content below Nyquist as possible. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
Last edited by JovianPyx on Tue Apr 19, 2016 4:26 pm; edited 1 time in total |
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Apr 19, 2016 4:17 pm Post subject:
|
|
|
Ok .. going to be messy at audio rates ... it would boil down to some guess work basically ... to apply a BLEP like algorithm you'd want to know the fractional delay time (between samples) of the discontinuity. It may be possible to calculate that point assuming a saw comes in with a known amplitude. The first article referenced above mentions the drawbacks of guessing wrong.
(that one uses BLAMP which seems to not change the idea much, but the guesswork could be done better than there I think. But then again being able to go to 3 kHz is better than the naive thing which will get nasty at around 220 Hz or so.)
Anyway .. I use this mostly to generate faster LFO rates from a slow LFO, and it will still be very usable for me for that .. like for instance to modulate a delay line with a saw and another one with a saw 3 times faster.
I often end up with a slow rate LFO controlling a patch and deriving faster signals from that .. works often better for me than starting with as fast clock and then dividing it down to make the slow things. And this was the main reason for me to want frequency multiplication. _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Tue Apr 19, 2016 4:30 pm Post subject:
|
|
|
heh - I understand ... but surely those waveforms look interesting... and integer freq mult is musically interesting. As well as some non integer ones. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
|
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Wed Apr 20, 2016 12:46 pm Post subject:
|
|
|
'Arbitrary waveforms' ... as I read it, this needs to be interpreted as 'known waveforms with arbitrary discontinuities in either the wave or it's derivative' .. not really completely arbitrary. The waveform must be known in order to compute the irregular point with sub-sample precision. The first paper gives an interesting way to guesstimate such points.
http://home.mit.bme.hu/~bank/publist/smc13.pdf extends it to phase distorted triangle waves, with some algorithmic examples.
Anyway, not applicable to my case here, as I must assume unknown wave forms.
The principle could be integrated into an oscillator though, and in that case the papers would apply. _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Wed Apr 20, 2016 4:27 pm Post subject:
|
|
|
Disappointing... That's what I've also seen while looking for low computational cost anti-alias methods. They seem to rely on knowing where the problems are in advance so truly arbitrary waveforms aren't always going to apply.
Oh well.
I keep thinking that there's a way to make an algorithm that splines everything. Large transient changes would naturally be splined. Small changes in value would be splined as well, but would have less effect. Not sure how it would handle corners like on tri waves. It would, of course, introduce distortion. Possibly low pass filter effect. Also not sure how effective it could be, if at all. I do want to try it tho. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
|
|
Back to top
|
|
|
ian-s
Joined: Apr 01, 2004 Posts: 2669 Location: Auckland, New Zealand
Audio files: 42
G2 patch files: 626
|
Posted: Thu Apr 21, 2016 12:17 am Post subject:
|
|
|
JovianPyx wrote: | Large transient changes would naturally be splined. Small changes in value would be splined as well |
I have been waiting for faster DACs. The HiFi DIY people have started to use 384K devices in their media players.
If you can calculate naive waveforms at 16x, and send it to a 768k DAC it would probably sound pretty good. Throw in a polyBlep and it should sound nearly as good as a 1.5MHz DAC
I find most of the common anti-alias techniques used in commercial, dsp based synthesisers add something unpleasant to the sound. |
|
Back to top
|
|
|
JovianPyx
Joined: Nov 20, 2007 Posts: 1988 Location: West Red Spot, Jupiter
Audio files: 224
|
Posted: Thu Apr 21, 2016 4:07 pm Post subject:
|
|
|
Faster DACs are nice. I've used a 1 MHz DAC and even though it's only 12 bits, it sounds very nice at 1 MHz. That was on an FPGA. I used naive waveforms at 1 MHz and there were no audible alias artifacts, even with portamento.
Couple things to remember is that a DAC that operates well above moderate baud rates, it's capable of producing signal components that could be well above what was intended in some given audio amplifier and speakers, so you still want to limit at around 20 kHz (this can sometimes be implied in the generation algorithm or part of the DAC's reconstruction filter). The other thing is that the faster the sample rate used, the less time for computation between samples. With the 1 MHz DAC, I was using a 50 MHz system clock, so I had 50 clocks between samples. At 44.1 kHz, there are 1133 clocks between samples.
What is desirable are methods to de-alias an audio signal waveform of arbitrary shape at moderate sample rates. Ideally with little or no distortion. Upsample/downsample type systems increase the computational load, so we tend not to like those either. The idea is to preserve as much CPU power as possible to apply to the algorithmic engines that make sound. _________________ FPGA, dsPIC and Fatman Synth Stuff
Time flies like a banana. Fruit flies when you're having fun. BTW, Do these genes make my ass look fat? corruptio optimi pessima
|
|
Back to top
|
|
|
|