Group Multiple Audio Objects into One Class

Status
Not open for further replies.
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)
};

Screen Shot 2021-03-07 at 8.26.28 PM.jpg
 
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.
 
with that you can create a voice class like this:
TigerBalmExample_voice.png

then using the n-mixer use it like this:
TigerBalmExample_synth.png

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"}}}}
}
 
Status
Not open for further replies.
Back
Top