Source file: /~heha/hsn/maus32.zip/melodie/melodie.cpp

/* Ausgabe einer monofonen Melodie auf PC-Speaker,
 * Töne auf Kommandozeile ähnlich Handyklingeltonformat RTTTL / Nokring
 */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <math.h>

#define elemof(x) (sizeof(x)/sizeof(*(x)))

extern "C" {
int _fltused;
#ifdef _M_IX86
long _declspec(naked) _cdecl _ftol2_sse(void){ _asm{
	push	eax
 	fistp	dword ptr [esp]
	fwait
	pop	eax
	ret
}}
#endif
}
//---------------------------------------------------------------------------

int Note2Freq(int note) {
 static const double C = 0.057762265046662109118102676788181; //log (2) / 12;
 return (int)(440*exp(note*C)+0.5);
}

int Note2Freq(const char *s) {
 int nb = 0;	// "Noten-Basis"

 if ( *s == '#') {nb++; s++; }	// Kreuz als Präfix
// effektiver Kode   		a  b  c  d  e  f  g  h
 static const signed char NB[]={0, 1,-9,-7,-5,-4,-2, 2};
 register int idx=*s++ - 'a';	// Index zum Zugriff auf Tabelle
 if ((unsigned)idx>=elemof(NB)) return 0;	// falsche Zeichen -> Pause
 nb+=NB[idx];
 switch (*s++) {		// Postfixe "#", "b", "s" (für "es" und "as")
  case '#': nb++; break;	// sowie "~is" und "~es" auswerten
  case 'b':
  case 's': nb--; break;
  case 'i': nb++; goto kommt_s;
  case 'e': nb--; kommt_s:
   if (*s != 's') return 0;	// nur "i" oder "e" macht Pause
   s++;
  break;
  default: s--;			// kein Postfix: Zeiger zurückstellen
 }
 return Note2Freq (nb + atoi(s)*12);	// Oktave als numerischer Postfix
}

#ifdef _M_IX86
// Wie Windows NT auf allen Windows-Versionen (da fehlt ein shlwapi.Beep?)
BOOL MyBeep(DWORD dwFreq, DWORD dwDuration) {
 if ((long)GetVersion()>=0) return Beep(dwFreq,dwDuration);
 else{	// Win32s, Win9x/Me
  if (dwFreq<1843200L/0x10000/2) return FALSE;
  dwFreq=1843200L/2/dwFreq;	// Teilerwert
  _asm{
	cli
	mov	al,0xB6	// Timer2: Rechteckgenerator, 16bit
	out	0x43,al
	mov	eax,dwFreq
	out	0x42,al	// Timer2: Endwert Low-Teil setzen
	xchg	ah,al
	out	0x42,al	// Timer2: Endwert High-Teil setzen
	in	al,0x61
	or	al,0x03
	out	0x61,al	// Ein- und Ausgang des Timer2 freischalten
	sti
  }
  Sleep(dwDuration);
  _asm{
	cli
	in	al,0x61
	and	al,~0x03
	out	0x61,al	// Ein- und Ausgang des Timer2 sperren
	sti
  }
  return TRUE;
 }
}
#else
# define MyBeep(f,d) Beep(f,d)
#endif

void PlayNote(const char *s) {		// Spielt die angegebene Note
 int laen = atoi(s);		// Länge
 while (*s>='0' && *s<='9') s++;
 if (laen <= 0) laen = 4;		// Wenn nicht angegeben: Viertelnote
 int ms = 1000/laen;			// Hier: Ganze Note = 1 Sekunde
 if (*s == '.') { ms += ms>>1; s++; }	// Punktierte Note = 1½fache Länge
 int hz = Note2Freq(s);			// String-Rest macht Tonhöhe
 if (hz <= 0) Sleep(ms);		// Pause oder Ton
 else MyBeep(hz, ms);
}

extern "C" int CALLBACK WinMainCRTStartup() {
 char *lpCmdLine=GetCommandLine();
 for (;;) {
  while (*lpCmdLine==' ') lpCmdLine++;	// Führende Leerzeichen wegparsen
  LPSTR p=strchr(lpCmdLine,' ');// aufs nächste Leerzeichen
  if (p) *p='\0';		// Wenn vorhanden, dann wegpatchen
  PlayNote(lpCmdLine);
  if (!p) break;		// raus!
  lpCmdLine=p+1;		// HINTER das (eine) Leerzeichen
 }
 return 0;
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded