Problem description

We would like a way to insert MIDI program changes in the middle of tracks.

This is a common feature in many sequencer programs, but it is not currently supported by RG. Also, the “import MIDI files” function can't be properly fixed now to process MIDI files having PC events in the middle of the tracks.

Proposal summary

Put program changes at the beginning of the segments. Implement this in Rosegarden associating the Instrument (which holds the bank/program numbers) to the Segment class instead of the Track. Change the MIDI file import function to create a new segment whenever it finds a bank/program change events in the middle of a track.

Discussion

On Tuesday 20 Jun 2006 21:04, Pedro Lopez-Cabanillas wrote:
> On Monday, 19 June 2006 18:32, Chris Cannam wrote:
> > Note that none of this is an issue when importing MIDI files, because
> > each distinct program gets separated out to a distinct track
>
> This isn't the current behavior of the MIDI import function, and I don't
> remember it was as you say in the past.

No, you're right. I was thinking of tracks that have channel events sent to
more than one channel, which we split out into more than one track in order
to assign each to a different instrument.

> On the other hand, I find some features related to Instruments very poor or
> even wrong. For instance: why the MIDI channel is an attribute of the
> Instrument? why the Instruments are attributes of the tracks instead of the
> segments? And as a consequence: there shouldn't be a limitation of 16
> instruments per device.

16 instruments per device is an arbitrary number that just coincidentally
happens to be the same as the number of MIDI channels. If you change the 16
at AlsaDriver.cpp line 1005 to something else, you'll get a different number.
It works just as well with 24 or 32, or 200 -- try it!

But I fear and mistrust the instrument/device handling code, and particularly
the logic that creates the instruments in the first place and tries to keep
them in sync between GUI and sequencer.

For example, look at what the .rg file loader (rosexmlhandler.cpp:1868 and
thereabouts) does when reading the instrument elements within each device
element. It looks up the instrument according to its ID, which is a global
numbering from 2000 upwards for MIDI instruments, and applies the given bank
and program to that instrument if it exists, dropping them entirely if it
doesn't.

The significant points are (a) this code never actually creates instruments or
assigns instrument IDs to devices -- that's done when the devices are
created, which is originated by the sequencer if the devices are created to
match existing available MIDI connections -- and (b) the instrument ID is not
local to the device, but global. Put together, this means this code has no
way of dealing with (or really knowing about) the situation where an
instrument ID is found on the wrong device. For example, if you save a file
with 16 instruments per device (so that instrument IDs 2000-2015 are on
device 0, 2016-2031 on device 1 etc), then increase the number of
auto-generated instruments per device to 24 and reload the file, the
instruments 2016-2023 will have moved from device 1 to device 0 and tracks
set to those instruments will suddenly play through a different MIDI port.

The root cause of this is that instruments are being created in the wrong
place -- they're created on the whim of the sequencer, and then propagated
back to the GUI. This happens because we want to make sure there are
candidate instruments with likely connections available for the MIDI ports
that the sequencer finds on startup. As a result the code that really should
have the ultimate control over the device and instrument setup (the code that
reads in the saved devices and instruments from the .rg file) doesn't have
any real control at all, because the instruments are already there. It can
ask for the sequencer to create a new device, but it's still at the mercy of
the sequencer's built-in count of instruments for that device. In fact, all
the instruments and devices should be created at the GUI, or at least the GUI
should have control over when and what is created -- only the available
connections should be managed on the sequencer side.

> My proposal is to associate Instruments to segments instead of tracks, and
> dissociate the MIDI channels from instruments moving them to the track
> level.

I'm not sure that this latter bit is necessary, if there can in fact be more
or less than 16 instruments per device -- is it? Would it make much
difference either way?

Associating instruments with segments seems at first glance like an excellent
idea. I wonder if there are any big disadvantages? It sounds equally useful
for audio instruments, to allow you to apply different effects plugins to
different segments on the same track.


[ later ]


> Yes, but the extra instruments don't bring any extra advantage.

Not in terms of the overall capability, but that's a limitation of MIDI (as
there only are 16 channels and you can't have two different programs on the
same one at the same time). I was just making the aside that the number of
instruments is not technically fixed to the number of MIDI channels. (It
could be an advantage to have more, simply from a management point of view --
assign separate instruments to all of your tracks and then worry about which
channels to play them through afterwards. That's not very relevant though.)

But you're right, if you make the instruments per-segment and channels
per-track, the problem goes away. Nice.

> I don't understand why the methods generateInstruments() and
> addInstrumentsForDevice() are members of the class AlsaDriver.

I sort-of answered this in the previous email -- the AlsaDriver creates a
default set of instruments to match up with the available output ports it
finds on startup. That's really the only reason this logic is there. The
original idea was probably to have the set of instruments completely fixed by
the sequencer -- you'd have to look at the aRts driver to see what the
initial design was, it's probably quite different (and simpler).

> The sequencer doesn't need to care about the Instruments at all.

Not true -- it needs to know about instruments because it also sequences to
things other than MIDI devices (e.g. synth plugins -- and note that DSSI
plugins don't have channels). Receiving events associated with particular
instruments, and then doing the mapping from instrument to output type based
on a separate relationship between the two, is probably the right thing.
It's just a question of who creates and manages that relationship.

> It is not strictly necessary, but may be a nightmare otherwise. Imagine
> this scenario: track one has two segments, both assigned to channel#1.
> Second track has an instrument assigned to channel#2. If you change the
> instrument for the second segment on the first track, and assign an
> instrument having channel #2, you are changing in fact the program for the
> second track.

Yes, with this and the earlier example I'm convinced.

> Can it be useful for DSSI instruments too? I think so, but I don't know too
> much the internals.

I would expect so.

Quite a bit of work though, all in all.
 
 
dev/instruments_and_devices.txt · Last modified: 2022/05/06 16:07 (external edit)
Recent changes RSS feed Creative Commons License Valid XHTML 1.0 Valid CSS Driven by DokuWiki