@weasel79 exactly.
since i have to modify it anyway, i started with trying to send SysEx to different ports
Mattilyn Mattroe contributions
Hey Weasel, no din isn’t working to send sysex with this object on 1.0.12.
However 2.0 has din sysex support so it probably will work there. I haven’t yet migrated to 2.0 so haven’t tested
does not compile on 2.0:
compiling /home/private/chaocrator/axoloti-2.0.0/build/xpatch.cpp
In file included from /opt/Axoloti/app/api/xpatch.h:21:0,
from <command-line>:0:
/home/private/chaocrator/axoloti-2.0.0/build/xpatch.cpp: In member function 'void rootc::instancecustom::dsp(rootc*, bool, int32_t)':
/opt/Axoloti/app/api/midi_legacy.h:18:44: error: 'midiSendSysEx' was not declared in this scope
#define MidiSendSysEx(dev,port,bytes,len) midiSendSysEx(dev,bytes,len)
^
/home/private/chaocrator/axoloti-2.0.0/build/xpatch.cpp:172:2: note: in expansion of macro 'MidiSendSysEx'
MidiSendSysEx(MIDI_DEVICE_DIN, 1,sysexArray,13);
^~~~~~~~~~~~~
/opt/Axoloti/app/api/midi_legacy.h:18:44: note: suggested alternative: 'MidiSendSysEx'
#define MidiSendSysEx(dev,port,bytes,len) midiSendSysEx(dev,bytes,len)
^
Thanks for testing, I wonder if it's implemented differently indicated by "midi_legacy.h:18:44: error:"
MIDI implementation in 2.0 is significantly different, it introduced virtual MIDI ports layer and other things.
(that's the reason for me to keep at least one board at 1.0.12, because it serves MIDI routing via Miditech MIDIface 8x8. in new implementation virtual 8 MIDI i/o ports just can't address 16 physical i/o ports of MIDIface. in 1.0.12, i have all of them working, plus Axoloti's own MIDI DIN ports, totally 18.)
Hey guys I tried to build a sysex object with @MattilynMattroe's launchpad object (thx matt ). Somehow no sysex was arriving.
BUT I managed to send sysex via the din output with this line of code suggested by johannes
Thanks for that Smyth, will investigate, what are you trying to send sysex to?
I am sending it down the host port thru a Novation Remote SL and then on to din, sometimes the remote sl can be finnicky about start up sequence, so it has to be on & connected to a power source before connecting to the host port or it won't work, just a thought, also the sysex string is in decimal so you will have to convert your hex string,
eg alpha juno filter cutoff of (midi channel 4) is;
F0 41 36 03 23 20 01 10 i F7 (where i is the data being changed)
and in the object the sysex string appears as 240,65,54,3,35,32,1,16,i,247
I'm sending sysex to my voice live touch. I'm using it to acces hidden parameters that can niether changed in the units ui nor through midi cc.
For the object hex or decimal doesn't really matter:
My strings are slightly more complicated because the Vlt uses 28bit values that are packed into four bytes and can be positive and negative.
I'm quite happy about this atm because my usb host ports are blocked by midi controllers anyway. But in the future I plan on changing my setup and using a midi interface to controll more of my hardware.
this looks awesome, was thinking about how to send more complex strings, I know you've basically just given me the guts but is there any chance you could upload your object so I can have a look at the rest?
Sure, this is a patch with the object:
vlt touch sysex works.axp (2.1 KB)
If you wanna find out how it works with your hardware you need to find out all the specific bytes and how they package their data etc. (thats why they call it system exclusive, there is no standart for it)
With the voice live touch it was all documented in the sysex manual.
superb, thanks very much, I'm cool with sysex implementation, but not so cool with coding, there's an old Akai S3000xl over there taunting me, saying I can't realtime mess with it's loop points
wow, what good news! saves me a bit of money, and what's more important, simplifies my commutation scheme
sending lots of SysEx via DIN is bad idea in any case, because MIDI DIN ports still work at 31250 baud, and SysEx messages are byte hogs.
so, to avoid many kinds of problems, some king of thinning has to be applied before actually sending them.
here's a quote from Gearslutz that explains it very well:
Another more thorough answer to this in case it's not already fully covered. (I wrote this out mostly for my own understanding of why this is necessary, so please do correct me on any of this that I got wrong.)
- MIDI runs at 31250 baud. That's 31250 bits every second
- To transmit each byte, actually takes 10 bits: 1 start bit, 8 data bits, and 1 stop bit. So that's 3125 bytes transmitted every second
- A "note on" message takes 3 bytes (noteon+channel, key, velocity), so that's 1042 note ons messages per second. Alternatively every note on message takes around 1 millisecond.
- A chord on a poly device might have up to for instance 16 note ons. A drum machine might have e.g. 8 voices. Add a few monos for good luck and you're in the realm of events that happen at the "same time" from a conceptual perspective are now around 30 milliseconds different in time.
- Also consider that we require a 3 byte "note off" message, regular clock messages, 3 byte CC messages, multi byte Sysex messages etc. all to take up the same time slices that we want to send note on info within.
- Now consider a bass note that might be as low as 30 Hz for sake of argument (i.e a period of 30 milliseconds). Imagine that you are trying to place two competing notes in a similar frequency band (perhaps these are actually a bass note and a kick drum). Place two 30Hz sine waves 15 ms apart and they cancel out. Place them 30 milliseconds apart and they play double as loud. You can see how being constrained about where note placement happens based on other messages on the same physical channel hurts things musically and sonically.
- The easiest way to get around the situation where playing notes for things that conflict like this at more exacting times is to add more physical channels.
- Note: This is one example, another similar example is to just consider the emotive feel to drums / piano. We notice small 10s of milliseconds changes in these values.
- Also consider the values that you might enter using percentage based swing. A 51% swing value at 120BPM shifts the delayed note just 10milliseconds (50% swing: notes at 0ms and 500ms, 51% swing: notes at 0ms and 510ms).
So how many physical channels is enough? The answer to this likely depends on how deep your GAS budget is and how much you face the above problems.
I'm also super happy, been wanting this for like months
Allright thanks for pointing that out!
For now I only want to controll like 2 parameters in real time, but my voice live gets it's midi via a dsi tetra that is also receiving midi notes. So i have to see how that works.
The Ideal solution for me would be usb support and then having one midi stream for each device.
Should we move this discussion maybe? I feel a bit we are cluttering up Mattroe's thread.
That's this thread https://sebiik.github.io/community.axoloti.com.backup/t/solved-sysex-questions-and-answers/5089/18 for those that come after. Apologies Matt for plotting in your playground
Hi Mat,
I'm curious to try your midi looper, however I get some errors when I want to compile your help patch:
Start compiling patch
Compiling patch... with /Applications/Axoloti.app/Contents/Java/firmware
BDIR = /Users/simonschmidt/Documents/axoloti/build
FIRMWARE = .
RM
APP
! /Users/simonschmidt/Documents/axoloti/build/xpatch.h.gch
. /Applications/Axoloti.app/Contents/Java/firmware/../chibios/ext/fatfs/src/ff.h
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp: In member function 'void rootc::instanceclock__2::dsp(bool, bool, int32_t, bool&, bool&, bool&, int, int, int, int)':
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp:1128:24: warning: integer overflow in expression [-Woverflow]
_posfrac &= (1<<31)-1;
^
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp: In member function 'void rootc::instancesave__1::dsp(const char*, bool)':
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp:1197:34: error: 'class rootc' has no member named 'instancemidiloopc_i'
int rem_sz = sizeof(parent->instancemidiloopc_i.array)parent->instancemidiloopc_i.LENGTH;
^
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp:1197:69: error: 'class rootc' has no member named 'instancemidiloopc_i'
int rem_sz = sizeof(parent->instancemidiloopc_i.array)parent->instancemidiloopc_i.LENGTH;
^
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp:1201:48: error: 'class rootc' has no member named 'instancemidiloopc_i'
memcpy((char *)fbuff,(char *)(&parent->instancemidiloopc_i.array[0]) + offset, sizeof(fbuff));
^
/Users/simonschmidt/Documents/axoloti/build/xpatch.cpp:1206:48: error: 'class rootc' has no member named 'instancemidiloopc_i'
memcpy((char *)fbuff,(char *)(&parent->instancemidiloopc_i.array[0]) + offset, rem_sz);
^
make: *** [/Users/simonschmidt/Documents/axoloti/build/xpatch.bin] Error 1
shell task failed, exit value: 2
Compiling patch failed ( /Users/simonschmidt/Dropbox/Axolonatics/Simons Patches/experimental/midi looper help.axh )
Any Ideas?
EDIT: Found it. There is a typo in the table/save object. There is a c after midiloop that doesnt belong there
Whoops!
I've actually almost finished an entirely new midi Looper object which is simpler to set up, and better generally.
I'll post it as soon as I've had a chance to make a help patch
Ah very interesting! I've been struggling a bit to set this one up with an internal synth somehow...it seems i got midi feedback. The first played note turns into a crazy synth drone and the patcher crashes.
MIDI LOOPER PRO!
So, I haven't quite finished it yet, but it's pretty stable. Needs some tidying/optimizing and stuff. I haven't uploaded to the library yet, but here's an embedded patch-
midi looper PRO upload.axp (104.9 KB)
If you find any bugs/have suggestions, let me know!
It doesn't use a poly subpatch, which means the object is quite 'big' inside. I'm going to make some stripped back versions with less voices.
It's currently set up to record 9 voices at once and play back 15.
The patch is set to record up to 7 slots, and each slot can be 8 bars. You can vary this on the object settings.
Control is set up like Ableton's clip slots-
trigger an empty slot to start recording, trigger again to play back. If recording and it reaches the maximum bar length, it starts playing.
Trigger a full slot to play it, if playing it will restart.
Most controls are quantized to the bar (trigger, and it starts recording at the next bar).
It uses a few objects, one for sync to midi clock, one to record/play back notes, one to record/play pitch bend, cc and mono touch. Another that record/plays poly touch. Did them as separate objects so you can get rid of what you don't need.
It records at 128ppq, and can quantize to 1/4, 1/8, 1/16 and 1/32. Note lengths are preserved while quantizing.
It works fine with internal synths, as far as I've found!
Any suggestions, etc, let me know
Midi looper internal route problem