Revert r5601 in its entirety. This fixes MIDI playback on Windows.

git-svn-id: https://svn.eduke32.com/eduke32@5650 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2016-03-07 11:22:07 +00:00
parent dd0f16875f
commit e577335bd9
9 changed files with 2463 additions and 347 deletions

View file

@ -1,12 +1,10 @@
//-------------------------------------------------------------------------
/* /*
Copyright (C) 2016 EDuke32 developers and contributors Copyright (C) 1994-1995 Apogee Software, Ltd.
This file is part of EDuke32. This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
EDuke32 is free software; you can redistribute it and/or as published by the Free Software Foundation; either version 2
modify it under the terms of the GNU General Public License version 2 of the License, or (at your option) any later version.
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -17,14 +15,27 @@ See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
*/ */
//------------------------------------------------------------------------- /**********************************************************************
module: _MIDI.H
author: James R. Dose
date: May 25, 1994
Private header for MIDI.C. Midi song file playback routines.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef ___MIDI_H #ifndef ___MIDI_H
#define ___MIDI_H #define ___MIDI_H
#include "compat.h" #include "compat.h"
#define RELATIVE_BEAT(measure, beat, tick) ((tick) + ((beat) << 9) + ((measure) << 16)) #define RELATIVE_BEAT( measure, beat, tick ) \
( ( tick ) + ( ( beat ) << 9 ) + ( ( measure ) << 16 ) )
//Bobby Prince thinks this may be 100 //Bobby Prince thinks this may be 100
//#define GENMIDI_DefaultVolume 100 //#define GENMIDI_DefaultVolume 100
@ -92,7 +103,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define EMIDI_GeneralMIDI 0 #define EMIDI_GeneralMIDI 0
#define EMIDI_AffectsCurrentCard(c, type) (((c) == EMIDI_ALL_CARDS) || ((c) == (type))) #define EMIDI_AffectsCurrentCard( c, type ) \
( ( ( c ) == EMIDI_ALL_CARDS ) || ( ( c ) == ( type ) ) )
#define EMIDI_NUM_CONTEXTS 7 #define EMIDI_NUM_CONTEXTS 7
typedef struct typedef struct
@ -136,10 +149,134 @@ static void _MIDI_ResetTracks( void );
static void _MIDI_AdvanceTick( void ); static void _MIDI_AdvanceTick( void );
static void _MIDI_MetaEvent( track *Track ); static void _MIDI_MetaEvent( track *Track );
static void _MIDI_SysEx( track *Track ); static void _MIDI_SysEx( track *Track );
static int32_t _MIDI_InterpretControllerInfo(track *Track, int32_t TimeSet, int32_t channel, int32_t c1, int32_t c2); static int32_t _MIDI_InterpretControllerInfo( track *Track, int32_t TimeSet,
int32_t channel, int32_t c1, int32_t c2 );
static int32_t _MIDI_SendControlChange( int32_t channel, int32_t c1, int32_t c2 ); static int32_t _MIDI_SendControlChange( int32_t channel, int32_t c1, int32_t c2 );
static void _MIDI_SetChannelVolume( int32_t channel, int32_t volume ); static void _MIDI_SetChannelVolume( int32_t channel, int32_t volume );
static void _MIDI_SendChannelVolumes( void ); static void _MIDI_SendChannelVolumes( void );
static int32_t _MIDI_ProcessNextTick( void );
static void _MIDI_InitEMIDI( void ); static void _MIDI_InitEMIDI( void );
/*
if ( c1 == EMIDI_LOOP_START )
{
if ( c2 == 0 )
{
Track->context[ 0 ].loopcount = EMIDI_INFINITE;
}
else
{
Track->context[ 0 ].loopcount = c2;
}
Track->context[ 0 ].pos = Track->pos;
Track->context[ 0 ].loopstart = Track->pos;
Track->context[ 0 ].RunningStatus = Track->RunningStatus;
Track->context[ 0 ].time = _MIDI_Time;
Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
Track->context[ 0 ].tick = _MIDI_Tick;
Track->context[ 0 ].beat = _MIDI_Beat;
Track->context[ 0 ].measure = _MIDI_Measure;
Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat;
Track->context[ 0 ].TimeBase = _MIDI_TimeBase;
break;
}
if ( ( c1 == EMIDI_LOOP_END ) &&
( c2 == EMIDI_END_LOOP_VALUE ) )
{
if ( ( Track->context[ 0 ].loopstart != NULL ) &&
( Track->context[ 0 ].loopcount != 0 ) )
{
if ( Track->context[ 0 ].loopcount != EMIDI_INFINITE )
{
Track->context[ 0 ].loopcount--;
}
Track->pos = Track->context[ 0 ].loopstart;
Track->RunningStatus = Track->context[ 0 ].RunningStatus;
if ( !TimeSet )
{
_MIDI_Time = Track->context[ 0 ].time;
_MIDI_FPSecondsPerTick = Track->context[ 0 ].FPSecondsPerTick;
_MIDI_Tick = Track->context[ 0 ].tick;
_MIDI_Beat = Track->context[ 0 ].beat;
_MIDI_Measure = Track->context[ 0 ].measure;
_MIDI_BeatsPerMeasure = Track->context[ 0 ].BeatsPerMeasure;
_MIDI_TicksPerBeat = Track->context[ 0 ].TicksPerBeat;
_MIDI_TimeBase = Track->context[ 0 ].TimeBase;
TimeSet = TRUE;
}
}
break;
}
if ( c1 == MIDI_MONO_MODE_ON )
{
Track->pos++;
}
if ( ( c1 == MIDI_VOLUME ) && ( !Track->EMIDI_VolumeChange ) )
{
_MIDI_SetChannelVolume( channel, c2 );
break;
}
else if ( ( c1 == EMIDI_VOLUME_CHANGE ) &&
( Track->EMIDI_VolumeChange ) )
{
_MIDI_SetChannelVolume( channel, c2 );
break;
}
if ( ( c1 == EMIDI_PROGRAM_CHANGE ) &&
( Track->EMIDI_ProgramChange ) )
{
_MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c2 & 0x7f ] );
break;
}
if ( c1 == EMIDI_CONTEXT_START )
{
break;
}
if ( c1 == EMIDI_CONTEXT_END )
{
if ( ( Track->currentcontext != _MIDI_Context ) ||
( Track->context[ _MIDI_Context ].pos == NULL )
{
break;
}
Track->currentcontext = _MIDI_Context;
Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart;
Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount;
Track->pos = Track->context[ _MIDI_Context ].pos;
Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus;
if ( TimeSet )
{
break;
}
_MIDI_Time = Track->context[ _MIDI_Context ].time;
_MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick;
_MIDI_Tick = Track->context[ _MIDI_Context ].tick;
_MIDI_Beat = Track->context[ _MIDI_Context ].beat;
_MIDI_Measure = Track->context[ _MIDI_Context ].measure;
_MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure;
_MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat;
_MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase;
TimeSet = TRUE;
break;
}
if ( _MIDI_Funcs->ControlChange )
{
_MIDI_Funcs->ControlChange( channel, c1, c2 );
}
*/
#endif #endif

View file

@ -1,12 +1,10 @@
//-------------------------------------------------------------------------
/* /*
Copyright (C) 2016 EDuke32 developers and contributors Copyright (C) 1994-1995 Apogee Software, Ltd.
This file is part of EDuke32. This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
EDuke32 is free software; you can redistribute it and/or as published by the Free Software Foundation; either version 2
modify it under the terms of the GNU General Public License version 2 of the License, or (at your option) any later version.
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -17,8 +15,19 @@ See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
*/ */
//------------------------------------------------------------------------- /**********************************************************************
module: MUSIC.H
author: James R. Dose
date: March 25, 1994
Public header for MUSIC.C
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef __MUSIC_H #ifndef __MUSIC_H
#define __MUSIC_H #define __MUSIC_H
@ -32,20 +41,52 @@ enum MUSIC_ERRORS
MUSIC_Warning = -2, MUSIC_Warning = -2,
MUSIC_Error = -1, MUSIC_Error = -1,
MUSIC_Ok = 0, MUSIC_Ok = 0,
MUSIC_ASSVersion,
MUSIC_SoundCardError,
MUSIC_MPU401Error,
MUSIC_InvalidCard,
MUSIC_MidiError, MUSIC_MidiError,
MUSIC_TaskManError,
MUSIC_DPMI_Error
}; };
typedef struct
{
uint32_t tickposition;
uint32_t milliseconds;
uint32_t measure;
uint32_t beat;
uint32_t tick;
} songposition;
#define MUSIC_LoopSong ( 1 == 1 ) #define MUSIC_LoopSong ( 1 == 1 )
#define MUSIC_PlayOnce ( !MUSIC_LoopSong ) #define MUSIC_PlayOnce ( !MUSIC_LoopSong )
const char *MUSIC_ErrorString( int32_t ErrorNumber ); const char *MUSIC_ErrorString( int32_t ErrorNumber );
int32_t MUSIC_Init(int32_t SoundCard); int32_t MUSIC_Init( int32_t SoundCard, int32_t Address );
int32_t MUSIC_Shutdown( void ); int32_t MUSIC_Shutdown( void );
void MUSIC_SetVolume( int32_t volume ); void MUSIC_SetVolume( int32_t volume );
void MUSIC_SetMidiChannelVolume( int32_t channel, int32_t volume );
void MUSIC_ResetMidiChannelVolumes( void );
int32_t MUSIC_GetVolume( void );
void MUSIC_SetLoopFlag( int32_t loopflag );
int32_t MUSIC_SongPlaying( void );
void MUSIC_Continue( void ); void MUSIC_Continue( void );
void MUSIC_Pause( void ); void MUSIC_Pause( void );
int32_t MUSIC_StopSong( void ); int32_t MUSIC_StopSong( void );
int32_t MUSIC_PlaySong( char *song, int32_t loopflag ); int32_t MUSIC_PlaySong( char *song, int32_t loopflag );
void MUSIC_SetContext( int32_t context );
int32_t MUSIC_GetContext( void );
void MUSIC_SetSongTick( uint32_t PositionInTicks );
void MUSIC_SetSongTime( uint32_t milliseconds );
void MUSIC_SetSongPosition( int32_t measure, int32_t beat, int32_t tick );
void MUSIC_GetSongPosition( songposition *pos );
void MUSIC_GetSongLength( songposition *pos );
int32_t MUSIC_FadeVolume( int32_t tovolume, int32_t milliseconds );
int32_t MUSIC_FadeActive( void );
void MUSIC_StopFade( void );
void MUSIC_RerouteMidiChannel( int32_t channel, int32_t ( *function )( int32_t, int32_t, int32_t ) );
void MUSIC_RegisterTimbreBank( char *timbres );
void MUSIC_Update(void); void MUSIC_Update(void);
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,10 @@
//-------------------------------------------------------------------------
/* /*
Copyright (C) 2016 EDuke32 developers and contributors Copyright (C) 1994-1995 Apogee Software, Ltd.
This file is part of EDuke32. This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
EDuke32 is free software; you can redistribute it and/or as published by the Free Software Foundation; either version 2
modify it under the terms of the GNU General Public License version 2 of the License, or (at your option) any later version.
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -17,14 +15,26 @@ See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
*/ */
//------------------------------------------------------------------------- /**********************************************************************
module: MIDI.H
author: James R. Dose
date: May 25, 1994
Public header for MIDI.C. Midi song file playback routines.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef __MIDI_H #ifndef __MIDI_H
#define __MIDI_H #define __MIDI_H
enum MIDI_Errors enum MIDI_Errors
{ {
MIDI_Warning = -2,
MIDI_Error = -1, MIDI_Error = -1,
MIDI_Ok = 0, MIDI_Ok = 0,
MIDI_NullMidiModule, MIDI_NullMidiModule,
@ -32,6 +42,8 @@ enum MIDI_Errors
MIDI_UnknownMidiFormat, MIDI_UnknownMidiFormat,
MIDI_NoTracks, MIDI_NoTracks,
MIDI_InvalidTrack, MIDI_InvalidTrack,
MIDI_NoMemory,
MIDI_DPMI_Error
}; };
@ -44,24 +56,44 @@ extern char MIDI_PatchMap[ 128 ];
typedef struct typedef struct
{ {
void(*NoteOff)(char channel, char key, char velocity); void ( *NoteOff )( int32_t channel, int32_t key, int32_t velocity );
void(*NoteOn)(char channel, char key, char velocity); void ( *NoteOn )( int32_t channel, int32_t key, int32_t velocity );
void(*PolyAftertouch)(char channel, char key, char pressure); void ( *PolyAftertouch )( int32_t channel, int32_t key, int32_t pressure );
void(*ControlChange)(char channel, char number, char value); void ( *ControlChange )( int32_t channel, int32_t number, int32_t value );
void(*ProgramChange)(char channel, char program); void ( *ProgramChange )( int32_t channel, int32_t program );
void(*ChannelAftertouch)(char channel, char pressure); void ( *ChannelAftertouch )( int32_t channel, int32_t pressure );
void(*PitchBend)(char channel, char lsb, char msb); void ( *PitchBend )( int32_t channel, int32_t lsb, int32_t msb );
void ( *ReleasePatches )( void );
void ( *LoadPatch )( int32_t number );
void ( *SetVolume )( int32_t volume );
int32_t ( *GetVolume )( void );
void ( *FinishBuffer )( void );
} midifuncs; } midifuncs;
void MIDI_RerouteMidiChannel( int32_t channel, int32_t ( *function )( int32_t event, int32_t c1, int32_t c2 ) );
int32_t MIDI_AllNotesOff( void ); int32_t MIDI_AllNotesOff( void );
void MIDI_SetUserChannelVolume( int32_t channel, int32_t volume );
void MIDI_ResetUserChannelVolume( void );
int32_t MIDI_Reset( void ); int32_t MIDI_Reset( void );
int32_t MIDI_SetVolume( int32_t volume ); int32_t MIDI_SetVolume( int32_t volume );
int32_t MIDI_GetVolume( void );
void MIDI_SetMidiFuncs( midifuncs *funcs ); void MIDI_SetMidiFuncs( midifuncs *funcs );
void MIDI_SetContext( int32_t context );
int32_t MIDI_GetContext( void );
void MIDI_SetLoopFlag( int32_t loopflag );
void MIDI_ContinueSong( void ); void MIDI_ContinueSong( void );
void MIDI_PauseSong( void ); void MIDI_PauseSong( void );
int32_t MIDI_SongPlaying( void );
void MIDI_StopSong( void ); void MIDI_StopSong( void );
int32_t MIDI_PlaySong( char *song, int32_t loopflag ); int32_t MIDI_PlaySong( char *song, int32_t loopflag );
void MIDI_SetTempo( int32_t tempo ); void MIDI_SetTempo( int32_t tempo );
int32_t MIDI_GetTempo( void );
void MIDI_SetSongTick( uint32_t PositionInTicks );
void MIDI_SetSongTime( uint32_t milliseconds );
void MIDI_SetSongPosition( int32_t measure, int32_t beat, int32_t tick );
void MIDI_GetSongPosition( songposition *pos );
void MIDI_GetSongLength( songposition *pos );
void MIDI_LoadTimbres( void );
void MIDI_UpdateMusic(void); void MIDI_UpdateMusic(void);
void MIDI_SetDivision( int32_t division ); void MIDI_SetDivision( int32_t division );

View file

@ -1,6 +1,6 @@
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/* /*
Copyright (C) 2016 EDuke32 developers and contributors Copyright (C) 2010 EDuke32 developers and contributors
This file is part of EDuke32. This file is part of EDuke32.
@ -20,6 +20,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/**********************************************************************
module: MPU401.C
author: James R. Dose
date: January 1, 1994
Low level routines to support sending of MIDI data to MPU401
compatible MIDI interfaces.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#include "mpu401.h" #include "mpu401.h"
#include "compat.h" #include "compat.h"
#include "pragmas.h" #include "pragmas.h"
@ -32,6 +44,13 @@ static HMIDISTRM hmido = (HMIDISTRM)-1;
static MIDIOUTCAPS midicaps; static MIDIOUTCAPS midicaps;
static DWORD mididevice = -1; static DWORD mididevice = -1;
typedef struct
{
int32_t time;
int32_t stream;
int32_t event;
}
MIDIEVENTHEAD;
#define PAD(x) ((((x)+3)&(~3))) #define PAD(x) ((((x)+3)&(~3)))
#define BUFFERLEN (32*4*4) #define BUFFERLEN (32*4*4)
@ -39,11 +58,11 @@ static DWORD mididevice = -1;
static char eventbuf[NUMBUFFERS][BUFFERLEN]; static char eventbuf[NUMBUFFERS][BUFFERLEN];
static int32_t eventcnt[NUMBUFFERS]; static int32_t eventcnt[NUMBUFFERS];
static MIDIHDR bufferheaders[NUMBUFFERS]; static MIDIHDR bufferheaders[NUMBUFFERS];
static int32_t _MPU_CurrentBuffer = 0; int32_t _MPU_CurrentBuffer = 0;
int32_t _MPU_BuffersWaiting = 0; int32_t _MPU_BuffersWaiting = 0;
extern uint32_t _MIDI_GlobalPositionInTicks; extern uint32_t _MIDI_GlobalPositionInTicks;
static uint32_t _MPU_LastEvent=0; uint32_t _MPU_LastEvent=0;
#define MIDI_NOTE_OFF 0x80 #define MIDI_NOTE_OFF 0x80
#define MIDI_NOTE_ON 0x90 #define MIDI_NOTE_ON 0x90
@ -58,6 +77,14 @@ static uint32_t _MPU_LastEvent=0;
#define MIDI_MONO_MODE_ON 0x7E #define MIDI_MONO_MODE_ON 0x7E
#define MIDI_ALL_NOTES_OFF 0x7B #define MIDI_ALL_NOTES_OFF 0x7B
/**********************************************************************
Memory locked functions:
**********************************************************************/
void MPU_FinishBuffer(int32_t buffer) void MPU_FinishBuffer(int32_t buffer)
{ {
if (!eventcnt[buffer]) return; if (!eventcnt[buffer]) return;
@ -90,6 +117,8 @@ void MPU_Unpause(void)
void CALLBACK MPU_MIDICallback(HMIDIOUT handle, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) void CALLBACK MPU_MIDICallback(HMIDIOUT handle, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{ {
int32_t i;
UNREFERENCED_PARAMETER(dwInstance); UNREFERENCED_PARAMETER(dwInstance);
UNREFERENCED_PARAMETER(dwParam2); UNREFERENCED_PARAMETER(dwParam2);
@ -97,7 +126,7 @@ void CALLBACK MPU_MIDICallback(HMIDIOUT handle, UINT uMsg, DWORD_PTR dwInstance,
{ {
case MOM_DONE: case MOM_DONE:
midiOutUnprepareHeader((HMIDIOUT)handle, (MIDIHDR *)dwParam1, sizeof(MIDIHDR)); midiOutUnprepareHeader((HMIDIOUT)handle, (MIDIHDR *)dwParam1, sizeof(MIDIHDR));
for (int i=0; i<NUMBUFFERS; i++) for (i=0; i<NUMBUFFERS; i++)
{ {
if ((MIDIHDR *)dwParam1 == &bufferheaders[i]) if ((MIDIHDR *)dwParam1 == &bufferheaders[i])
{ {
@ -113,27 +142,36 @@ void CALLBACK MPU_MIDICallback(HMIDIOUT handle, UINT uMsg, DWORD_PTR dwInstance,
} }
} }
/*---------------------------------------------------------------------
Function: MPU_SendMidi
Queues a MIDI message to the music device.
---------------------------------------------------------------------*/
int32_t MPU_GetNextBuffer(void) int32_t MPU_GetNextBuffer(void)
{ {
for (int i = 0; i < NUMBUFFERS; i++) int32_t i;
if (eventcnt[i] == 0) for (i=0; i<NUMBUFFERS; i++)
return i; {
if (eventcnt[i] == 0) return i;
}
return -1; return -1;
} }
static int32_t const masks[3] ={ 0x00ffffffl, 0x0000ffffl, 0x000000ffl };
void MPU_SendMidi(char *data, int32_t count) void MPU_SendMidi(char *data, int32_t count)
{ {
if (count <= 0) return; char *p;
int32_t padded, nextbuffer;
static int32_t masks[3] = { 0x000000ffl, 0x0000ffffl, 0x00ffffffl };
if (count <= 0) return;
if (count <= 3) if (count <= 3)
{ {
if (eventcnt[_MPU_CurrentBuffer] + 12 > BUFFERLEN) if (eventcnt[_MPU_CurrentBuffer] + 12 > BUFFERLEN)
{ {
// buffer over-full // buffer over-full
int32_t nextbuffer = MPU_GetNextBuffer(); nextbuffer = MPU_GetNextBuffer();
if (nextbuffer < 0) if (nextbuffer < 0)
{ {
// printf("All buffers full!\n"); // printf("All buffers full!\n");
@ -143,7 +181,7 @@ void MPU_SendMidi(char *data, int32_t count)
_MPU_CurrentBuffer = nextbuffer; _MPU_CurrentBuffer = nextbuffer;
} }
char *p = eventbuf[_MPU_CurrentBuffer] + eventcnt[_MPU_CurrentBuffer]; p = eventbuf[_MPU_CurrentBuffer] + eventcnt[_MPU_CurrentBuffer];
((int32_t *)p)[0] = _MIDI_GlobalPositionInTicks - _MPU_LastEvent; ((int32_t *)p)[0] = _MIDI_GlobalPositionInTicks - _MPU_LastEvent;
((int32_t *)p)[1] = 0; ((int32_t *)p)[1] = 0;
((int32_t *)p)[2] = (MEVT_SHORTMSG << 24) | ((*((int32_t *)data)) & masks[count-1]); ((int32_t *)p)[2] = (MEVT_SHORTMSG << 24) | ((*((int32_t *)data)) & masks[count-1]);
@ -151,11 +189,11 @@ void MPU_SendMidi(char *data, int32_t count)
} }
else else
{ {
int32_t padded = PAD(count); padded = PAD(count);
if (eventcnt[_MPU_CurrentBuffer] + 12 + padded > BUFFERLEN) if (eventcnt[_MPU_CurrentBuffer] + 12 + padded > BUFFERLEN)
{ {
// buffer over-full // buffer over-full
int32_t nextbuffer = MPU_GetNextBuffer(); nextbuffer = MPU_GetNextBuffer();
if (nextbuffer < 0) if (nextbuffer < 0)
{ {
// printf("All buffers full!\n"); // printf("All buffers full!\n");
@ -165,7 +203,7 @@ void MPU_SendMidi(char *data, int32_t count)
_MPU_CurrentBuffer = nextbuffer; _MPU_CurrentBuffer = nextbuffer;
} }
char *p = eventbuf[_MPU_CurrentBuffer] + eventcnt[_MPU_CurrentBuffer]; p = eventbuf[_MPU_CurrentBuffer] + eventcnt[_MPU_CurrentBuffer];
((int32_t *)p)[0] = _MIDI_GlobalPositionInTicks - _MPU_LastEvent; ((int32_t *)p)[0] = _MIDI_GlobalPositionInTicks - _MPU_LastEvent;
((int32_t *)p)[1] = 0; ((int32_t *)p)[1] = 0;
((int32_t *)p)[2] = (MEVT_LONGMSG<<24) | (count & 0xffffffl); ((int32_t *)p)[2] = (MEVT_LONGMSG<<24) | (count & 0xffffffl);
@ -178,69 +216,228 @@ void MPU_SendMidi(char *data, int32_t count)
_MPU_LastEvent = _MIDI_GlobalPositionInTicks; _MPU_LastEvent = _MIDI_GlobalPositionInTicks;
} }
int32_t MPU_Reset(void)
/*---------------------------------------------------------------------
Function: MPU_SendMidiImmediate
Sends a MIDI message immediately to the the music device.
---------------------------------------------------------------------*/
void MPU_SendMidiImmediate(char *data, int32_t count)
{
MIDIHDR mhdr;
static int32_t masks[3] = { 0x00ffffffl, 0x0000ffffl, 0x000000ffl };
if (!count) return;
if (count<=3) midiOutShortMsg((HMIDIOUT)hmido, (*((int32_t *)data)) & masks[count-1]);
else
{
ZeroMemory(&mhdr, sizeof(mhdr));
mhdr.lpData = data;
mhdr.dwBufferLength = count;
midiOutPrepareHeader((HMIDIOUT)hmido, &mhdr, sizeof(MIDIHDR));
midiOutLongMsg((HMIDIOUT)hmido, &mhdr, sizeof(MIDIHDR));
while (!(mhdr.dwFlags & MHDR_DONE)) ;
midiOutUnprepareHeader((HMIDIOUT)hmido, &mhdr, sizeof(MIDIHDR));
}
}
/*---------------------------------------------------------------------
Function: MPU_Reset
Resets the MPU401 card.
---------------------------------------------------------------------*/
int32_t MPU_Reset
(
void
)
{ {
midiStreamStop(hmido); midiStreamStop(hmido);
midiStreamClose(hmido); midiStreamClose(hmido);
return MPU_Ok; return(MPU_Ok);
} }
int32_t MPU_Init(int32_t addr)
/*---------------------------------------------------------------------
Function: MPU_Init
Detects and initializes the MPU401 card.
---------------------------------------------------------------------*/
int32_t MPU_Init
(
int32_t addr
)
{ {
for (int i=0; i<NUMBUFFERS; i++) eventcnt[i]=0; int32_t i;
for (i=0; i<NUMBUFFERS; i++) eventcnt[i]=0;
mididevice = addr; mididevice = addr;
if (midiOutGetDevCaps(mididevice, &midicaps, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR) return MPU_Error; if (midiOutGetDevCaps(mididevice, &midicaps, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR) return MPU_Error;
if (midiStreamOpen(&hmido,(LPUINT)&mididevice,1,(DWORD_PTR)MPU_MIDICallback,0L,CALLBACK_FUNCTION) != MMSYSERR_NOERROR) return MPU_Error; if (midiStreamOpen(&hmido,(LPUINT)&mididevice,1,(DWORD_PTR)MPU_MIDICallback,0L,CALLBACK_FUNCTION) != MMSYSERR_NOERROR) return(MPU_Error);
return MPU_Ok; return(MPU_Ok);
} }
void MPU_NoteOff(char channel, char key, char velocity)
/*---------------------------------------------------------------------
Function: MPU_NoteOff
Sends a full MIDI note off event out to the music device.
---------------------------------------------------------------------*/
void MPU_NoteOff
(
int32_t channel,
int32_t key,
int32_t velocity
)
{ {
char msg[] = { (char)(MIDI_NOTE_OFF | channel), key, velocity }; char msg[3];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_NOTE_OFF | channel);
msg[1] = (key);
msg[2] = (velocity);
MPU_SendMidi(msg, 3);
} }
void MPU_NoteOn(char channel, char key, char velocity)
/*---------------------------------------------------------------------
Function: MPU_NoteOn
Sends a full MIDI note on event out to the music device.
---------------------------------------------------------------------*/
void MPU_NoteOn
(
int32_t channel,
int32_t key,
int32_t velocity
)
{ {
char msg[] = { (char)(MIDI_NOTE_ON | channel), key, velocity }; char msg[3];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_NOTE_ON | channel);
msg[1] = (key);
msg[2] = (velocity);
MPU_SendMidi(msg, 3);
} }
void MPU_PolyAftertouch(char channel, char key, char pressure)
/*---------------------------------------------------------------------
Function: MPU_PolyAftertouch
Sends a full MIDI polyphonic aftertouch event out to the music device.
---------------------------------------------------------------------*/
void MPU_PolyAftertouch
(
int32_t channel,
int32_t key,
int32_t pressure
)
{ {
char msg[] = { (char) (MIDI_POLY_AFTER_TCH | channel), key, pressure }; char msg[3];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_POLY_AFTER_TCH | channel);
msg[1] = (key);
msg[2] = (pressure);
MPU_SendMidi(msg, 3);
} }
void MPU_ControlChange(char channel, char number, char value)
/*---------------------------------------------------------------------
Function: MPU_ControlChange
Sends a full MIDI control change event out to the music device.
---------------------------------------------------------------------*/
void MPU_ControlChange
(
int32_t channel,
int32_t number,
int32_t value
)
{ {
char msg[] = { (char) (MIDI_CONTROL_CHANGE | channel), number, value }; char msg[3];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_CONTROL_CHANGE | channel);
msg[1] = (number);
msg[2] = (value);
MPU_SendMidi(msg, 3);
} }
void MPU_ProgramChange(char channel, char program)
/*---------------------------------------------------------------------
Function: MPU_ProgramChange
Sends a full MIDI program change event out to the music device.
---------------------------------------------------------------------*/
void MPU_ProgramChange
(
int32_t channel,
int32_t program
)
{ {
char msg[] = { (char)(MIDI_PROGRAM_CHANGE | channel), program }; char msg[2];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_PROGRAM_CHANGE | channel);
msg[1] = (program);
MPU_SendMidi(msg, 2);
} }
void MPU_ChannelAftertouch(char channel, char pressure)
/*---------------------------------------------------------------------
Function: MPU_ChannelAftertouch
Sends a full MIDI channel aftertouch event out to the music device.
---------------------------------------------------------------------*/
void MPU_ChannelAftertouch
(
int32_t channel,
int32_t pressure
)
{ {
char msg[] = { (char)(MIDI_AFTER_TOUCH | channel), pressure }; char msg[2];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_AFTER_TOUCH | channel);
msg[1] = (pressure);
MPU_SendMidi(msg, 2);
} }
void MPU_PitchBend(char channel, char lsb, char msb)
/*---------------------------------------------------------------------
Function: MPU_PitchBend
Sends a full MIDI pitch bend event out to the music device.
---------------------------------------------------------------------*/
void MPU_PitchBend
(
int32_t channel,
int32_t lsb,
int32_t msb
)
{ {
char msg[] = { (char)(MIDI_PITCH_BEND | channel), lsb, msb }; char msg[3];
MPU_SendMidi(msg, sizeof(msg)); msg[0] = (MIDI_PITCH_BEND | channel);
msg[1] = (lsb);
msg[2] = (msb);
MPU_SendMidi(msg, 3);
} }
void MPU_SetTempo(int32_t tempo) void MPU_SetTempo(int32_t tempo)
{ {
MIDIPROPTEMPO prop; MIDIPROPTEMPO prop;
@ -257,3 +454,45 @@ void MPU_SetDivision(int32_t division)
midiStreamProperty(hmido, (LPBYTE)&prop, MIDIPROP_SET|MIDIPROP_TIMEDIV); midiStreamProperty(hmido, (LPBYTE)&prop, MIDIPROP_SET|MIDIPROP_TIMEDIV);
} }
void MPU_SetVolume(int32_t volume)
{
/*
HMIXER hmixer;
int32_t mixerid;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxcdu;
MMRESULT mme;
if (mididevice < 0) return;
mme = mixerOpen(&hmixer, mididevice, 0,0, MIXER_OBJECTF_MIDIOUT);
if (mme) {
puts("Failed opening mixer");
return;
}
mixerGetID(hmixer, &mixerid, MIXER_OBJECTF_HMIXER);
printf("mixerid=%d\n",mixerid);
ZeroMemory(&mxcd,sizeof(mxcd));
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = (LPVOID)&mxcdu;
mxcdu.dwValue = (volume << 8) & 0xffff;
printf("set %d\n",mixerSetControlDetails((HMIXEROBJ)mididevice, &mxcd,
MIXER_OBJECTF_MIDIOUT|MIXER_SETCONTROLDETAILSF_VALUE));
mixerClose(hmixer);
*/
UNREFERENCED_PARAMETER(volume);
}
int32_t MPU_GetVolume(void)
{
// if (mididevice < 0) return 0;
return 0;
}

View file

@ -1,12 +1,10 @@
//-------------------------------------------------------------------------
/* /*
Copyright (C) 2016 EDuke32 developers and contributors Copyright (C) 1994-1995 Apogee Software, Ltd.
This file is part of EDuke32. This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
EDuke32 is free software; you can redistribute it and/or as published by the Free Software Foundation; either version 2
modify it under the terms of the GNU General Public License version 2 of the License, or (at your option) any later version.
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -17,35 +15,51 @@ See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
*/
#ifndef __MPU401_H #ifndef __MPU401_H
#define __MPU401_H #define __MPU401_H
#include "compat.h" #include "compat.h"
#define MPU_DefaultAddress 0x330
enum MPU_ERRORS enum MPU_ERRORS
{ {
MPU_Warning = -2,
MPU_Error = -1, MPU_Error = -1,
MPU_Ok = 0 MPU_Ok = 0
}; };
#define MPU_NotFound -1
#define MPU_UARTFailed -2
#define MPU_ReadyToWrite 0x40
#define MPU_ReadyToRead 0x80
#define MPU_CmdEnterUART 0x3f
#define MPU_CmdReset 0xff
#define MPU_CmdAcknowledge 0xfe
extern int32_t _MPU_CurrentBuffer;
extern int32_t _MPU_BuffersWaiting; extern int32_t _MPU_BuffersWaiting;
void MPU_SendMidi( char *data, int32_t count ); void MPU_SendMidi( char *data, int32_t count );
void MPU_SendMidiImmediate( char *data, int32_t count );
int32_t MPU_Reset( void ); int32_t MPU_Reset( void );
int32_t MPU_Init( int32_t addr ); int32_t MPU_Init( int32_t addr );
void MPU_NoteOff( char channel, char key, char velocity ); void MPU_NoteOff( int32_t channel, int32_t key, int32_t velocity );
void MPU_NoteOn( char channel, char key, char velocity ); void MPU_NoteOn( int32_t channel, int32_t key, int32_t velocity );
void MPU_PolyAftertouch( char channel, char key, char pressure ); void MPU_PolyAftertouch( int32_t channel, int32_t key, int32_t pressure );
void MPU_ControlChange( char channel, char number, char value ); void MPU_ControlChange( int32_t channel, int32_t number, int32_t value );
void MPU_ProgramChange( char channel, char program ); void MPU_ProgramChange( int32_t channel, int32_t program );
void MPU_ChannelAftertouch( char channel, char pressure ); void MPU_ChannelAftertouch( int32_t channel, int32_t pressure );
void MPU_PitchBend( char channel, char lsb, char msb ); void MPU_PitchBend( int32_t channel, int32_t lsb, int32_t msb );
void MPU_SetTempo(int32_t tempo); void MPU_SetTempo(int32_t tempo);
void MPU_SetDivision(int32_t division); void MPU_SetDivision(int32_t division);
void MPU_SetVolume(int32_t volume);
int32_t MPU_GetVolume(void);
void MPU_BeginPlayback( void ); void MPU_BeginPlayback( void );
void MPU_Pause(void); void MPU_Pause(void);

View file

@ -1,6 +1,6 @@
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/* /*
Copyright (C) 2016 EDuke32 developers and contributors Copyright (C) 2010 EDuke32 developers and contributors
This file is part of EDuke32. This file is part of EDuke32.
@ -20,6 +20,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/**********************************************************************
module: MUSIC.C
author: James R. Dose
date: March 25, 1994
Device independant music playback routines.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "music.h" #include "music.h"
@ -27,16 +38,41 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mpu401.h" #include "mpu401.h"
#include "compat.h" #include "compat.h"
#ifndef TRUE
#define TRUE ( 1 == 1 )
#define FALSE ( !TRUE )
#endif
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef max
# define max(a,b) ( ((a) > (b)) ? (a) : (b) )
#endif
int32_t MUSIC_SoundDevice = -1; int32_t MUSIC_SoundDevice = -1;
int32_t MUSIC_ErrorCode = MUSIC_Ok; int32_t MUSIC_ErrorCode = MUSIC_Ok;
static midifuncs MUSIC_MidiFunctions; static midifuncs MUSIC_MidiFunctions;
int32_t MUSIC_InitMidi(midifuncs *Funcs); int32_t MUSIC_InitMidi(int32_t card, midifuncs *Funcs, int32_t Address);
#define MUSIC_SetErrorCode(status) MUSIC_ErrorCode = (status); #define MUSIC_SetErrorCode( status ) \
MUSIC_ErrorCode = ( status );
/*---------------------------------------------------------------------
Function: MUSIC_ErrorString
Returns a pointer to the error message associated with an error
number. A -1 returns a pointer the current error.
---------------------------------------------------------------------*/
const char *MUSIC_ErrorString
(
int32_t ErrorNumber
)
const char *MUSIC_ErrorString(int32_t ErrorNumber)
{ {
const char *ErrorString; const char *ErrorString;
@ -51,10 +87,33 @@ const char *MUSIC_ErrorString(int32_t ErrorNumber)
ErrorString = "Music ok."; ErrorString = "Music ok.";
break; break;
case MUSIC_ASSVersion :
ErrorString = "Apogee Sound System Version WinMM "
"Programmed by Jim Dose, Ported by Jonathon Fowler\n"
"(c) Copyright 1996 James R. Dose. All Rights Reserved.\n";
break;
case MUSIC_SoundCardError :
case MUSIC_MPU401Error :
ErrorString = "Could not detect MPU-401.";
break;
case MUSIC_InvalidCard :
ErrorString = "Invalid Music device.";
break;
case MUSIC_MidiError : case MUSIC_MidiError :
ErrorString = "Error playing MIDI file."; ErrorString = "Error playing MIDI file.";
break; break;
case MUSIC_TaskManError :
ErrorString = "TaskMan error.";
break;
case MUSIC_DPMI_Error :
ErrorString = "DPMI Error in MUSIC.";
break;
default : default :
ErrorString = "Unknown Music error code."; ErrorString = "Unknown Music error code.";
break; break;
@ -63,57 +122,371 @@ const char *MUSIC_ErrorString(int32_t ErrorNumber)
return(ErrorString); return(ErrorString);
} }
int32_t MUSIC_Init(int32_t SoundCard)
/*---------------------------------------------------------------------
Function: MUSIC_Init
Selects which sound device to use.
---------------------------------------------------------------------*/
int32_t MUSIC_Init
(
int32_t SoundCard,
int32_t Address
)
{
int32_t i;
int32_t status;
for (i = 0; i < 128; i++)
{ {
for (int i = 0; i < 128; i++)
MIDI_PatchMap[ i ] = i; MIDI_PatchMap[ i ] = i;
}
MUSIC_SoundDevice = SoundCard; MUSIC_SoundDevice = SoundCard;
return MUSIC_InitMidi(&MUSIC_MidiFunctions); status = MUSIC_InitMidi(SoundCard, &MUSIC_MidiFunctions, Address);
return(status);
} }
int32_t MUSIC_Shutdown(void)
/*---------------------------------------------------------------------
Function: MUSIC_Shutdown
Terminates use of sound device.
---------------------------------------------------------------------*/
int32_t MUSIC_Shutdown
(
void
)
{ {
int32_t status;
status = MUSIC_Ok;
MIDI_StopSong(); MIDI_StopSong();
return MUSIC_Ok; //MPU_Reset();
return(status);
} }
void MUSIC_SetVolume(int32_t volume)
{
volume = clamp(volume, 0, 255);
/*---------------------------------------------------------------------
Function: MUSIC_SetVolume
Sets the volume of music playback.
---------------------------------------------------------------------*/
void MUSIC_SetVolume
(
int32_t volume
)
{
volume = max(0, volume);
volume = min(volume, 255);
if (MUSIC_SoundDevice != -1) if (MUSIC_SoundDevice != -1)
{
MIDI_SetVolume(volume); MIDI_SetVolume(volume);
} }
}
void MUSIC_Continue(void) { MIDI_ContinueSong(); }
void MUSIC_Pause(void) { MIDI_PauseSong(); } /*---------------------------------------------------------------------
Function: MUSIC_SetMidiChannelVolume
Sets the volume of music playback on the specified MIDI channel.
---------------------------------------------------------------------*/
void MUSIC_SetMidiChannelVolume
(
int32_t channel,
int32_t volume
)
int32_t MUSIC_StopSong(void)
{ {
MIDI_SetUserChannelVolume(channel, volume);
}
/*---------------------------------------------------------------------
Function: MUSIC_ResetMidiChannelVolumes
Sets the volume of music playback on all MIDI channels to full volume.
---------------------------------------------------------------------*/
void MUSIC_ResetMidiChannelVolumes
(
void
)
{
MIDI_ResetUserChannelVolume();
}
/*---------------------------------------------------------------------
Function: MUSIC_GetVolume
Returns the volume of music playback.
---------------------------------------------------------------------*/
int32_t MUSIC_GetVolume
(
void
)
{
if (MUSIC_SoundDevice == -1)
{
return(0);
}
return(MIDI_GetVolume());
}
/*---------------------------------------------------------------------
Function: MUSIC_SetLoopFlag
Set whether the music will loop or end when it reaches the end of
the song.
---------------------------------------------------------------------*/
void MUSIC_SetLoopFlag
(
int32_t loopflag
)
{
MIDI_SetLoopFlag(loopflag);
}
/*---------------------------------------------------------------------
Function: MUSIC_SongPlaying
Returns whether there is a song playing.
---------------------------------------------------------------------*/
int32_t MUSIC_SongPlaying
(
void
)
{
return(MIDI_SongPlaying());
}
/*---------------------------------------------------------------------
Function: MUSIC_Continue
Continues playback of a paused song.
---------------------------------------------------------------------*/
void MUSIC_Continue
(
void
)
{
MIDI_ContinueSong();
}
/*---------------------------------------------------------------------
Function: MUSIC_Pause
Pauses playback of a song.
---------------------------------------------------------------------*/
void MUSIC_Pause
(
void
)
{
MIDI_PauseSong();
}
/*---------------------------------------------------------------------
Function: MUSIC_StopSong
Stops playback of current song.
---------------------------------------------------------------------*/
int32_t MUSIC_StopSong
(
void
)
{
MUSIC_StopFade();
MIDI_StopSong(); MIDI_StopSong();
MUSIC_SetErrorCode(MUSIC_Ok); MUSIC_SetErrorCode(MUSIC_Ok);
return MUSIC_Ok; return(MUSIC_Ok);
} }
int32_t MUSIC_PlaySong(char *song, int32_t loopflag)
/*---------------------------------------------------------------------
Function: MUSIC_PlaySong
Begins playback of MIDI song.
---------------------------------------------------------------------*/
int32_t MUSIC_PlaySong
(
char *song,
int32_t loopflag
)
{
int32_t status;
{ {
MUSIC_StopSong(); MUSIC_StopSong();
status = MIDI_PlaySong(song, loopflag);
if (MIDI_PlaySong(song, loopflag) != MIDI_Ok) if (status != MIDI_Ok)
{ {
MUSIC_SetErrorCode(MUSIC_MidiError); MUSIC_SetErrorCode(MUSIC_MidiError);
return MUSIC_Warning; return(MUSIC_Warning);
}
} }
return MUSIC_Ok; return(MUSIC_Ok);
} }
int32_t MUSIC_InitMidi(midifuncs *Funcs)
/*---------------------------------------------------------------------
Function: MUSIC_SetContext
Sets the song context.
---------------------------------------------------------------------*/
void MUSIC_SetContext
(
int32_t context
)
{ {
MIDI_SetContext(context);
}
/*---------------------------------------------------------------------
Function: MUSIC_GetContext
Returns the current song context.
---------------------------------------------------------------------*/
int32_t MUSIC_GetContext
(
void
)
{
return MIDI_GetContext();
}
/*---------------------------------------------------------------------
Function: MUSIC_SetSongTick
Sets the position of the song pointer.
---------------------------------------------------------------------*/
void MUSIC_SetSongTick
(
uint32_t PositionInTicks
)
{
MIDI_SetSongTick(PositionInTicks);
}
/*---------------------------------------------------------------------
Function: MUSIC_SetSongTime
Sets the position of the song pointer.
---------------------------------------------------------------------*/
void MUSIC_SetSongTime
(
uint32_t milliseconds
)
{
MIDI_SetSongTime(milliseconds);
}
/*---------------------------------------------------------------------
Function: MUSIC_SetSongPosition
Sets the position of the song pointer.
---------------------------------------------------------------------*/
void MUSIC_SetSongPosition
(
int32_t measure,
int32_t beat,
int32_t tick
)
{
MIDI_SetSongPosition(measure, beat, tick);
}
/*---------------------------------------------------------------------
Function: MUSIC_GetSongPosition
Returns the position of the song pointer.
---------------------------------------------------------------------*/
void MUSIC_GetSongPosition
(
songposition *pos
)
{
MIDI_GetSongPosition(pos);
}
/*---------------------------------------------------------------------
Function: MUSIC_GetSongLength
Returns the length of the song.
---------------------------------------------------------------------*/
void MUSIC_GetSongLength
(
songposition *pos
)
{
MIDI_GetSongLength(pos);
}
int32_t MUSIC_InitMidi
(
int32_t card,
midifuncs *Funcs,
int32_t Address
)
{
UNREFERENCED_PARAMETER(card);
UNREFERENCED_PARAMETER(Address);
Funcs->NoteOff = MPU_NoteOff; Funcs->NoteOff = MPU_NoteOff;
Funcs->NoteOn = MPU_NoteOn; Funcs->NoteOn = MPU_NoteOn;
Funcs->PolyAftertouch = MPU_PolyAftertouch; Funcs->PolyAftertouch = MPU_PolyAftertouch;
@ -121,12 +494,101 @@ int32_t MUSIC_InitMidi(midifuncs *Funcs)
Funcs->ProgramChange = MPU_ProgramChange; Funcs->ProgramChange = MPU_ProgramChange;
Funcs->ChannelAftertouch = MPU_ChannelAftertouch; Funcs->ChannelAftertouch = MPU_ChannelAftertouch;
Funcs->PitchBend = MPU_PitchBend; Funcs->PitchBend = MPU_PitchBend;
Funcs->ReleasePatches = NULL;
Funcs->LoadPatch = NULL;
Funcs->SetVolume = NULL /*MPU_SetVolume*/;
Funcs->GetVolume = NULL /*MPU_GetVolume*/;
MIDI_SetMidiFuncs(Funcs); MIDI_SetMidiFuncs(Funcs);
return MIDI_Ok; return(MIDI_Ok);
} }
/*---------------------------------------------------------------------
Function: MUSIC_FadeVolume
Fades music volume from current level to another over a specified
period of time.
---------------------------------------------------------------------*/
int32_t MUSIC_FadeVolume
(
int32_t tovolume,
int32_t milliseconds
)
{
UNREFERENCED_PARAMETER(milliseconds);
MIDI_SetVolume(tovolume);
return(MUSIC_Ok);
}
/*---------------------------------------------------------------------
Function: MUSIC_FadeActive
Returns whether the fade routine is active.
---------------------------------------------------------------------*/
int32_t MUSIC_FadeActive
(
void
)
{
return(0);
}
/*---------------------------------------------------------------------
Function: MUSIC_StopFade
Stops fading the music.
---------------------------------------------------------------------*/
void MUSIC_StopFade
(
void
)
{}
/*---------------------------------------------------------------------
Function: MUSIC_RerouteMidiChannel
Sets callback function to reroute MIDI commands from specified
function.
---------------------------------------------------------------------*/
void MUSIC_RerouteMidiChannel
(
int32_t channel,
int32_t(*function)(int32_t, int32_t, int32_t)
)
{
MIDI_RerouteMidiChannel(channel, function);
}
/*---------------------------------------------------------------------
Function: MUSIC_RegisterTimbreBank
Halts playback of all sounds.
---------------------------------------------------------------------*/
void MUSIC_RegisterTimbreBank
(
char *timbres
)
{
UNREFERENCED_PARAMETER(timbres);
}
void MUSIC_Update(void) void MUSIC_Update(void)
{ {
MIDI_UpdateMusic(); MIDI_UpdateMusic();

View file

@ -64,10 +64,12 @@ static int32_t external_midi = 0;
int32_t MUSIC_ErrorCode = MUSIC_Ok; int32_t MUSIC_ErrorCode = MUSIC_Ok;
static char warningMessage[80];
static char errorMessage[80]; static char errorMessage[80];
static int32_t music_initialized = 0; static int32_t music_initialized = 0;
static int32_t music_context = 0; static int32_t music_context = 0;
static int32_t music_loopflag = MUSIC_PlayOnce;
static Mix_Music *music_musicchunk = NULL; static Mix_Music *music_musicchunk = NULL;
static void setErrorMessage(const char *msg) static void setErrorMessage(const char *msg)
@ -81,45 +83,70 @@ const char *MUSIC_ErrorString(int32_t ErrorNumber)
{ {
switch (ErrorNumber) switch (ErrorNumber)
{ {
case MUSIC_Warning:
return(warningMessage);
case MUSIC_Error: case MUSIC_Error:
return errorMessage; return(errorMessage);
case MUSIC_Ok: case MUSIC_Ok:
return "OK; no error."; return("OK; no error.");
case MUSIC_ASSVersion:
return("Incorrect sound library version.");
case MUSIC_SoundCardError:
return("General sound card error.");
case MUSIC_InvalidCard:
return("Invalid sound card.");
case MUSIC_MidiError: case MUSIC_MidiError:
return "MIDI error."; return("MIDI error.");
case MUSIC_MPU401Error:
return("MPU401 error.");
case MUSIC_TaskManError:
return("Task Manager error.");
//case MUSIC_FMNotDetected:
// return("FM not detected error.");
case MUSIC_DPMI_Error:
return("DPMI error.");
default: default:
return "Unknown error."; return("Unknown error.");
} // switch } // switch
return NULL; return(NULL);
} // MUSIC_ErrorString } // MUSIC_ErrorString
int32_t MUSIC_Init(int32_t SoundCard) int32_t MUSIC_Init(int32_t SoundCard, int32_t Address)
{ {
#ifdef __ANDROID__ #ifdef __ANDROID__
music_initialized = 1; music_initialized = 1;
return MUSIC_Ok; return(MUSIC_Ok);
#endif #endif
// Use an external MIDI player if the user has specified to do so // Use an external MIDI player if the user has specified to do so
char *command = getenv("EDUKE32_MUSIC_CMD"); char *command = getenv("EDUKE32_MUSIC_CMD");
const SDL_version *linked = Mix_Linked_Version(); const SDL_version *linked = Mix_Linked_Version();
UNREFERENCED_PARAMETER(SoundCard); UNREFERENCED_PARAMETER(SoundCard);
UNREFERENCED_PARAMETER(Address);
if (music_initialized) if (music_initialized)
{ {
setErrorMessage("Music system is already initialized."); setErrorMessage("Music system is already initialized.");
return MUSIC_Error; return(MUSIC_Error);
} // if } // if
if (SDL_VERSIONNUM(linked->major,linked->minor,linked->patch) < MIX_REQUIREDVERSION) if (SDL_VERSIONNUM(linked->major,linked->minor,linked->patch) < MIX_REQUIREDVERSION)
{ {
// reject running with SDL_Mixer versions older than what is stated in sdl_inc.h // reject running with SDL_Mixer versions older than what is stated in sdl_inc.h
initprintf("You need at least v%d.%d.%d of SDL_mixer for music\n",SDL_MIXER_MIN_X,SDL_MIXER_MIN_Y,SDL_MIXER_MIN_Z); initprintf("You need at least v%d.%d.%d of SDL_mixer for music\n",SDL_MIXER_MIN_X,SDL_MIXER_MIN_Y,SDL_MIXER_MIN_Z);
return MUSIC_Error; return(MUSIC_Error);
} }
external_midi = (command != NULL && command[0] != 0); external_midi = (command != NULL && command[0] != 0);
@ -205,16 +232,18 @@ int32_t MUSIC_Init(int32_t SoundCard)
# endif # endif
#endif #endif
music_initialized = 1; music_initialized = 1;
return MUSIC_Ok; return(MUSIC_Ok);
fallback: fallback:
initprintf("Error setting music command, falling back to timidity.\n"); initprintf("Error setting music command, falling back to timidity.\n");
} }
{
static const char *s[] = { "/etc/timidity.cfg", "/etc/timidity/timidity.cfg", "/etc/timidity/freepats.cfg" }; static const char *s[] = { "/etc/timidity.cfg", "/etc/timidity/timidity.cfg", "/etc/timidity/freepats.cfg" };
FILE *fp; FILE *fp;
int32_t i;
for (int i = ARRAY_SIZE(s)-1; i>=0; i--) for (i = ARRAY_SIZE(s)-1; i>=0; i--)
{ {
fp = Bfopen(s[i], "r"); fp = Bfopen(s[i], "r");
if (fp == NULL) if (fp == NULL)
@ -224,16 +253,17 @@ fallback:
initprintf("Error: couldn't open any of the following files:\n"); initprintf("Error: couldn't open any of the following files:\n");
for (i = ARRAY_SIZE(s)-1; i>=0; i--) for (i = ARRAY_SIZE(s)-1; i>=0; i--)
initprintf("%s\n",s[i]); initprintf("%s\n",s[i]);
return MUSIC_Error; return(MUSIC_Error);
} }
continue; continue;
} }
else break; else break;
} }
Bfclose(fp); Bfclose(fp);
}
music_initialized = 1; music_initialized = 1;
return MUSIC_Ok; return(MUSIC_Ok);
} // MUSIC_Init } // MUSIC_Init
@ -248,11 +278,18 @@ int32_t MUSIC_Shutdown(void)
MUSIC_StopSong(); MUSIC_StopSong();
music_context = 0; music_context = 0;
music_initialized = 0; music_initialized = 0;
music_loopflag = MUSIC_PlayOnce;
return MUSIC_Ok; return(MUSIC_Ok);
} // MUSIC_Shutdown } // MUSIC_Shutdown
void MUSIC_SetMaxFMMidiChannel(int32_t channel)
{
UNREFERENCED_PARAMETER(channel);
} // MUSIC_SetMaxFMMidiChannel
void MUSIC_SetVolume(int32_t volume) void MUSIC_SetVolume(int32_t volume)
{ {
volume = max(0, volume); volume = max(0, volume);
@ -262,6 +299,36 @@ void MUSIC_SetVolume(int32_t volume)
} // MUSIC_SetVolume } // MUSIC_SetVolume
void MUSIC_SetMidiChannelVolume(int32_t channel, int32_t volume)
{
UNREFERENCED_PARAMETER(channel);
UNREFERENCED_PARAMETER(volume);
} // MUSIC_SetMidiChannelVolume
void MUSIC_ResetMidiChannelVolumes(void)
{
} // MUSIC_ResetMidiChannelVolumes
int32_t MUSIC_GetVolume(void)
{
return(Mix_VolumeMusic(-1) << 1); // convert 0-128 to 0-255.
} // MUSIC_GetVolume
void MUSIC_SetLoopFlag(int32_t loopflag)
{
music_loopflag = loopflag;
} // MUSIC_SetLoopFlag
int32_t MUSIC_SongPlaying(void)
{
return((Mix_PlayingMusic()) ? TRUE : FALSE);
} // MUSIC_SongPlaying
void MUSIC_Continue(void) void MUSIC_Continue(void)
{ {
if (Mix_PausedMusic()) if (Mix_PausedMusic())
@ -311,7 +378,7 @@ int32_t MUSIC_StopSong(void)
external_midi_pid = -1; external_midi_pid = -1;
} }
return MUSIC_Ok; return(MUSIC_Ok);
} }
#endif #endif
@ -319,7 +386,7 @@ int32_t MUSIC_StopSong(void)
if (!Mix_QuerySpec(NULL, NULL, NULL)) if (!Mix_QuerySpec(NULL, NULL, NULL))
{ {
setErrorMessage("Need FX system initialized, too. Sorry."); setErrorMessage("Need FX system initialized, too. Sorry.");
return MUSIC_Error; return(MUSIC_Error);
} // if } // if
if ((Mix_PlayingMusic()) || (Mix_PausedMusic())) if ((Mix_PlayingMusic()) || (Mix_PausedMusic()))
@ -330,7 +397,7 @@ int32_t MUSIC_StopSong(void)
music_musicchunk = NULL; music_musicchunk = NULL;
return MUSIC_Ok; return(MUSIC_Ok);
} // MUSIC_StopSong } // MUSIC_StopSong
#if defined FORK_EXEC_MIDI #if defined FORK_EXEC_MIDI
@ -437,5 +504,82 @@ int32_t MUSIC_PlaySong(char *song, int32_t loopflag)
return MUSIC_Ok; return MUSIC_Ok;
} }
void MUSIC_SetContext(int32_t context)
{
music_context = context;
} // MUSIC_SetContext
int32_t MUSIC_GetContext(void)
{
return(music_context);
} // MUSIC_GetContext
void MUSIC_SetSongTick(uint32_t PositionInTicks)
{
UNREFERENCED_PARAMETER(PositionInTicks);
} // MUSIC_SetSongTick
void MUSIC_SetSongTime(uint32_t milliseconds)
{
UNREFERENCED_PARAMETER(milliseconds);
}// MUSIC_SetSongTime
void MUSIC_SetSongPosition(int32_t measure, int32_t beat, int32_t tick)
{
UNREFERENCED_PARAMETER(measure);
UNREFERENCED_PARAMETER(beat);
UNREFERENCED_PARAMETER(tick);
} // MUSIC_SetSongPosition
void MUSIC_GetSongPosition(songposition *pos)
{
UNREFERENCED_PARAMETER(pos);
} // MUSIC_GetSongPosition
void MUSIC_GetSongLength(songposition *pos)
{
UNREFERENCED_PARAMETER(pos);
} // MUSIC_GetSongLength
int32_t MUSIC_FadeVolume(int32_t tovolume, int32_t milliseconds)
{
UNREFERENCED_PARAMETER(tovolume);
Mix_FadeOutMusic(milliseconds);
return(MUSIC_Ok);
} // MUSIC_FadeVolume
int32_t MUSIC_FadeActive(void)
{
return((Mix_FadingMusic() == MIX_FADING_OUT) ? TRUE : FALSE);
} // MUSIC_FadeActive
void MUSIC_StopFade(void)
{
} // MUSIC_StopFade
void MUSIC_RerouteMidiChannel(int32_t channel, int32_t (*function)(int32_t, int32_t, int32_t))
{
UNREFERENCED_PARAMETER(channel);
UNREFERENCED_PARAMETER(function);
} // MUSIC_RerouteMidiChannel
void MUSIC_RegisterTimbreBank(char *timbres)
{
UNREFERENCED_PARAMETER(timbres);
} // MUSIC_RegisterTimbreBank
void MUSIC_Update(void) void MUSIC_Update(void)
{} {}

View file

@ -101,7 +101,7 @@ void S_MusicStartup(void)
{ {
initprintf("Initializing music...\n"); initprintf("Initializing music...\n");
if (MUSIC_Init(0) == MUSIC_Ok || MUSIC_Init(1) == MUSIC_Ok) if (MUSIC_Init(0, 0) == MUSIC_Ok || MUSIC_Init(1, 0) == MUSIC_Ok)
{ {
MUSIC_SetVolume(MASTER_VOLUME(ud.config.MusicVolume)); MUSIC_SetVolume(MASTER_VOLUME(ud.config.MusicVolume));
return; return;