forked from craigsapp/midifile
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmidi2beep.cpp
119 lines (93 loc) · 2.72 KB
/
midi2beep.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//
// Programmer: Tom M. <[email protected]>
// Creation Date: Sat Nov 05 14:51:00 PST 2016
// Last Modified: Sat Nov 05 14:51:00 PST 2016
// Filename: midifile/src-programs/mid2beep.cpp
// Web Address: https://github.com/craigsapp/midifile/blob/master/src-programs/mid2beep.cpp
// Syntax: C++
//
// Description: Linux-only: Play a monophonic midi file on the PC Speaker (i.e. the midi file contains only a single track
// on a single channel playing a single note at a time)
//
#include "MidiFile.h"
#include "Options.h"
#include <iostream>
#include <cmath>
#include <unistd.h> // usleep()
#include <signal.h>
#ifdef __APPLE__
#include <sys/uio.h>
#else
#include <sys/io.h>
#endif
using namespace std;
using namespace smf;
void beepOff(int)
{
int r = inb(0x61);
outb(r|3, 0x61);
outb(r & 0xFC, 0x61);
exit(0);
}
void beep(int fre, int usDuration)
{
if (fre > 0) {
int ff = 1193180/fre;
outb( 0xB6, 0x43);
outb( ff & 0xff, 0x42);
outb((ff >> 8) & 0xff, 0x42);
}
int r = inb(0x61);
if(fre > 0) outb(r|3, 0x61);
usleep(usDuration);
outb(r & 0xFC, 0x61);
}
int main(int argc, char** argv)
{
signal(SIGINT, beepOff);
Options options;
options.process(argc, argv);
MidiFile midifile;
if (options.getArgCount() == 1) {
midifile.read(options.getArg(1));
}
else
{
cout << "usage: " << argv[0] << " file.mid" << endl;
return -1;
}
int k= iopl(3);
printf("\n Result iopl: %d \n", k);
if (k<0)
{
cerr << " iopl() " << endl;
return k;
}
midifile.linkNotePairs();
midifile.joinTracks();
midifile.doTimeAnalysis();
midifile.absoluteTicks();
double lastNoteFinished = 0.0;
for (int track=0; track < midifile.getTrackCount(); track++) {
for (int i=0; i<midifile[track].size(); i++) {
MidiEvent* mev = &midifile[track][i];
if (!mev->isNoteOn() || mev->getLinkedEvent() == NULL) {
continue;
}
// pause, silence
int silence = static_cast<int>((midifile.getTimeInSeconds(mev->tick) - lastNoteFinished) * 1000 * 1000);
if(silence >0)
{
usleep(silence);
}
double duration = mev->getDurationInSeconds();
int halfTonesFromA4 = mev->getKeyNumber() - 69; // 69 == A4 == 440Hz
int frq = 440 * pow(2, halfTonesFromA4/12.0);
// play note
beep(frq, static_cast<int>(duration*1000*1000));
MidiEvent* off = mev->getLinkedEvent();
lastNoteFinished = midifile.getTimeInSeconds(off->tick);
}
}
return 0;
}