Skip to content

Instantly share code, notes, and snippets.

@mythagel
Created March 4, 2015 05:09
Show Gist options
  • Save mythagel/67a78c8d02e89a0aee78 to your computer and use it in GitHub Desktop.
Save mythagel/67a78c8d02e89a0aee78 to your computer and use it in GitHub Desktop.
/*
* 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