Skip to content

Instantly share code, notes, and snippets.

@JLChnToZ
Last active December 16, 2017 13:00
Show Gist options
  • Save JLChnToZ/6989006 to your computer and use it in GitHub Desktop.
Save JLChnToZ/6989006 to your computer and use it in GitHub Desktop.
"MML Beep" -- Plays MML (Music Macro Language) sequence in BEEP sound with motherboard buzzer.
/*
*
* MML BEEP Ver 1.0
* Plays MML sequence in BEEP sound.
* Copyright (C) 2011, Jeremy Lam.
* http://explosivetheormlab.wordpress.com
*
* It is free to use any part of this program anywhere you want. But only thing
* I want is put my name into your program's credits which is used part of this
* program (Jeremy Lam or JLChnToZ, both name are OK, it is better to put my
* website's link with it).
*
* DISCLAIMER
* This software is provided by Jeremy Lam and contributors "as is"
* and any express or implied warranties, including, but not limited
* to, the implied warranties of merchantability and fitness for a
* particular purpose are disclaimed. In no event shall Jeremy Lam or
* contributors be liable for any direct, indirect, incidental, special,
* exemplary, or consequential damages (Including, but not limited to,
* procurement of substitute goods or services; loss of use, data, or
* profits; or business interruption) however caused and on any theory
* of liability, whether in contract, strict liability, or tort
* (Including negligence or otherwise) arising in any way out of the
* use of this software, even if advised of the possibility of such damage.
*
*/
#include <iostream>
#include <fstream>
#include <cmath>
#ifdef WIN32
#include <windows.h>
#endif
#ifdef __linux__
#include <fcntl.h>
#include <linux/kd.h>
#endif
using namespace std;
int getNoteKeyByName(char);
int charToNum(char);
char charToLowerCase(char);
int main(int argc, char* argv[]) {
cout << "MML Beep" << endl << "Copyright (C) Jeremy Lam, 2011." << endl;
#ifdef __linux__
int linuxcons = open("/dev/console", O_WRONLY);
#endif
for(int i = 1; i < argc; i++) {
int CurrentBPM = 120, CurrentOative = 4;
double CurrentNoteLength, DefNoteLength = 4;
double ConvNoteFreq, ConvNoteLen;
int NoteKey = 49, Mode = 0;
int dots = 0, DefDots = 0;
int NoteBefore = 0;
char MML;
cout << "Reading file " << argv[i] << endl;
ifstream infile(argv[i], ios::binary);
infile.seekg(0, ios::end);
int length = infile.tellg();
cout << "File Length: " << length << endl;
infile.seekg(0, ios::beg);
char* buffer = new char[length+1];
infile.read(buffer, length);
infile.close();
for(int j = 0; j <= length; j++) {
MML = charToLowerCase(buffer[j]);
if(NoteBefore && (j == length || MML == 'a' || MML == 'b' || MML == 'c' || MML == 'd' || MML == 'e' || MML == 'f'
|| MML == 'g' || MML == 'l' || MML == 'n' || MML == 'o' || MML == 'r' || MML == 't' || MML == 'v' || MML == '<' || MML == '>')) {
if(CurrentNoteLength <= 0) {
if(dots <= 0) dots = DefDots;
CurrentNoteLength = DefNoteLength;
}
cout << "NoteLength:1/" << CurrentNoteLength << "+" << dots << "dot(s)";
cout << " BPM:" << CurrentBPM << " Key:" << NoteKey;
if(dots > 0) CurrentNoteLength *= pow((double)2, dots)/(2*pow((double)2, dots)-1);
ConvNoteFreq = 440*pow((double)2, (double)(NoteKey-57)/12);
ConvNoteLen = 240000/(double)CurrentBPM/CurrentNoteLength;
cout << " Length(MS):" << ConvNoteLen << " Frequency:";
if(NoteKey < 0) {
cout << "N/A";
#ifdef WIN32
Sleep((DWORD)ConvNoteLen);
#endif
#ifdef __linux__
usleep(ConvNoteLen*1000);
#endif
} else {
cout << ConvNoteFreq << "Hz";
#ifdef WIN32
Beep((DWORD)ConvNoteFreq, (DWORD)ConvNoteLen);
#endif
#ifdef __linux__
ioctl(linuxcons, KIOCSOUND, (int)(1193180/ConvNoteFreq));
usleep(ConvNoteLen*1000);
ioctl(linuxcons, KIOCSOUND, 0);
#endif
}
NoteBefore = 0;
cout << endl;
}
switch(MML) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'r':
NoteKey = MML == 'r' ? -1 : CurrentOative*12+getNoteKeyByName(MML);
CurrentNoteLength = 0;
dots = 0;
NoteBefore = 1;
Mode = 3;
break;
case 'n':
NoteKey = 0;
CurrentNoteLength = 0;
NoteBefore = 1;
Mode = 1;
break;
case 't':
CurrentBPM = 0;
Mode = 2;
break;
case 'l':
DefNoteLength = 0;
DefDots = 0;
Mode = 7;
break;
case 'v':
Mode = 9;
break;
case 'o':
CurrentOative = 0;
Mode = 5;
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0':
switch(Mode) {
case 1:
NoteKey = NoteKey*10+charToNum(MML);
break;
case 2:
CurrentBPM = CurrentBPM*10+charToNum(MML);
break;
case 3:
CurrentNoteLength = CurrentNoteLength*10+charToNum(MML);
break;
case 7:
DefNoteLength = DefNoteLength*10+charToNum(MML);
break;
case 5:
CurrentOative = CurrentOative*10+charToNum(MML);
}
break;
case '.':
if(Mode == 3 || Mode == 4) {
dots++;
Mode = 4;
} else if(Mode == 7 || Mode == 8) {
DefDots++;
Mode = 8;
}
break;
case '+': case '#':
NoteKey++;
Mode = 3;
break;
case '-':
NoteKey--;
Mode = 3;
break;
case '<':
CurrentOative--;
Mode = 6;
break;
case '>':
CurrentOative++;
Mode = 6;
}
}
cout << endl;
}
#ifdef __linux__
close(linuxcons);
#endif
return 0;
}
int getNoteKeyByName(char Note) {
switch(Note) {
case 'c': return 0;
case 'd': return 2;
case 'e': return 4;
case 'f': return 5;
case 'g': return 7;
case 'a': return 9;
case 'b': return 11;
default: return -1;
}
}
int charToNum(char Num) {
if(Num >= '1' && Num <= '9') return Num-'1'+1;
return 0;
}
char charToLowerCase(char str) {
if(str >= 'A' && str <= 'Z') str -= 'A'-'a';
return str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment