Home › Forums › General › Programming › Storing received sysex dump as memoryblock then process
Tagged: memory block, midi received
- This topic has 12 replies, 4 voices, and was last updated 3 years, 8 months ago by samoht.
-
AuthorPosts
-
June 26, 2020 at 3:30 am #118900
Hi,
I worked on my panel with a hard coded midi dump message in my global “on received midi” LUA script while my DP4 was out of order. I kept a buffer dump from before the unit failure.Now that it’s repaired, I have some problem getting the midi message received by Ctrlr stored as a memoryblock.
This is the following script on “Called when the panel received a midi message”, I must have something wrong somewhere at the beginning. It used to work when using the hardcoded message I commented :
midiMessageReceived = function(midiMessage) midiMessageRawSize = midiMessageReceived:getSize() MessageType = midiMessageReceived:getByte(5) if midiMessageRawSize == 334 and MessageType == 0x25 then -- determine if the message is Edit Buffer Type hex25 with size 334bytes t={} midiMessage = MemoryBlock() -- midiMessage = MemoryBlock([[F0 0F 40 00 00 25 01 00 00 03 02 02 00 05 03 06 0F 07 05 07 02 06 03 06 05 02 00 04 03 06 0F 06 0E 06 06 06 09 06 07 02 00 00 01 02 0F 00 00 03 00 04 08 05 04 04 09 02 05 01 0B 04 0B 00 00 00 07 07 05 00 00 01 0C 01 06 00 00 05 01 00 0A 00 0D 00 01 09 04 04 0B 04 09 00 06 00 01 02 0C 07 0F 00 07 00 03 02 0F 05 0D 07 0F 07 0F 00 03 02 00 01 02 02 0D 05 01 03 02 04 0E 02 0E 01 04 00 04 00 00 02 09 09 0D 00 00 00 0C 02 0D 00 00 01 07 01 03 00 00 00 00 05 0E 0E 0D 02 00 00 06 00 01 03 0F 07 0F 00 07 00 03 02 00 00 00 07 0F 07 0F 00 00 00 00 02 0B 00 0D 02 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 07 0F 00 00 00 02 00 00 07 0F 07 0F 07 0F 02 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 07 0F 00 00 00 02 00 00 07 0F 07 0F 04 00 00 00 00 00 00 02 00 01 00 00 00 00 01 00 00 00 F7]]) for i=9, midiMessage:getSize()-2,2 do assert(i < midiMessage:getSize()) -- For debugging only msb = bit.lshift(midiMessage:getByte(i),4) lsb = midiMessage:getByte(i+1) total = msb+lsb -- console(String(string.format("[%d] = %.2X",i,total))) table.insert(t,total) end EditBufferMessage = MemoryBlock() EditBufferMessage:createFromTable(t) --console(String(EditBufferMessage:toHexString(1))) --panel:getLabel("Debug"):setText(EditBufferMessage:toHexString(1)) ActiveUnitDecode(midiMessage) BufferPstNameDecode(EditBufferMessage) BypassStatusDecode(EditBufferMessage) UAAlgoLblDecode(EditBufferMessage) UBAlgoLblDecode(EditBufferMessage) UCAlgoLblDecode(EditBufferMessage) UDAlgoLblDecode(EditBufferMessage) ConfigSrcTypeDecode(EditBufferMessage) UAAlgoDecode(EditBufferMessage) UBAlgoDecode(EditBufferMessage) UCAlgoDecode(EditBufferMessage) UDAlgoDecode(EditBufferMessage) panel:getModulatorByName("ViButComEdit"):getComponent():setValue(1, true) end end
When I send a request to the Unit, I get the following error:
At line 8 : string “midiMessageReceived
Error message : string “midiMessageReceived”:8: attempt to index global ‘midiMessageReceived (a function value)I want to store midiMessage (the received dump) as the MemoryBlock to be able after that to process all the different function from it.
EDIT: I edited my post and it disapeared and there’s no way to bring it back to life. This Edit bug on the forum is horrible…
Thanks a lot for your help
Damien
June 26, 2020 at 4:35 am #118901Hi Damien,
I feel your pain with regards to the edit three times and strike you’re out. If that happens hit the back button on your browser, cut and paste and wait a few hours to re-post. Not familiar with WordPress, but the admins surely could fix that somehow?
The problem with the code above is you are doing a getSize() on the function name. Also you declare a midiMessage=MemoryBlock() – that would zero out the midiMessage passed into the function.
I would initialise total outside the loop just to be safe and also I recommend keeping everything local if possible.
midiMessageReceived = function(midiMessage) local midiMessageRawSize = midiMessage:getSize() local MessageType = midiMessage:getData():getByte(5) if midiMessageRawSize == 334 and MessageType == 0x25 then -- determine if the message is Edit Buffer Type hex25 with size 334bytes local t,total={},0 --local newMidiMessage = MemoryBlock() don't need this for i=9,midiMessageRawSize-2,2 do --assert(i < midiMessage:getSize()) -- For debugging only local msb = bit.lshift(midiMessage:getData():getByte(i),4) local lsb = midiMessage:getData():getByte(i+1) total = msb+lsb -- console(String(string.format("[%d] = %.2X",i,total))) table.insert(t,total) end EditBufferMessage = MemoryBlock() EditBufferMessage:createFromTable(t) --console(String(EditBufferMessage:toHexString(1))) --panel:getLabel("Debug"):setText(EditBufferMessage:toHexString(1)) ActiveUnitDecode(midiMessage) BufferPstNameDecode(EditBufferMessage) BypassStatusDecode(EditBufferMessage) UAAlgoLblDecode(EditBufferMessage) UBAlgoLblDecode(EditBufferMessage) UCAlgoLblDecode(EditBufferMessage) UDAlgoLblDecode(EditBufferMessage) ConfigSrcTypeDecode(EditBufferMessage) UAAlgoDecode(EditBufferMessage) UBAlgoDecode(EditBufferMessage) UCAlgoDecode(EditBufferMessage) UDAlgoDecode(EditBufferMessage) panel:getModulatorByName("ViButComEdit"):getComponent():setValue(1, true) end end
June 26, 2020 at 5:53 am #118903thanks dnldoog,
I’m back for the last stretch in this project.
I tried what you suggested but get an error :Error message: [string “midiMessageReceived”]:19: attempt to call method ‘getByte’ (a nil value)
My sysex request is going to the unit properly:
To MIDI output port 0 SysEx Ensoniq 7 bytes F0 0F 40 00 00 15 F7And the message is sent back to ctrlr properly :
From MIDI input port 0 SysEx Ensoniq 334 bytes F0 0F 40 00 00 25 02 00 00 03 04 02 00 05 03 07 02 06 03 03 0A 03 04 02 00 04 0D 06 0F 06 0E 06…So it’s probably just a syntax error but cannot find out what’s wrong with it.
I did a simple request to display the string in the console and get an error for nil value as well:
midiMessageReceived = function(midiMessage) local midiMessageRawSize = midiMessage:getSize() if midiMessageRawSize == 334 then console(String(midiMessage:toHexString(1))) end end
It’s probably coming from the very top of the script.
Any idea about what’s wrong with it? the stripped down version should give at least the sysex message in the console?
Thanks a lot!
June 26, 2020 at 7:47 am #118904Ah! realised with midiMessage you need:
midiMessage:getData():getByte(i)
added getData() to my first reply
- This reply was modified 3 years, 8 months ago by dnaldoog.
June 26, 2020 at 8:58 am #118907Error message: [string “midiMessageReceived”]:19: attempt to call method ‘getByte’ (a nil value)
It’s probably coming from the very top of the script.
The error message tells you that the error is on line 19. Unfortunately, error messages are no always that clear.
June 26, 2020 at 9:08 am #118908Well I don’t know what’s happening, it’s more like if the ctrl don’t receive the sysex message.
Tomorrow I’ll try a simple button that send the dump request message.Then display the message received by ctrlr in the console.
something like :midiMessageReceived = function(midiMessage) console(String(midiMessage:toHexString(1))) end
It should display the sysex message received in the console isn’t it?
June 26, 2020 at 9:53 am #118909Hi Damien,
That should be:
midiMessageReceived = function(midiMessage) console(String(midiMessage:getData():toHexString(1))) end
I’m surprised adding the additional getData() method didn’t fix the problem on line 19:
Error message: [string “midiMessageReceived”]:19: attempt to call method ‘getByte’ (a nil value)
Incidentally you can do midiMessage:getSize() just as in a normal MemoryBlock, but to access data on an incoming MIDI message, you need getData()
June 26, 2020 at 12:14 pm #118910Hi Damien, Dnaldoog, Possemo: this is working for me;
midiMessageReceived = function(midi)� local s = midi:getSize() local Id1 = midi:getLuaData():getByte(5) local Id2 = midi:getLuaData():getByte(6) � if s == 60 then if Id1 == 0x10 then if Id2 == 0x10 then t1Nibbles = midi:getData():getRange(8, 24) --clear() elseif Id2 == 0x11 then t21Nibbles = midi:getData():getRange(8, 24) --clear() elseif Id2 == 0x12 then t3Nibbles = midi:getData():getRange(8, 24) --clear() elseif Id2 == 0x13 then t41Nibbles = midi:getData():getRange(8, 24) --clear() elseif Id2 == 0x14 then t51Nibbles = midi:getData():getRange(8, 24) --clear() elseif Id2 == 0x15 then t61Nibbles = midi:getData():getRange(8, 24) --clear() end end end� end --f
- This reply was modified 3 years, 8 months ago by samoht.
June 26, 2020 at 12:56 pm #118912I am new to Lua as well as Ctrlr and Juce. One thing has become clear to me though: you have to find a way, starting in Lua, through Ctrlr and Juce, always in full respect for midi bytes and nibbles and for the quirks of each platform (f.i. a lua “string” apparently is not identical to a Juce “string” and so on) and always paying attention that the roads do not to often end up in “memory full” loops, or worst crashes 🙂
- This reply was modified 3 years, 8 months ago by samoht.
June 26, 2020 at 9:20 pm #118914And…
it’s….
WORKING!!!!
midiMessage:getData():getByte(i) was a keypoint but error still occured.
I messed with the script and removed the “local” tag and it worked.So everything is dumped from the unit to ctrlr every parameter are updated.
I have to think about a way to add a timer between sent messages because the unit is cluttered rapidly.
Everytime a message is received, processed and complete the unit send an acknowledge “error” message telling the unit is ready for operation again.Message received is (my commented console report) :
LUA>> Displays the RAW Received Midi Message LUA>> f0 0f 40 00 00 02 00 f7 LUA>> Displays the Received Midi Message Type in decimal LUA>> 2 LUA>> Displays the MessageErrorCode in decimal LUA>> 0 LUA>> 0 Meaning TX over - Ackowledge (ACK) - No Error
So I’ll think about a way to wait the ACK message for sending new message to avoid cluttering the input of the DP4.
Thanks a lot for all your help! I deeply appreciate the support.
DamienJune 27, 2020 at 12:11 am #118915Hi Damien,
Great that it’s working.
So if you need to send an ACK message, but need a delay, just before you send the message try:
os.execute(sleep(125))
125=Milliseconds for example.
Or an example of timer code in this post (with example panel)
ctrlr.org/forums/topic/midi-out-led/#post-118738
June 27, 2020 at 3:28 am #118916For the delay time between messages I went with a setting in the “general” preference pane called:
Global delay for midi message [ms]It’s working great.
I was talking about waiting the message “ready” FROM the Ensoniq.
Everytime the unit is ready for a new task it sends a sysex message “I’m ready”:
f0 0f 40 00 00 02 00 f7It’s very useful because sometime it’s still in process so considering this type of flag is a nice tool to avoid errors.
Thanks!
June 27, 2020 at 12:35 pm #118929Damien wrote:
I messed with the script and removed the “local” tag and it worked.
Dnaldoog wrote:
I recommend keeping everything local if possible.
Sometimes variables need to be global. But this should always be used with caution since they easily cause subtle bugs!
-
AuthorPosts
- The forum ‘Programming’ is closed to new topics and replies.