136 lines
2.7 KiB
C++
136 lines
2.7 KiB
C++
//
|
|
// Programmer: Tom M. <tom.mbrt@gmail.com>
|
|
// Creation Date: Sat Nov 05 14:51:00 PST 2016
|
|
// Last Modified: Sat Nov 05 14:51:00 PST 2016
|
|
// Filename: tools/mid2beep.cpp
|
|
// URL: https://github.com/craigsapp/midifile/blob/master/tools/midi2beep.cpp
|
|
// Syntax: C++11
|
|
// vim: ts=3
|
|
//
|
|
// Description: Linux-only: Play a monophonic midi file on the PC Speaker (i.e. the
|
|
// midifile contains only a single track on a single channel playing
|
|
// a single note at a time).
|
|
//
|
|
|
|
#include "MidiFile.h"
|
|
#include "Options.h"
|
|
|
|
#include <cmath>
|
|
#include <iostream>
|
|
#include <signal.h>
|
|
#include <unistd.h> // usleep()
|
|
|
|
#ifdef __APPLE__
|
|
#include <sys/uio.h>
|
|
#else
|
|
#include <sys/io.h>
|
|
#endif
|
|
|
|
using namespace std;
|
|
using namespace smf;
|
|
|
|
|
|
void beepOff (int);
|
|
void beep (int fre, int usDuration);
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////
|
|
//
|
|
// beepOff --
|
|
|
|
void beepOff(int) {
|
|
int r = inb(0x61);
|
|
outb(r|3, 0x61);
|
|
outb(r & 0xFC, 0x61);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////
|
|
//
|
|
// beep --
|
|
//
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
|