34 m_midiInitialized =
FALSE;
36 m_bufferCurrentSize = 0;
38 m_bufferCurrentOffset = 0;
61 if (!p_fromDestructor) {
71 if (m_midiInitialized) {
72 if (m_bufferCurrentSize == 0) {
73 if (m_loopCount != -1) {
85 if (m_midiHdrP->dwFlags & MHDR_DONE || m_midiHdrP->dwFlags & MHDR_PREPARED) {
86 if (midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP,
sizeof(MIDIHDR)) != MMSYSERR_NOERROR) {
90 memset(m_midiHdrP, 0,
sizeof(MIDIHDR));
93 m_bufferCurrentOffset += 4;
94 DWORD length = *((
DWORD*) m_bufferCurrentOffset);
95 m_bufferCurrentOffset +=
sizeof(
DWORD);
97 m_midiHdrP->lpData = (LPSTR) m_bufferCurrentOffset;
98 m_midiHdrP->dwBufferLength = length;
99 m_midiHdrP->dwBytesRecorded = length;
101 if (!midiOutPrepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP,
sizeof(MIDIHDR))) {
102 if (!midiStreamOut(m_midiStreamH, m_midiHdrP,
sizeof(MIDIHDR))) {
104 m_bufferCurrentOffset += length;
105 m_bufferCurrentSize--;
117 m_bufferCurrentOffset = m_bufferOffset;
118 m_bufferCurrentSize = m_bufferSize;
122void MxMusicManager::SetMIDIVolume()
125 HMIDISTRM streamHandle = m_midiStreamH;
128 MxS32 volume = CalculateVolume(result);
129 midiOutSetVolume((HMIDIOUT) streamHandle, volume);
134void CALLBACK MxMusicManager::MidiCallbackProc(HDRVR p_hdrvr, UINT p_uMsg,
DWORD p_dwUser,
DWORD p_dw1,
DWORD p_dw2)
136 if (p_uMsg == MOM_DONE) {
148 if (p_createThread) {
195 m_multiplier = p_multiplier;
201MxS32 MxMusicManager::CalculateVolume(
MxS32 p_volume)
203 MxS32 result = (p_volume * 0xffff) / 100;
204 return (result << 0x10) | result;
214 if (!m_midiInitialized) {
215 MxU32 total = midiOutGetNumDevs();
218 for (; device < total; device++) {
220 midiOutGetDevCapsA(device, &caps,
sizeof(MIDIOUTCAPSA));
221 if (caps.wTechnology == MOD_FMSYNTH) {
226 if (device >= total) {
230 if (midiStreamOpen(&m_midiStreamH, &device, 1, (
DWORD) MidiCallbackProc, (
DWORD)
this, CALLBACK_FUNCTION) !=
237 m_midiHdrP =
new MIDIHDR();
242 memset(m_midiHdrP, 0,
sizeof(MIDIHDR));
244 MIDIPROPTIMEDIV timediv;
245 timediv.cbStruct = 8;
246 m_bufferOffset = p_data;
247 m_bufferOffset += 0x14;
248 timediv.dwTimeDiv = *((
DWORD*) m_bufferOffset);
250 if (midiStreamProperty(m_midiStreamH, (LPBYTE) &timediv, MIDIPROP_SET | MIDIPROP_TIMEDIV) != MMSYSERR_NOERROR) {
254 m_bufferOffset += 0x14;
255 m_bufferSize = *((
MxU32*) m_bufferOffset);
256 m_bufferOffset +=
sizeof(
MxU32);
257 m_loopCount = p_loopCount;
258 m_midiInitialized =
TRUE;
266 if (midiStreamRestart(m_midiStreamH) != MMSYSERR_NOERROR) {
283 if (m_midiInitialized) {
284 m_midiInitialized =
FALSE;
285 midiStreamStop(m_midiStreamH);
286 midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP,
sizeof(MIDIHDR));
287 midiOutSetVolume((HMIDIOUT) m_midiStreamH, m_midiVolume);
288 midiStreamClose(m_midiStreamH);
MxResult Create() override
[AI] Initializes audio subsystem resources and registers an instance for global audio management.
virtual void SetVolume(MxS32 p_volume)
[AI] Sets the current global audio volume.
MxS32 m_volume
[AI] Holds the current global audio volume for the game.
void Destroy() override
[AI] Tears down the audio subsystem instance and unregisters it from global management.
void Enter()
[AI] Acquires/gains entry to the critical section or mutex, blocking if not available.
void Leave()
[AI] Releases/leaves the critical section or mutex.
Manages MIDI music playback with Win32 MIDI streaming for the LEGO Island engine.
void InitData()
Initializes and zeros all associated MIDI-related member data.
MxMusicManager()
Constructs an instance and initializes member data.
void Destroy() override
Releases all resources and stops streaming.
void DeinitializeMIDI()
Stops playback and releases all MIDI streaming resources.
void SetMultiplier(MxS32 p_multiplier)
Sets the volume multiplier for scaling volume output.
MxResult ResetStream()
Schedules and streams the next chunk of MIDI data; handles buffer looping and completion.
void Init()
Initializes multipliers and buffer with default values; called from constructor/Destroy.
MxResult InitializeMIDI(MxU8 *p_data, MxS32 p_loopCount)
Initializes streaming for a MIDI data buffer and begins playback.
void GetMIDIVolume(DWORD &p_volume)
Retrieves the current hardware MIDI out volume.
void SetVolume(MxS32 p_volume) override
Sets the music playback volume, taking into account multiplier for overall gain adjustment.
void ResetBuffer()
Resets the MIDI buffer to the starting offset and sets the buffer size to the full stream.
~MxMusicManager() override
Destructor, ensures proper cleanup of resources and MIDI deinitialization.
void Terminate()
[AI] Signals the thread to terminate.
MxResult Start(MxS32 p_stackSize, MxS32 p_flag)
[AI] Starts the thread with a given stack size and creation flags.
virtual void UnregisterClient(MxCore *p_client)
[AI] Unregisters (marks for destruction) a previously registered client.
virtual void RegisterClient(MxCore *p_client, MxTime p_interval)
[AI] Registers an MxCore object to receive periodic tickles.
MxTickleThread periodically calls Tickle() on a target MxCore object in a separate thread.
typedef DWORD(FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper
#define DECOMP_SIZE_ASSERT(T, S)
#define NULL
[AI] Null pointer value (C/C++ semantics).
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
MxTickleManager * TickleManager()
[AI] Provides access to the global tickle manager.