Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 2 FirstFirst 1 2
Results 26 to 42 of 42

Thread: triangle & sawtooth oscillators : how to deal with aliasing ?

  1. #26
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    Triangle waves don't behave as badly as the discontinuity is 2nd-order, pulse type I've not looked at. It may be an easy
    generalization of square wave or not, hopefully the former.

  2. #27
    Senior Member
    Join Date
    Apr 2019
    Posts
    120
    Yes, triangles sound fine. The variable triangle wave can be varied to a sawtooth and reverse sawtooth, I imagine trying to band-limit at just those points is a pain. The square and sawtooth are a fantastic improvement that people have been requesting for several years.

  3. #28
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    And the latest changes to the branch support WAVEFORM_BANDLIMIT_PULSE !

    My sanity was restored by finding an online midi file of Toccata and Fugue in D-minor to replace the William Tell score array
    in the PlaySynthMusic example BTW!

  4. #29
    Senior Member
    Join Date
    Apr 2019
    Posts
    120
    Great! I'll test. Yes, I was reminded of Walter/Wendy Carlos and Clockwork Orange while listening to it...

  5. #30
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    Released another change, sets the WAVEFORM_BANDWIDTH_PULSE DC offset to match the duty cycle to greatly reduce pumping effect on note attach/release.
    It might cause issues with rapidly modulated pulse widths though as its not sophisticated! Compare it to the original PULSE to see what I mean.

    Because of the shift in offset the amplitude necessarily has to be a lot lower than the existing PULSE waveform.

  6. #31
    Senior Member
    Join Date
    Apr 2019
    Posts
    120
    Hello Mark. Square and sawtooth are great, the pulse wave is fine until there's any sort of modulation, even around 0.5Hz. There's digital noise that isn't regular but often. Can it be improved? Many thanks for all your work on the Audio Library.

    Manual adjustment and then lfo:
    pulsewave.wav




    Code:
    // demonstrate pulse with slow changes in pulse width
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    const float NOTEFREQS[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
    
    // GUItool: begin automatically generated code
    AudioOutputUSB           usbAudio;       //xy=2356,593
    AudioSynthWaveformModulated       waveform1;      //xy=188,240
    AudioSynthWaveform       pwmWave;      //xy=188,240
    AudioEffectEnvelope      envelope1;      //xy=371,237
    AudioOutputI2S           i2s1;           //xy=565,241
    AudioConnection          patchCord1(pwmWave, 0, waveform1, 1);
    AudioConnection          patchCord6t(waveform1, envelope1);
    AudioConnection          patchCord2(envelope1, 0, i2s1, 0);
    AudioConnection          patchCord3(envelope1, 0, i2s1, 1);
    AudioConnection          patchCord4(envelope1, 0, usbAudio, 0);
    AudioConnection          patchCord5(envelope1, 0, usbAudio, 1);
    AudioControlSGTL5000     audioShield;     //xy=586,175
    // GUItool: end automatically generated code
    
    
    void setup(void) {
      // Set up
      AudioMemory(8);
      audioShield.enable();
      audioShield.volume(0.40);
    
      pwmWave.begin(0.8f, 0.5f, WAVEFORM_SINE);
      // waveform1.begin(0.4, 220, WAVEFORM_PULSE);
      waveform1.begin(0.4, 220, WAVEFORM_BANDLIMIT_PULSE);
    
      envelope1.attack(50);
      envelope1.decay(50);
      envelope1.release(250);
    
      usbMIDI.setHandleNoteOff(myNoteOff);
      usbMIDI.setHandleNoteOn(myNoteOn);
    }
    
    void myNoteOn(byte channel, byte note, byte velocity) {
      waveform1.frequency(NOTEFREQS[note]);
      envelope1.noteOn();
    }
    
    void myNoteOff(byte channel, byte note, byte velocity) {
      envelope1.noteOff();
    }
    void loop() {
      usbMIDI.read(); //USB Client MIDI
    }

  7. #32
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    Quote Originally Posted by UHF View Post
    Hello Mark. Square and sawtooth are great, the pulse wave is fine until there's any sort of modulation, even around 0.5Hz. There's digital noise that isn't regular but often. Can it be improved? Many thanks for all your work on the Audio Library.
    Thanks for testing - and I've reworked the pulse code to be much better - it should have fixed modulation issues and I've
    improved the generality by allows arbitrarily fine pulses and fixed the DC-offset compensation to actually be scaled
    correctly (so the modulation frequency shouldn't generate a hum component, upto a point).

    The pulse shape modulation is now sampled at the rising edge of the pulse waveform so its no longer a moving target while
    processing samples (its hard enough when just the phase increment is arbitrary!). I've not run your code but have been
    using simultaneous FM and pulse modulation a fair bit with pulse modulation at full amplitude.

    [ Scope shot: Click image for larger version. 

Name:	pulse_waveform_mod.png 
Views:	21 
Size:	31.5 KB 
ID:	21209 ]
    Last edited by MarkT; 07-30-2020 at 04:26 PM. Reason: add photo

  8. #33
    Senior Member
    Join Date
    Apr 2019
    Posts
    120
    Beautiful! Thanks...

  9. #34
    Junior Member
    Join Date
    Oct 2019
    Posts
    16
    Seems like different people are working in parallel at the same problems

    I recently created a polyBLEP oscillator, you might have a look at it (https://forum.pjrc.com/threads/62240...ited-hard-sync)
    Apparently i was too fast with opening a new thread as there are already posts on bandlimited waveforms!

  10. #35
    Senior Member
    Join Date
    Apr 2019
    Posts
    120
    Hard sync! Great, I'll have play.

  11. #36
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    Had a play with my spectrum analyzer today (it rolls off below 9kHz so not great for audio, but has a resolution bw down to 1Hz so it can
    pick up a lot).

    Audio lib's standard sawtooth spectrum:
    Click image for larger version. 

Name:	raw_saw.png 
Views:	15 
Size:	11.5 KB 
ID:	21618

    And my band-limited version:
    Click image for larger version. 

Name:	bandlimit_saw.png 
Views:	20 
Size:	11.1 KB 
ID:	21619

    Which shows the power of a bandlimited step of reasonable resolution...
    The cutoff is below the SGTL5000's in-built filtering point, and much stronger,
    completely knocking out the 5th harmonic at 20kHz

    I must try this out on flo's PolyBLOB too.

  12. #37
    Junior Member
    Join Date
    Oct 2020
    Posts
    4
    Has this bandlimited version been incorporated yet?
    If so, how might one get it installed?
    (i'm new to this, so forgive naive question.)

    thanks,
    tim.

  13. #38
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    The sources aren't private, their open. https://github.com/PaulStoffregen/Audio

    You can see the outstanding pull requests and changes, and the dates of last update for the files.

    And from the relevant pull request you can see the answer is no, not yet (and its probably my fault...) :
    https://github.com/PaulStoffregen/Audio/pull/360

    I think more testing of my branch would be useful to gain enough confidence in it...

  14. #39
    Junior Member
    Join Date
    Oct 2020
    Posts
    4

    Smile

    Thanks MarkT, for the information.
    It looks like the difference is just 4 files (3 changed files and one new file).

    data_bandlimit_step.c
    keywords.txt
    synth_waveform.cpp
    synth_waveform.h

    I can just put these in ..Arduino\hardware\teensy\avr\libraries\Audio
    changed my project to use WAVEFORM_BANDLIMIT_SAWTOOTH, instead of WAVEFORM_SAWTOOTH.
    Restarted arduino app, then rebuilt the project, right?

    The arduino environment is new to me, so I'm not sure if there is anything else I'm supposed to do.

    UPDATE:
    I tried this out and the new code seems to work great! (WAVEFORM_BANDLIMIT_SAWTOOTH anyway--haven't tried the others yet). Way better than the original--no more aliasing.

    Thanks for that.

    Thanks
    Last edited by tigger; 11-03-2020 at 05:09 PM.

  15. #40
    Senior Member
    Join Date
    Jul 2020
    Posts
    565
    Excellent - any issues I suggest report back to this thread.

  16. #41
    Another way, which might be better for procedurally generated waveforms, is oversampling. Say you do 4x oversampling, you use 1/4 the phase increment you normally would, but calculate the oscillator function 4 times, each time adding the result to an accumulator. for the final output sample, divide the accumulated result by 4 which averages the 4 oversamples.

    notice the "4" in 4x oversampling is used everywhere, it can be a variable controlled by a button or potentiometer if you need to test it on the fly (good to hear immediate change on listening test!) you could even get fancy and have the oversampling decrease as cpu load increases due to polyphony and/or unison.

    each 2x you oversample raises the point where aliasing becomes noticeable about an octave higher.

    Depending on the complexity of the oscillator function, the teensy 4.x cache can help a lot here.

    Oversampling can help with wavetables as well, but fetching the wavetable data repeatedly causes a performance hit, especially at higher frequencies and with large wavetables.

  17. #42
    If you want, you can try out my generated headers to use with waveform.begin(WAVEFORM_ARBITRARY)
    You'll also find examples on how to use.

    https://github.com/SMattsson/bandlimited-waveforms


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •