unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
function CMIDI_Create(uResID: UINT;
pWndParent: THandle=0): BOOL;overload;
function CMIDI_Create(pszResID
char;pWndParent:THandle=0):BOOL;overload;
function CMIDI_Create(pSoundData
ointer;
dwSize
WORD;pWndParent:THandle=0):BOOL;overload;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
mmsystem,Midi_H;
const MThd=$6468544D; // Start of file
const MTrk=$6B72544D; // Start of track
const BUFFER_TIME_LENGTH=60;
// Amount to fill in milliseconds
type
MIDIFILEHDR = record
wFormat: WORD;
// Format (hi-lo)
wTrackCount: WORD;
// # tracks (hi-lo)
wTimeDivision: WORD;
// Time division (hi-lo)
end;
var
m_hBufferReturnEvent:THandle;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
m_hBufferReturnEvent := CreateEvent(0, FALSE, FALSE, Pchar('Wait For Buffer Return'));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if(m_hBufferReturnEvent)<>NULL then
CloseHandle(m_hBufferReturnEvent);
end;
function TForm1.CMIDI_Create(uResID:UINT;pWndParent:THandle=0):BOOL;
begin
//Result:=CMIDI_Create(MAKEINTRESOURCE(uResID),pWndParent);
end;
function TForm1.CMIDI_Create(pszResID
char;pWndParent:THandle=0):BOOL;
var
hApp:Cardinal;
hResInfo:HRSRC;
hRes: HGLOBAL;
pTheSound
ointer;
dwTheSound
WORD;
begin
//////////////////////////////////////////////////////////////////
Result:=False;
// load resource
hApp:= GetModuleHandle(0);
hResInfo := FindResource(hApp, pszResID, Pchar('MIDI'));
if(hResInfo = 0) then
Exit;
hRes:= LoadResource(hApp, hResInfo);
if(hRes = 0) then
Exit;
pTheSound := LockResource(hRes);
if(pTheSound = nil) then
Exit;
dwTheSound := SizeofResource(hApp, hResInfo);
// return Create(pTheSound, dwTheSound, pWndParent);
end;
function TForm1.CMIDI_Create(pSoundData
ointer;
dwSize
WORD;pWndParent:THandle=0):BOOL;
begin
Result:=False;
if( m_pSoundData<>nil) then
begin
// already created
// ASSERT(FALSE);
Exit;
end;
register LPBYTE p = LPBYTE(pSoundData);
// check header of MIDI
if(*(DWORD*)p != MThd) {
ASSERT(FALSE);
return FALSE;
}
p += sizeof(DWORD);
// check header size
DWORD dwHeaderSize = DWORDSWAP(*(DWORD*)p);
if( dwHeaderSize != sizeof(MIDIFILEHDR) ) {
ASSERT(FALSE);
return FALSE;
}
p += sizeof(DWORD);
// get header
MIDIFILEHDR hdr;
::CopyMemory(&hdr, p, dwHeaderSize);
m_dwFormat = DWORD(WORDSWAP(hdr.wFormat));
m_dwTrackCount = DWORD(WORDSWAP(hdr.wTrackCount));
m_dwTimeDivision = DWORD(WORDSWAP(hdr.wTimeDivision));
p += dwHeaderSize;
// create the array of tracks
m_Tracks.resize(m_dwTrackCount);
for(register DWORD i = 0;
i < m_dwTrackCount;
++i) {
// check header of track
if(*(DWORD*)p != MTrk) {
ASSERT(FALSE);
return FALSE;
}
p += sizeof(DWORD);
m_Tracks
.dwTrackLength = DWORDSWAP(*(DWORD*)p);
p += sizeof(DWORD);
m_Tracks.pTrackStart = m_Tracks.pTrackCurrent = p;
p += m_Tracks.dwTrackLength;
// Handle bozo MIDI files which contain empty track chunks
if( !m_Tracks.dwTrackLength ) {
m_Tracks.fdwTrack |= ITS_F_ENDOFTRK;
continue;
}
// We always preread the time from each track so the mixer code can
// determine which track has the next event with a minimum of work
if( !GetTrackVDWord( &m_Tracks, &m_Tracks.tkNextEventDue )) {
TRACE0("Error in MIDI data/n");
ASSERT(FALSE);
return FALSE;
}
}
m_pSoundData = pSoundData;
m_dwSoundSize = dwSize;
m_pWndParent = pWndParent;
// allocate volume channels and initialise them
m_Volumes.resize(NUM_CHANNELS, VOLUME_INIT);
if( ! StreamBufferSetup() ) {
ASSERT(FALSE);
return FALSE;
}
return TRUE;
}
end.