Created
March 4, 2015 05:09
-
-
Save mythagel/67a78c8d02e89a0aee78 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* main.cpp | |
* | |
* Created on: 22/03/2012 | |
* Author: mythagel | |
*/ | |
#include <cstdio> | |
#include <cstdlib> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <sys/ioctl.h> | |
#include <linux/kd.h> | |
#include <unistd.h> | |
#include <string> | |
#include <map> | |
#include <vector> | |
#include <sstream> | |
/* | |
* No sound? sudo modprobe pcspk !!! | |
*/ | |
class ToneGenerator | |
{ | |
private: | |
int m_ConsoleFD; | |
static const int Hertz8254 = 1193180; | |
std::map<std::string, double> m_Notes; | |
ToneGenerator() | |
{ | |
m_ConsoleFD = open("/dev/console", O_WRONLY); | |
if(m_ConsoleFD == -1) | |
fprintf(stderr, "Unable to open console\n"); | |
InitNotes(); | |
} | |
void InitNotes() | |
{ | |
m_Notes["C0"] = 16.35; | |
m_Notes["C#0"] = 17.32; | |
m_Notes["D0"] = 18.35; | |
m_Notes["D#0"] = 19.45; | |
m_Notes["E0"] = 20.60; | |
m_Notes["F0"] = 21.83; | |
m_Notes["F#0"] = 23.12; | |
m_Notes["G0"] = 24.50; | |
m_Notes["G#0"] = 25.96; | |
m_Notes["A0"] = 27.50; | |
m_Notes["A#0"] = 29.14; | |
m_Notes["B0"] = 30.87; | |
m_Notes["C1"] = 32.70; | |
m_Notes["C#1"] = 34.65; | |
m_Notes["D1"] = 36.71; | |
m_Notes["D#1"] = 38.89; | |
m_Notes["E1"] = 41.20; | |
m_Notes["F1"] = 43.65; | |
m_Notes["F#1"] = 46.25; | |
m_Notes["G1"] = 49.00; | |
m_Notes["G#1"] = 51.91; | |
m_Notes["A1"] = 55.00; | |
m_Notes["A#1"] = 58.27; | |
m_Notes["B1"] = 61.74; | |
m_Notes["C2"] = 65.41; | |
m_Notes["C#2"] = 69.30; | |
m_Notes["D2"] = 73.42; | |
m_Notes["D#2"] = 77.78; | |
m_Notes["E2"] = 82.41; | |
m_Notes["F2"] = 87.31; | |
m_Notes["F#2"] = 92.50; | |
m_Notes["G2"] = 98.00; | |
m_Notes["G#2"] = 103.83; | |
m_Notes["A2"] = 110.00; | |
m_Notes["A#2"] = 116.54; | |
m_Notes["B2"] = 123.47; | |
m_Notes["C3"] = 130.81; | |
m_Notes["C#3"] = 138.59; | |
m_Notes["D3"] = 146.83; | |
m_Notes["D#3"] = 155.56; | |
m_Notes["E3"] = 164.81; | |
m_Notes["F3"] = 174.61; | |
m_Notes["F#3"] = 185.00; | |
m_Notes["G3"] = 196.00; | |
m_Notes["G#3"] = 207.65; | |
m_Notes["A3"] = 220.00; | |
m_Notes["A#3"] = 233.08; | |
m_Notes["B3"] = 246.94; | |
m_Notes["C4"] = 261.63; | |
m_Notes["C#4"] = 277.18; | |
m_Notes["D4"] = 293.66; | |
m_Notes["D#4"] = 311.13; | |
m_Notes["E4"] = 329.63; | |
m_Notes["F4"] = 349.23; | |
m_Notes["F#4"] = 369.99; | |
m_Notes["G4"] = 392.00; | |
m_Notes["G#4"] = 415.30; | |
m_Notes["A4"] = 440.00; | |
m_Notes["A#4"] = 466.16; | |
m_Notes["B4"] = 493.88; | |
m_Notes["C5"] = 523.25; | |
m_Notes["C#5"] = 554.37; | |
m_Notes["D5"] = 587.33; | |
m_Notes["D#5"] = 622.25; | |
m_Notes["E5"] = 659.26; | |
m_Notes["F5"] = 698.46; | |
m_Notes["F#5"] = 739.99; | |
m_Notes["G5"] = 783.99; | |
m_Notes["G#5"] = 830.61; | |
m_Notes["A5"] = 880.00; | |
m_Notes["A#5"] = 932.33; | |
m_Notes["B5"] = 987.77; | |
m_Notes["C6"] = 1046.50; | |
m_Notes["C#6"] = 1108.73; | |
m_Notes["D6"] = 1174.66; | |
m_Notes["D#6"] = 1244.51; | |
m_Notes["E6"] = 1318.51; | |
m_Notes["F6"] = 1396.91; | |
m_Notes["F#6"] = 1479.98; | |
m_Notes["G6"] = 1567.98; | |
m_Notes["G#6"] = 1661.22; | |
m_Notes["A6"] = 1760.00; | |
m_Notes["A#6"] = 1864.66; | |
m_Notes["B6"] = 1975.53; | |
m_Notes["C7"] = 2093.00; | |
m_Notes["C#7"] = 2217.46; | |
m_Notes["D7"] = 2349.32; | |
m_Notes["D#7"] = 2489.02; | |
m_Notes["E7"] = 2637.02; | |
m_Notes["F7"] = 2793.83; | |
m_Notes["F#7"] = 2959.96; | |
m_Notes["G7"] = 3135.96; | |
m_Notes["G#7"] = 3322.44; | |
m_Notes["A7"] = 3520.00; | |
m_Notes["A#7"] = 3729.31; | |
m_Notes["B7"] = 3951.07; | |
m_Notes["C8"] = 4186.01; | |
m_Notes["C#8"] = 4434.92; | |
m_Notes["D8"] = 4698.64; | |
m_Notes["D#8"] = 4978.03; | |
} | |
protected: | |
struct Tone | |
{ | |
double freq; | |
int duration; | |
Tone(double freq, int duration) | |
: freq(freq), duration(duration) | |
{ | |
} | |
Tone(const std::string& note, int duration) | |
: freq(ToneGenerator::Instance()->Note(note)), duration(duration) | |
{ | |
} | |
static bool Parse(const std::string& tonestr, std::vector<Tone>* tones) | |
{ | |
std::stringstream s(tonestr); | |
while(!s.eof()) | |
{ | |
std::string tone; | |
int duration; | |
s >> tone; | |
s >> duration; | |
if(tone.empty()) | |
return false; | |
if(isalpha(tone[0])) | |
tones->push_back(Tone(tone, duration)); | |
else | |
tones->push_back(Tone(atof(tone.c_str()), duration)); | |
} | |
return true; | |
} | |
}; | |
void StartTone(double freq, long duration_ms) | |
{ | |
if(m_ConsoleFD != -1) | |
{ | |
int tone(0); | |
if(static_cast<int>(freq)) | |
tone = static_cast<int>(Hertz8254 / freq); | |
fprintf(stderr, "tone: %fhz/%ldms\n", freq, duration_ms); | |
ioctl(m_ConsoleFD, KIOCSOUND, tone); | |
usleep(1000*duration_ms); | |
} | |
} | |
void StopTone() | |
{ | |
if(m_ConsoleFD != -1) | |
{ | |
fprintf(stderr, "tone: stop\n"); | |
ioctl(m_ConsoleFD, KIOCSOUND, 0); | |
} | |
} | |
double Note(const std::string& note) const | |
{ | |
std::map<std::string, double>::const_iterator it = m_Notes.find(note); | |
if(it != m_Notes.end()) | |
return it->second; | |
fprintf(stderr, "Unrecognised note '%s'\n", note.c_str()); | |
return 0.0; | |
} | |
void Play(const std::vector<Tone>& tones) | |
{ | |
for(std::vector<Tone>::const_iterator it = tones.begin(); it != tones.end(); ++it) | |
StartTone(it->freq, it->duration); | |
StopTone(); | |
} | |
public: | |
static ToneGenerator* Instance() | |
{ | |
static ToneGenerator tg; | |
return &tg; | |
} | |
void Play(const std::string& tonestr) | |
{ | |
std::vector<Tone> tones; | |
if(Tone::Parse(tonestr, &tones)) | |
Play(tones); | |
} | |
~ToneGenerator() | |
{ | |
StopTone(); | |
} | |
}; | |
int main() | |
{ | |
ToneGenerator::Instance()->Play("440.1234 300 C5 100 D5 100 E5 100 F5 100 0 350 G5 100 0 150 F5 350"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment