2024-07-15 11:46:59 +08:00

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);
}