Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

midi_tracks() #1

Open
jarnoh opened this issue Sep 27, 2013 · 1 comment
Open

midi_tracks() #1

jarnoh opened this issue Sep 27, 2013 · 1 comment

Comments

@jarnoh
Copy link
Owner

jarnoh commented Sep 27, 2013

I have no idea what the method does, or why it is written like that. Copy paste errors or is it using some awesome drum syncing?

@JayFoxRox
Copy link

JayFoxRox commented Apr 12, 2021

(Just to clarify: I did not write the original code; I just thought it would be fun to document it)


It's a bit ugly, but otherwise makes sense; here's the code for reference:

doomsday/demo.cpp

Lines 52 to 57 in 571f553

if(*midi_tech04!=-1)
{
while(*midi_tech04!=-1 && *midi_tech04/960.f<=t) midi_tech04+=3;
tech04_keytime[midi_tech04[-2]]=midi_tech04[-3]/960.f;
tech04_keyvelocity[midi_tech04[-2]]=midi_tech04[-1]/127.f;
}


midi_tech04 points into a list of MIDI events (track_tech04), the structure of each MIDI event appears to be like this (with negative indices referring to the previous event):

// All fields will be -1 for the last event, to signal end of track
struct {
  int time;     // access using [0] or [-3]
  int key;      // access using [1] or [-2]
  int velocity; // access using [2] or [-1]
};
// Equivalent to `midi_tech04[0]` or `midi_tech04.time` (also used in next step)
// Checks if playback has finished (timestamp will be -1)
if(*midi_tech04!=-1)
{
    // Search for the next event by repeatedly skipping events (advance pointer 3 fields = 1 event)
    // Done while the current timestamp is reached (`/960.f<=t`, where `960.f` is timescale) and end isn't reached (`!=-1`).
    while(*midi_tech04!=-1 && *midi_tech04/960.f<=t) midi_tech04+=3;

    // Note: Pseudocode differs below:
    //       `midi_tech04` named fields should access at previous event (`midi_tech04-3`).

    // Equivalent to `tech04_keytime[midi_tech04.key]=midi_tech04.time/960.f;`
    // (where `/960.0f` is timescale)
    tech04_keytime[midi_tech04[-2]]=midi_tech04[-3]/960.f;

    // Equivalent to `tech04_keyvelocity[midi_tech04.key]=midi_tech04.velocity/127.f;`
    // (where `/127.f` is volume control)
    tech04_keyvelocity[midi_tech04[-2]]=midi_tech04[-1]/127.f;
}

The same code pattern repeats for each MIDI track.
So, for each track, it just advances to the next MIDI event and punches the key for that event.

The issue with it that I'm seeing is that it only plays one key for each track at a time.
So if midi_tracks() isn't called often enough (= t advances so much that more than 1 key would play) it will skip keys.
The loop from line 54 should also contain line 55 and 56 (punching keys) to address this.

Probably written like this to keep the music exporter simple + lazyness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants