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

Thread: Group Multiple Audio Objects into One Class

  1. #1
    Junior Member
    Join Date
    Mar 2021
    Posts
    18

    Group Multiple Audio Objects into One Class

    I'm really enjoying Teensy and the user friendliness of the Audio Library has "unlocked" for me the ability to code my own synthesizer. (I'm a mechanical engineer by training)

    As I transition from monophonic to polyphonic, it is getting hard to manage the sheer number of audio objects in my code. Each voice needs multiple oscillators, mixers, envelopes, etc. I wanted to make a "Voice" class that has audio objects as member variables, which would greatly simplify my code. I don't know how to do that, so here's what I landed on: my Voice object has POINTERS to audio objects as member variables. I still use the audio GUI to generate code for my big polyphonic audio graph and insert that at the top of my main.cpp. Then, I instanciate each of my voices and pass audio object pointers into their constructor functions.

    After this hard coded plumbing, the voice objects work well and make all the following code simpler. The problem: if I want to add or remove audio object pointers from the voice class I need to edit each voice in the GUI tool and update all the hard coded plumping. It would be great to make my voice object contain the audio objects and audio connections as member variables. Also, the member objects should instanciate when I instanciate the voice.

    Is that possible? I saw Paul's tutorial about making new audio objects for the audio library. That article is a little too advanced for me and it doesn't address this question of nested audio objects. Can anyone please point me in the right direction? Thank you! Below is a picture of my audio graph and the Voice class definition.

    Code:
    class Voice 
    {
      public:
        Voice (AudioSynthWaveformModulated * oscAPtr, 
              AudioSynthWaveformModulated * oscBPtr,
              AudioSynthNoiseWhite * noisePtr,
              AudioMixer4 * mixAPtr,
              AudioEffectEnvelope * envPtr,
              AudioAmplifier * ampPtr,
              AudioFilterStateVariable * filterPtr);
        int noteOn;
        int attack;
        int release;
    
        int xMod;
        int yMod;
        int zMod;
        int noteNum;
        int velocity;
    
        //One pointer per audio object
        AudioSynthWaveformModulated * oscA;
        AudioSynthWaveformModulated * oscB;
        AudioSynthNoiseWhite * noise;
        AudioMixer4 * mixA;
        AudioEffectEnvelope * env;
        AudioAmplifier * amp;
        AudioFilterStateVariable * filter;
    
        void begin(); //initialize things
    };
    
    Voice::Voice(AudioSynthWaveformModulated * oscAPtr, 
                AudioSynthWaveformModulated * oscBPtr,
                AudioSynthNoiseWhite * noisePtr,
                AudioMixer4 * mixAPtr,
                AudioEffectEnvelope * envPtr,
                AudioAmplifier * ampPtr,
                AudioFilterStateVariable * filterPtr) {
      noteOn = 0;
      attack = 0;
      release = 0;
    
      xMod = 0;
      yMod = 0;
      zMod = 0;
      noteNum = 0;
      velocity = 0;
    
      //assign all the audio object pointers to member vars
      oscA = oscAPtr;
      oscB = oscBPtr;
      noise = noisePtr;
      mixA = mixAPtr;
      env = envPtr; 
      amp = ampPtr;
      filter = filterPtr;
    }
    
    void Voice::begin() {
      oscA->begin(1,440,WAVEFORM_SAWTOOTH);
      oscB->begin(0.9,440,WAVEFORM_SQUARE);
      noise->amplitude(0.7);
      mixA->gain(0,.7);
      mixA->gain(1,.7);
      mixA->gain(2,.2);
    
      //setup envelope
      env->delay(0);
      env->attack(10);
      env->decay(0);
      env->sustain(1.0);
      env->release(10);
    
      //setup amp
      amp->gain(0.7);
    
      filter->frequency(10000);
      filter->resonance(0.7);
    }
    
    //Voice Object Instantiation
    const int numVoices = 4;
    Voice voice[] = {
      Voice(&oscA1,&oscB1,&noise1,&mixA1,&env1,&amp1,&filter1),
      Voice(&oscA2,&oscB2,&noise2,&mixA2,&env2,&amp2,&filter2),
      Voice(&oscA3,&oscB3,&noise3,&mixA3,&env3,&amp3,&filter3),
      Voice(&oscA4,&oscB4,&noise4,&mixA4,&env4,&amp4,&filter4)
    };
    Click image for larger version. 

Name:	Screen Shot 2021-03-07 at 8.26.28 PM.jpg 
Views:	31 
Size:	41.4 KB 
ID:	23966

  2. #2
    Hello TigerBalm.

    I've had this problem too, when building my synthesizer. You can access the audio objects from an array, like described in this post.
    https://forum.pjrc.com/threads/58158...-from-an-Array

    You can also dynamically connect audio objects, but I would not recommend this.
    https://forum.pjrc.com/threads/60062...io-Connections

    As a general guideline, many topics already got discussed in the forum ;D


    Have fun

  3. #3
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    288
    There is this extended Tool that allow this.
    https://Manicken.github.io
    There you can group items into a voice class.
    There is one example at the main menu- examples-poly synth.
    That describes how to use the tab input/outputs.

  4. #4
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    288
    with that you can create a voice class like this:
    Click image for larger version. 

Name:	TigerBalmExample_voice.png 
Views:	33 
Size:	13.5 KB 
ID:	23967

    then using the n-mixer use it like this:
    Click image for larger version. 

Name:	TigerBalmExample_synth.png 
Views:	34 
Size:	42.6 KB 
ID:	23968

    JSON code:
    Code:
    {"version":1,"settings":{"arduino":{"ProjectName":"TigerBalm2","Board":{"Platform":"","Board":"","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{}},"workspaces":[{"type":"tab","id":"Main","label":"Voice","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","settings":{"showNodeToolTip":false,"showGridHminor":false,"showGridHmajor":false,"showGridVminor":false,"showGridVmajor":false},"nodes":[{"id":"Main_waveformMod1","type":"AudioSynthWaveformModulated","name":"oscA","comment":"","x":115,"y":115,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_mixer4_1:0"]]},{"id":"Main_waveformMod2","type":"AudioSynthWaveformModulated","name":"oscB","comment":"","x":115,"y":165,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_mixer4_1:1"]]},{"id":"Main_noise1","type":"AudioSynthNoiseWhite","name":"noise","comment":"","x":115,"y":210,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_mixer4_1:2"]]},{"id":"Voice_mixer4_1","type":"AudioMixer4","name":"mix","comment":"","inputs":"3","x":245,"y":165,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_envelope1:0"]]},{"id":"Voice_envelope1","type":"AudioEffectEnvelope","name":"envelope","comment":"","x":385,"y":165,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_amp1:0"]]},{"id":"Voice_amp1","type":"AudioAmplifier","name":"amp","comment":"","x":510,"y":165,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_filter1:0"]]},{"id":"Voice_filter1","type":"AudioFilterStateVariable","name":"filter","comment":"","x":625,"y":170,"z":"Main","bgColor":"#E6E0F8","wires":[["Voice_Out1:0"],[],[]]},{"id":"Voice_Out1","type":"TabOutput","name":"Out","comment":"","x":740,"y":155,"z":"Main","bgColor":"#cce6ff","wires":[]}]},{"type":"tab","id":"b7a13683.ae9978","label":"Synth","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","settings":{"showNodeToolTip":false,"showGridHminor":false,"showGridHmajor":false,"showGridVminor":false,"showGridVmajor":false},"nodes":[{"id":"Synth_Voice1","type":"Voice","name":"Voice[4]","x":151,"y":99,"z":"b7a13683.ae9978","bgColor":"#CCFFCC","wires":[["Synth_mixer1:0"]]},{"id":"Synth_codeFile1","type":"CodeFile","name":"theMixer.h","comment":"/* Audio Library for Teensy 3.X\r\n * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com\r\n *\r\n * Development of this audio library was funded by PJRC.COM, LLC by sales of\r\n * Teensy and Audio Adaptor boards.  Please support PJRC's efforts to develop\r\n * open source software by purchasing Teensy or other PJRC products.\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"Software\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice, development funding notice, and this permission\r\n * notice shall be included in all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n  * THE SOFTWARE.\r\n */\r\n\r\n#ifndef themixer_h_\r\n#define themixer_h_\r\n\r\n#include <Arduino.h>\r\n#include <AudioStream.h>\r\n\r\n//#define AudioMixer4 AudioMixer<4>\r\n\r\n#if defined(__ARM_ARCH_7EM__)\r\n\r\n#define MULTI_UNITYGAIN 65536\r\n#define MULTI_UNITYGAIN_F 65536.0f\r\n#define MAX_GAIN 32767.0f\r\n#define MIN_GAIN -32767.0f\r\n#define MULT_DATA_TYPE int32_t\r\n\r\n#elif defined(KINETISL)\r\n\r\n#define MULTI_UNITYGAIN 256\r\n#define MULTI_UNITYGAIN_F 256.0f\r\n#define MAX_GAIN 127.0f\r\n#define MIN_GAIN -127.0f\r\n#define MULT_DATA_TYPE int16_t\r\n\r\n#endif\r\n\r\ntemplate <int NN> class AudioMixer : public AudioStream\r\n{\r\npublic:\r\n  AudioMixer(void) : AudioStream(NN, inputQueueArray) {\r\n    for (int i=0; i<NN; i++) multiplier[i] = MULTI_UNITYGAIN;\r\n  } \r\n  virtual void update();\r\n  \r\n  /**\r\n   * this sets the individual gains\r\n   * @param channel\r\n   * @param gain\r\n   */\r\n  void gain(unsigned int channel, float gain);\r\n  /**\r\n   * set all channels to specified gain\r\n   * @param gain\r\n   */\r\n  void gain(float gain);\r\n\r\nprivate:\r\n  MULT_DATA_TYPE multiplier[NN];\r\n  audio_block_t *inputQueueArray[NN];\r\n};\r\n\r\n// the following Forward declarations \r\n// must be defined when we use template \r\n// the compiler throws some warnings that should be errors otherwise\r\n\r\nstatic int32_t signed_multiply_32x16b(int32_t a, uint32_t b); \r\nstatic int32_t signed_multiply_32x16t(int32_t a, uint32_t b);\r\nstatic int32_t signed_saturate_rshift(int32_t val, int bits, int rshift);\r\nstatic uint32_t pack_16b_16b(int32_t a, int32_t b);\r\nstatic uint32_t signed_add_16_and_16(uint32_t a, uint32_t b);\r\n\r\n// because of the template use applyGain and applyGainThenAdd functions\r\n// must be in this file and NOT in cpp file\r\n#if defined(__ARM_ARCH_7EM__)\r\n\r\n  static void applyGain(int16_t *data, int32_t mult)\r\n  {\r\n    uint32_t *p = (uint32_t *)data;\r\n    const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES);\r\n\r\n    do {\r\n      uint32_t tmp32 = *p; // read 2 samples from *data\r\n      int32_t val1 = signed_multiply_32x16b(mult, tmp32);\r\n      int32_t val2 = signed_multiply_32x16t(mult, tmp32);\r\n      val1 = signed_saturate_rshift(val1, 16, 0);\r\n      val2 = signed_saturate_rshift(val2, 16, 0);\r\n      *p++ = pack_16b_16b(val2, val1);\r\n    } while (p < end);\r\n  }\r\n\r\n  static void applyGainThenAdd(int16_t *data, const int16_t *in, int32_t mult)\r\n  {\r\n    uint32_t *dst = (uint32_t *)data;\r\n    const uint32_t *src = (uint32_t *)in;\r\n    const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES);\r\n\r\n    if (mult == MULTI_UNITYGAIN) {\r\n      do {\r\n        uint32_t tmp32 = *dst;\r\n        *dst++ =  signed_add_16_and_16(tmp32, *src++);\r\n        tmp32 = *dst;\r\n        *dst++ =  signed_add_16_and_16(tmp32, *src++);\r\n      } while (dst < end);\r\n    } else {\r\n      do {\r\n        uint32_t tmp32 = *src++; // read 2 samples from *data\r\n        int32_t val1 =  signed_multiply_32x16b(mult, tmp32);\r\n        int32_t val2 =  signed_multiply_32x16t(mult, tmp32);\r\n        val1 =  signed_saturate_rshift(val1, 16, 0);\r\n        val2 =  signed_saturate_rshift(val2, 16, 0);\r\n        tmp32 =  pack_16b_16b(val2, val1);\r\n        uint32_t tmp32b = *dst;\r\n        *dst++ =  signed_add_16_and_16(tmp32, tmp32b);\r\n      } while (dst < end);\r\n    }\r\n  }\r\n\r\n#elif defined(KINETISL)\r\n\r\n  static void applyGain(int16_t *data, int32_t mult)\r\n  {\r\n    const int16_t *end = data + AUDIO_BLOCK_SAMPLES;\r\n\r\n    do {\r\n      int32_t val = *data * mult;\r\n      *data++ = signed_saturate_rshift(val, 16, 0);\r\n    } while (data < end);\r\n  }\r\n\r\n  static void applyGainThenAdd(int16_t *dst, const int16_t *src, int32_t mult)\r\n  {\r\n    const int16_t *end = dst + AUDIO_BLOCK_SAMPLES;\r\n\r\n    if (mult == MULTI_UNITYGAIN) {\r\n      do {\r\n        int32_t val = *dst + *src++;\r\n        *dst++ = signed_saturate_rshift(val, 16, 0);\r\n      } while (dst < end);\r\n    } else {\r\n      do {\r\n        int32_t val = *dst + ((*src++ * mult) >> 8); // overflow possible??\r\n        *dst++ = signed_saturate_rshift(val, 16, 0);\r\n      } while (dst < end);\r\n    }\r\n  }\r\n#endif\r\n\r\ntemplate <int NN> void AudioMixer<NN>::gain(unsigned int channel, float gain) {\r\n  if (channel >= NN) return;\r\n  if (gain > MAX_GAIN) gain = MAX_GAIN;\r\n  else if (gain < MIN_GAIN) gain = MIN_GAIN;\r\n  multiplier[channel] = gain * MULTI_UNITYGAIN_F; // TODO: proper roundoff?\r\n}\r\n\r\ntemplate <int NN> void AudioMixer<NN>::gain(float gain) {\r\n  for (int i = 0; i < NN; i++) {\r\n    if (gain > MAX_GAIN) gain = MAX_GAIN;\r\n    else if (gain < MIN_GAIN) gain = MIN_GAIN;\r\n    multiplier[i] = gain * MULTI_UNITYGAIN_F; // TODO: proper roundoff?\r\n  } \r\n}\r\n\r\ntemplate <int NN> void AudioMixer<NN>::update() {\r\n  audio_block_t *in, *out=NULL;\r\n  unsigned int channel;\r\n  for (channel=0; channel < NN; channel++) {\r\n    if (!out) {\r\n      out = receiveWritable(channel);\r\n      if (out) {\r\n        int32_t mult = multiplier[channel];\r\n        if (mult != MULTI_UNITYGAIN) applyGain(out->data, mult);\r\n      }\r\n    } else {\r\n      in = receiveReadOnly(channel);\r\n      if (in) {\r\n        applyGainThenAdd(out->data, in->data, multiplier[channel]);\r\n        release(in);\r\n      }\r\n    }\r\n  }\r\n  if (out) {\r\n    transmit(out);\r\n    release(out);\r\n  }\r\n}\r\n// this class and function forces include \r\n// of functions applyGainThenAdd and applyGain used by the template\r\nclass DummyClass\r\n{\r\n  public:\r\n    virtual void dummyFunction();\r\n};\r\nvoid DummyClass::dummyFunction() {\r\n  applyGainThenAdd(0, 0, 0);\r\n  applyGain(0,0);\r\n    \r\n}\r\n\r\n#endif","x":165,"y":260,"z":"b7a13683.ae9978","bgColor":"#DDFFBB","wires":[]},{"id":"Synth_mixer1","type":"AudioMixer","name":"voiceMix","inputs":"1","comment":"","x":310,"y":100,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_mixer2:0"]]},{"id":"Synth_filter2","type":"AudioFilterStateVariable","name":"delayFilterHP","comment":"","x":375,"y":185,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[[],[],["Synth_mixer2:1"]]},{"id":"Synth_filter1","type":"AudioFilterStateVariable","name":"delayFilterLP","comment":"","x":375,"y":275,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_filter2:0"],[],[]]},{"id":"Synth_mixer2","type":"AudioMixer","name":"delayMix","inputs":"2","comment":"","x":545,"y":106,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_delay1:0","Synth_mixer3:0","Synth_reverb1:0"]]},{"id":"Synth_delay1","type":"AudioEffectDelay","name":"delay","comment":"","outputs":"8","x":540,"y":415,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_filter1:0"],[],[],[],[],[],[],[]]},{"id":"Synth_reverb1","type":"AudioEffectReverb","name":"reverb","comment":"","x":720,"y":200,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_filter3:0"]]},{"id":"Synth_filter3","type":"AudioFilterStateVariable","name":"reverbFilterLP","comment":"","x":730,"y":275,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_mixer3:1"],[],[]]},{"id":"Synth_mixer3","type":"AudioMixer","name":"reverbMix","inputs":"2","comment":"","x":870,"y":110,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_amp1:0"]]},{"id":"Synth_amp1","type":"AudioAmplifier","name":"mainOut","comment":"","x":1040,"y":110,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[["Synth_i2s1:0","Synth_i2s1:1"]]},{"id":"Synth_i2s1","type":"AudioOutputI2S","name":"i2s","comment":"","x":1175,"y":110,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[]},{"id":"Synth_sgtl5000_1","type":"AudioControlSGTL5000","name":"sgtl5000","comment":"","x":1165,"y":160,"z":"b7a13683.ae9978","bgColor":"#E6E0F8","wires":[]}]}],"nodeAddons":{"sdad":{"isAddon":true,"label":"","description":"","credits":"","homepage":"","url":"https://api.github.com/repos/[user]/[repository]/contents/[subpath if any]","types":{}},"manicken_justSomeFiles_main_index_html":{"label":"Addon Nodes","description":"Addon Nodes (old type version)","url":"","isAddon":true,"types":{"AudioAnalyzePhase_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"phaseDet","inputs":"1","output":"0","category":"analyze","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioAnalyzePeak_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"peak","inputs":1,"outputs":0,"category":"analyze","color":"#E6E0F8","icon":"arrow-in.png"},"AudioAnalyzeRMS_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"rms","inputs":1,"outputs":0,"category":"analyze","color":"#E6E0F8","icon":"arrow-in.png"},"AudioAnalyzeFFT1024_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"FFT1024","inputs":1,"outputs":"0","category":"analyze","color":"#E6E0F8","icon":"arrow-in.png"},"AudioAnalyzeFFT256_IQ_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"FFT256iq","inputs":2,"outputs":"4","category":"analyze","color":"#E6E0F8","icon":"arrow-in.png"},"AudioCalcEnvelope_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"calcEnvelope","inputs":"1","output":"0","category":"calc","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioCalcGainWDRC_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"calcGainWDRC","inputs":"NaN","output":"0","category":"calc","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"},"AudioCalcLevel_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"calcLevel","inputs":"NaN","output":"0","category":"calc","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"},"AudioConvert_I16toF32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"convert_I16toF32","inputs":"0","output":"0","category":"convert","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioConvert_F32toI16":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"convert_F32toI16","inputs":"1","output":"0","category":"convert","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"},"AudioEffectCompWDRC_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"compWDRC","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEffectCompressor_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"compressor","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEffectDelay_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"delay","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEmpty_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"empty","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEffectCompressor2_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"compressor2","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEffectNoiseGate_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"noiseGate","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEffectFreqShiftFD_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"freqShift","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioEffectGain_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"gain","inputs":"1","output":"0","category":"effect","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"},"AudioFilterFIRGeneral_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"filterFIRgeneral","inputs":"1","output":"0","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioFilterEqualizer_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"filterEqualizer","inputs":"1","output":"0","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioFilter90Deg_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"filter90deg","inputs":"2","output":"2","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"},"AudioFilterBiquad_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"biquad","inputs":"1","output":"0","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioFilterFIR_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"fir","inputs":"1","output":"0","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioFilterFreqWeighting_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"freqWeight","inputs":"NaN","output":"0","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"},"AudioFilterTimeWeighting_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"timeWeight","inputs":"1","output":"0","category":"filter","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioMathAdd_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"mathAdd","inputs":"2","output":"0","category":"math","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioMathMultiply_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"mathMultiply","inputs":"2","output":"0","category":"math","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioMathOffset_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"mathOffset","inputs":"1","output":"0","category":"math","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioMathScale_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"mathScale","inputs":"1","output":"0","category":"math","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioMixer4_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"mixer4","inputs":"4","output":"0","category":"mixer","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioMixer8_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"mixer8","inputs":"8","output":"0","category":"mixer","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioSwitch4_OA_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"switch4","inputs":"1","output":"0","category":"mixer","color":"#E6E0F8","icon":"arrow-in.png","outputs":"4"},"AudioSwitch8_OA_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"switch8","inputs":"1","output":"0","category":"mixer","color":"#E6E0F8","icon":"arrow-in.png","outputs":"8"},"FFT_Overlapped_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"blockwiseFFT","inputs":"NaN","output":"0","category":"analyze","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"},"IFFT_Overlapped_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"blockwiseIFFT","inputs":"NaN","output":"0","category":"analyze","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"},"AudioInputI2S_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"audioInI2S","inputs":"0","output":"0","category":"input","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"},"AudioOutputI2S_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"audioOutI2S","inputs":"2","output":"0","category":"output","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"},"AudioInputUSB_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"audioInUSB","inputs":"0","output":"0","category":"input","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"},"AudioOutputUSB_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"audioOutUSB","inputs":"2","output":"0","category":"output","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"},"AudioPlayQueue_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"playQueue","inputs":"0","output":"0","category":"play","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioRecordQueue_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"recordQueue","inputs":"1","output":"0","category":"record","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"},"AudioSynthNoisePink_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"noisePink","inputs":"0","output":"0","category":"synth","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioSynthWaveformSine_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"sine","inputs":"0","output":"0","category":"synth","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioSynthSineCosine_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"sine-cos","inputs":"0","output":"0","category":"synth","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"},"AudioSynthWaveform_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"waveform","inputs":"0","output":"0","category":"synth","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioSynthNoiseWhite_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"noiseWhite","inputs":"0","output":"0","category":"synth","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"AudioSynthGaussian_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"GaussianWhiteNoise","inputs":"0","output":"0","category":"synth","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"RadioFMDetector_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"FMDetector","inputs":"1","output":"0","category":"radio","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"radioNoiseBlanker_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"NoiseBlank","inputs":"1","output":"0","category":"radio","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"},"RadioIQMixer_F32":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"I-QMixer","inputs":"1","output":"0","category":"radio","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"},"AudioControlSGTL5000":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"sgtl5000","inputs":0,"outputs":0,"category":"control","color":"#E6E0F8","icon":"arrow-in.png"},"AudioControlAK4558":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"ak4558","inputs":0,"outputs":0,"category":"control","color":"#E6E0F8","icon":"arrow-in.png"},"AudioControlCS4272":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"cs4272","inputs":0,"outputs":0,"category":"control","color":"#E6E0F8","icon":"arrow-in.png"},"AudioControlWM8731":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"wm8731","inputs":0,"outputs":0,"category":"control","color":"#E6E0F8","icon":"arrow-in.png"},"AudioControlWM8731master":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"wm8731m","inputs":0,"outputs":0,"category":"control","color":"#E6E0F8","icon":"arrow-in.png"},"AudioControlCS42448":{"defaults":{"name":{"value":"new"},"color":{"value":"#E6E0F8"}},"shortName":"cs42448","inputs":0,"outputs":0,"category":"control","color":"#E6E0F8","icon":"arrow-in.png"}}}}
    }

  5. #5
    I had the same issue and base on the response of manicksan I could somehow find one solution to solve the problem: https://forum.pjrc.com/threads/66608...class?p=273525

    But I wonder if there would still not be a nicer solution by making our synth voice an AudioStream, so it would be consitant with the rest of the audio library...

  6. #6
    Actually, I think this https://forum.pjrc.com/threads/66608...l=1#post273534 is the solution. I made a monolog explaining each step during my research, so hopefully you can understand the process. Let's see if someone propose an even better solution cause I am still beginning with this lib.

  7. #7
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    288
    Quote Originally Posted by apiel View Post
    But I wonder if there would still not be a nicer solution by making our synth voice an AudioStream, so it would be consitant with the rest of the audio library...
    I have answered that question on your original thread
    https://forum.pjrc.com/threads/66608...l=1#post273538

Posting Permissions

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