|
|
instruments_and_devices [2008/05/01 11:12] cannam created |
— (current) |
====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==== | |
| |
<code> | |
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. | |
| |
</code> | |
| |