Lua beginner problems

Hi!

I want to add a controller for choosing the MIDI channel for a device. But I fail much earlier: How can I create multiple devices for one preset? I manage to create one device with one MIDI channel - more is not possible - at least I can’t find a way. Got it, just 5 minutes after writing…

But even if I have only this one device: how do I find out the ID from the device name to change the MIDI channel?

My previous test was a failure… probably there are a lot of errors and it’s much easier than that:

print ("Hello World!!!")

function idByName (name)
    local id
    
    for id = 1,32 do
        local device = devices.get (id)
        if(device) then
            if (device:getName (id) == name) then
                return id
            end
        end
    end
    return 0
end

print (idByName("Test2"))

Has anyone a hint what I am doing wrong?

TIA, Holger

1 Like

Well it looks like you want to make controls on your preset that are solely expressed in synth names, but you want to avoid that the mapping between device ID and the synth names are to be managed on two places.

Why not the other way round, and express code and controls mainly in the device ID’s ( these are at least fixed from 1…32) and then use getName to find its name?

1 Like

Ok, this seems to be the way.

Is the assignment of device-id to MIDI channel unique? Can I assume that device ID 1 corresponds to port 1/MIDI channel 1 and device ID 18 to port 2/MIDI channel 2?

But why does this not work (I created two Devices: Test1 on port1/channel1 and Test2 on port1/channel2):

print ("Hello World!!!")
local d=devices.get(1)
print(d.getName())

This throws an error for devices.get():

10:44:15.749 ---- START ----
10:44:15.761 lua: Hello World!!!
10:44:15.772 loadLuaModule: error loading file: filename=ctrlv2/slots/p001.lua, error=ctrlv2/slots/p001.lua:17: failed: device 1 does not exist
10:44:15.777

There are two important things to mention:

devices.get(1) returns an object. Therefore the getName() must be called using the object:method notation. print(d:getName())

Also, a device is added to the preset model when it has at least one control assigned. It might be that you do not have any controls in your preset, therefore the devices.get(1) does not return any instance of device. This is to save resources on E1 side. I guess it should be mentioned in the docs.

2 Likes

The relationship between device-ID 's and MIDI channels is not fixed. That is useful, for instance when you make a preset for a bitimbral or a multitimbral synth: you then can reuse the same controls for another timbre, just by changing the MIDI channel of the device.

Let’s take the A-station preset as an example . I’ve assigned all the controls to the first device in the list (the one with ID=1), and then renamed that device to “A-station” and assigned it MIDI channel 11.

When you click here, it’ll bring you to all 32 devices:

image

Unfortunately the devices here are ranked according to MIDI channel, which I think is better not to do that way and just keep the device with ID=1 on the first place. Bear that in mind.

If someone with an A-station wants to use this preset as well, all he needs to do is change the MIDI channel of “A-station” device in the one he uses.

In the lua code, I assume no one will change the ID’s of the devices, but they are allowed to change the name of the device and the channel.

Therefor, a typical lua code starts with verifying the main characteristics of the device that is being used:

deviceId = 1 -- the preset is build with all controls for device 1
device = devices.get(deviceId)
devPort = device:getPort()
channel = device:getChannel()
2 Likes

Sure… too much C++ programmed the last years :slight_smile:

Ahhh - got it!!! That was my mistake!I used a complete empty preset as default - only th two devices.

Thanks!

2 Likes

Ok, thanks @NewIgnis for the great explanation with the pictures. I think I have understood it. Unfortunately this doesn’t solve my problem, because I could only change the MIDI channel using the web app.

I am trying to build a preset for my Zynthian and keep it as flexible as possible. With the Zynthian I can put many different software synths (LV2 instances) on different MIDI channels and save them as a snapshot. I use different snapshots on which the software synth ZynAddSubFX (e.g.) is sometimes on MIDI channel 2 and sometimes on 7 and 8.

So I could build a suitable preset for each snapshot - but it would be much more flexible for me to have a generic preset, where I can select the MIDI channel for the ZynAddSubFx by a E1 controller and then read in the current parameters. This would then work without an external computer (what is necessary for me). Do you think this is possible?

It is certainly possible. I don’t know anything about Zynthian (I’m more a hardware person). What are the possibilities for Zynthian to read out current parameters ? Does it send all of its parameters in CC or NRPN in one go? Does it use SysEx and performs edit buffer sound dumps?

1 Like

It depends on which software synth you use. This is a different problem for me for now. Zynthian is a standalone Synth based on a Raspberry Pi (4) running a meanwhile quite mature and flexible interface. With this you can start all possible software synths (LV2 based) or samplers and use it multitimbral.

I ported Dexed for Zynthian to LV2 back then and it could be prompted for parameter output using SYSEX. Other synths react differently or may not have such a thing implemented at all…

For me there is also the other way: One preset via Zynthian snapshot. The preparation is more complex and you are not flexible enough without a computer, but you could also just learn the MIDI-CCs of the E1 controllers into the Zynthian… this is easier, but with more “stupid” mapping. I think this is what I will tackle first. Then I can see how complex I want to make it…

The way i try to handle it is with a user setup/configuration screen.

I try to determine what I need when the preset starts up and if I can’t, I jump the user to a config page where they have to choose things like the port, MIDI channel, and in my particular case, which OS version is in the device.

If the units are all connected and powered up in the right sequence I can usually query the device to find it out automatically, but all of that isnt guaranteed and I don’t want to force them to always have the computer and web UI running

Do you have a hint where I can take a look at this code or can you send me some code where I can try to learn from?

If you can wait until later today, I can put together a quick subset of what I have.
Basic idea - create a momentary button, label it config.
Create a function (I call it jumpPage) and add it to the button. You can do this without the button if the user is willing to use the soft button in the bottom right, plus select a page.

On the config page, create the controls you need like MIDI channel, port, etc.
When the user selects that value, save it as a global.

in the LUA code, I typically define my globals like that with some default value so that if the user just tries to use the preset, it may do something, but the config page is where it can be changed.

This all reads harder than it is to do. For now, think about what kinds of controls/prompts you’ll need to interact with the user.

1 Like

That would be fantastic. No hurry! Many thanks!!!

Currently I would be very happy if I could change the MIDI channel of a synth via a control element. I program a lot of C/C++ and bash. I understand Lua, but I haven’t got into the depths of the E.1 Lua API yet. Unfortunately, I have found very little information about the use of the Devices. I would try to collect my findings and then make them available as a demo preset.

Take a look through this example. Config example

Basic use - press the Get Dev Info button to populate the data.
Press the Config button to jump to the config page.

Mess around with the port, channel, and rate.
Go back to the main page and press the Get Dev info button again.

You can use the CC control to send Volume data to the selected MIDI channel and port.

Look through the functions, ask questions.

I was using virtual controls so they would not send out MIDI, but I was storing/using the parameterMap.
The volume control sends CCs.

1 Like

The device stuff is interesting. I tried using a control to scan through all the devices, but if you don’t have anything, it comes back undefined. Not really sure how you can identify the device ID on startup other than by trying to get the name or something from each one and ignoring the errors or something.

This is a rabbit hole I’m not sure you should jump into :joy:
If you still do after that warning, check what @kris is doing in knobkraft wrt device identification (tldr all synths behave differently)

Many thanks @oldgearguy! I will take a look at this at evening (now have to do something for getting beer into the fridge).

Regards, Holger

Sometimes I open a beer to celebrate some success with a preset and sometimes I open many beers to dull the pain of figuring out why nothing is working. lol

3 Likes

I stopped doing this when I moved to a place close to Dutch/Belgian border. Celebrating the success with one Belgian beer ruins productivity for whole rest of the day :slight_smile:

5 Likes

After three Duvels it gets better again :smiley:

2 Likes