[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-users] SimpleMIDIFile, get the duration and onset-time of the events



Hi Daniel,

indeed for conversion ticks - seconds and vv. adjustEndOfTrack should be called first (in case of a self-generated file, an imported file usually already has a correct endOftrack). If this is not done SimpleMIDIFile will assume that the track is empty (endOfTrack at time 0) and ignores the events that may be in it. For file writing however it is not completely necessary to do it, as <mf>.write does it internally as well. Also a conversion to ticks is done within the write method (in fact to a copy of the object so that the original times and timemode stay untouched).

cheers,
Wouter

ps nice to see the survey indeed :-). Btw one to-do on SimpleMIDIFile is implementation of sysex. I haven't had a reason or time to do that yet (most of wslib came to existence out of necessity ;-) ) but anyone who feels up to that job is very welcome.

Op 7 mrt. 2019, om 23:59 heeft daniel-mayer@xxxxxxxx het volgende geschreven:



Am 07.03.2019 um 14:45 schrieb mailinglists@xxxxxxxxxxxxxx:

When a MIDI file is written to disk however, information will be converted back to ticks, and the timing resolution will be dictated by the division setting (ticks are stored as integers). 

Hey Wouter,

thanks, this side-remark clarifies a lot !

I have to withdraw my remark from last post:

>>my quick tests showed some quirks:

>>.) Resetting time mode ( m.timeMode = \seconds; ) doesn't convert into seconds
>>.) In some cases this doesn't seem to work with multitrack files


Everything works perfectly fine now, supposed we do 'adjustEndOfTrack" and write the MIDI file !

(
m = SimpleMIDIFile( "~/Desktop/midifiletest.mid" ); // create empty file

m.init0(1); // init for type 0

m.timeMode = \ticks;

((0, 20..500)).do({ |starttick| // add random notes
m.addNote(36 + 36.rand, 64 + 32.rand, starttick, rrand(1, 100), 127, 
channel: 0  
)
});

~ticks = Pseq([10, 20, 30], inf).iter;

((0, 20..500)).do({ |starttick| // add random notes to next track
m.addNote(72 + 36.rand, 64 + 32.rand, starttick, ~ticks.next, 127, 
channel: 1  
)
});
)

// finish and store is necessary for changing mode!

m.adjustEndOfTrack;

m.write;


m.midiEvents.dopostln; 

// get lengths in ticks
m.noteSustainEvents(0).dopostln; // length values at 6th position
m.noteSustainEvents(1).dopostln;


m.timeMode = \seconds;

m.midiEvents.dopostln; 

// get lengths in seconds
m.noteSustainEvents(0).dopostln; // length values at 6th position
m.noteSustainEvents(1).dopostln;


//////////////////////////////////////

// version with multitrack midi file

(
m = SimpleMIDIFile( "~/Desktop/midifiletest.mid" ); // create empty file

m.init1(3, 120, "4/4"); // init for type 0

m.timeMode = \ticks;

((0, 20..500)).do({ |starttick| // add random notes
m.addNote(36 + 36.rand, 64 + 32.rand, starttick, rrand(1, 100), 127, 
channel: 0,
track: 0,
)
});

~ticks = Pseq([10, 20, 30], inf).iter;

((0, 20..500)).do({ |starttick| // add random notes to next track
m.addNote(72 + 36.rand, 64 + 32.rand, starttick, ~ticks.next, 127, 
channel: 5,
track: 1
)
});
)

// finish and store is necessary for changing mode!

m.adjustEndOfTrack;

m.write;


m.midiEvents.dopostln; 

// get lengths in ticks
m.noteSustainEvents(0, 0).dopostln; // length values at 6th position
m.noteSustainEvents(5, 1).dopostln;


m.timeMode = \seconds;

m.midiEvents.dopostln; 

// get lengths in seconds
m.noteSustainEvents(0, 0).dopostln; // length values at 6th position
m.noteSustainEvents(5, 1).dopostln;


No wonder wslib quark turned out to be so popular in the user survey, it's a must have :)

Cheers

Daniel

-----------------------------
http://daniel-mayer.at
-----------------------------