1
OxygenBasic Examples / Re: Playing with the Beep function
« Last post by Roland Stowasser on Yesterday at 02:40:58 PM »Hi Charles,
apparently I need to learn a bit more about midi to create effective tones. I don't quite understand the parameters for midiOutShortMsg in particular. But I found an old app that still works after some small tweaks. I believe it contains all the necessary functions I need. But I need to read the explanations a little more carefully.
apparently I need to learn a bit more about midi to create effective tones. I don't quite understand the parameters for midiOutShortMsg in particular. But I found an old app that still works after some small tweaks. I believe it contains all the necessary functions I need. But I need to read the explanations a little more carefully.
Code: [Select]
/*---------------------------------------------------
BACHTOCC.o2bas -- Bach Toccata in D Minor (First Bar)
(c) Charles Petzold, 1998
---------------------------------------------------*/
'Ported to Oxygenbasic
$ filename "BACHTOCC.exe"
'uses rtl32
'uses rtl64
uses corewin
'uses minmidi
'octave 0..10
extern lib "Winmm.dll"
sys midiOutOpen(sys *phmo, uDeviceID,dwCallback, dwInstance,fdwOpen)
sys midiOutShortMsg( sys hmo, dwMsg)
sys midiOutClose( sys hmo)
sys midiOutReset(sys hmo)
% COLOR_WINDOW = 5
% MIDIMAPPER = 0xFFFFFFFF
'=======================
'MAIN CODE
'=======================
sys hInstance = GetModuleHandle(0)
'========================================'
string szClassName = "BachTocc"
string WindowTitle = "Bach Toccata in D Minor (First Bar)"
% ID_TIMER = 1
function MidiOutMsg(sys hMidi, int iStatus, iChannel, iData1, iData2) as dword
dword dwMessage = iStatus + iChannel + (iData1 * 0x100) + (iData2 * 0x10000)
return midiOutShortMsg(hMidi, dwMessage)
end function
int iDur = 1
int iNote = 2
int noteseq[] =
{110, 69, 81,
110, 67, 79,
990, 69, 81,
220, -1, -1,
110, 67, 79,
110, 65, 77,
110, 64, 76,
110, 62, 74,
220, 61, 73,
440, 62, 74,
1980,-1, -1,
110, 57, 69,
110, 55, 67,
990, 57, 69,
220, -1, -1,
220, 52, 64,
220, 53, 65,
220, 49, 61,
440, 50, 62,
1980, -1, -1}
sys hMidiOut
int iIndex = 1
function WndProc(sys hwnd, Message, wParam, lParam) as sys callback
int i
switch Message
case WM_CREATE
// Open MIDIMAPPER device
if midiOutOpen(hMidiOut, MIDIMAPPER, 0, 0, 0) then
MessageBeep(MB_ICONEXCLAMATION)
MessageBox(hwnd, "Cannot open MIDI output device!",
szClassname, MB_ICONEXCLAMATION or MB_OK)
return -1
end if
// Send Program Change messages for "Church Organ"
'MidiOutMsg(hMidiOut, 0xC0, 0, 19, 0)
'Send Program Change messages for "Piccolo"
MidiOutMsg(hMidiOut, 0xC0, 0, 72, 0)
SetTimer(hwnd, ID_TIMER, 1000, NULL)
case WM_TIMER
// Loop for 2-note polyphony
for i = 1 to 2
// Note Off messages for previous note
if iIndex <> 1 and noteseq[iIndex-iDur-iNote + i] <> -1 then
MidiOutMsg(hMidiOut, 0x80, 0,
noteseq[iIndex-iDur-iNote +i], 0)
end if
// Note On messages for new note
if iIndex <= 20*(iDur+iNote) and
noteseq[iIndex +i] <> -1 then
MidiOutMsg(hMidiOut, 0x90, 0,
noteseq[iIndex +i], 127)
end if
next i
if iIndex <= 20*(iDur+iNote) then
SetTimer(hwnd, ID_TIMER, noteseq[iIndex] - 1, NULL)
iIndex = iIndex + iDur + iNote
else
KillTimer(hwnd, ID_TIMER)
DestroyWindow (hwnd)
end if
case WM_DESTROY
midiOutReset(hMidiOut)
midiOutClose(hMidiOut)
PostQuitMessage(0)
case else
return DefWindowProc(hwnd, Message, wParam, lParam)
end switch
return 0
end function
function WinMain(sys nCmdShow) as sys
WNDCLASSEX wc
MSG Msg
sys hwnd
wc.cbSize = sizeof(WNDCLASSEX)
wc.style = 0
wc.lpfnWndProc = @WndProc
wc.cbClsExtra = 0
wc.cbWndExtra = 0
wc.hInstance = hInstance
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION)
wc.hCursor = LoadCursor(NULL, IDC_ARROW)
wc.hbrBackground = COLOR_WINDOW+1
wc.lpszMenuName = NULL
wc.lpszClassName = strptr(szClassName)
wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION)
if not RegisterClassEx(&wc) then
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONERROR)
return 0
end if
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
szClassName,
WindowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, // x, y positon
500, 300, // x size, y size
NULL,
NULL, // window menu handle
hInstance, NULL)
if hwnd = NULL then
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONERROR)
return 0
end if
ShowWindow(hwnd, nCmdShow)
UpdateWindow(hwnd)
sys bRet
do while (bRet := GetMessage(&Msg, NULL, 0, 0))
TranslateMessage(&Msg)
DispatchMessage(&Msg)
wend
return Msg.wParam
end function
'WINDOWS START
'=============
WinMain(SW_NORMAL)