ramon (15) [Avatar] Offline
#1
Hi,

I am so glad I found this forum.

I need to know what notes play at each time x in a SMF.
e.g.
At time 1.120seconds
track 1 plays notes 64,67,70 with velocity of 100,111,90
track 2 plays notes 50 with velocity of 43

The SMF contains multiple tracks with multiple notes with multiple set_tempo events.

Can you help me?

greetings,
Ramon
ramon (15) [Avatar] Offline
#2
Implementation in C
this is a programm that reads the smf and returns the events of track 1:

What I need is a list of pitch, track, velocity of all notes at time t /ms
e.g.
[[[tracknum,pitch,velocity],[tracknum,pitch,velocity]],[[

#include <stdio.h>
#include <windows.h>
#include <MaxMidi.h>

int main(void) {

int NumOfTracks;
HSMF hSmf;
int format;
DWORD NumOfEvents;
int wTrack;
LPMIDIEVENT lpMidiBuff;
DWORD dwBuffLen;
DWORD eventCount;
HMOUT hMidiOut;

printf("read_smf Version 0.1
");

hSmf = OpenSMF("C:\midi.mid", &format, 'r', &NumOfTracks);
printf("hSmf = %d
", hSmf);
if (!hSmf)
return;
// read the first track
wTrack = 1;
// use a 512 event buffer
dwBuffLen = 512L;
// allocate memory for the buffer
lpMidiBuff = (LPMIDIEVENT)GlobalAlloc(GPTR, dwBuffLen * sizeof(MidiEvent));

NumOfEvents = ReadSMF(hSmf, wTrack, lpMidiBuff, dwBuffLen);
printf("NumOfEvents = %d", NumOfEvents );

eventCount = 0;
while (eventCount < NumOfEvents) {

printf("Event = %3d: time=%4d, status =%4d; %4d %4d %4d
", eventCount,
(lpMidiBuff + eventCount)->time,
(UINT)((lpMidiBuff + eventCount)->status),
(UINT)((lpMidiBuff + eventCount)->data1),
(UINT)((lpMidiBuff + eventCount)->data2),
(UINT)((lpMidiBuff + eventCount)->data3));
eventCount++;
}
}
KUMA (56) [Avatar] Offline
#3
Re: Implementation in C
First, you'll need to calculate the absolute time of every note on event.
Then you'll get the time-interval [note-on time, note-off time) for every note.
So given t, you'll be able to spesify those intervals contain t.
Using CMaxMidiTrack functions you'll be able to do this easily.
If you don't want to work with C++ you need to calculate the absolute time by adding up all the time stamps of preceding events.
ramon (15) [Avatar] Offline
#4
Re: Implementation in C
Yes. Thank you for your answer.
But given multiple set_tempo events this task becomes somewhat harder. Since one can not simply add the delta times. From the moment the set_tempo event changes the microseconds per beat, the duration of a tick changes.
ramon (15) [Avatar] Offline
#5
Re: Implementation in C
Hi again,

I do not understand the implementation in C++. I do not know where I have to put the code that is printed on page 201 to get a result.
KUMA (56) [Avatar] Offline
#6
Re: Implementation in C
Add up all the timestamps up to the second set-tempo event and you'll get the elapsed time in milliseconds from the start to the second set-tempo, call it t(1), then add up all the timestamps of succeeding events up to the third set-tempo and you'll get the elapsed time from the second set-tempo to the third one, call it t(2), then the elapsed time from the start to the third set-tempo will be t(1) + t(2), and so on.
This done the task can be done with ticks not with milliseconds.

CMaxMidiTrack and CMaxMidiSMF are pure C++ not depend on MFC. So you will be able to utilize them relatively easily. I recommend you to learn C++.
ramon (15) [Avatar] Offline
#7
Re: Implementation in C
"Add up all the timestamps up to the second set-tempo event"

-- What do you mean by timestamps? How can I access timestamps from smf?

"[...] then add up all the timestamps of succeeding events up to the third set-tempo and you'll get the elapsed time from the second set-tempo to the third one [...]"

-- the duration of a tick changes according to the set_tempo event, so one can not add up all the timestamps
KUMA (56) [Avatar] Offline
#8
Re: Implementation in C
Read the book!
In tis case timestamp means delta-ticks. You can accsess the timestamps by (lpMidiBuff + eventCount)->time.

For example, let the resolution be 480tpb, the meter be 4/4, and the initial tempo be 120bpm, and let the second set-tempo event be at the head of the 5th measure and then tempo be changed to 160bpm. Then the ticks from the start up to the head of the 5th measure is 480*16 and the elapsed time is 0.5*16 = 8sec.
Now, what is the velue of the elapsed time at, say, the head of the 6th measure? The delta-time of the head of the 6th measure and the head of the 5th measure is (60/160)*4 = 1.5sec, so the elapsed time in question is 9.5sec. On the other hand, what is the number of ticks up to the head of the 6th measure? Surely 480*20. It is intact whether there is the second set-tempo or not.
So given t, you can calculate approximately the corresponding ticks n and specify a note such that the ticks m from the start up to the note is less than or equal to n and the ticks correspoding to the note's duration + m is greater than n.
ramon (15) [Avatar] Offline
#9
Re: Implementation in C
Thank you for the examples. I think they are quite exact.
It is a pity that there is no code already available, that does compute these values.

To find the corresponding notes is not as easy as it seems.
KUMA (56) [Avatar] Offline
#10
Re: Implementation in C
Here is a sample code to calculate note's duration.

http://www.manning-sandbox.com/thread.jspa?threadID=6022&tstart=350

It utilizes CMaxMidiTrack. Again I recomend you to learn C++.