New Tool (2.8): Guru

Well at the moment we can’t do much because the 3n channel issue. I tried to hack something together but I don’t know lua at all. Going to learn a little I guess :)

Was having issues where it couldn’t cast a string or something in the if clause.

Are any of these tools hosted on github? Might be cool.

How do you like the Radias? I came very close to getting that one instead of the MS-2000.

I like it a lot, I own it for a second time now. I sold it, missed it, bought it again.
It’s basically the MS2000 but with more virtual patches and 2 filters instead of one some more effects…
the drum sounds I rarely use but the big plus is the polyphony of 24 instead of 4.
The sounds are for most part identical but the DWGS sounds are somewhat different as far as I can tell.

Hi,

I’m putting together a Guru file for the Yamaha AN1X. Everything is in SysEx, no RNPN, so sometimes I’ve got to send a max value fixed at 255 and not 127. The synth seems to awaits a SysEx string with two “nn” instead of one, for the upper and lower bytes wich “glued” gives an higher value. I don’t know how to work this out, maybe someone could help me ?

Thank you !

Mutable Instruments Anushri drums controller.

(midi channel has to be set on 10)

Similar issue here, there is a signed and unsigned vv and pp in the MS2000 midi spec:

  
 NOTE 7: MIDI Parameter Change Message Format  
 F0,42,3n,58,41,pp,PP,vv,VV,F7  
 n :Global MIDI Ch.  
 58 :MS2000 ID  
  
 parameter No. :PPpp = 0~3FFF  
 parameter value :VVvv = signed value  
  
 VV(PP):0MMMMMMM vv(pp):0LLLLLLL value(No.):MMMMMM MLLLLLLL  
  

Holy crap, there’s a lot of people using, or trying to use, Guru. Which is nice, unfortunately I’m busy doing other stuff.

Sorry I am not able to look at all your problems and midi needs, you need to provide me with more specific explanations of what needs to be done. Excerpts from the manuals and so, in a PM.

Also the code is there to modify, it’s not hard.

Later
CB

:(
maybe danoise can integrate guru into duplex somehow?
without data retrieving from synth this tool is pretty half-baked

Hi,

I found a solution to send SysEx value superior to 127. Here is my code :

  
value_callback = function(parameter)  
 local synth_definition = parameter.synth_definition  
 local msb = math.floor(parameter:value() / 127)  
 if parameter:value() < 128  
 then parameter.number = 0  
 return parameter:value()  
 else parameter.number = msb  
 return parameter:value() - ( msb * 127 )  
 end  
end  
  

The SysEx needs to be set in the Parameter, as I use the number to send to upper byte :

Parameter {  
sysex_message_template = {0xF0,0x43,0x10,0x5C,0x10,0x10,0x0D,"nn","vv",0xF7};  
...  

Of course the template depends on your hardware, nn is for the MS, vv the LS.

I hope it will work for, and be adaptable to, other devices ! Works for me, I’ll upload the AN1X map soon.

Thanks for your code! I’ll give it a shot in the MS2K one I’m working on.

I refactored the code to support 3n and the Korg MS-2000 SysEx formats for LSB/MSB:

This adds 3n, PP , and VV support which send the MSB, LSB.

Here is the MS-2000 sysex_template:
sysex_message_template = { 0xF0, 0x42, 0x30, 0x58, 0x4E, 0x01, 0x00, 0xF7, 0xF0, 0x42, “3n”, 0x58, 0x41, “PP”, “VV”, 0xF7 },

Note that the first message: 0xF0, 0x42, 0x30, 0x58, 0x4E, 0x01, 0x00, 0xF7 enables EDIT mode in the MS-2000 it doesn’t seem to work without sending this message first.

class_midi.lua:

  
 function Midi:send_sysex(message_template, number, value)  
 if value == nil then return end  
 local message = {}  
 for k,v in pairs(message_template) do  
 if v == "cc" then  
 table.insert(message, self.midi_channel-1)  
 elseif v == "3n" then  
 local midich = 0x30 + (self.midi_channel-1)  
 table.insert(message, midich)  
 elseif v == "PP" then  
 local ms_nibble = math.floor(number/128)  
 number = number - (ms_nibble*128)  
 table.insert(message, number)  
 table.insert(message, ms_nibble)  
 elseif v == "nn" then  
 table.insert(message, number)  
 elseif v == "vv" then  
 if (value > 127) then  
 local ms_nibble = math.floor(value/128)  
 value = value - (ms_nibble*128)  
 table.insert(message, ms_nibble)  
 table.insert(message, value)  
 else  
 table.insert(message, value)  
 end  
 elseif v == "VV" then  
 local ms_nibble = math.floor(value/128)  
 value = value - (ms_nibble*128)  
 table.insert(message, value)  
 table.insert(message, ms_nibble)  
 else  
 table.insert(message, v)  
 end  
 end  
 local debug_message = ""  
 for k, v in pairs(message) do   
 debug_message = debug_message .. string.format("%02X", v) .. " "  
 end   
 print(debug_message)  
 self:send(message)  
 end  
  

The korg uses 0x3n where n = midi channel
Also the VV and PP values are reversed MSB comes first, then LSB.

Here is an example for toggling the arp:

  
local group_arp = Group {  
 name = "Arpeggio",  
 Parameter {  
 id = "arp_toggle",  
 name = "Arpeggio",  
 type = "sysex",  
 default_value = 1,  
 number = "27",  
 items = {  
 "OFF", "ON"  
 },  
 item_values = {  
 0, 1  
 }  
 }  
}  

From the Korg MS-2000 specs I posted, Table 8 is the one to use and 27 == 0x1B.

Therefore now we can implement the full spec :)

Hope this helps someone!

Hi,

So here is the Yamaha AN1X map I was working on. Two things :

  • When you select “Sc Ctrl” in the Common Section, the Scene 2 and its matrix values will be updated when you change values of the Scene 1 and its matrix.
  • I didn’t code the changing of min and max value depending on the FX you pick, it’s boring and kind of useless ^^ The synth will discard the values that do not fit.

I also didn’t put the control of the CC of the hardware controlers (ribbon and knobs), if someone wants it I will.

I hope someone will use it, is there anyone here with a Yam AN1X ?

I completed the full implementation (minus the Vocoder for now - I don’t use it myself) of my Korg MS-2000 at last! :)/>

Download it here. (this includes the modifications below)

I modified file class_parameter.lua line 277 to read:

  
if (self.items ~= nil and self.gui_type ~= "slider") then  
  

The above modification allows us to explicitly set ```
gui_type = “slider”

  
Also as I mentioned I modified file class_midi.lua (entire send_sysex method) to read:  

function Midi:send_sysex(message_template, number, value)
if value == nil then return end
local message = {}
for k,v in pairs(message_template) do
if v == “cc” then
table.insert(message, self.midi_channel-1)
elseif v == “3n” then
local midich = 0x30 + (self.midi_channel-1)
table.insert(message, midich)
elseif v == “PP” then
local ms_nibble = math.floor(number/128)
number = number - (ms_nibble128)
table.insert(message, number)
table.insert(message, ms_nibble)
elseif v == “nn” then
table.insert(message, number)
elseif v == “vv” then
if (value > 127) then
local ms_nibble = math.floor(value/128)
value = value - (ms_nibble
128)
table.insert(message, ms_nibble)
table.insert(message, value)
else
table.insert(message, value)
end
elseif v == “VV” then
local ms_nibble = math.floor(value/128)
value = value - (ms_nibble*128)
table.insert(message, value)
table.insert(message, ms_nibble)
else
table.insert(message, v)
end
end
local debug_message = “”
for k, v in pairs(message) do
debug_message = debug_message … string.format("%02X", v) … " "
end
print(debug_message)
self:send(message)
end

  
This refactored code is to support 3n MIDI channel requirements of the Korg MS-2000 SysEx formats, and also for little endian LSB/MSB:  
  
This patch adds new sysex_template variables ```  
"3n", "PP", and "VV"  
``` (case is important!) which send the MSB, LSB in reverse order for the MS-2000.  
  
Also, in my synth definitions sysex_template, I prefix a EDIT MODE sysex switch:  

sysex_message_template = { 0xF0, 0x42, 0x30, 0x58, 0x4E, 0x01, 0x00, 0xF7, 0xF0, 0x42, “3n”, 0x58, 0x41, “PP”, “VV”, 0xF7 }

  
The first message: 0xF0, 0x42, 0x30, 0x58, 0x4E, 0x01, 0x00, 0xF7 throws the MS-2000 into EDIT mode (and without doing this no sysex is recognized).   
The second message: 0xF0, 0x42, "3n", 0x58, 0x41, "PP", "VV", 0xF7 uses the new template variables as described above.  
  
Last thing, I threw a function in my synth definition file h2d (which converts hexidecimal to decimal, as I had some issues inserting raw hex into the tables for some reason).  
  
Anyway, enjoy I know I will be ![:)](https://files.renoise.com/forum/emoticons/default/smile.gif)/>

If you downloaded the MS-2000 zip file from my prior post, please re-download it. I had erroneously set the default value for OSC1 CTRL1 and CTRL2 in both Timbres to 1 instead of 0. Fixed and updated.

:)

Hi guys,

I wasn’t satisfied with having the patches not named in my synth for me, and so I added a patch_save_callback into the synthdefinition, which gets called as you save a patch.

From within my synthdefinition (Korg_MS2000-gj.lua):

  
local patch_name_char_map = {  
 [" "] = 32,  
 ["!"] = 33,  
 ['"'] = 34,  
 ["#"] = 35,  
 ["$"] = 36,  
 ["%"] = 37,  
 ["&"] = 38,  
 ["'"] = 39,  
 ["("] = 40,  
 [")"] = 41,  
 ["*"] = 42,  
 ["+"] = 43,  
 [","] = 44,  
 ["-"] = 45,  
 ["."] = 46,  
 ["/"] = 47,  
 ["0"] = 48,  
 ["1"] = 49,  
 ["2"] = 50,  
 ["3"] = 51,  
 ["4"] = 52,  
 ["5"] = 53,  
 ["6"] = 54,  
 ["7"] = 55,  
 ["8"] = 56,  
 ["9"] = 57,  
 [":"] = 58,  
 [";"] = 59,  
 [" ["="] = 61,  
 [">"] = 62,  
 ["?"] = 63,  
 ["@"] = 64,  
 ["A"] = 65,  
 ["B"] = 66,  
 ["C"] = 67,  
 ["D"] = 68,  
 ["E"] = 69,  
 ["F"] = 70,  
 ["G"] = 71,  
 ["H"] = 72,  
 ["I"] = 73,  
 ["J"] = 74,  
 ["K"] = 75,  
 ["L"] = 76,  
 ["M"] = 77,  
 ["N"] = 78,  
 ["O"] = 79,  
 ["P"] = 80,  
 ["Q"] = 81,  
 ["R"] = 82,  
 ["S"] = 83,  
 ["T"] = 84,  
 ["U"] = 85,  
 ["V"] = 86,  
 ["W"] = 87,  
 ["X"] = 88,  
 ["Y"] = 89,  
 ["Z"] = 90,  
 ["["] = 91,  
 ["¥"] = 92,  
 ["]"] = 93,  
 ["^"] = 94,  
 ["_"] = 95,  
 ["`"] = 96,  
 ["a"] = 97,  
 ["b"] = 98,  
 ["c"] = 99,  
 ["d"] = 100,  
 ["e"] = 101,  
 ["f"] = 102,  
 ["g"] = 103,  
 ["h"] = 104,  
 ["i"] = 105,  
 ["j"] = 106,  
 ["k"] = 107,  
 ["l"] = 108,  
 ["m"] = 109,  
 ["n"] = 110,  
 ["o"] = 111,  
 ["p"] = 112,  
 ["q"] = 113,  
 ["r"] = 114,  
 ["s"] = 115,  
 ["t"] = 116,  
 ["u"] = 117,  
 ["v"] = 118,  
 ["w"] = 119,  
 ["x"] = 120,  
 ["y"] = 121,  
 ["z"] = 122,  
 ["{"] = 123,  
 ["|"] = 124,  
 ["}"] = 125,  
 ["»"] = 126,  
 ["«"] = 127   
}  
  
  
--Update patch name  
function update_patch_name(name)  
 print("update_patch_name(" .. name .. ")")  
 local patch_name = {}  
 for char in name:gmatch"." do  
 table.insert(patch_name, patch_name_char_map[char])  
 end  
 print("UPDATE_PATCH_NAME VALUES -----")  
 rprint(patch_name)  
 return patch_name  
end  
  
  
  
return SynthDefinition {  
 patch_save_callback = update_patch_name,  
 id = "KorgMS2000",  
 ...etc...  
  

in class_synthdefinition.lua (insert from line 13 just before self.beta = tbl.beta):

  
 if tbl.patch_save_callback ~= nil and type(tbl.patch_save_callback) == "function" then  
 print("****** SYNTH DEF HAS CALLBACK ********")  
 self.patch_save_callback = tbl.patch_save_callback  
 end  
  

in class_synthdefinition.lua (insert just after line 405 that reads if patch_name ~= nil and patch_name ~= “” then):

  
 if self.patch_save_callback ~= nil then  
 print("Patch save callback exists... running...")  
 local number = 0  
 for i,value in pairs(self.patch_save_callback(patch_name)) do  
 self.midi:send_sysex(self.sysex_message_template, number, value)  
 number = number + 1  
 end  
 end  
  

How it works is it uses the patch_name_char_map to map letters in the patch name from the save dialog as decimal values for send_sysex, then when you save, it walks through and saves them that way.

I’m not sure if this is portable to all stuff, but thought I would share. I think the map may be able to contain params and values, but I’m still learning lua. Anyway hope it helps someone.

@cornbeast: it would be really good if you had a github repo or something for Guru :)/> really loving your work my friend!

I’ve attached the file here for MS-2000 owners that are interested, and also updated the original post.

Mmmm this script might make me consider buying hardware :drummer:

Yo!

Damn, can’t find the time to be working on this. I don’t have a git but svn on google code;

http://code.google.com/p/stepbrother/source/browse/#svn%2Ftrunk%2FGuru%20xrnx%2Fcom.cornbeast.Guru.xrnx

Later
CB

Made definition for Clavia Nord Lead/Rack 2/2x.
It has one part (1 of 4) of NR2 for controling one par (A, B, C or D) with each new instance of interface (i.e. no performance mode and channel select implemented yet, only main sound control).

Also made a simple .Net app wich can read s Clavia’s Nord Lead syx files (tipical sysex fo…f7 data) and show/save them as synth parameter list (for preparing the presets manually).
Sorry, but app does not use a locale settings (I just don’t get it yet) for menu language, so menu entries - Open, Save and Exit in Russian only.
http://rghost.ru/42782705 - (it’s an .exe - can’t upload it here, so it’s just a small .Net app … but may be better “virus check” it after downloading just before execute).

I think, what at near future I’ll be able to add a .syx to .xml convertion (to a normal guru definition patch format, and after that I will convert whole NR2/2x library and some other NR2 sounds from various artists) and add a multilang support to the app.

Also have an issue then manually tweak NR2x patches - values can jump at slider type parameters.
For example - “osc2 coarse tune” or “amp attack” parameter shows 0, 1 and suddenly(!) - 3 just after 1…for amp attack it does not do any big deal, but at “osc2 coarse tune” I can’t get an octave tunning - value between 15 and 17…


new version of Patch Viewer.
http://rghost.ru/42966573
added language select option (rus|eng) and a save to xml option (xml patch used by Guru definition).

Any interest in putting this on github? Might make it easier to exchange code patches, and merge in new synth definitions.

Also, someone upthread was talking about a patch manager. I’m thinking of writing a definition file for the Korg Prophecy, but it’s rather complicated with a ton of parameters, so I’m wondering about some way to either read the current patch parameters from the synth initially (so the GUI would reflect them) in preparation for further editing. Otherwise, it seems like I would have to create a “blank” patch on the synth as a starting point.

Seems like a great idea to put it on github, I’ll try to look into that!

Cool. Github is pretty easy to set up, so I hope you can find the time. Then others who want to patch the code can simply fork your repository to start developing, then submit stuff back to you later using simple commands.

Also, I had a question about the interaction of Guru with the patches on the hardware synth. When the synth is started up, it loads some initial patch, usually the first patch from the first bank. Does Guru “synchronize” the UI by reading the parameter data from the synth somehow? Or do I put some defaults in my synth def which would then be written back to the synth, overwriting the selected patch?

EDIT: One more question about sending the data to the synth. The Korg Prophecy has several different SysEx messages it can use to load patch data. There’s a message for setting a single parameter of the current patch, and another message for loading all the parameters at once. I assume that I would use the single-parameter method in the synth def, but is there any support for whole-patch saving/loading?

Thanks.