mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-12 19:20:38 +00:00
More audiolib work
git-svn-id: https://svn.eduke32.com/eduke32@8218 1a8010ca-5511-0410-912e-c29ae57300e0 # Conflicts: # source/audiolib/src/music.cpp # Conflicts: # GNUmakefile # platform/Windows/audiolib.vcxproj # platform/Windows/audiolib.vcxproj.filters # source/duke3d/src/menus.cpp
This commit is contained in:
parent
8b20118026
commit
8a1681fb5a
16 changed files with 412 additions and 719 deletions
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (C) 1994-1995 Apogee Software, Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
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
|
|
||||||
#define __MPU401_H
|
|
||||||
|
|
||||||
#include "compat.h"
|
|
||||||
|
|
||||||
#define MPU_DefaultAddress 0x330
|
|
||||||
|
|
||||||
enum MPU_ERRORS
|
|
||||||
{
|
|
||||||
MPU_Warning = -2,
|
|
||||||
MPU_Error = -1,
|
|
||||||
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 int _MPU_CurrentBuffer;
|
|
||||||
extern int _MPU_BuffersWaiting;
|
|
||||||
|
|
||||||
void MPU_SendMidi( char *data, int count );
|
|
||||||
void MPU_SendMidiImmediate( char *data, int count );
|
|
||||||
int MPU_Reset( void );
|
|
||||||
int MPU_Init( int addr );
|
|
||||||
void MPU_NoteOff( int channel, int key, int velocity );
|
|
||||||
void MPU_NoteOn( int channel, int key, int velocity );
|
|
||||||
void MPU_PolyAftertouch( int channel, int key, int pressure );
|
|
||||||
void MPU_ControlChange( int channel, int number, int value );
|
|
||||||
void MPU_ProgramChange( int channel, int program );
|
|
||||||
void MPU_ChannelAftertouch( int channel, int pressure );
|
|
||||||
void MPU_PitchBend( int channel, int lsb, int msb );
|
|
||||||
|
|
||||||
void MPU_SetTempo(int tempo);
|
|
||||||
void MPU_SetDivision(int division);
|
|
||||||
void MPU_SetVolume(int volume);
|
|
||||||
int MPU_GetVolume(void);
|
|
||||||
|
|
||||||
void MPU_BeginPlayback( void );
|
|
||||||
void MPU_Pause(void);
|
|
||||||
void MPU_Unpause(void);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -124,7 +124,7 @@ void MV_SetReverseStereo(int setting);
|
||||||
int MV_GetReverseStereo(void);
|
int MV_GetReverseStereo(void);
|
||||||
int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initdata);
|
int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initdata);
|
||||||
int MV_Shutdown(void);
|
int MV_Shutdown(void);
|
||||||
void MV_HookMusicRoutine(void (*callback)(char *buffer, int length));
|
void MV_HookMusicRoutine(void (*callback)(void));
|
||||||
void MV_UnhookMusicRoutine(void);
|
void MV_UnhookMusicRoutine(void);
|
||||||
|
|
||||||
static inline void MV_SetPrintf(void (*function)(const char *, ...)) { if (function) MV_Printf = function; }
|
static inline void MV_SetPrintf(void (*function)(const char *, ...)) { if (function) MV_Printf = function; }
|
||||||
|
|
|
@ -37,7 +37,6 @@ typedef enum
|
||||||
ASS_SDL,
|
ASS_SDL,
|
||||||
ASS_DirectSound,
|
ASS_DirectSound,
|
||||||
ASS_WinMM,
|
ASS_WinMM,
|
||||||
ASS_MPU401,
|
|
||||||
ASS_OPL3,
|
ASS_OPL3,
|
||||||
ASS_NumSoundCards,
|
ASS_NumSoundCards,
|
||||||
ASS_AutoDetect = -2
|
ASS_AutoDetect = -2
|
||||||
|
|
|
@ -48,6 +48,8 @@ namespace OPLMusic {
|
||||||
#define MIDI_PAN 10
|
#define MIDI_PAN 10
|
||||||
#define MIDI_DETUNE 94
|
#define MIDI_DETUNE 94
|
||||||
#define MIDI_RHYTHM_CHANNEL 9
|
#define MIDI_RHYTHM_CHANNEL 9
|
||||||
|
#define MIDI_BANK_SELECT_MSB 0
|
||||||
|
#define MIDI_BANK_SELECT_LSB 32
|
||||||
#define MIDI_RPN_MSB 100
|
#define MIDI_RPN_MSB 100
|
||||||
#define MIDI_RPN_LSB 101
|
#define MIDI_RPN_LSB 101
|
||||||
#define MIDI_DATAENTRY_MSB 6
|
#define MIDI_DATAENTRY_MSB 6
|
||||||
|
@ -67,8 +69,13 @@ namespace OPLMusic {
|
||||||
#define MIDI_SYSEX_CONTINUE 0xF7
|
#define MIDI_SYSEX_CONTINUE 0xF7
|
||||||
#define MIDI_META_EVENT 0xFF
|
#define MIDI_META_EVENT 0xFF
|
||||||
#define MIDI_END_OF_TRACK 0x2F
|
#define MIDI_END_OF_TRACK 0x2F
|
||||||
|
#define MIDI_HOLD1 0x40
|
||||||
|
#define MIDI_SOSTENUTO 0x42
|
||||||
#define MIDI_TEMPO_CHANGE 0x51
|
#define MIDI_TEMPO_CHANGE 0x51
|
||||||
#define MIDI_TIME_SIGNATURE 0x58
|
#define MIDI_TIME_SIGNATURE 0x58
|
||||||
|
#define MIDI_REVERB 0x5b
|
||||||
|
#define MIDI_CHORUS 0x5d
|
||||||
|
#define MIDI_ALL_SOUNDS_OFF 0x78
|
||||||
#define MIDI_RESET_ALL_CONTROLLERS 0x79
|
#define MIDI_RESET_ALL_CONTROLLERS 0x79
|
||||||
#define MIDI_ALL_NOTES_OFF 0x7b
|
#define MIDI_ALL_NOTES_OFF 0x7b
|
||||||
#define MIDI_MONO_MODE_ON 0x7E
|
#define MIDI_MONO_MODE_ON 0x7E
|
||||||
|
|
|
@ -231,6 +231,11 @@ extern Pan MV_PanTable[ MV_NUMPANPOSITIONS ][ MV_MAXVOLUME + 1 ];
|
||||||
extern int MV_ErrorCode;
|
extern int MV_ErrorCode;
|
||||||
extern int MV_Installed;
|
extern int MV_Installed;
|
||||||
extern int MV_MixRate;
|
extern int MV_MixRate;
|
||||||
|
extern char *MV_MusicBuffer;
|
||||||
|
extern int MV_BufferSize;
|
||||||
|
|
||||||
|
extern int MV_MIDIRenderTempo;
|
||||||
|
extern int MV_MIDIRenderTimer;
|
||||||
|
|
||||||
static FORCE_INLINE int MV_SetErrorCode(int status)
|
static FORCE_INLINE int MV_SetErrorCode(int status)
|
||||||
{
|
{
|
||||||
|
|
103
source/audiolib/src/driver_adlib.cpp
Normal file
103
source/audiolib/src/driver_adlib.cpp
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* Adlib MIDI output
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "driver_adlib.h"
|
||||||
|
|
||||||
|
#include "al_midi.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "midifuncs.h"
|
||||||
|
#include "midi.h"
|
||||||
|
#include "_multivc.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AdlibErr_Warning = -2,
|
||||||
|
AdlibErr_Error = -1,
|
||||||
|
AdlibErr_Ok = 0,
|
||||||
|
AdlibErr_Uninitialised,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ErrorCode = AdlibErr_Ok;
|
||||||
|
|
||||||
|
int AdlibDrv_GetError(void)
|
||||||
|
{
|
||||||
|
return ErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AdlibDrv_ErrorString( int ErrorNumber )
|
||||||
|
{
|
||||||
|
const char *ErrorString;
|
||||||
|
|
||||||
|
switch( ErrorNumber )
|
||||||
|
{
|
||||||
|
case AdlibErr_Warning :
|
||||||
|
case AdlibErr_Error :
|
||||||
|
ErrorString = AdlibDrv_ErrorString( ErrorCode );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AdlibErr_Ok :
|
||||||
|
ErrorString = "Adlib ok.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AdlibErr_Uninitialised:
|
||||||
|
ErrorString = "Adlib uninitialised.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ErrorString = "Unknown Adlib error.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AdlibDrv_MIDI_Init(midifuncs *funcs)
|
||||||
|
{
|
||||||
|
AdlibDrv_MIDI_Shutdown();
|
||||||
|
Bmemset(funcs, 0, sizeof(midifuncs));
|
||||||
|
|
||||||
|
funcs->NoteOff = OPLMusic::AL_NoteOff;
|
||||||
|
funcs->NoteOn = OPLMusic::AL_NoteOn;
|
||||||
|
funcs->PolyAftertouch = NULL;
|
||||||
|
funcs->ControlChange = OPLMusic::AL_ControlChange;
|
||||||
|
funcs->ProgramChange = OPLMusic::AL_ProgramChange;
|
||||||
|
funcs->ChannelAftertouch = NULL;
|
||||||
|
funcs->PitchBend = OPLMusic::AL_SetPitchBend;
|
||||||
|
|
||||||
|
return AdlibErr_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdlibDrv_MIDI_Shutdown(void)
|
||||||
|
{
|
||||||
|
AdlibDrv_MIDI_HaltPlayback();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AdlibDrv_MIDI_StartPlayback(void (*service)(void))
|
||||||
|
{
|
||||||
|
AdlibDrv_MIDI_HaltPlayback();
|
||||||
|
|
||||||
|
OPLMusic::AL_Init(MV_MixRate);
|
||||||
|
MV_HookMusicRoutine(service);
|
||||||
|
|
||||||
|
return MIDI_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdlibDrv_MIDI_HaltPlayback(void)
|
||||||
|
{
|
||||||
|
MV_UnhookMusicRoutine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdlibDrv_MIDI_SetTempo(int tempo, int division)
|
||||||
|
{
|
||||||
|
MV_MIDIRenderTempo = (tempo * division)/60;
|
||||||
|
MV_MIDIRenderTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdlibDrv_MIDI_Lock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdlibDrv_MIDI_Unlock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
32
source/audiolib/src/driver_adlib.h
Normal file
32
source/audiolib/src/driver_adlib.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midifuncs.h"
|
||||||
|
|
||||||
|
int AdlibDrv_GetError(void);
|
||||||
|
const char *AdlibDrv_ErrorString( int ErrorNumber );
|
||||||
|
|
||||||
|
int AdlibDrv_MIDI_Init(midifuncs *);
|
||||||
|
void AdlibDrv_MIDI_Shutdown(void);
|
||||||
|
int AdlibDrv_MIDI_StartPlayback(void (*service)(void));
|
||||||
|
void AdlibDrv_MIDI_HaltPlayback(void);
|
||||||
|
void AdlibDrv_MIDI_SetTempo(int tempo, int division);
|
||||||
|
void AdlibDrv_MIDI_Lock(void);
|
||||||
|
void AdlibDrv_MIDI_Unlock(void);
|
|
@ -65,7 +65,7 @@ static HANDLE midiMutex;
|
||||||
static BOOL midiStreamRunning;
|
static BOOL midiStreamRunning;
|
||||||
static int midiLastDivision;
|
static int midiLastDivision;
|
||||||
#define THREAD_QUEUE_INTERVAL 10 // 1/10 sec
|
#define THREAD_QUEUE_INTERVAL 10 // 1/10 sec
|
||||||
#define MIDI_BUFFER_SPACE (12*128) // 128 note-on events
|
#define MIDI_BUFFER_SPACE (12*128u) // 128 note-on events
|
||||||
|
|
||||||
typedef struct MidiBuffer {
|
typedef struct MidiBuffer {
|
||||||
struct MidiBuffer *next;
|
struct MidiBuffer *next;
|
||||||
|
@ -79,7 +79,6 @@ static volatile MidiBuffer activeMidiBuffers;
|
||||||
static volatile MidiBuffer spareMidiBuffers;
|
static volatile MidiBuffer spareMidiBuffers;
|
||||||
static MidiBuffer *currentMidiBuffer;
|
static MidiBuffer *currentMidiBuffer;
|
||||||
|
|
||||||
|
|
||||||
#define MIDI_NOTE_OFF 0x80
|
#define MIDI_NOTE_OFF 0x80
|
||||||
#define MIDI_NOTE_ON 0x90
|
#define MIDI_NOTE_ON 0x90
|
||||||
#define MIDI_POLY_AFTER_TCH 0xA0
|
#define MIDI_POLY_AFTER_TCH 0xA0
|
||||||
|
@ -94,8 +93,6 @@ static MidiBuffer *currentMidiBuffer;
|
||||||
#define MIDI_ALL_NOTES_OFF 0x7B
|
#define MIDI_ALL_NOTES_OFF 0x7B
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int WinMMDrv_GetError(void)
|
int WinMMDrv_GetError(void)
|
||||||
{
|
{
|
||||||
return ErrorCode;
|
return ErrorCode;
|
||||||
|
@ -357,7 +354,7 @@ static void midi_setup_event(int length, unsigned char ** data)
|
||||||
*/
|
*/
|
||||||
static BOOL midi_get_buffer(int length, unsigned char ** data)
|
static BOOL midi_get_buffer(int length, unsigned char ** data)
|
||||||
{
|
{
|
||||||
int datalen;
|
unsigned int datalen;
|
||||||
MidiBuffer * node;
|
MidiBuffer * node;
|
||||||
|
|
||||||
// determine the space to alloc.
|
// determine the space to alloc.
|
||||||
|
@ -646,6 +643,8 @@ static DWORD midi_get_tick(void)
|
||||||
|
|
||||||
static DWORD WINAPI midiDataThread(LPVOID lpParameter)
|
static DWORD WINAPI midiDataThread(LPVOID lpParameter)
|
||||||
{
|
{
|
||||||
|
UNREFERENCED_PARAMETER(lpParameter);
|
||||||
|
|
||||||
DWORD waitret;
|
DWORD waitret;
|
||||||
DWORD sequenceTime;
|
DWORD sequenceTime;
|
||||||
DWORD sleepAmount = 100 / THREAD_QUEUE_INTERVAL;
|
DWORD sleepAmount = 100 / THREAD_QUEUE_INTERVAL;
|
||||||
|
@ -677,7 +676,7 @@ static DWORD WINAPI midiDataThread(LPVOID lpParameter)
|
||||||
sequenceTime = midi_get_tick();
|
sequenceTime = midi_get_tick();
|
||||||
|
|
||||||
sleepAmount = 100 / THREAD_QUEUE_INTERVAL;
|
sleepAmount = 100 / THREAD_QUEUE_INTERVAL;
|
||||||
if ((int)(midiThreadTimer - sequenceTime) > midiThreadQueueTicks) {
|
if ((midiThreadTimer - sequenceTime) > midiThreadQueueTicks) {
|
||||||
// we're running ahead, so sleep for half the usual
|
// we're running ahead, so sleep for half the usual
|
||||||
// amount and try again
|
// amount and try again
|
||||||
sleepAmount /= 2;
|
sleepAmount /= 2;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "drivers.h"
|
#include "drivers.h"
|
||||||
|
|
||||||
#include "driver_nosound.h"
|
#include "driver_nosound.h"
|
||||||
|
#include "driver_adlib.h"
|
||||||
|
|
||||||
#ifdef RENDERTYPESDL
|
#ifdef RENDERTYPESDL
|
||||||
# include "driver_sdl.h"
|
# include "driver_sdl.h"
|
||||||
|
@ -141,50 +142,23 @@ static struct {
|
||||||
#else
|
#else
|
||||||
UNSUPPORTED_COMPLETELY
|
UNSUPPORTED_COMPLETELY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: create the driver functions for these
|
|
||||||
//
|
|
||||||
// older MPU-401 code...
|
|
||||||
#ifdef _WIN32
|
|
||||||
{
|
|
||||||
"MPU-401",
|
|
||||||
WinMMDrv_GetError,
|
|
||||||
WinMMDrv_ErrorString,
|
|
||||||
|
|
||||||
UNSUPPORTED_PCM,
|
|
||||||
|
|
||||||
WinMMDrv_MIDI_Init,
|
|
||||||
WinMMDrv_MIDI_Shutdown,
|
|
||||||
WinMMDrv_MIDI_StartPlayback,
|
|
||||||
WinMMDrv_MIDI_HaltPlayback,
|
|
||||||
WinMMDrv_MIDI_SetTempo,
|
|
||||||
WinMMDrv_MIDI_Lock,
|
|
||||||
WinMMDrv_MIDI_Unlock,
|
|
||||||
},
|
|
||||||
#else
|
|
||||||
UNSUPPORTED_COMPLETELY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// OPL3 emulation
|
// OPL3 emulation
|
||||||
{
|
{
|
||||||
"OPL3",
|
"Nuked OPL3",
|
||||||
WinMMDrv_GetError,
|
AdlibDrv_GetError,
|
||||||
WinMMDrv_ErrorString,
|
AdlibDrv_ErrorString,
|
||||||
|
|
||||||
UNSUPPORTED_PCM,
|
UNSUPPORTED_PCM,
|
||||||
|
|
||||||
WinMMDrv_MIDI_Init,
|
AdlibDrv_MIDI_Init,
|
||||||
WinMMDrv_MIDI_Shutdown,
|
AdlibDrv_MIDI_Shutdown,
|
||||||
WinMMDrv_MIDI_StartPlayback,
|
AdlibDrv_MIDI_StartPlayback,
|
||||||
WinMMDrv_MIDI_HaltPlayback,
|
AdlibDrv_MIDI_HaltPlayback,
|
||||||
WinMMDrv_MIDI_SetTempo,
|
AdlibDrv_MIDI_SetTempo,
|
||||||
WinMMDrv_MIDI_Lock,
|
AdlibDrv_MIDI_Lock,
|
||||||
WinMMDrv_MIDI_Unlock,
|
AdlibDrv_MIDI_Unlock,
|
||||||
},
|
},
|
||||||
#else
|
|
||||||
UNSUPPORTED_COMPLETELY
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "midi.h"
|
#include "midi.h"
|
||||||
|
|
||||||
#include "_midi.h"
|
#include "_midi.h"
|
||||||
|
#include "_multivc.h"
|
||||||
#include "al_midi.h"
|
#include "al_midi.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "mpu401.h"
|
|
||||||
#include "multivoc.h"
|
#include "multivoc.h"
|
||||||
#include "music.h"
|
#include "music.h"
|
||||||
#include "pragmas.h"
|
#include "pragmas.h"
|
||||||
#include "sndcards.h"
|
#include "sndcards.h"
|
||||||
#include "windows_inc.h"
|
|
||||||
|
|
||||||
extern int MV_MixRate;
|
extern int MV_MixRate;
|
||||||
extern int ASS_MIDISoundDriver;
|
extern int ASS_MIDISoundDriver;
|
||||||
|
@ -87,11 +86,10 @@ static midifuncs *_MIDI_Funcs;
|
||||||
|
|
||||||
static int _MIDI_Reset;
|
static int _MIDI_Reset;
|
||||||
|
|
||||||
int MIDI_Tempo = 120;
|
static int MIDI_Tempo = 120;
|
||||||
|
|
||||||
static int _MIDI_PlayRoutine = -1;
|
int MV_MIDIRenderTempo = -1;
|
||||||
static int _MIDI_MixRate = 44100;
|
int MV_MIDIRenderTimer;
|
||||||
static int _MIDI_MixTimer;
|
|
||||||
|
|
||||||
static int _MIDI_ReadNumber(void *from, size_t size)
|
static int _MIDI_ReadNumber(void *from, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -521,13 +519,18 @@ static int _MIDI_SendControlChange(int channel, int c1, int c2)
|
||||||
|
|
||||||
int MIDI_AllNotesOff(void)
|
int MIDI_AllNotesOff(void)
|
||||||
{
|
{
|
||||||
|
SoundDriver_MIDI_Lock();
|
||||||
|
|
||||||
for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++)
|
for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++)
|
||||||
{
|
{
|
||||||
_MIDI_SendControlChange(channel, 0x40, 0);
|
_MIDI_SendControlChange(channel, MIDI_HOLD1, 0);
|
||||||
|
_MIDI_SendControlChange(channel, MIDI_SOSTENUTO, 0);
|
||||||
_MIDI_SendControlChange(channel, MIDI_ALL_NOTES_OFF, 0);
|
_MIDI_SendControlChange(channel, MIDI_ALL_NOTES_OFF, 0);
|
||||||
_MIDI_SendControlChange(channel, 0x78, 0);
|
_MIDI_SendControlChange(channel, MIDI_ALL_SOUNDS_OFF, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SoundDriver_MIDI_Unlock();
|
||||||
|
|
||||||
return MIDI_Ok;
|
return MIDI_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,6 +557,8 @@ int MIDI_Reset(void)
|
||||||
{
|
{
|
||||||
MIDI_AllNotesOff();
|
MIDI_AllNotesOff();
|
||||||
|
|
||||||
|
SoundDriver_MIDI_Lock();
|
||||||
|
|
||||||
for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++)
|
for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++)
|
||||||
{
|
{
|
||||||
_MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0);
|
_MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0);
|
||||||
|
@ -566,6 +571,8 @@ int MIDI_Reset(void)
|
||||||
|
|
||||||
_MIDI_SendChannelVolumes();
|
_MIDI_SendChannelVolumes();
|
||||||
|
|
||||||
|
SoundDriver_MIDI_Unlock();
|
||||||
|
|
||||||
_MIDI_Reset = TRUE;
|
_MIDI_Reset = TRUE;
|
||||||
|
|
||||||
return MIDI_Ok;
|
return MIDI_Ok;
|
||||||
|
@ -615,8 +622,6 @@ void MIDI_ContinueSong(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_MIDI_SongActive = TRUE;
|
_MIDI_SongActive = TRUE;
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
|
||||||
MPU_Unpause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIDI_PauseSong(void)
|
void MIDI_PauseSong(void)
|
||||||
|
@ -626,8 +631,6 @@ void MIDI_PauseSong(void)
|
||||||
|
|
||||||
_MIDI_SongActive = FALSE;
|
_MIDI_SongActive = FALSE;
|
||||||
MIDI_AllNotesOff();
|
MIDI_AllNotesOff();
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
|
||||||
MPU_Pause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIDI_SetMidiFuncs(midifuncs *funcs) { _MIDI_Funcs = funcs; }
|
void MIDI_SetMidiFuncs(midifuncs *funcs) { _MIDI_Funcs = funcs; }
|
||||||
|
@ -637,15 +640,11 @@ void MIDI_StopSong(void)
|
||||||
if (!_MIDI_SongLoaded)
|
if (!_MIDI_SongLoaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SoundDriver_MIDI_HaltPlayback();
|
||||||
|
|
||||||
_MIDI_SongActive = FALSE;
|
_MIDI_SongActive = FALSE;
|
||||||
_MIDI_SongLoaded = FALSE;
|
_MIDI_SongLoaded = FALSE;
|
||||||
|
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
|
||||||
{
|
|
||||||
MPU_Reset();
|
|
||||||
MPU_Init(ASS_MIDISoundDriver);
|
|
||||||
}
|
|
||||||
|
|
||||||
MIDI_Reset();
|
MIDI_Reset();
|
||||||
_MIDI_ResetTracks();
|
_MIDI_ResetTracks();
|
||||||
|
|
||||||
|
@ -658,10 +657,6 @@ void MIDI_StopSong(void)
|
||||||
_MIDI_TotalTicks = 0;
|
_MIDI_TotalTicks = 0;
|
||||||
_MIDI_TotalBeats = 0;
|
_MIDI_TotalBeats = 0;
|
||||||
_MIDI_TotalMeasures = 0;
|
_MIDI_TotalMeasures = 0;
|
||||||
|
|
||||||
if (ASS_MIDISoundDriver == ASS_OPL3)
|
|
||||||
MV_UnhookMusicRoutine();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MIDI_PlaySong(char *song, int loopflag)
|
int MIDI_PlaySong(char *song, int loopflag)
|
||||||
|
@ -728,16 +723,6 @@ int MIDI_PlaySong(char *song, int loopflag)
|
||||||
if (_MIDI_SongLoaded)
|
if (_MIDI_SongLoaded)
|
||||||
MIDI_StopSong();
|
MIDI_StopSong();
|
||||||
|
|
||||||
switch (ASS_MIDISoundDriver)
|
|
||||||
{
|
|
||||||
case ASS_MPU401:
|
|
||||||
MPU_Init(0/*MUSIC_SoundDevice*/);
|
|
||||||
break;
|
|
||||||
case ASS_OPL3:
|
|
||||||
OPLMusic::AL_Init(MV_MixRate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_MIDI_Loop = loopflag;
|
_MIDI_Loop = loopflag;
|
||||||
_MIDI_NumTracks = My_MIDI_NumTracks;
|
_MIDI_NumTracks = My_MIDI_NumTracks;
|
||||||
|
@ -753,59 +738,34 @@ int MIDI_PlaySong(char *song, int loopflag)
|
||||||
|
|
||||||
_MIDI_Reset = FALSE;
|
_MIDI_Reset = FALSE;
|
||||||
|
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
if (ASS_MIDISoundDriver == ASS_OPL3)
|
||||||
{
|
{
|
||||||
MIDI_SetDivision(_MIDI_Division);
|
MV_MIDIRenderTempo = 100;
|
||||||
//MIDI_SetTempo( 120 );
|
MV_MIDIRenderTimer = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_MIDI_PlayRoutine = 100;
|
|
||||||
_MIDI_MixTimer = 0;
|
|
||||||
|
|
||||||
//MIDI_SetDivision(_MIDI_Division);
|
MIDI_SetTempo(120);
|
||||||
MIDI_SetTempo( 120 );
|
|
||||||
}
|
if (SoundDriver_MIDI_StartPlayback(ASS_MIDISoundDriver == ASS_OPL3 ? MV_RenderMIDI : _MIDI_ServiceRoutine) != MIDI_Ok)
|
||||||
|
return MIDI_DriverError;
|
||||||
|
|
||||||
_MIDI_SongLoaded = TRUE;
|
_MIDI_SongLoaded = TRUE;
|
||||||
_MIDI_SongActive = TRUE;
|
_MIDI_SongActive = TRUE;
|
||||||
|
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
|
||||||
{
|
|
||||||
while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine();
|
|
||||||
MPU_BeginPlayback();
|
|
||||||
}
|
|
||||||
else if (ASS_MIDISoundDriver == ASS_OPL3)
|
|
||||||
{
|
|
||||||
MV_HookMusicRoutine(MIDI_MusicMix);
|
|
||||||
_MIDI_MixRate = MV_MixRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIDI_Ok;
|
return MIDI_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIDI_SetTempo(int tempo)
|
void MIDI_SetTempo(int tempo)
|
||||||
{
|
{
|
||||||
int tickspersecond;
|
|
||||||
|
|
||||||
MIDI_Tempo = tempo;
|
MIDI_Tempo = tempo;
|
||||||
tickspersecond = ((tempo) * _MIDI_Division)/60;
|
SoundDriver_MIDI_SetTempo(tempo, _MIDI_Division);
|
||||||
|
int const tickspersecond = tempo * _MIDI_Division / 60;
|
||||||
_MIDI_FPSecondsPerTick = tabledivide32_noinline(1 << TIME_PRECISION, tickspersecond);
|
_MIDI_FPSecondsPerTick = tabledivide32_noinline(1 << TIME_PRECISION, tickspersecond);
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
|
||||||
{
|
|
||||||
MPU_SetTempo(tempo);
|
|
||||||
}
|
|
||||||
else if (ASS_MIDISoundDriver == ASS_OPL3)
|
|
||||||
{
|
|
||||||
_MIDI_PlayRoutine = tickspersecond;
|
|
||||||
_MIDI_MixTimer = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIDI_SetDivision(int division)
|
void MIDI_SetDivision(int division)
|
||||||
{
|
{
|
||||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
UNREFERENCED_PARAMETER(division);
|
||||||
MPU_SetDivision(division);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MIDI_GetTempo(void) { return MIDI_Tempo; }
|
int MIDI_GetTempo(void) { return MIDI_Tempo; }
|
||||||
|
@ -816,9 +776,6 @@ static void _MIDI_InitEMIDI(void)
|
||||||
|
|
||||||
switch (ASS_MIDISoundDriver)
|
switch (ASS_MIDISoundDriver)
|
||||||
{
|
{
|
||||||
case ASS_MPU401:
|
|
||||||
type = EMIDI_GeneralMIDI;
|
|
||||||
break;
|
|
||||||
case ASS_OPL3:
|
case ASS_OPL3:
|
||||||
type = EMIDI_Adlib;
|
type = EMIDI_Adlib;
|
||||||
break;
|
break;
|
||||||
|
@ -1026,21 +983,21 @@ static void _MIDI_InitEMIDI(void)
|
||||||
_MIDI_ResetTracks();
|
_MIDI_ResetTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIDI_MusicMix(char *buffer, int length)
|
void MV_RenderMIDI(void)
|
||||||
{
|
{
|
||||||
int16_t * buffer16 = (int16_t *)buffer;
|
int16_t * buffer16 = (int16_t *)MV_MusicBuffer;
|
||||||
int const samples = length >> 2;
|
int const samples = MV_BufferSize >> 2;
|
||||||
|
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
{
|
{
|
||||||
Bit16s buf[2];
|
Bit16s buf[2];
|
||||||
while (_MIDI_MixTimer >= _MIDI_MixRate)
|
while (MV_MIDIRenderTimer >= MV_MixRate)
|
||||||
{
|
{
|
||||||
if (_MIDI_PlayRoutine >= 0)
|
if (MV_MIDIRenderTempo >= 0)
|
||||||
_MIDI_ServiceRoutine();
|
_MIDI_ServiceRoutine();
|
||||||
_MIDI_MixTimer -= _MIDI_MixRate;
|
MV_MIDIRenderTimer -= MV_MixRate;
|
||||||
}
|
}
|
||||||
if (_MIDI_PlayRoutine >= 0) _MIDI_MixTimer += _MIDI_PlayRoutine;
|
if (MV_MIDIRenderTempo >= 0) MV_MIDIRenderTimer += MV_MIDIRenderTempo;
|
||||||
OPL3_GenerateResampled(&OPLMusic::chip, buf);
|
OPL3_GenerateResampled(&OPLMusic::chip, buf);
|
||||||
*buffer16++ = clamp(buf[0]<<1, INT16_MIN, INT16_MAX);
|
*buffer16++ = clamp(buf[0]<<1, INT16_MIN, INT16_MAX);
|
||||||
*buffer16++ = clamp(buf[1]<<1, INT16_MIN, INT16_MAX);
|
*buffer16++ = clamp(buf[1]<<1, INT16_MIN, INT16_MAX);
|
||||||
|
@ -1050,7 +1007,6 @@ void MIDI_MusicMix(char *buffer, int length)
|
||||||
|
|
||||||
void MIDI_UpdateMusic(void)
|
void MIDI_UpdateMusic(void)
|
||||||
{
|
{
|
||||||
if (!_MIDI_SongLoaded || !_MIDI_SongActive) return;
|
|
||||||
while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,20 +54,20 @@ enum MIDI_Errors
|
||||||
|
|
||||||
#define MIDI_MaxVolume 255
|
#define MIDI_MaxVolume 255
|
||||||
|
|
||||||
int MIDI_AllNotesOff(void);
|
int MIDI_AllNotesOff(void);
|
||||||
int MIDI_Reset(void);
|
int MIDI_Reset(void);
|
||||||
int MIDI_SetVolume(int volume);
|
int MIDI_SetVolume(int volume);
|
||||||
int MIDI_GetVolume(void);
|
int MIDI_GetVolume(void);
|
||||||
void MIDI_SetMidiFuncs(midifuncs *funcs);
|
void MIDI_SetMidiFuncs(midifuncs *funcs);
|
||||||
void MIDI_SetLoopFlag(int loopflag);
|
void MIDI_SetLoopFlag(int loopflag);
|
||||||
void MIDI_ContinueSong(void);
|
void MIDI_ContinueSong(void);
|
||||||
void MIDI_PauseSong(void);
|
void MIDI_PauseSong(void);
|
||||||
void MIDI_StopSong(void);
|
void MIDI_StopSong(void);
|
||||||
int MIDI_PlaySong(char *song, int loopflag);
|
int MIDI_PlaySong(char *song, int loopflag);
|
||||||
void MIDI_SetTempo(int tempo);
|
void MIDI_SetTempo(int tempo);
|
||||||
int MIDI_GetTempo(void);
|
int MIDI_GetTempo(void);
|
||||||
void MIDI_MusicMix(char *buffer, int length);
|
void MV_RenderMIDI(void);
|
||||||
void MIDI_UpdateMusic(void);
|
void MIDI_UpdateMusic(void);
|
||||||
void MIDI_SetDivision(int division);
|
void MIDI_SetDivision(int division);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,497 +0,0 @@
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
||||||
Copyright (C) 2019 Nuke.YKT
|
|
||||||
|
|
||||||
This file is part of NBlood.
|
|
||||||
|
|
||||||
NBlood is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License version 2
|
|
||||||
as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
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.
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
// This object is shared by all Build games with MIDI playback!
|
|
||||||
|
|
||||||
#include "mpu401.h"
|
|
||||||
#include "compat.h"
|
|
||||||
#include "pragmas.h"
|
|
||||||
|
|
||||||
#define NEED_MMSYSTEM_H
|
|
||||||
#include "windows_inc.h"
|
|
||||||
|
|
||||||
static HMIDISTRM hmido = (HMIDISTRM)-1;
|
|
||||||
static MIDIOUTCAPS midicaps;
|
|
||||||
static DWORD mididevice = -1;
|
|
||||||
|
|
||||||
#define PAD(x) ((((x)+3)&(~3)))
|
|
||||||
|
|
||||||
#define BUFFERLEN (32*4*4)
|
|
||||||
#define NUMBUFFERS 6
|
|
||||||
static char eventbuf[NUMBUFFERS][BUFFERLEN];
|
|
||||||
static int eventcnt[NUMBUFFERS];
|
|
||||||
static MIDIHDR bufferheaders[NUMBUFFERS];
|
|
||||||
int _MPU_CurrentBuffer = 0;
|
|
||||||
int _MPU_BuffersWaiting = 0;
|
|
||||||
|
|
||||||
extern uint32_t _MIDI_GlobalPositionInTicks;
|
|
||||||
uint32_t _MPU_LastEvent=0;
|
|
||||||
|
|
||||||
#define MIDI_NOTE_OFF 0x80
|
|
||||||
#define MIDI_NOTE_ON 0x90
|
|
||||||
#define MIDI_POLY_AFTER_TCH 0xA0
|
|
||||||
#define MIDI_CONTROL_CHANGE 0xB0
|
|
||||||
#define MIDI_PROGRAM_CHANGE 0xC0
|
|
||||||
#define MIDI_AFTER_TOUCH 0xD0
|
|
||||||
#define MIDI_PITCH_BEND 0xE0
|
|
||||||
#define MIDI_META_EVENT 0xFF
|
|
||||||
#define MIDI_END_OF_TRACK 0x2F
|
|
||||||
#define MIDI_TEMPO_CHANGE 0x51
|
|
||||||
#define MIDI_MONO_MODE_ON 0x7E
|
|
||||||
#define MIDI_ALL_NOTES_OFF 0x7B
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
|
|
||||||
Memory locked functions:
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
void MPU_FinishBuffer(int buffer)
|
|
||||||
{
|
|
||||||
if (!eventcnt[buffer]) return;
|
|
||||||
ZeroMemory(&bufferheaders[buffer], sizeof(MIDIHDR));
|
|
||||||
bufferheaders[buffer].lpData = eventbuf[buffer];
|
|
||||||
bufferheaders[buffer].dwBufferLength =
|
|
||||||
bufferheaders[buffer].dwBytesRecorded = eventcnt[buffer];
|
|
||||||
midiOutPrepareHeader((HMIDIOUT)hmido, &bufferheaders[buffer], sizeof(MIDIHDR));
|
|
||||||
midiStreamOut(hmido, &bufferheaders[buffer], sizeof(MIDIHDR));
|
|
||||||
// printf("Sending %d bytes (buffer %d)\n",eventcnt[buffer],buffer);
|
|
||||||
_MPU_BuffersWaiting++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU_BeginPlayback(void)
|
|
||||||
{
|
|
||||||
_MPU_LastEvent = _MIDI_GlobalPositionInTicks;
|
|
||||||
if (hmido != (HMIDISTRM)-1) midiStreamRestart(hmido);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU_Pause(void)
|
|
||||||
{
|
|
||||||
if (hmido != (HMIDISTRM)-1) midiStreamPause(hmido);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU_Unpause(void)
|
|
||||||
{
|
|
||||||
if (hmido != (HMIDISTRM)-1) midiStreamRestart(hmido);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CALLBACK MPU_MIDICallback(HMIDIOUT handle, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(dwInstance);
|
|
||||||
UNREFERENCED_PARAMETER(dwParam2);
|
|
||||||
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case MOM_DONE:
|
|
||||||
midiOutUnprepareHeader((HMIDIOUT)handle, (MIDIHDR *)dwParam1, sizeof(MIDIHDR));
|
|
||||||
for (i=0; i<NUMBUFFERS; i++)
|
|
||||||
{
|
|
||||||
if ((MIDIHDR *)dwParam1 == &bufferheaders[i])
|
|
||||||
{
|
|
||||||
eventcnt[i] = 0; // marks the buffer as free
|
|
||||||
// printf("Finished buffer %d\n",i);
|
|
||||||
_MPU_BuffersWaiting--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_SendMidi
|
|
||||||
|
|
||||||
Queues a MIDI message to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int MPU_GetNextBuffer(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0; i<NUMBUFFERS; i++)
|
|
||||||
{
|
|
||||||
if (eventcnt[i] == 0) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU_SendMidi(char *data, int count)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
int padded, nextbuffer;
|
|
||||||
static int masks[3] = { 0x000000ffl, 0x0000ffffl, 0x00ffffffl };
|
|
||||||
|
|
||||||
if (count <= 0) return;
|
|
||||||
if (count <= 3)
|
|
||||||
{
|
|
||||||
if (eventcnt[_MPU_CurrentBuffer] + 12 > BUFFERLEN)
|
|
||||||
{
|
|
||||||
// buffer over-full
|
|
||||||
nextbuffer = MPU_GetNextBuffer();
|
|
||||||
if (nextbuffer < 0)
|
|
||||||
{
|
|
||||||
// printf("All buffers full!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MPU_FinishBuffer(_MPU_CurrentBuffer);
|
|
||||||
_MPU_CurrentBuffer = nextbuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = eventbuf[_MPU_CurrentBuffer] + eventcnt[_MPU_CurrentBuffer];
|
|
||||||
((int *)p)[0] = _MIDI_GlobalPositionInTicks - _MPU_LastEvent;
|
|
||||||
((int *)p)[1] = 0;
|
|
||||||
((int *)p)[2] = (MEVT_SHORTMSG << 24) | ((*((int *)data)) & masks[count-1]);
|
|
||||||
eventcnt[_MPU_CurrentBuffer] += 12;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
padded = PAD(count);
|
|
||||||
if (eventcnt[_MPU_CurrentBuffer] + 12 + padded > BUFFERLEN)
|
|
||||||
{
|
|
||||||
// buffer over-full
|
|
||||||
nextbuffer = MPU_GetNextBuffer();
|
|
||||||
if (nextbuffer < 0)
|
|
||||||
{
|
|
||||||
// printf("All buffers full!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MPU_FinishBuffer(_MPU_CurrentBuffer);
|
|
||||||
_MPU_CurrentBuffer = nextbuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = eventbuf[_MPU_CurrentBuffer] + eventcnt[_MPU_CurrentBuffer];
|
|
||||||
((int *)p)[0] = _MIDI_GlobalPositionInTicks - _MPU_LastEvent;
|
|
||||||
((int *)p)[1] = 0;
|
|
||||||
((int *)p)[2] = (MEVT_LONGMSG<<24) | (count & 0xffffffl);
|
|
||||||
p+=12; eventcnt[_MPU_CurrentBuffer] += 12;
|
|
||||||
for (; count>0; count--, padded--, eventcnt[_MPU_CurrentBuffer]++)
|
|
||||||
*(p++) = *(data++);
|
|
||||||
for (; padded>0; padded--, eventcnt[_MPU_CurrentBuffer]++)
|
|
||||||
*(p++) = 0;
|
|
||||||
}
|
|
||||||
_MPU_LastEvent = _MIDI_GlobalPositionInTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_SendMidiImmediate
|
|
||||||
|
|
||||||
Sends a MIDI message immediately to the the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
void MPU_SendMidiImmediate(char *data, int count)
|
|
||||||
{
|
|
||||||
MIDIHDR mhdr;
|
|
||||||
static int masks[3] = { 0x00ffffffl, 0x0000ffffl, 0x000000ffl };
|
|
||||||
|
|
||||||
if (!count) return;
|
|
||||||
if (count<=3) midiOutShortMsg((HMIDIOUT)hmido, (*((int *)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.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int MPU_Reset
|
|
||||||
(
|
|
||||||
void
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
midiStreamStop(hmido);
|
|
||||||
midiStreamClose(hmido);
|
|
||||||
hmido = (HMIDISTRM)-1;
|
|
||||||
|
|
||||||
return MPU_Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_Init
|
|
||||||
|
|
||||||
Detects and initializes the MPU401 card.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int MPU_Init
|
|
||||||
(
|
|
||||||
int addr
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
if (hmido != (HMIDISTRM)-1)
|
|
||||||
return MPU_Ok;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<NUMBUFFERS; i++) eventcnt[i]=0;
|
|
||||||
|
|
||||||
mididevice = addr;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
return MPU_Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_NoteOff
|
|
||||||
|
|
||||||
Sends a full MIDI note off event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_NoteOff
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int key,
|
|
||||||
int velocity
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[3];
|
|
||||||
msg[0] = (MIDI_NOTE_OFF | channel);
|
|
||||||
msg[1] = (key);
|
|
||||||
msg[2] = (velocity);
|
|
||||||
MPU_SendMidi(msg, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_NoteOn
|
|
||||||
|
|
||||||
Sends a full MIDI note on event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_NoteOn
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int key,
|
|
||||||
int velocity
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[3];
|
|
||||||
msg[0] = (MIDI_NOTE_ON | channel);
|
|
||||||
msg[1] = (key);
|
|
||||||
msg[2] = (velocity);
|
|
||||||
MPU_SendMidi(msg, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_PolyAftertouch
|
|
||||||
|
|
||||||
Sends a full MIDI polyphonic aftertouch event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_PolyAftertouch
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int key,
|
|
||||||
int pressure
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[3];
|
|
||||||
msg[0] = (MIDI_POLY_AFTER_TCH | channel);
|
|
||||||
msg[1] = (key);
|
|
||||||
msg[2] = (pressure);
|
|
||||||
MPU_SendMidi(msg, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_ControlChange
|
|
||||||
|
|
||||||
Sends a full MIDI control change event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_ControlChange
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int number,
|
|
||||||
int value
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[3];
|
|
||||||
msg[0] = (MIDI_CONTROL_CHANGE | channel);
|
|
||||||
msg[1] = (number);
|
|
||||||
msg[2] = (value);
|
|
||||||
MPU_SendMidi(msg, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_ProgramChange
|
|
||||||
|
|
||||||
Sends a full MIDI program change event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_ProgramChange
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int program
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[2];
|
|
||||||
msg[0] = (MIDI_PROGRAM_CHANGE | channel);
|
|
||||||
msg[1] = (program);
|
|
||||||
MPU_SendMidi(msg, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_ChannelAftertouch
|
|
||||||
|
|
||||||
Sends a full MIDI channel aftertouch event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_ChannelAftertouch
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int pressure
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[2];
|
|
||||||
msg[0] = (MIDI_AFTER_TOUCH | channel);
|
|
||||||
msg[1] = (pressure);
|
|
||||||
MPU_SendMidi(msg, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
Function: MPU_PitchBend
|
|
||||||
|
|
||||||
Sends a full MIDI pitch bend event out to the music device.
|
|
||||||
---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void MPU_PitchBend
|
|
||||||
(
|
|
||||||
int channel,
|
|
||||||
int lsb,
|
|
||||||
int msb
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
char msg[3];
|
|
||||||
msg[0] = (MIDI_PITCH_BEND | channel);
|
|
||||||
msg[1] = (lsb);
|
|
||||||
msg[2] = (msb);
|
|
||||||
MPU_SendMidi(msg, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MPU_SetTempo(int tempo)
|
|
||||||
{
|
|
||||||
MIDIPROPTEMPO prop;
|
|
||||||
prop.cbStruct = sizeof(MIDIPROPTEMPO);
|
|
||||||
prop.dwTempo = tabledivide32_noinline(60000000l, tempo);
|
|
||||||
midiStreamProperty(hmido, (LPBYTE)&prop, MIDIPROP_SET|MIDIPROP_TEMPO);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU_SetDivision(int division)
|
|
||||||
{
|
|
||||||
MIDIPROPTIMEDIV prop;
|
|
||||||
prop.cbStruct = sizeof(MIDIPROPTIMEDIV);
|
|
||||||
prop.dwTimeDiv = division;
|
|
||||||
midiStreamProperty(hmido, (LPBYTE)&prop, MIDIPROP_SET|MIDIPROP_TIMEDIV);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU_SetVolume(int volume)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
HMIXER hmixer;
|
|
||||||
int 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MPU_GetVolume(void)
|
|
||||||
{
|
|
||||||
// if (mididevice < 0) return 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ int MV_Installed;
|
||||||
static int MV_TotalVolume = MV_MAXTOTALVOLUME;
|
static int MV_TotalVolume = MV_MAXTOTALVOLUME;
|
||||||
static int MV_MaxVoices = 1;
|
static int MV_MaxVoices = 1;
|
||||||
|
|
||||||
static int MV_BufferSize = MV_MIXBUFFERSIZE;
|
int MV_BufferSize = MV_MIXBUFFERSIZE;
|
||||||
static int MV_BufferLength;
|
static int MV_BufferLength;
|
||||||
|
|
||||||
static int MV_NumberOfBuffers = MV_NUMBEROFBUFFERS;
|
static int MV_NumberOfBuffers = MV_NUMBEROFBUFFERS;
|
||||||
|
@ -92,8 +92,8 @@ float MV_VolumeSmooth = 1.f;
|
||||||
|
|
||||||
int MV_Locked;
|
int MV_Locked;
|
||||||
|
|
||||||
static char *MV_MusicBuffer;
|
char *MV_MusicBuffer;
|
||||||
static void (*MV_MusicCallback)(char *buffer, int length) = NULL;
|
static void (*MV_MusicCallback)(void);
|
||||||
static int MV_MixMusic = FALSE;
|
static int MV_MixMusic = FALSE;
|
||||||
|
|
||||||
static bool MV_Mix(VoiceNode * const voice, int const buffer)
|
static bool MV_Mix(VoiceNode * const voice, int const buffer)
|
||||||
|
@ -269,10 +269,10 @@ static void MV_ServiceVoc(void)
|
||||||
|
|
||||||
if (MV_MixMusic)
|
if (MV_MixMusic)
|
||||||
{
|
{
|
||||||
MV_MusicCallback(MV_MusicBuffer, MV_BufferSize);
|
MV_MusicCallback();
|
||||||
int16_t *source = (int16_t*)MV_MusicBuffer;
|
int16_t *source = (int16_t*)MV_MusicBuffer;
|
||||||
int16_t *dest = (int16_t*)MV_MixBuffer[MV_MixPage+MV_NumberOfBuffers];
|
int16_t *dest = (int16_t*)MV_MixBuffer[MV_MixPage+MV_NumberOfBuffers];
|
||||||
for (int i = 0; i < MV_BufferSize / 4; i++)
|
for (int i = 0; i < MV_BufferSize>>2; i++)
|
||||||
{
|
{
|
||||||
int sl = *source++;
|
int sl = *source++;
|
||||||
int sr = *source++;
|
int sr = *source++;
|
||||||
|
@ -716,7 +716,7 @@ static int MV_StartPlayback(void)
|
||||||
|
|
||||||
MV_MixPage = 1;
|
MV_MixPage = 1;
|
||||||
|
|
||||||
if (SoundDriver_PCM_BeginPlayback(MV_MixBuffer[0], MV_BufferSize, MV_NumberOfBuffers, MV_ServiceVoc) != MV_Ok)
|
if (SoundDriver_PCM_BeginPlayback(MV_MixBuffer[MV_NumberOfBuffers], MV_BufferSize, MV_NumberOfBuffers, MV_ServiceVoc) != MV_Ok)
|
||||||
return MV_SetErrorCode(MV_DriverError);
|
return MV_SetErrorCode(MV_DriverError);
|
||||||
|
|
||||||
return MV_Ok;
|
return MV_Ok;
|
||||||
|
@ -789,7 +789,7 @@ int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initd
|
||||||
MV_SetErrorCode(MV_Ok);
|
MV_SetErrorCode(MV_Ok);
|
||||||
|
|
||||||
// MV_TotalMemory + 2: FIXME, see valgrind_errors.log
|
// MV_TotalMemory + 2: FIXME, see valgrind_errors.log
|
||||||
int const totalmem = Voices * sizeof(VoiceNode) + (MV_TOTALBUFFERSIZE << 1) + 2;
|
int const totalmem = Voices * sizeof(VoiceNode) + (MV_TOTALBUFFERSIZE<<1) + (MV_MIXBUFFERSIZE<<2);
|
||||||
|
|
||||||
char *ptr = (char *) Xaligned_alloc(16, totalmem);
|
char *ptr = (char *) Xaligned_alloc(16, totalmem);
|
||||||
|
|
||||||
|
@ -845,6 +845,8 @@ int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initd
|
||||||
ptr += MV_BufferSize;
|
ptr += MV_BufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MV_MusicBuffer = ptr;
|
||||||
|
|
||||||
// Calculate pan table
|
// Calculate pan table
|
||||||
MV_CalcPanTable();
|
MV_CalcPanTable();
|
||||||
|
|
||||||
|
@ -894,7 +896,7 @@ int MV_Shutdown(void)
|
||||||
return MV_Ok;
|
return MV_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MV_HookMusicRoutine(void(*callback)(char *buffer, int length))
|
void MV_HookMusicRoutine(void(*callback)(void))
|
||||||
{
|
{
|
||||||
MV_Lock();
|
MV_Lock();
|
||||||
MV_MusicCallback = callback;
|
MV_MusicCallback = callback;
|
||||||
|
@ -904,10 +906,13 @@ void MV_HookMusicRoutine(void(*callback)(char *buffer, int length))
|
||||||
|
|
||||||
void MV_UnhookMusicRoutine(void)
|
void MV_UnhookMusicRoutine(void)
|
||||||
{
|
{
|
||||||
MV_Lock();
|
if (MV_MusicCallback)
|
||||||
MV_MusicCallback = NULL;
|
{
|
||||||
MV_MixMusic = FALSE;
|
MV_Lock();
|
||||||
MV_Unlock();
|
MV_MusicCallback = NULL;
|
||||||
|
MV_MixMusic = FALSE;
|
||||||
|
MV_Unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *loopStartTags[loopStartTagCount] = { "LOOP_START", "LOOPSTART", "LOOP" };
|
const char *loopStartTags[loopStartTagCount] = { "LOOP_START", "LOOPSTART", "LOOP" };
|
||||||
|
|
158
source/audiolib/src/music.cpp
Normal file
158
source/audiolib/src/music.cpp
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||||
|
Copyright (C) 2019 Nuke.YKT
|
||||||
|
|
||||||
|
This file is part of NBlood.
|
||||||
|
|
||||||
|
NBlood is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License version 2
|
||||||
|
as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This object is shared by all Build games with MIDI playback!
|
||||||
|
|
||||||
|
#include "music.h"
|
||||||
|
|
||||||
|
#include "al_midi.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "drivers.h"
|
||||||
|
#include "midi.h"
|
||||||
|
#include "multivoc.h"
|
||||||
|
#include "sndcards.h"
|
||||||
|
|
||||||
|
int MUSIC_ErrorCode = MUSIC_Ok;
|
||||||
|
|
||||||
|
static midifuncs MUSIC_MidiFunctions;
|
||||||
|
|
||||||
|
#define MUSIC_SetErrorCode(status) MUSIC_ErrorCode = (status);
|
||||||
|
|
||||||
|
const char *MUSIC_ErrorString(int ErrorNumber)
|
||||||
|
{
|
||||||
|
const char *ErrorString;
|
||||||
|
|
||||||
|
switch (ErrorNumber)
|
||||||
|
{
|
||||||
|
case MUSIC_Warning:
|
||||||
|
case MUSIC_Error: ErrorString = MUSIC_ErrorString(MUSIC_ErrorCode); break;
|
||||||
|
case MUSIC_Ok: ErrorString = "Music ok."; break;
|
||||||
|
case MUSIC_MidiError: ErrorString = "Error playing MIDI file."; break;
|
||||||
|
default: ErrorString = "Unknown Music error code."; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MUSIC_Init(int SoundCard)
|
||||||
|
{
|
||||||
|
int detected = 0;
|
||||||
|
|
||||||
|
if (SoundCard == ASS_AutoDetect)
|
||||||
|
{
|
||||||
|
redetect:
|
||||||
|
detected++;
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
SoundCard = ASS_WinMM;
|
||||||
|
#elif RENDERTYPESDL
|
||||||
|
SoundCard = ASS_SDL;
|
||||||
|
#else
|
||||||
|
SoundCard = ASS_NoSound;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards)
|
||||||
|
{
|
||||||
|
failed:
|
||||||
|
MV_Printf("failed!\n");
|
||||||
|
MUSIC_ErrorCode = MUSIC_MidiError;
|
||||||
|
return MUSIC_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SoundDriver_IsMIDISupported(SoundCard))
|
||||||
|
{
|
||||||
|
MV_Printf("Couldn't init %s\n", SoundDriver_GetName(SoundCard));
|
||||||
|
|
||||||
|
if (detected < 2)
|
||||||
|
goto redetect;
|
||||||
|
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASS_MIDISoundDriver = SoundCard;
|
||||||
|
|
||||||
|
int status = SoundDriver_MIDI_Init(&MUSIC_MidiFunctions);
|
||||||
|
|
||||||
|
if (status != MUSIC_Ok)
|
||||||
|
{
|
||||||
|
if (detected < 2)
|
||||||
|
goto redetect;
|
||||||
|
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
MV_Printf("successfully initialized %s!\n", SoundDriver_GetName(SoundCard));
|
||||||
|
|
||||||
|
MIDI_SetMidiFuncs(&MUSIC_MidiFunctions);
|
||||||
|
|
||||||
|
return MUSIC_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MUSIC_Shutdown(void)
|
||||||
|
{
|
||||||
|
MIDI_StopSong();
|
||||||
|
|
||||||
|
return MUSIC_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MUSIC_SetVolume(int volume) { MIDI_SetVolume(min(max(0, volume), 255)); }
|
||||||
|
|
||||||
|
|
||||||
|
int MUSIC_GetVolume(void) { return MIDI_GetVolume(); }
|
||||||
|
void MUSIC_SetLoopFlag(int loopflag) { MIDI_SetLoopFlag(loopflag); }
|
||||||
|
void MUSIC_Continue(void) { MIDI_ContinueSong(); }
|
||||||
|
void MUSIC_Pause(void) { MIDI_PauseSong(); }
|
||||||
|
|
||||||
|
int MUSIC_StopSong(void)
|
||||||
|
{
|
||||||
|
MIDI_StopSong();
|
||||||
|
MUSIC_SetErrorCode(MUSIC_Ok);
|
||||||
|
return MUSIC_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MUSIC_PlaySong(char *song, int songsize, int loopflag, const char *fn /*= nullptr*/)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(songsize);
|
||||||
|
UNREFERENCED_PARAMETER(fn);
|
||||||
|
|
||||||
|
MUSIC_SetErrorCode(MUSIC_Ok)
|
||||||
|
|
||||||
|
if (MIDI_PlaySong(song, loopflag) != MIDI_Ok)
|
||||||
|
{
|
||||||
|
MUSIC_SetErrorCode(MUSIC_MidiError);
|
||||||
|
return MUSIC_Warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MUSIC_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MUSIC_Update(void)
|
||||||
|
{
|
||||||
|
MIDI_UpdateMusic();
|
||||||
|
}
|
|
@ -1131,7 +1131,7 @@ static MenuEntry_t ME_SAVE_NEW = MAKE_MENUENTRY( s_NewSaveGame, &MF_Minifont, &M
|
||||||
static MenuEntry_t *ME_SAVE;
|
static MenuEntry_t *ME_SAVE;
|
||||||
static MenuEntry_t **MEL_SAVE;
|
static MenuEntry_t **MEL_SAVE;
|
||||||
|
|
||||||
static int32_t soundrate, soundvoices;
|
static int32_t soundrate, soundvoices, musicdevice;
|
||||||
static MenuOption_t MEO_SOUND = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &snd_enabled.Value );
|
static MenuOption_t MEO_SOUND = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &snd_enabled.Value );
|
||||||
static MenuEntry_t ME_SOUND = MAKE_MENUENTRY( "Sound:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND, Option );
|
static MenuEntry_t ME_SOUND = MAKE_MENUENTRY( "Sound:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND, Option );
|
||||||
|
|
||||||
|
@ -1165,6 +1165,23 @@ static MenuRangeInt32_t MEO_SOUND_NUMVOICES = MAKE_MENURANGE( &soundvoices, &MF_
|
||||||
static MenuEntry_t ME_SOUND_NUMVOICES = MAKE_MENUENTRY( "Voices:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_NUMVOICES, RangeInt32 );
|
static MenuEntry_t ME_SOUND_NUMVOICES = MAKE_MENUENTRY( "Voices:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_NUMVOICES, RangeInt32 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static char const *MEOSN_SOUND_MUSICDEVICE[] = {
|
||||||
|
#ifdef _WIN32
|
||||||
|
"Windows",
|
||||||
|
#endif
|
||||||
|
"OPL3",
|
||||||
|
};
|
||||||
|
static int32_t MEOSV_SOUND_MUSICDEVICE[] = {
|
||||||
|
#ifdef _WIN32
|
||||||
|
ASS_WinMM,
|
||||||
|
#endif
|
||||||
|
ASS_OPL3,
|
||||||
|
};
|
||||||
|
|
||||||
|
static MenuOptionSet_t MEOS_SOUND_MUSICDEVICE = MAKE_MENUOPTIONSET( MEOSN_SOUND_MUSICDEVICE, MEOSV_SOUND_MUSICDEVICE, 0x2 );
|
||||||
|
static MenuOption_t MEO_SOUND_MUSICDEVICE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_SOUND_MUSICDEVICE, &musicdevice );
|
||||||
|
static MenuEntry_t ME_SOUND_MUSICDEVICE = MAKE_MENUENTRY( "Music device:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_MUSICDEVICE, Option );
|
||||||
|
|
||||||
static MenuEntry_t ME_SOUND_RESTART = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link );
|
static MenuEntry_t ME_SOUND_RESTART = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link );
|
||||||
|
|
||||||
#ifndef EDUKE32_SIMPLE_MENU
|
#ifndef EDUKE32_SIMPLE_MENU
|
||||||
|
@ -1190,6 +1207,7 @@ static MenuEntry_t *MEL_ADVSOUND[] = {
|
||||||
&ME_SOUND_NUMVOICES,
|
&ME_SOUND_NUMVOICES,
|
||||||
&ME_Space2_Redfont,
|
&ME_Space2_Redfont,
|
||||||
#endif
|
#endif
|
||||||
|
&ME_SOUND_MUSICDEVICE,
|
||||||
&ME_SOUND_RESTART,
|
&ME_SOUND_RESTART,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3219,6 +3237,7 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry)
|
||||||
{
|
{
|
||||||
snd_mixrate = soundrate;
|
snd_mixrate = soundrate;
|
||||||
snd_numvoices = soundvoices;
|
snd_numvoices = soundvoices;
|
||||||
|
ud.config.MusicDevice = musicdevice;
|
||||||
|
|
||||||
S_SoundShutdown();
|
S_SoundShutdown();
|
||||||
S_MusicShutdown();
|
S_MusicShutdown();
|
||||||
|
@ -4241,6 +4260,7 @@ static void Menu_AboutToStartDisplaying(Menu_t * m)
|
||||||
case MENU_ADVSOUND:
|
case MENU_ADVSOUND:
|
||||||
soundrate = snd_mixrate;
|
soundrate = snd_mixrate;
|
||||||
soundvoices = snd_numvoices;
|
soundvoices = snd_numvoices;
|
||||||
|
musicdevice = ud.config.MusicDevice;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -112,7 +112,7 @@ void S_SoundShutdown(void)
|
||||||
|
|
||||||
void S_MusicStartup(void)
|
void S_MusicStartup(void)
|
||||||
{
|
{
|
||||||
initprintf("Initializing music...\n");
|
initprintf("Initializing music... ");
|
||||||
|
|
||||||
if (MUSIC_Init(ud.config.MusicDevice) == MUSIC_Ok || MUSIC_Init(0) == MUSIC_Ok || MUSIC_Init(1) == MUSIC_Ok)
|
if (MUSIC_Init(ud.config.MusicDevice) == MUSIC_Ok || MUSIC_Init(0) == MUSIC_Ok || MUSIC_Init(1) == MUSIC_Ok)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue