Page 1 of 1

MIDI Instrument Map and Rosegarden

Posted: Mon Feb 25, 2008 12:03 am
by dahnielson
There's a chance that this is completely useless to anyone else than me. But here it is anyway.

I'm currently using Rosegarden as my MIDI sequencer and an extensive MIDI instrument map to load instruments without using any of the GUIs. To make it happen I first created the instrument map using Fantasia, having already put together an instrument database made it a breeze to sort through and adding the wanted instruments to the map.

If you build large maps you will soon realize that there seems to be some complexity issues relating to the communication between Fantasia and LinuxSampler when adding an instrument take longer and longer time (it seems like Fantasia update after each adding by receiving and rebuilding the whole map). [Update: This is no longer true and have been fixed in both Fantasia and LinuxSampler.] So I prefer to build it in chunks, separating the banks into separate maps and then merge them by hand in a text editor after exporting them. And if you realize you need to reorder banks and programs then doing it manually is currently the only option.

After creating the map with LinuxSampler and tidying it up a bit in a text editor I use the following pyton script,, to create a corresponding RGD file (a Rosegarden Device file) that can be imported into Rosegarden:

Code: Select all


import sys, gzip, re

pattern = re.compile(r"MAP[\s]*MIDI_INSTRUMENT[\s]*([\d]+)[\s]*([\d]+)[\s]*([\d]+)[\s]*([\w]+)[\s]*'([\S]+)'[\s]*([\d]+)[\s]*([\d]+.[\d]+)[\s]*([\w]+)[\s]*'(.+)'[\s]*$")

preamble = '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rosegarden-data>
  <studio thrufilter="0" recordfilter="0">
    <device id="0" name="LinuxSampler" type="midi">
      <librarian name="Anders Dahnielson" email=""/>

postamble = '''
rgd = open('%s.rgd' % (sys.argv[1]), 'w')
out = gzip.GzipFile(mode='w', filename = "audio/x-rosegarden-device", fileobj=rgd)
out.filename = "audio/x-rosegarden-device"

total_programs = 0
current_bank = -1
lscp = open(sys.argv[1], 'r')
for line in lscp:
    line = line.strip()
    tokens = line.split(' ')
    if tokens[0] == '#' and tokens[1] and len(tokens) == 2:
        bank_name = tokens[1]
    elif tokens[0] == 'MAP' and tokens[1] == 'MIDI_INSTRUMENT':
        total_programs += 1
        m = pattern.match(line)
        bank, program, name = int(, int(,"\'", "'")
        if bank != current_bank:
            if current_bank != -1:
                out.write('      </bank>\n\n')
            current_bank = int(bank)
            out.write('      <bank name="%s" msb="%d" lsb="%d">\n' % (bank_name, 0, bank))
        out.write('        <program id="%d" name="%s"/>\n' % (program, name))
out.write('      </bank>\n')

print "%d programs in %d banks" % (total_programs, current_bank+1)
The script takes an LSCP file that looks something like the following excerpt of the piano bank. (I only use comments to name the banks.)

Code: Select all

# PI
MAP MIDI_INSTRUMENT 0 27 0 GIG '/home/anders/Studio/instruments/gig/Mats\x20Helgesson/maestro_concert_grand_v2.gig' 0 1.0 ON_DEMAND 'Maestro Concert Grand'
MAP MIDI_INSTRUMENT 0 27 1 GIG '/home/anders/Studio/instruments/gig/Mats\x20Helgesson/maestro_concert_grand_v2.gig' 1 1.0 ON_DEMAND 'MCG Sustains + Releases'
MAP MIDI_INSTRUMENT 0 27 2 GIG '/home/anders/Studio/instruments/gig/G-Town/G-Town_Church_Piano_Staccs.gig' 0 1.0 ON_DEMAND 'Piano Staccs'
MAP MIDI_INSTRUMENT 0 27 3 GIG '/home/anders/Studio/instruments/gig/G-Town/G-Town_Church_Piano_FX.gig' 0 1.0 ON_DEMAND 'Prepared Piano Effects'
MAP MIDI_INSTRUMENT 0 27 4 GIG '/home/anders/Studio/instruments/gig/Westgate/Demo/Westgate\x20Piano\x20FX.gig' 0 1.0 ON_DEMAND 'Piano FX'
MAP MIDI_INSTRUMENT 0 27 5 GIG '/home/anders/Studio/instruments/gig/SAM/Demo/SAM\x20Ambient\x20Bass\x20Piano\x20+\x20Tbn.gig' 0 1.0 ON_DEMAND 'SAM Amb Bass Piano'
MAP MIDI_INSTRUMENT 0 27 6 GIG '/home/anders/Studio/instruments/gig/SAM/Demo/SAM\x20Ambient\x20Bass\x20Piano\x20+\x20Tbn.gig' 1 1.0 ON_DEMAND 'SAM Amb Bass Piano (-8)'
MAP MIDI_INSTRUMENT 0 27 7 GIG '/home/anders/Studio/instruments/gig/SAM/Demo/SAM\x20Ambient\x20Bass\x20Piano\x20+\x20Tbn.gig' 2 1.0 ON_DEMAND 'SAM Amb Bass Piano + Tbn'
MAP MIDI_INSTRUMENT 0 27 8 GIG '/home/anders/Studio/instruments/gig/SAM/Demo/SAM\x20Ambient\x20Bass\x20Piano\x20+\x20Tbn.gig' 3 1.0 ON_DEMAND 'SAM Amb Bass Piano + Tbn (-8)'
And gets turned into something like this:

Code: Select all

      <bank name="PI" msb="0" lsb="27">
        <program id="0" name="Maestro Concert Grand"/>
        <program id="1" name="MCG Sustains + Releases"/>
        <program id="2" name="Piano Staccs"/>
        <program id="3" name="Prepared Piano Effects"/>
        <program id="4" name="Piano FX"/>
        <program id="5" name="SAM Amb Bass Piano"/>
        <program id="6" name="SAM Amb Bass Piano (-8)"/>
        <program id="7" name="SAM Amb Bass Piano + Tbn"/>
        <program id="8" name="SAM Amb Bass Piano + Tbn (-8)"/>
I added some statistics to the script and it counted 800 programs in 35 banks in my case.

Re: MIDI Instrument Map and Rosegarden

Posted: Tue Feb 26, 2008 12:35 pm
by Alex
Interesting stuff, Anders.

As an aside to this, is there any way of increasing the number of audio channels available in Rosegarden?
I get to 16 and it doesn't seem to want to go further.


Re: MIDI Instrument Map and Rosegarden

Posted: Tue Feb 26, 2008 12:50 pm
by dahnielson
Hmm, don't really know. I'm using Ardour for all audio stuff (a lot more flexible), Rosegarden is purely a sequencer to me.