Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 20 of 20

Thread: Creating custom audio objects that are more similar to modular synth components.

  1. #1

    Creating custom audio objects that are more similar to modular synth components.

    I have been working for some time on a polyphonic synthesizer, however I have been running into a lot of scalability issues due to some very spaghetti code and difficulty interfacing between my sketch and the audio library. A potential solution I have been considering is creating some custom objects for the audio library. I've made some rough diagrams of what I'm thinking of making, but i could do with some advice on the feasibility and difficulty of creating them. Any help is much appreciated.
    https://imgur.com/a/SwYSYGc

  2. #2
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    Best way to get started is to delve into the library and learn how the existing things work. The osc you describe could just be the existing osc with some added control inputs.

    Here's a really simple effect. It's a basic full wave lossless rectifier. Combine it with a biquad, you got an envelope follower. This is what the library is all about
    Attached Files Attached Files

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,637
    Should I merge this rectifier effect into the audio library?

    Any chance you might be willing to contribute an example program using it with the filter?

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,450
    There's a bug in the rectifier code. It appears to work for all input values except 0x8000. In this case it should return 0x7fff (maximum positive value) but it returns 0x8000.
    I used a rectifier effect in some code I wrote a few years back. I vaguely remember getting the code from Paul somehow. Anyway, it does the rectify like this, where the variable 's' is declared int16_t:
    Code:
        if (s < 0) {
          if (s == -32768) {
            s = 32767;
          } else {
            s = -s;
          }
        }
    I suspect that this could be made more efficient in assembler code. If I figure it out, I'll post it here.

    @ thedreiskre
    For your oscillator, start with the audio library code for synth_sine.cpp and/or synth_waveform.cpp to see how the existing code generates those waveforms and then tweak the code to do what you want.

    Pete

  5. #5
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    Quote Originally Posted by PaulStoffregen View Post
    Should I merge this rectifier effect into the audio library?

    Any chance you might be willing to contribute an example program using it with the filter?
    I'd be flattered if you would merge it into the library. It would save me having to edit my copy and paste code from the gui to make my own rectifier links.

    Here's a vocoder I made based on another sketch. Very basic but it's functional and demonstrates how to use the object. Of course, right now to copy and paste it back into the gui you'd need to change the "AudioEffectRectifier" to AudioEffectFade (that's the stub I use) so the gui can construct the full diagram.
    Attached Files Attached Files

  6. #6
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    Scratch that, that's a weeks old file. Here's a basic demo that uses a built in noise source to get things started.
    Attached Files Attached Files

  7. #7
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    And here's an updated c module minus the bug pointed out by el_supremo
    Attached Files Attached Files

  8. #8
    How about mixers with 8 and 16 inputs? This would make some designs a lot simpler.

    Thanks,
    Michael

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,637
    About the original question...

    Click image for larger version. 

Name:	E0U1NWj.png 
Views:	15 
Size:	43.3 KB 
ID:	20636

    Like with any software project, a key first step is to start with a clear idea of the code will actually do. This picture probably means something specific to you, but I'm confused. I don't really understand why it has "Exp Frequency" and also "Exp Frequency adjust". It also has 2 similarly named inputs for "Linear Frequency". That seems like 4 separate inputs which all do the same thing, in slightly different ways.

    While you could probably build such code, what will it do if signals are connected to both the Linear and Exp inputs? These are important details when it comes to actually writing the code....

  10. #10
    I was thinking to create an audio object to neaten up my code and audio graph. To implement all the types of synthesis my design needs would take a pretty complex node setup and program. For example, when making an 8 voice polysynth I pretty much had to make everything 8 times, the resulting graph looked like this https://imgur.com/a/RuPcej8.

    The project I'm now working on is monophonic, however I am looking to implement multiple different generation algorithms. If i was working purely with 1 arduino sketch and the audio node editor, this would become a very complex system (and that is without adding in filters, multiple oscillators, lfos etc.

    While implementing each one of these algorithms using separate objects is relatively simple, I dont see how they could be condensed into a single object, let alone changing the algorithm with a value and having the inputs then control different settings.

    What would be the best way to go about coding a single object which has multiple oscillation algorithms within it , and can take inputs via the audio graph?

    revised diagram: https://imgur.com/a/jVIrMYh

  11. #11
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    130
    Quote Originally Posted by aaaxon View Post
    How about mixers with 8 and 16 inputs? This would make some designs a lot simpler.

    Thanks,
    Michael

    Here's a simple modification of the standard mixer with 10 inputs, cheers Paul

    mixer10.zip

  12. #12
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    Can we delete attachments? I now have two of effect_rectifier.cpp files in my attachments manager.

    Anyway, this one is elegant and works great.
    Attached Files Attached Files

  13. #13
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,450
    @ boxxofrobots
    I don't see how your latest version is any better. The problem is that you are copying an int16_t into an int32_t and apparently assuming that the 16-bit integer is copied into the high order 16 bits of the int32_t. But if block->data[i] is 0x8000 then after this:
    Code:
      sampleRect = block->data[i];
    sampleRect will be 0xFFFF8000, not 0x80000000. There is also the problem that when sampleRect is assigned to be 0x7fffffff, and the following statement is executed:
    Code:
       	block->data[i] = sampleRect;
    this will set block->data[i] to 0xffff (-1), not 0x7fff.
    You would be better off declaring sampleRect to be int16_t and use code similar to what I posted in #4.

    Pete

  14. #14
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    Interesting. I see your point, but the api seems to be doing the heavy lifting because it works as specified. Here's a proof.

    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>

    // GUItool: begin automatically generated code
    AudioSynthWaveformSineHires sine_hires1; //xy=773,891
    AudioEffectRectifier rect1; //xy=1096,933
    AudioOutputI2S i2s1; //xy=1271,810
    AudioOutputUSB usb1; //xy=1283,1057
    AudioConnection patchCord1(sine_hires1, 0, i2s1, 0);
    AudioConnection patchCord2(sine_hires1, 0, usb1, 1);
    AudioConnection patchCord3(sine_hires1, 0, rect1, 0);
    AudioConnection patchCord4(rect1, 0, usb1, 0);
    AudioConnection patchCord5(rect1, 0, i2s1, 1);
    AudioControlSGTL5000 sgtl5000_1; //xy=992,1058
    // GUItool: end automatically generated code



    void setup() {
    // put your setup code here, to run once:
    AudioMemory(10);
    sgtl5000_1.enable();
    sgtl5000_1.volume(1);
    // noise1.amplitude(0.5);
    // waveform1.begin(WAVEFORM_SINE);
    sine_hires1.amplitude(1);
    sine_hires1.frequency(1000);

    }

    void loop() {
    // put your main code here, to run repeatedly:
    Serial.println("Nothing");
    }

  15. #15
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,450
    While testing your code I realized that what you've implemented is a half-wave rectifier. I had needed a full-wave rectifier and got confused. Sorry about that.
    However, if you are doing a half wave rectifier wouldn't this be a lot simpler?
    Code:
      for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
        if(block->data[i] < 0)block->data[i] = 0;
      }
    Pete

  16. #16
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,637
    I wrote a slightly different implementation, using the saturate and halfword pack instructions.

    https://github.com/PaulStoffregen/Au...2000567a8bdc76

  17. #17
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,637
    Click image for larger version. 

Name:	file.png 
Views:	16 
Size:	28.9 KB 
ID:	20649

    Code:
    #include <Audio.h>
    
    AudioSynthWaveformSine sine;
    AudioEffectRectifier rect;
    AudioOutputAnalog dac;
    AudioConnection p1(sine, 0, rect, 0);
    AudioConnection p2(rect, 0, dac, 0);
    
    void setup() {
      AudioMemory(10);
      sine.amplitude(0.9);
      sine.frequency(440);
    }
    
    void loop() {
    }

  18. #18
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    Quote Originally Posted by PaulStoffregen View Post
    I wrote a slightly different implementation, using the saturate and halfword pack instructions.

    https://github.com/PaulStoffregen/Au...2000567a8bdc76
    This is why you get paid the bucks. Thanks! When will it show up in the gui?

  19. #19
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,637
    Quote Originally Posted by thedreiskre View Post
    I was thinking to create an audio object to neaten up my code and audio graph. To implement all the types of synthesis my design needs would take a pretty complex node setup and program. For example, when making an 8 voice polysynth I pretty much had to make everything 8 times
    I believe this problem would be best solved in the design tool. Someday I hope we can support hierarchical designs, where you can create objects which are actually entire designed in themselves. The export process would flatten the whole thing to a long list of instances to copy into Arduino.

    A custom object with new features might also be useful for other reasons. But consider that processing input streams is expensive in terms of CPU performance, as you do more and more math for every audio sample, 44100 times per second.

  20. #20
    Senior Member
    Join Date
    Apr 2020
    Location
    Tucson
    Posts
    124
    What about supporting naming conventions like osc[1], adsr[4], etc? Presently a copy and paste of such names results in a mess like osc[1]1, adsr[4]1, etc.

Posting Permissions

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