Mattilyn Mattroe contributions


#15

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)
                                            ^

#16

Thanks for testing, I wonder if it's implemented differently indicated by "midi_legacy.h:18:44: error:"


#17

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.)


#18

Hey guys I tried to build a sysex object with @MattilynMattroe's launchpad object (thx matt :raised_hands:). Somehow no sysex was arriving.

BUT I managed to send sysex via the din output with this line of code suggested by johannes


#19

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


#20

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.


#21

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?


#22

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.


#23

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


#24

wow, what good news! saves me a bit of money, and what's more important, simplifies my commutation scheme :star_struck: :money_mouth_face:

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.)

  1. MIDI runs at 31250 baud. That's 31250 bits every second
  2. 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
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.
  9. 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.


#25

I'm also super happy, been wanting this for like months :blush:

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.


#26

good idea. we could use my SysEx thread for that.


#27

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


#28

No worries, good luck on the sysex hunt!


#29

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 :wink:


#30

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


#31

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.


#32

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
#33

Cool thanks for sharing! That was much easier to setup. I got it working looping and all. I was experiencing sometimes that a recorded note would sound sound like very short, although I had hold it very long.
Then I tried to just replace the fucked up note, by overdubbing it, which didn't really work either, only the extremly short note stayed.

I think the feature set looks very very good. It has almost all that I would expect from a midi looper! Making a launch style midi interface with buttons and leds on a controller could be a lot of fun.

I have some more observations:

I think a more common choice here is 96ppq and the option to quantize to 1/3, 1/6 etc. so you can do triplet grooves.

Is it really neccessary to take a 16b table? Wouldnt 8b be sufficient?


#34

Glad you got it working! Thanks for the feedback, always welcome.

The short note may be to do with the loop point, it will cut short notes that go over the loop point, I think. I may be able to fix that. Out of interest, were you quantizing? I haven't used it as much unquantized when testing recently and may have not noticed something.

Usually, if you record a note that is the same over a pre recorded note, it should overwrite the recorded note, either cutting it short or replacing it if it has the same, or a later, start point.

Re 96ppq- good point re triplets. I did it at 128 just because I was thinking in factors of 2 because it seemed seemed easier that way. But I hadn't factored in triplets, where I'll prob need a ppq divisible by three! Adding triplets was next on my to do list so I would have found the problem then... It shouldn't be hard to adjust. I might take it up to 192 instead of down to 96 in order to preserve resolution for cc/bend/touch recording. Though that would mean bigger tables for the cc/bend/touch recorders. Note recorder would be unaffected, other than resolution.

I think you need an 16b table unless I'm missing something... An 8b integer can't be larger than 256, and I need to store start/end points for the notes and they get much higher than that. A start point of 256 would only be around 2 and a half bars at 96ppq, so loops wouldn't be able to be longer than that

Thinking about it, an 8b table could be used for the cc/bend recorder as that works very differently to the note recorder and it's only storing the midi data. But then that leads to multiple tables for the Looper...

I've got the Looper working in a patch that has 3 midi loopers and an audio Looper, all controlled from a launchpad mini, Ableton style clip buttons for the Looper. It seems to be working well so far, but I haven't had a chance to play much yet. I'll probably start finding more little bugs while I'm jamming, rather than testing, as is usually the case.