Problem F
Quantiser
MIDI (Musical Instrument Digital Interface) is
a standard for transmitting musical performance data between
devices. With MIDI, each event of a performance (e.g., pressing
or releasing a key of a piano) is encoded in a message. A typical
MIDI message essentially consists of a code and a note,
and says that a given key (corresponding to a given note)
was pressed (the code NoteOn) or released (NoteOff code).
If we register all the events of a performance
and associate a convenient time stamp with them, we will be able
to reproduce the performance later with precision. We may also
make many other things, like editing the data or producing a
score in standard, human readable, music notation. This last
application will be our focus: we want to prepare performance
data stored in a file so that the production of a score becomes
easy.
Figure 1 presents an example of a performance
(4 notes, 8 events) and the corresponding data, in the form
<code, note, time-stamp>. The time stamp is represented by
the triple <measure:beat:tick>. To make things simpler, we
will consider that a measure is a positive integer and has always
4 beats (numbered 1 to 4) and each beat has 480 ticks (numbered 0
to 479).
|
NoteOn, 35, 23:1:0
NoteOn, 52, 23:1:0
NoteOn, 43, 23:2:0
NoteOff, 52, 23:3:0
NoteOff, 35, 23:4:0
NoteOn, 35, 24:1:0
NoteOff, 43, 24:1:0
NoteOff, 35, 24:2:0
|
Figure 1
This performance may be easily converted to
standard music notation, as all the events occur at the exact
beginning of a beat (tick 0). The same would happen if they
occurred in points corresponding to subdivisions of the beat that
match certain musical rhythm symbols. To simplify, we will
consider divisions of the beats in 2, 4 and 8 parts as
corresponding to legal musical notation; thus, if the events
occur in ticks like 60, 240 or 420, the production of the score
will be possible.
The events in Figure 1, however, could hardly
be produced by an human. Humans can’t be so precise: their
performances have subtle "imprecisions" in timing and
in other parameters. These imprecisions make a direct production
of a score virtually impossible. Figure 2 represents a possible
human performance.
|
NoteOn, 35, 23:1:006
NoteOn, 52, 23:1:017
NoteOn, 43, 23:2:010
NoteOff, 52, 23:3:015
NoteOff, 35, 23:3:252
NoteOn, 35, 23:4:473
NoteOn, 33, 23:4:478
NoteOff, 43, 24:1:011
NoteOff, 33, 24:1:012
NoteOff, 35, 24:2:003
|
Figure 2
We may see that the times where the events
occur are close to "correct" points. For instance, the
fourth event occurs close to 23:3:000, the fifth close to
23:3:240 and the sixth close to 24:1:000. To produce a readable
score from this data, we may change the time stamps to make them
fit the closest "correct" points: this process is
called Quantisation.
The short note 33 near the beginning of measure
24 (in italic) represents a special case: after quantisation, its
duration becomes zero. We will filter notes in these
conditions.
Problem
Make a program that, given a performance
consisting of a sequence of no more than 2.000 events, produces a
new sequence after quantising the data. Notes whose
duration becomes zero after quantisation must be filtered out.
If a time stamp is equally close to two different correct points,
quantise it to the upper point (for example, "23 1 30" becomes
"23 1 60").
The program should be able to process several performances each
time it runs.
Input
The input file represents several performances.
Input for each performance consists of a sequence of lines, as
follows:
First line: n
where n is the number of messages
of the performance
Next n lines (up to 2.000): code note
m b t
where code is the number 1
for a Note On event or the number 0 for a Note Off
event; note is a positive number representing a
piano key; m is a positive integer representing
the measure; b is 1, 2, 3 or 4 and represents the
beat; t is an integer between 0 and 479, and
represents the tick.
The messages of a performance are ordered by
increasing times.
Successive values on a line are separated by
one blank. The integer -1 follows the data of the last
performance.
Output
Output should give, for each given performance,
the following output:
First line: n
where n is the number of the
messages of the quantised performance
Next n lines: code note m b t
where the meaning of the symbols is the
same as for the input file
The messages of each performance must be
ordered by increasing times.
The integer -1 must follow the data of the last
performance.
Sample Input
10
1 35 23 1 6
1 52 23 1 17
1 43 23 2 10
0 52 23 3 15
0 35 23 3 252
1 35 23 4 473
1 33 23 4 478
0 43 24 1 11
0 33 24 1 12
0 35 24 2 3
10
1 42 14 1 55
1 38 14 1 126
0 42 14 1 177
1 42 14 1 230
1 51 14 1 241
0 42 14 1 248
1 42 14 1 352
0 38 14 1 356
0 51 14 1 472
0 42 14 2 244
-1
Sample Output
8
1 35 23 1 0
1 52 23 1 0
1 43 23 2 0
0 52 23 3 0
0 35 23 3 240
1 35 24 1 0
0 43 24 1 0
0 35 24 2 0
8
1 42 14 1 60
1 38 14 1 120
0 42 14 1 180
1 51 14 1 240
1 42 14 1 360
0 38 14 1 360
0 51 14 2 0
0 42 14 2 240
-1
Amílcar Cardoso, MIUP'2002
題目描述:
一個音訊的訊息(不用重新排序),他給定時間單位進行量化,
時間單位為秒,每秒中間又分 4 拍,每一拍中間又分 480 個刻度。
量化按照每 60 刻度當作一個畫分界線,將每個不同的音符起落時間進行量化,
量化標準找最靠近分界線,如果相同則找最上方的。
如果某段聲音量化之後不存在則刪除。
特別要注意拍是從 1, 2, 3, 4, 轉換要特別注意而不是 0 1 2 3
題目解法:
分別進行量化後,O(N*N) 檢查對應的 OFF 時間,進行刪除。
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
struct E {//event
int code, note, m, b, t;
bool operator<(const E &A) const {
if(m != A.m) return m < A.m;
if(b != A.b) return b < A.b;
if(t != A.t) return t < A.t;
if(note != A.note)
return note < A.note;
return code < A.code;
}
};
bool cmp(E a, E b) {
if(a.note != b.note)
return a.note < b.note;
if(a.m != b.m) return a.m < b.m;
if(a.b != b.b) return a.b < b.b;
if(a.t != b.t) return a.t < b.t;
return a.code < b.code;
}
int main() {
int n;
int i, j, k;
E D[2005];
while(scanf("%d", &n) == 1 && n >= 0) {
for(i = 0; i < n; i++)
scanf("%d %d %d %d %d", &D[i].code, &D[i].note, &D[i].m, &D[i].b, &D[i].t);
for(i = 0; i < n; i++) {
int v = D[i].t + (D[i].b-1)*480 + D[i].m*4*480;
int m, b, t, q;
q = (v+30)/60*60;
t = q%480, b = (q/480)%4, m = q/480/4;
D[i].m = m;
D[i].b = b+1;
D[i].t = t;
//printf("%d %d %d %d %d\n", D[i].code, D[i].note, D[i].m, D[i].b, D[i].t);
}
int ban[2005] = {};
for(i = 0; i < n; i++) {
if(D[i].code == 0) continue;
for(j = i+1; j < n; j++) {
if(D[j].code == 1) continue;
if(D[j].note == D[i].note) {
if(D[j].m == D[i].m && D[j].b == D[i].b && D[j].t == D[i].t)
ban[i] = ban[j] = 1;
break;
}
}
}
int ret = 0;
for(i = 0; i < n; i++)
ret += ban[i] == 0;
printf("%d\n", ret);
for(i = 0; i < n; i++) {
if(ban[i] == 0)
printf("%d %d %d %d %d\n", D[i].code, D[i].note, D[i].m, D[i].b, D[i].t);
}
}
puts("-1");
return 0;
}
/*
4
1 0 0 0 0
0 0 0 0 58
1 0 0 0 62
0 0 0 0 118
*/
文章定位: