Open Sound Control (OSC) Teensy Audio Library Implementation

Playing with this has shown up a problem with not recording the connection names: if you connect mixerL to i2s you might get a connection called mixerL0i2s0; if you then rename mixerL to mixer1, and delete the connection, the GUI tries to delete mixer10i2s0, which doesn't exist. So I think it is necessary to track connections in the GUI, after all.

Actually I have already implemented that, but maybe forgot to mention it :p :confused:

the debug message shown in (bottom log) shows the new names (between the parenthesis)
I have now added so that it also shows the "real"(when it was created) link name (between brackets)

the "real" name is used when deleting links

here is the updated log format:
Code:
added link [mixerL0i2s0] (mixerL, 0, i2s, 0)
renamed node from mixerL to mixer1
removed link [mixerL0i2s0] (mixer1, 0, i2s, 0)

note.
the link name is not saved between sessions of the tool
that require some redesign of the internal structure
 
the link name is not saved between sessions of the tool
that require some redesign of the internal structure

Was not that hard as I thought.

so now it saves the link name between "sessions"

one problem with that is,
if for example a new mixer is created
and called mixerL
and a new link is created from that to the i2s
then there will be a duplicate of that link name

hmm.
maybe it's best to just rename the link if either the source/target object changes name
will implement/fix that later
as it will need to check what wires is connected to an object to rename them
so it's more time consuming to implement.
 
Was not that hard as I thought.

so now it saves the link name between "sessions"

one problem with that is,
if for example a new mixer is created
and called mixerL
and a new link is created from that to the i2s
then there will be a duplicate of that link name

hmm.
maybe it's best to just rename the link if either the source/target object changes name
will implement/fix that later
as it will need to check what wires is connected to an object to rename them
so it's more time consuming to implement.
Agreed, working for me. I usually use OSC / Simple / Send to reset the server Teensy to be in sync with the GUI, so it's not a major problem if things go out of sync between sessions.

The system doesn't let you create a link (or anything else) with a duplicate name .... in theory. Do say if you spot it doing so! And the reply will tell you that the operation didn't work, so the GUI++ could remove the link / node that didn't get created.

Do you think it would be useful to have a "dump Teensy connectivity" operation? I'd need the system to remember the object types e.g. as a text string; and if we do it, I should also record the XY positions so the GUI++ layout could be restored. Shouldn't be hard, but maybe there are better things to do first .... actually, I know what I want to think about ... how to implement your GUI++ voice arrays! Oh, and inter-converting OSC and MIDI, so we can address @JayShoe's original interests.
 
Hello Guys,

I did successfully compile the project. But I haven't had much luck getting any audio out yet. I suspect it's because of the fact that my STGL5000 hasn't been initialized in the Setup() code yet. But I might be wrong.

Here is what I've tested, and some initial feedback on the design thus far, if you don't mind. This might help us discover improvements, and it could maybe help with documentation.


Setup

1. Installed arduinoAPIwebserver by copying folder in zip "API_WebServer" to Arduino/Tools/API_WebServer.
2. Put main branch "trunk" of OSCAudio into Arduino/LibrariesOSCAudio
3. Put branch "features/dynamic-updates" into Arduino/Libraries/Audio/
4. Overwrote the "cores" library in "C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores" with https://github.com/h4yn0nnym0u5e/cores (This part was more difficult because it's hard to Git in the Program Files...)

Testing

Opened OSCAudio/examples/OSCAudioEmpty/ it compiled successfully and everything worked fine. Note, at this point my keyboard and mouse stop working. I unplug them and plug them back in and I can get the keyboard and mouse back up. I suspect this has to do with the Serial port on the example. I think my keyboard was on the same serial number maybe? I don't know. But an interesting issue nonetheless. This has happened to me 3 times already so something is going on with the keyboard/mouse stopping.

Opened https://manicken.github.io/

Opened Examples>Empty New Project

Renamed "#define HWSERIALPORT Serial7" to #define HWSERIALPORT Serial3 in the arduino project although I'm not sure if this is right. The reason I did that was because in the GUI tool it sees my Teensy on Serial 3. But I'm fairly positive that I'm screwing this up. I suspect that Serial 3 is what Windows believes the Teensy is. But I don't think that the Teensy currently knows how to understand the data. Because you guys are using the FTDI on the Serial 7 pins of the Teensy.

Connect to Serial on the GUI Tool.

Screenshot 2021-12-13 125837.png


- Added control/AudioControlSGTL5000
- Added input/other/usb
- Added output/i2s1/i2s
- Linked USB to I2S x 2

Code:
Welcome to the WebSocketServer!new connection: /added node (AudioControlSGTL5000) sgtl5000
added node (AudioInputUSB) usb
added node (AudioOutputI2S) i2s
added link [usb0i2s0] (usb, 0, i2s, 0)
added link [usb1i2s1] (usb, 1, i2s, 1)

Something is working, I think...

But now no sound yet. My board in Arduino is set to Serial + MIDI + Audio.

Screenshot 2021-12-13 130443.jpg

I think that maybe the SGTL isn't getting setup properly yet. It's not turned on... So therefore no audio. But I'm not sure, this is just the test that I tried to document first. Maybe you have some advice. I have some thoughts as well....

Jay
 
If you are open to feedback/feature requests here are my thoughts.

Would it be possible to add another side-bar, this time between the grid and the right column... here...

Screenshot 2021-12-13 130753.jpg

This sidebar could be called "Object Control Panel". It would be a place where every object has some information on it's controls, and possibly the ability to actually control it. When you select an item in the grid, this Object Control Panel (OCP) would display something like.

- A list of OSC addresses.
- Buttons or sliders, as pre-defined on a per object basis, or potentially automatically generated based on the classes.

For example, the mixer would show 4 sliders (for each channel in the mixer) or at least 4 input boxes, so one could type in values into each channel to modify the volumes. The sine object would have amplitude, frequency, phase sliders (or input boxes). The AudioControlSGTL5000 might have a button for "enable()"... To manually initialize the SGTL5000.

We would need probably a few different button types and we would need to apply those button types to the classes in some programmable way.
- Slider for volumes, frequencies, phases, etc. function(i or f);
- Switch for booleens function(bool);
- Button for classes();
- Input boxes for everything? (for simple entry of .5, for example in a volume bar or a specific frequency value).

Or if not automatic, then manually we could define OCP's for each object (and I could contribute my time to manually create it...)

Anyway, if this existed then there is no need to even build a custom GUI at all. For a quick and dirty implementation of a device, adding a bunch of objects to the grid and clicking around in the Object Control Pane would be a completely visual prototyping tool. Then someone can work on a custom GUI after tweaking around this way for a while. It would help the user to create a custom surface on another app because all the OSC addresses would be displayed on the Object Control Pane. So the user dives into the grid, finds the control they want to setup, get the address easily from the list, and off to the races they go.

I will definitely keep working on this to see if I can get some sound as in my test. I'll try some other tests as well and continue to tinker.
 
Short post @ mobile
Could not the object type just be like a static const string in each of the OSC<something> objects, the nice thing about the x,y positions is that they could just be stored into two float values in each of the created objects thus save a lot of memory.
I believe that the array functionality could be implemented using the current implementation, but if you have a idea how it could be done I'm open ears (arrays of arrays)/special object to store other linked lists(will give better example later and pros/cons of that i think)
I have also thought of something like OCP
I plan to have it in the right panel (where info and settings live) an reuse the whole code for the "workspace"/view but only allow UI objects there.
Cool that you use the Arduino ide plugin.

Hmm. Maybe not so short answer
 
@JayShoe, you might want to try this, which is my current testbed. Copy the JSON, including the trailing } on the second line, and paste it into the box you get using Import / </>JSON in GUI++
Code:
{"version":1,"settings":{"arduino":{"ProjectName":"DynamicDesignTest","Board":{"Platform":"","Board":"teensy41","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{},"OSC":{}},"workspaces":[{"type":"tab","id":"Main","label":"Main","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","generateCppDestructor":false,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"Main_waveform2","type":"AudioSynthWaveform","name":"waveform1","comment":"","x":375,"y":340,"z":"Main","bgColor":"#E6E0F8","wires":[["Main_mixer4_2:0","Main_mixer4_1:0"]],"wireNames":[["waveform10mixer10","waveform10mixerR0"]]},{"id":"Main_waveform4","type":"AudioSynthWaveform","name":"waveform2","comment":"","x":375,"y":395,"z":"Main","bgColor":"#E6E0F8","wires":[["Main_mixer4_2:1","Main_mixer4_1:1"]],"wireNames":[["waveform20mixer11","waveform20mixerR1"]]},{"id":"Main_waveform1","type":"AudioSynthWaveform","name":"waveform3","comment":"","x":375,"y":450,"z":"Main","bgColor":"#E6E0F8","wires":[["Main_mixer4_2:2","Main_mixer4_1:2"]],"wireNames":[["waveform30mixer12","waveform30mixerR2"]]},{"id":"Main_waveform3","type":"AudioSynthWaveform","name":"waveform4","comment":"","x":375,"y":505,"z":"Main","bgColor":"#E6E0F8","wires":[["Main_mixer4_2:3","Main_mixer4_1:3"]],"wireNames":[["waveform40mixer13","waveform40mixerR3"]]},{"id":"Main_mixer4_2","type":"AudioMixer4","name":"mixer1","comment":"","inputs":"4","x":565,"y":390,"z":"Main","bgColor":"#E6E0F8","wires":[["Main_i2s1:0"]],"wireNames":[["mixer10i2s0"]]},{"id":"Main_mixer4_1","type":"AudioMixer4","name":"mixerR","comment":"","inputs":"4","x":565,"y":455,"z":"Main","bgColor":"#E6E0F8","wires":[["Main_i2s1:1"]],"wireNames":[["mixerR0i2s1"]]},{"id":"Main_i2s1","type":"AudioOutputI2S","name":"i2s","comment":"","x":801,"y":419,"z":"Main","bgColor":"#E6E0F8","wires":[],"wireNames":[]},{"id":"Main_sgtl5000_1","type":"AudioControlSGTL5000","name":"sgtl5000","comment":"","x":955,"y":415,"z":"Main","bgColor":"#E6E0F8","wires":[],"wireNames":[]},{"id":"Main_Slider1","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":35,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy*/audio/sgtl5000/vol','f',d.val/100.0)\nOSC.SendData(volCmd)","x":880,"y":705,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Piano1","type":"UI_Piano","name":"Piano","comment":"","w":210,"h":130,"textSize":14,"midiCh":"0","midiId":"0","octave":4,"sendCommand":"var freq = Math.pow(2,d.octave+(d.keyIndex-9)/12)*55/4\nvar w1Msg = OSC.CreateMessageData('/teensy1/audio/waveform1/be','ffi',0.1,freq,0)\nOSC.SendData(w1Msg)","headerHeight":30,"whiteKeysColor":"#FFFFFF","blackKeysColor":"#A0A0A0","blackKeysWidthDiff":6,"x":135,"y":115,"blackKeyLabelsVisible":true,"whiteKeyLabelsVisible":true,"z":"Main","bgColor":"#F6F8BC","wires":[],"wireNames":[]},{"id":"Main_Piano2","type":"UI_Piano","name":"Piano","comment":"","w":210,"h":130,"textSize":14,"midiCh":"0","midiId":"0","octave":4,"sendCommand":"var freq = Math.pow(2,d.octave+(d.keyIndex-9)/12)*55/4\nvar w1Msg = OSC.CreateMessageData('/teensy1/audio/waveform3/be','ffi',0.1,freq,0)\nOSC.SendData(w1Msg)","headerHeight":30,"whiteKeysColor":"#FFFFFF","blackKeysColor":"#A0A0A0","blackKeysWidthDiff":6,"x":130,"y":435,"blackKeyLabelsVisible":true,"whiteKeyLabelsVisible":true,"z":"Main","bgColor":"#F6F8BC","wires":[],"wireNames":[]},{"id":"Main_Piano3","type":"UI_Piano","name":"Piano","comment":"","w":210,"h":130,"textSize":14,"midiCh":"0","midiId":"0","octave":4,"sendCommand":"var freq = Math.pow(2,d.octave+(d.keyIndex-9)/12)*55/4\nvar w1Msg = OSC.CreateMessageData('/teensy1/audio/waveform2/be','ffi',0.1,freq,0)\nOSC.SendData(w1Msg)","headerHeight":30,"whiteKeysColor":"#FFFFFF","blackKeysColor":"#A0A0A0","blackKeysWidthDiff":6,"x":135,"y":280,"blackKeyLabelsVisible":true,"whiteKeyLabelsVisible":true,"z":"Main","bgColor":"#F6F8BC","wires":[],"wireNames":[]},{"id":"Main_Piano4","type":"UI_Piano","name":"Piano","comment":"","w":210,"h":130,"textSize":14,"midiCh":"0","midiId":"0","octave":5,"sendCommand":"var freq = Math.pow(2,d.octave+(d.keyIndex-9)/12)*55/4\nvar w1Msg = OSC.CreateMessageData('/teensy1/audio/waveform4/be','ffi',0.1,freq,0)\nOSC.SendData(w1Msg)","headerHeight":30,"whiteKeysColor":"#FFFFFF","blackKeysColor":"#A0A0A0","blackKeysWidthDiff":6,"x":125,"y":585,"blackKeyLabelsVisible":true,"whiteKeyLabelsVisible":true,"z":"Main","bgColor":"#F6F8BC","wires":[],"wireNames":[]},{"id":"Main_Slider2","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":7,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer1/ga','if',0,d.val/100.0)\nOSC.SendData(volCmd)","x":550,"y":685,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Button1","type":"UI_Button","name":"enable","comment":"","w":100,"h":30,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/sgtl5000/enabl','')\nOSC.SendData(volCmd)","x":965,"y":548,"z":"Main","bgColor":"#F6F8BC","wires":[],"wireNames":[]},{"id":"Main_scriptBtn1","type":"UI_ScriptButton","name":"delete all!","comment":"var volCmd = OSC.CreateMessageData('/teensy1/dynamic/clearAll','')\nOSC.SendData(volCmd)","w":100,"h":30,"textSize":14,"nodes":[],"x":835,"y":45,"z":"Main","bgColor":"#FF4623","wires":[],"wireNames":[]},{"id":"Main_Slider3","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":25,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer1/ga','if',1,d.val/100.0)\nOSC.SendData(volCmd)","x":615,"y":685,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider4","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":65,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer1/ga','if',2,d.val/100.0)\nOSC.SendData(volCmd)","x":680,"y":685,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider5","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":97,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer1/ga','if',3,d.val/100.0)\nOSC.SendData(volCmd)","x":740,"y":685,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider6","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":88,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer2/ga','if',0,d.val/100.0)\nOSC.SendData(volCmd)","x":530,"y":175,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider7","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":50,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer2/ga','if',1,d.val/100.0)\nOSC.SendData(volCmd)","x":600,"y":175,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider8","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":11,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer2/ga','if',2,d.val/100.0)\nOSC.SendData(volCmd)","x":665,"y":175,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider9","type":"UI_Slider","name":"volume","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":6,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer2/ga','if',3,d.val/100.0)\nOSC.SendData(volCmd)","x":725,"y":175,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]},{"id":"Main_Slider10","type":"UI_Slider","name":"volume (all)","comment":"","w":30,"h":300,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":9,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var volCmd = OSC.CreateMessageData('/teensy1/audio/mixer*/ga','if',0,d.val/100.0)\nOSC.SendData(volCmd)","x":420,"y":710,"z":"Main","bgColor":"#808080","wires":[],"wireNames":[]}]}],"nodeAddons":{}
}
All being well you'll get this layout:
2021-12-13 19_38_10-Audio System Design Tool++ for Teensy Audio Library.png
You will need to:
  • use OSC / Simple /Send to upload the layout to the Teensy
  • make sure gui run is checked
  • click the enable button to send an enable message to the SGTL5000
  • move the rightmost volume slider up to get some volume out
Then the Piano keyboards will set the waveforms playing sine waves (waveform4 is an octave up), and the other sliders will vary the gains of each channel on the two mixers. If the GUI isn't running you can look at the JavaScript underlying the controls' actions.

Having said all that, my system isn't working right now! But it's been fine all day...
 
@JayShoe, you might want to try this, which is my current testbed.

With which example? OSCAudioEmpty?

Or IDE>Upload?

Does one just need the JSON, or is a matching arduino file also required to make a project run?
 
With which example? OSCAudioEmpty?

Or IDE>Upload?

Does one just need the JSON, or is a matching arduino file also required to make a project run?
Sorry, yes, OSCAudioEmpty.ino on your Teensy - the GUI needs a "target" to talk to! It sounds as if you're close, though not 100% sure if you're actually communicating with the Teensy - we've been using the Teensy's own USB serial for debug, and an FTDI connected to Serial7 (or similar) for GUI++ traffic. But as you say, the SGTL does need the equivalent of sgtl5000.enable() to start up, which is what my enable button does ... so long as GUI comms is working!
 
Last edited:
Maybe we should start using the "USB Dual Serial" option instead?

I did a working example but did use the Serial which is the first USB serial
and used SerialUSB1 for the debug output

the problem here is that Serial is still the programming port.


and the only port that can be used with the SLIPEncodedUSBSerial
is the Serial

if I try to pass SerialUSB1 to SLIPEncodedUSBSerial constructor
like so:
SLIPEncodedUSBSerial HWSERIAL(SerialUSB1);

they are not compatible :(

so there need to be some rework of the SLIPEncodedUSBSerial to use SerialUSB1
to make it work

:(


@h4yn0nnym0u5e
I did try your example design
with the four pianos
It works but the sound of the keys are not sounding good.

before the state of the key could either be read out by local(in the function that calls eval) variable: pressed or by using (d.keyDown == 0x90)
now I have made that clearer
so the usage is as in the following example:
Code:
// here I use a predefined table of all note frequencies
var noteFreqs = [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];
    

if (d.pressed == true)
    var amp = 0.1;
else
    var amp = 0;
var freq = noteFreqs[d.octave*12 + d.keyIndex];

// send in bundle with two commands frequency and amplitude
var bundle = OSC.CreateBundle(0);
bundle.packets.push(OSC.CreatePacket('/teensy1/audio/waveform1/f*',"f", freq));
bundle.packets.push(OSC.CreatePacket('/teensy1/audio/waveform1/am*',"f", amp));
OSC.SendData(OSC.CreateBundleData(bundle));

// send as begin only
//var w1Msg = OSC.CreateMessageData('/teensy1/audio/waveform1/b*','ffi',amp,freq,1);
//OSC.SendData(w1Msg);
 
Last edited:
soon it will be like this statement
from https://www.pjrc.com/teensy/td_libs_AudioRoadmap.html

Dynamic Updates & Web Designer Control
Today, the audio objects really need to be statically allocated. Some distant future version will feature working object destructors, and constructors capable of adding objects and connections into a live system.
Eventually, I want to create an example that listens for commands to create & delete objects, and control many of their functions, and of course corresponding code in the GUI design tool. As you drag objects onto the canvas, and connect them, messages would be sent to your Teensy running that example, to actually implement as you draw.

This wonderful future would also have GUI control for the selected object in the right-side panel, so you'd be able to control the objects and cause them to make sound, see the live output of analysis objects in your browser, and so on. Just a "small matter" of more programming.....
 
@JayShoe
note that in the setup()

the line
while(!Serial);
blocks the program until you have connected to the USB serial

just so that you know
 
here is my current example of Dual Serial

https://github.com/manicken/OSCAudioPlatformIO
(in some haste I misspelled "some" in the commit)

it still uses Serial for OSC messages
and uses SerialUSB1 for the debug output

so that means it's blocking the programming port

the order of the ports in windows (in my case):
1. SerialUSB1 (COM7)
2. Serial (COM8)


Also I got the slip decoding + OSC decoding working in the Tool
so now the OSC receive data in the Tool is much easier to read

There is also new settings
newOSCsettings.png
 
note that it is a good idea to turn off both the rx output debug
when sending a lot off messages
ex.
coming from a slider
playing the piano

as the receive takes up to much time in the GUI
and make it sluggish
 
Do you think it would be useful to have a "dump Teensy connectivity" operation?
After some thinkin, I believe there is no need for reading the structure, not at least in the current implementation
because the "design" is not remembered between power cycles anyway.
And we will also loose everything else (gui elements/comments and alot other stuff)


To use that we need some kind of saving to a Non Volatile file system, either LittleFS ("internal"/program flash/external flash) or FAT on SD card

the SD card do offer much more space and can easily be replaced (if broken or just to have another set of designs)

I have been thinkin it could be implemented this way:
* the file format could just be the actual raw OSC message received, this way when loading a file the contents can just be passed into the OSC message "decoder"

* the current design filename could just be saved to annother file called designToLoad.txt
this file is loaded every time the teensy starts, to find out what design to use.
also by using designToLoad.txt we can also force a software reset to make sure that the memory is clean.

* we could also push the design JSON so that is also saved on the file system,
then that could be used to retrieve the complete design instead of using additional data for every object.

Oh, and inter-converting OSC and MIDI, so we can address @JayShoe's original interests.
The OSC message spec do mention MIDI messages as a special type.
 
note that it is a good idea to turn off both the rx output debug when sending a lot off messages, ex. coming from a slider playing the piano, as the receive takes up to much time in the GUI and make it sluggish
Good point, it's been on my mental list of stuff to do but there's always been something more interesting!
here is my current example of Dual Serial https://github.com/manicken/OSCAudioPlatformIO (in some haste I misspelled "some" in the commit)

it still uses Serial for OSC messages and uses SerialUSB1 for the debug output so that means it's blocking the programming port

the order of the ports in windows (in my case):
1. SerialUSB1 (COM7)
2. Serial (COM8)


Also I got the slip decoding + OSC decoding working in the Tool so now the OSC receive data in the Tool is much easier to read

There is also new settings
View attachment 26895
Sounds good - I'll take a look at some point.
After some thinkin, I believe there is no need for reading the structure, not at least in the current implementation because the "design" is not remembered between power cycles anyway. And we will also loose everything else (gui elements/comments and alot other stuff)

To use that we need some kind of saving to a Non Volatile file system, either LittleFS ("internal"/program flash/external flash) or FAT on SD card. the SD card do offer much more space and can easily be replaced (if broken or just to have another set of designs)

I have been thinkin it could be implemented this way:
* the file format could just be the actual raw OSC message received, this way when loading a file the contents can just be passed into the OSC message "decoder"

* the current design filename could just be saved to annother file called designToLoad.txt
this file is loaded every time the teensy starts, to find out what design to use.
also by using designToLoad.txt we can also force a software reset to make sure that the memory is clean.

* we could also push the design JSON so that is also saved on the file system,
then that could be used to retrieve the complete design instead of using additional data for every object.

The OSC message spec do mention MIDI messages as a special type.
That sounds like a good approach overall. It also means the OSCAudio engine doesn't get more complex, and an example sketch is fairly easy. I think we just need another endpoint, say /teensy/fs (which filesystem is defined by the application...) with methods:
  • /load<s>: string s is the name of a file containing an OSC bundle which should be fed back into the OSC decoder
  • /save<s><b>: save blob b to filename s; the blob can be anything but is likely to be either JSON or OSC
  • /send<s>: retrieve a file and send it in the reply to the GUI (or other client) as a blob
  • /delete<s>: delete a file
Then the GUI can save a network to the Teensy as both .JSON and .OSC, then later get the Teensy to send the .JSON back and either tell it to load the corresponding .OSC or the GUI could send the JSON back as an OSC bundle.

I'd noted that OSC can encapsulate MIDI, but not sure how useful that is for us. I've just got my system working routing an Alesis V Mini keyboard through to the Teensy using MIDI-OX, so I can start thinking about @JayShoe's original use cases! Never forget the client... This should result in a better demo layout with proper envelopes, not just 4 channels of drone.

So, lunchtime ending now, and busy tonight, but should be back on this tomorrow.
 
maybe it's best to just rename the link if either the source/target object changes name
will implement/fix that later
as it will need to check what wires is connected to an object to rename them
so it's more time consuming to implement.

This is now implemented

example.png

if for example the mixer1 is renamed to mixer
then all connections that go to/from mixer1 are renamed


I have also made a discovery
if you create a group around some objects (actually the objects need to be put into the group)
waveformTemplate.png
then the group name can be used as a global name for all the objects inside that group

javascript code that can be used in "child" objects:
Code:
var parentName = d.parentGroup.name;
var addr = "/teensy1/audio/"+parentName+"/b*";

here is a template to control a AudioSynthWaveForm
select all text don't forget the trailing ]
and use import-json (uncheck "replace flow")
Code:
[{"id":"Sheet_1_group1","type":"group","name":"waveform","comment":"","w":379,"h":416,"textSize":14,"nodes":["Sheet_1_Slider1","Sheet_1_Slider4","Sheet_1_ListBox2","Sheet_1_Button2","Sheet_1_Slider5","Sheet_1_Slider6","Sheet_1_Slider7"],"border_color":"rgba(153,153,153,1)","individualListBoxMode":true,"exportAsClass":true,"x":110,"y":50,"z":"241683b6.86a27c","bgColor":"rgba(221,255,187,1)","wires":[]},{"id":"Sheet_1_Slider1","type":"UI_Slider","name":"freq","comment":"","w":30,"h":282,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val + \"Hz\"","minVal":1,"maxVal":4186,"val":108,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var parentName = d.parentGroup.name;\nvar addr = \"/teensy1/audio/\"+parentName+\"/f*\";\nvar data = OSC.GetSimpleOSCdata(addr,\"f\", d.val);\nOSC.SendAsSlipToSerial(data);","parentGroup":"Sheet_1_group1","x":288.5714111328125,"y":101.42857360839844,"z":"241683b6.86a27c","bgColor":"#808080","wires":[]},{"id":"Sheet_1_Slider4","type":"UI_Slider","name":"gain","comment":"","w":30,"h":280,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":12,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var parentName = d.parentGroup.name;\nvar addr = \"/teensy1/audio/\"+parentName+\"/am*\";\nvar data = OSC.GetSimpleOSCdata(addr,\"f\", (d.val/d.maxVal));\nOSC.SendAsSlipToSerial(data);","parentGroup":"Sheet_1_group1","x":238.5714111328125,"y":101.42857360839844,"z":"241683b6.86a27c","bgColor":"#808080","wires":[]},{"id":"Sheet_1_ListBox2","type":"UI_ListBox","name":"wave type","comment":"","w":103,"h":301,"textSize":20,"midiCh":"","midiId":"20","itemTextSize":"","items":"Sine\nSawtooth\nSquare\nTriangle\nPulse\nSaw. Rev.\nSample H\nVar. Tri.","selectedIndex":2,"selectedIndexOffset":"","headerHeight":40,"itemBGcolor":"#FFFFFF","sendCommand":"var parentName = d.parentGroup.name;\nvar addr = \"/teensy1/audio/\"+parentName+\"/b*\";\nvar data = OSC.GetSimpleOSCdata(addr,\"i\", d.selectedIndex);\nOSC.SendAsSlipToSerial(data);\n","parentGroup":"Sheet_1_group1","x":123.5714111328125,"y":86.42857360839844,"z":"241683b6.86a27c","bgColor":"#F87A00","wires":[]},{"id":"Sheet_1_Button2","type":"UI_Button","name":"init waveform","comment":"","w":120,"h":34,"textSize":16,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"// example of a multi parameter message\r\n// this is for the begin(level, frequency, waveform) function\r\nvar parentName = d.parentGroup.name;\r\nvar addr = \"/teensy1/audio/\"+parentName+\"/b*\";\r\n\r\nvar data = osc.writePacket( {\r\n        address:addr,\r\n        args:[\r\n            {\r\n                type:\"f\",\r\n                value:0.25\r\n            },\r\n            {\r\n                type:\"f\",\r\n                value:110\r\n            },\r\n            {\r\n                type:\"i\",\r\n                value:2\r\n            }\r\n        ]});\r\nOSC.SendAsSlipToSerial(data);","parentGroup":"Sheet_1_group1","x":128.5714111328125,"y":411.42857360839844,"z":"241683b6.86a27c","bgColor":"#F6F8BC","wires":[]},{"id":"Sheet_1_Slider5","type":"UI_Slider","name":"offset","comment":"","w":30,"h":282,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":1,"maxVal":100,"val":100,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var parentName = d.parentGroup.name;\nvar addr = \"/teensy1/audio/\"+parentName+\"/o*\";\nvar data = OSC.GetSimpleOSCdata(addr,\"f\", (d.val/d.maxVal));\nOSC.SendAsSlipToSerial(data);","parentGroup":"Sheet_1_group1","x":338.5714111328125,"y":101.42857360839844,"z":"241683b6.86a27c","bgColor":"#808080","wires":[]},{"id":"Sheet_1_Slider6","type":"UI_Slider","name":"phase","comment":"","w":30,"h":282,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val","minVal":1,"maxVal":360,"val":100,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var parentName = d.parentGroup.name;\nvar addr = \"/teensy1/audio/\"+parentName+\"/ph*\";\nvar data = OSC.GetSimpleOSCdata(addr,\"f\", d.val);\nOSC.SendAsSlipToSerial(data);","parentGroup":"Sheet_1_group1","x":388.5714111328125,"y":101.42857360839844,"z":"241683b6.86a27c","bgColor":"#808080","wires":[]},{"id":"Sheet_1_Slider7","type":"UI_Slider","name":"PuWi","comment":"","w":30,"h":282,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val","minVal":1,"maxVal":360,"val":100,"outputFloat":false,"minValF":-1,"maxValF":1,"floatVal":0,"decimalCount":-1,"steps":201,"sendSpace":true,"repeat":false,"repeatPeriod":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var parentName = d.parentGroup.name;\nvar addr = \"/teensy1/audio/\"+parentName+\"/pu*\";\nvar data = OSC.GetSimpleOSCdata(addr,\"f\", d.val);\nOSC.SendAsSlipToSerial(data);","parentGroup":"Sheet_1_group1","x":438.5714111328125,"y":101.42857360839844,"z":"241683b6.86a27c","bgColor":"#808080","wires":[]}
]

this makes it very simple to create controls for different kind of objects
 
Have now added a button so that a selected "group box" with contents can be exported as a JSON string
it's shown @ the right info panel

there is also a keyboard shortcut Ctrl+O (output)
to create a JSON for the selected object/objects
 
I have been thinkin
we actually need some special object,
think we should use OSCAudioBase:s functionality
so that special object have it's own address "space"

to store the "entry" point for a linked list

so we then can create "cascaded linked lists".

Putting everything in a huge linked list,
would be not so performance wise
as every object has to be checked

When using the above proposed scheme
and accessing a cascaded linked list object
then first it can check if the address matches the special object
and thus skip all other objects in that "sub" linked list


now for some pictures to better describe it

here is first a simple Voice "class"
SimpleVoice.png

and here is the teensy root "class"
SimplePolySynth.png

so that we can create this (represents the linked lists)
CascadedLinkedLists_voices.jpg

the osc messages would be as follows:
(the special object typename for now is OSCCLL (OSC cascaded linked list)
Ø means a null char (the padding nulls are not included)
note. in this structure we don't use the "class type" Name (Voice) for voices

something inside a <n> means the value n in either int or float value
the real data for example a int32 <0> would be four zeroes (bytes) ØØØØ

Code:
// the container object for the voices
/teensy*/dynamic/createObject*,ssØOSCCLLØvoicesØ

/teensy*/voices/dynamic/createObject*,ssØOSCCLLØ0Ø
/teensy*/voices/0/dynamic/createObject*,ssØAudioSynthWaveformØwfØ
/teensy*/voices/0/dynamic/createObject*,ssØAudioEffectEnvelopeØenvØ
/teensy*/voices/0/dynamic/createConnection*,sØwf0env0Ø
/teensy*/voices/0/audio/wf0env0/connect*,sisiØwfØ<0>ØenvØ<0>Ø

/teensy*/voices/dynamic/createObject*,ssØOSCCLLØ1Ø
/teensy*/voices/1/dynamic/createObject*,ssØAudioSynthWaveformØwfØ
/teensy*/voices/1/dynamic/createObject*,ssØAudioEffectEnvelopeØenvØ
/teensy*/voices/1/dynamic/createConnection*,sØwf0env0Ø
/teensy*/voices/1/audio/wf0env0/connect*,sisiØwfØ<0>ØenvØ<0>Ø

/teensy*/voices/dynamic/createObject*,ssØOSCCLLØ2Ø
/teensy*/voices/2/dynamic/createObject*,ssØAudioSynthWaveformØwfØ
/teensy*/voices/2/dynamic/createObject*,ssØAudioEffectEnvelopeØenvØ
/teensy*/voices/2/dynamic/createConnection*,sØwf0env0Ø
/teensy*/voices/2/audio/wf0env0/connect*,sisiØwfØ<0>ØenvØ<0>Ø

/teensy*/voices/dynamic/createObject*,ssØOSCCLLØ3Ø
/teensy*/voices/3/dynamic/createObject*,ssØAudioSynthWaveformØwfØ
/teensy*/voices/3/dynamic/createObject*,ssØAudioEffectEnvelopeØenvØ
/teensy*/voices/3/dynamic/createConnection*,sØwf0env0Ø
/teensy*/voices/3/audio/wf0env0/connect*,sisiØwfØ<0>ØenvØ<0>Ø

/teensy*/dynamic/createObject*,ssØAudioMixer4ØvmØ
/teensy*/dynamic/createObject*,ssØAudioOutputI2SØi2sØ

// note. the following connections can only be done outside of the classes

/teensy*/dynamic/createConnection*,sØvoices0_env0_vm0Ø
/teensy*/audio/voices0_env0_vm0/connect*,sisiØvoices/0/envØ<0>ØvmØ<0>Ø

/teensy*/dynamic/createConnection*,sØvoices1_env0_vm1Ø
/teensy*/audio/voices1_env0_vm0/connect*,sisiØvoices/1/envØ<0>ØvmØ<1>Ø

/teensy*/dynamic/createConnection*,sØvoices2_env0_vm2Ø
/teensy*/audio/voices2_env0_vm0/connect*,sisiØvoices/2/envØ<0>ØvmØ<2>Ø

/teensy*/dynamic/createConnection*,sØvoices3_env0_vm3Ø
/teensy*/audio/voices3_env0_vm0/connect*,sisiØvoices/3/envØ<0>ØvmØ<3>Ø

/teensy*/dynamic/createConnection*,sØvm0_i2s0Ø
/teensy*/audio/vm0_i2s0/connect*,sisiØvm<0>Øi2sØ<0>Ø
/teensy*/dynamic/createConnection*,sØvm0_i2s1Ø
/teensy*/audio/vm0_i2s1/connect*,sisiØvm<0>Øi2sØ<1>Ø

But if we invent a Class Define command
it could be written as follows:

Code:
/teensy*/dynamic/defineObject*,ssØVoiceØ 
// following incremented lines is the content of the second string
// theese can then be executed when a Voice object is created
               dynamic/createObject*,ssØAudioSynthWaveformØwfØ
               dynamic/createObject*,ssØAudioEffectEnvelopeØenvØ
               dynamic/createConnection*,sØwf0env0Ø
               audio/wf0env0/connect*,sisiØwfØ<0>ØenvØ<0>ØØ
			
// the container object for the voices

/teensy*/dynamic/createObject*,ssØOSCCLLØvoicesØ

// now it's much easier to create new Voice objects

/teensy*/voices/dynamic/createObject*,ssØVoiceØ0Ø
/teensy*/voices/dynamic/createObject*,ssØVoiceØ1Ø
/teensy*/voices/dynamic/createObject*,ssØVoiceØ2Ø
/teensy*/voices/dynamic/createObject*,ssØVoiceØ3Ø


/teensy*/dynamic/createObject*,ssØAudioMixer4ØvmØ
/teensy*/dynamic/createObject*,ssØAudioOutputI2SØi2sØ

// note. the following connections can only be done outside of the classes

/teensy*/dynamic/createConnection*,sØvoices0_env0_vm0Ø
/teensy*/audio/voices0_env0_vm0/connect*,sisiØvoices/0/envØ<0>ØvmØ<0>Ø

/teensy*/dynamic/createConnection*,sØvoices1_env0_vm1Ø
/teensy*/audio/voices1_env0_vm0/connect*,sisiØvoices/1/envØ<0>ØvmØ<1>Ø

/teensy*/dynamic/createConnection*,sØvoices2_env0_vm2Ø
/teensy*/audio/voices2_env0_vm0/connect*,sisiØvoices/2/envØ<0>ØvmØ<2>Ø

/teensy*/dynamic/createConnection*,sØvoices3_env0_vm3Ø
/teensy*/audio/voices3_env0_vm0/connect*,sisiØvoices/3/envØ<0>ØvmØ<3>Ø

/teensy*/dynamic/createConnection*,sØvm0_i2s0Ø
/teensy*/audio/vm0_i2s0/connect*,sisiØvm<0>Øi2sØ<0>Ø
/teensy*/dynamic/createConnection*,sØvm0_i2s1Ø
/teensy*/audio/vm0_i2s1/connect*,sisiØvm<0>Øi2sØ<1>Ø

here is an example of a simple "array" of waveforms
CascadedLinkedLists_simpleArrayOfWaveforms.jpg

so what do you think?
 
I have now fixed the SLIPEncodedUSBSerial class
I did create a new one called SLIPEncodedUSBSerial1
where the changes are applied

download these two files and put them inside the sketch folder
https://github.com/manicken/OSCAudioPlatformIO/blob/main/src/SLIPEncodedUSBSerial1.cpp
https://github.com/manicken/OSCAudioPlatformIO/blob/main/src/SLIPEncodedUSBSerial1.h

the usage is:
Code:
#include <SLIPEncodedUSBSerial1.h>

SLIPEncodedUSBSerial1 OSC_SERIAL(SerialUSB1); // I renamed HWSERIAL to OSC_SERIAL for clarity

if you want to use the new name don't forget to change the names everywhere in the .ino file
such as in this file
https://github.com/manicken/OSCAudioPlatformIO/blob/main/src/OSCAudioEmpty.ino

note.
the order in windows is still in reverse (the com numbers are in my system, and can differ):

COM7 = SerialUSB1
COM8 = Serial (guess it would be named SerialUSB0 if it should have a USB name)

so when doing the connection in the Tool it's COM7 in this case.

don't forget to open the serial monitor in Arduino IDE

edit.
I did add a "OSC Live Update" checkbox button in the tool
 
I definitely need to take a look at all this work you're putting in! And try to get my head round your idea for dealing with voices...

I was going to look at MIDI today, but got distracted by the /fs idea (see #117), so that's what I've done and pushed up today. It's actually made almost no difference to the OSCAudio library, except that I've defined another error value for out of memory. The main items are a new sketch (OSCAudioUseFS.ino) and an associated Python 3 test file (OSCAudioFStest.py). it's a bit clunky, and in particular I've not structured it to make it easy to load a default network file at startup.

One other thing I did briefly look at was code size. If we cater for a fully-dynamic system then the memory footprint is very big, because code is included for every possible AudioStream object, even if they're not used. Unused object classes are highly likely, as a lot of them are input or output objects, and I can't see many designs using more than a few. For many purposes there will be a fixed network, and all OSC needs to do is control the objects. I think I have an idea of how to exclude the creation elements at compile time, on a per-project basis, but it'll be a while before that reaches the point where I can do something sensible, so for now we'll just have to put up with it.
 
One thing I keep forgetting to ask. Is there a way of getting rid of, or at least moving, the temporary information bubbles that pop up at the top of the GUI? Every time I press Refresh I can't do anything for about 10 seconds, because they're right over the buttons I want to use next!
 
Last edited:
One other thing I did briefly look at was code size. If we cater for a fully-dynamic system then the memory footprint is very big, because code is included for every possible AudioStream object, even if they're not used.

Do you mean flash "program" memory?
Think that is no problem (it only takes ~230KB)

The gain is a fully dynamic system.

And I think this is also to really try and learn about the different objects "live" without any boring recompile/upload.

But then again how many would use the different input/output objects,
(and as you say one design often use the same types of outputs)
me for example uses the PT8211 at "i2s port2", but I have a SGTL5000 waiting to be soldered to some stackable header pins

but even then how cool is it not just be able to hook up something to the teensy an just try it out live
(off course the power need to be cut before connecting anything live, but then again if it's done in the right way(connecting gnd first then VCC then IO:s) there should not be any big problems doing so live even if it should be avoided)

many but:s above, I know :p

One thing I keep forgetting to ask. Is there a way of getting rid of, or at least moving, the temporary information bubbles that pop up at the top? Every time I press Refresh I can't do anything for about 10 seconds, because they're right over the buttons I want to use next!
yes I also think they are annoying
have removed all that shows at the startup now I hope


I have now created a c++ function extractor @ .net C#
how did you do to get the short names, did you manually edit them?
 
believe I will just extract all the commands from OSCAudioAutogen-dynamic.h
that file is highly structured so extracting anything from that would not be any problem

I'm gonna use it to try autogenerating "control objects"
i.e. sliders/buttons/listboxes inside a group

or at least as a easy to read reference for all object "commands"
as all the generation cannot be done automatically

how should I differ between using a slider vs a listbox for controlling the waveform type?

and how should the slider ranges and calculations be autogenerated?

maybe in the "unknown" situations I will just put a textinput box together with a appy button
and they could then be replaced by a slider manually
 
Back
Top