開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 コンソール アプリケーション
プロジェクト名 morse
アプリケーションの種類 コンソール アプリケーション
追加のオプション 空のプロジェクト

使用例
C:\>morse -a0.2 -l5000 "トラ"

morse.cpp
// マルチバイト文字セット
 
#pragma comment(lib, "winmm")
 
#define _USE_MATH_DEFINES
 
#include <stdio.h>
#include <math.h>
#include <Windows.h>
#include <vector>
 
using namespace std;
 
#define SAFE_FREE(p)	if (p) { free(p); p = NULL; }
#define SAMPLING_RATE	11025
#define FREQ		882.0
 
// 関数プロトタイプ宣言
void AddDots(bool b, int count);
 
// 欧文文字
LPCTSTR letters[] = {
	"01",		// A
	"1000",		// B
	"1010",		// C
	"100",		// D
	"0",		// E
	"0010",		// F
	"110",		// G
	"0000",		// H
	"00",		// I
	"0111",		// J
	"101",		// K
	"0100",		// L
	"11",		// M
	"10",		// N
	"111",		// O
	"0110",		// P
	"1101",		// Q
	"010",		// R
	"000",		// S
	"1",		// T
	"001",		// U
	"0001",		// V
	"011",		// W
	"1001",		// X
	"1011",		// Y
	"1100",		// Z
};
 
// 数字
LPCTSTR numbers[] = {
	"11111",	// 0
	"01111",	// 1
	"00111",	// 2
	"00011",	// 3
	"00001",	// 4
	"00000",	// 5
	"10000",	// 6
	"11000",	// 7
	"11100",	// 8
	"11110",	// 9
};
 
// 記号
LPCTSTR punctuation[] = {
	"010101",	// . Period
	"110011",	// , Comma
	"001100",	// ? Question mark
	"011110",	// ' Apostrophe
	"101011",	// ! Exclamation mark
	"10010",	// / Slash, Fraction bar
	"10110",	// ( Parenthesis open
	"101101",	// ) Parenthesis close
	"01000",	// & Ampersand, Wait
	"111000",	// : Colon
	"101010",	// ; Semicolon
	"10001",	// = Double dash
	"01010",	// + Plus
	"100001",	// - Hyphen, Minus
	"001101",	// _ Underscore
	"010010",	// " Quotation mark
	"0001001",	// $ Dollar sign
	"011010",	// @ At sign
};
 
// 和文文字
LPCTSTR kana[] = {
	NULL,		// 。
	NULL,		// 「
	"010100",	// 」(段落)
	"010101",	// 、(区切点)
	NULL,		// ・
	"0111",		// ヲ
	NULL,		// ァ
	NULL,		// ィ
	NULL,		// ゥ
	NULL,		// ェ
	NULL,		// ォ
	NULL,		// ャ
	NULL,		// ュ
	NULL,		// ョ
	NULL,		// ッ
	"01101",	// ー(長音)
	"11011",	// ア
	"01",		// イ
	"001",		// ウ
	"10111",	// エ
	"01000",	// オ
	"0100",		// カ
	"10100",	// キ
	"0001",		// ク
	"1011",		// ケ
	"1111",		// コ
	"10101",	// サ
	"11010",	// シ
	"11101",	// ス
	"01110",	// セ
	"1110",		// ソ
	"10",		// タ
	"0010",		// チ
	"0110",		// ツ
	"01011",	// テ
	"00100",	// ト
	"010",		// ナ
	"1010",		// ニ
	"0000",		// ヌ
	"1101",		// ネ
	"0011",		// ノ
	"1000",		// ハ
	"11001",	// ヒ
	"1100",		// フ
	"0",		// ヘ
	"100",		// ホ
	"1001",		// マ
	"00101",	// ミ
	"1",		// ム
	"10001",	// メ
	"10010",	// モ
	"011",		// ヤ
	"10011",	// ユ
	"11",		// ヨ
	"000",		// ラ
	"110",		// リ
	"10110",	// ル
	"111",		// レ
	"0101",		// ロ
	"101",		// ワ
//	"01001",	// ヰ
//	"01100",	// ヱ
	"01010",	// ン
	"00",		// ゛(濁点)
	"00110",	// ゜(半濁点)
};
 
// 外部変数
DWORD sampleLength = 0;
PBYTE waveformData = NULL;
vector<bool> dots;
 
//==============================================================================
int main(int argc, char *argv[])
{
	// プログラム引数
	LPCTSTR words = NULL;
	double amp = 0.1;
	int loops = 0;
	int wpm = 20;
	for (int i = 1; i < argc; i++) {
		LPCTSTR p = argv[i];
		if (p[0] == '-') {
			switch (p[1]) {
			case 'a':
				amp = atof(p + 2);
				break;
			case 'l':
				loops = atoi(p + 2);
				break;
			case 'w':
				wpm = atoi(p + 2);
				break;
			}
		} else {
			words = p;
		}
	}
	if (words == NULL) {
		fprintf(stderr, "usage: morse -a(f) -l(n) -w(n) \"words\"\n");
		return 1;
	}
 
	// 符号化
	for (int i = 0; words[i]; i++) {
		LPCTSTR code = NULL;
		BYTE c = words[i];
		if (c == ' ') {
			AddDots(false, 4);
		} else if ('A' <= c && c <= 'Z') {
			code = letters[c - 'A'];
		} else if ('a' <= c && c <= 'z') {
			code = letters[c - 'a'];
		} else if (0xa1 <= c && c <= 0xdf) {
			code = kana[c - 0xa1];
		}
		if (code) {
			for ( ; *code; code++) {
				AddDots(true, (*code & 1) ? 3 : 1);
				AddDots(false, 1);
			}
			AddDots(false, 2);
		}
	}
 
	// 波形データの作成
	int dotLen = SAMPLING_RATE * 60 / (50 * wpm);
	sampleLength = dots.size() * dotLen;
	waveformData = (PBYTE)malloc(sampleLength);
 
	int i = 0;
	for (vector<bool>::iterator it = dots.begin(); it != dots.end(); it++) {
		if (*it) {
			for (int n = 0; n < dotLen; n++) {
				double t = fmod(FREQ * i / SAMPLING_RATE, 1);
				double y = amp * sin(2 * M_PI * t);
				waveformData[i++] = BYTE(128 + 127 * y);
			}
		} else {
			for (int n = 0; n < dotLen; n++) {
				waveformData[i++] = 128;
			}
		}
	}
 
	// Play
	WAVEFORMATEX wfx;
	wfx.wFormatTag		= WAVE_FORMAT_PCM;
	wfx.wBitsPerSample	= 8;
	wfx.nChannels		= 1;
	wfx.nSamplesPerSec	= SAMPLING_RATE;
	wfx.nBlockAlign		= (wfx.wBitsPerSample / 8) * wfx.nChannels;
	wfx.nAvgBytesPerSec	= wfx.nSamplesPerSec * wfx.nBlockAlign;
	wfx.cbSize		= 0;
 
	HWAVEOUT hwo;
	MMRESULT mmr = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, NULL, 0, CALLBACK_NULL);
 
	WAVEHDR wh;
	ZeroMemory(&wh, sizeof wh);
	wh.lpData		= (LPSTR)waveformData;
	wh.dwBufferLength	= sampleLength;
	wh.dwFlags		= WHDR_BEGINLOOP | WHDR_ENDLOOP;
	wh.dwLoops		= loops ? MAXDWORD : 1;
 
	mmr = waveOutPrepareHeader(hwo, &wh, sizeof wh);
 
	mmr = waveOutWrite(hwo, &wh, sizeof wh);
 
	// Wait
	Sleep(loops ? loops : 1000 * sampleLength / SAMPLING_RATE);
 
	// Stop
	mmr = waveOutReset(hwo);
	mmr = waveOutUnprepareHeader(hwo, &wh, sizeof wh);
	mmr = waveOutClose(hwo);
 
	SAFE_FREE(waveformData);
	return 0;
}
 
void AddDots(bool b, int count)
{
	for (int n = 0; n < count; n++) {
		dots.push_back(b);
	}
}
 
最終更新:2013年03月04日 08:56