mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 03:00:46 +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_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initdata);
|
||||
int MV_Shutdown(void);
|
||||
void MV_HookMusicRoutine(void (*callback)(char *buffer, int length));
|
||||
void MV_HookMusicRoutine(void (*callback)(void));
|
||||
void MV_UnhookMusicRoutine(void);
|
||||
|
||||
static inline void MV_SetPrintf(void (*function)(const char *, ...)) { if (function) MV_Printf = function; }
|
||||
|
|
|
@ -37,7 +37,6 @@ typedef enum
|
|||
ASS_SDL,
|
||||
ASS_DirectSound,
|
||||
ASS_WinMM,
|
||||
ASS_MPU401,
|
||||
ASS_OPL3,
|
||||
ASS_NumSoundCards,
|
||||
ASS_AutoDetect = -2
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace OPLMusic {
|
|||
#define MIDI_PAN 10
|
||||
#define MIDI_DETUNE 94
|
||||
#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_LSB 101
|
||||
#define MIDI_DATAENTRY_MSB 6
|
||||
|
@ -67,8 +69,13 @@ namespace OPLMusic {
|
|||
#define MIDI_SYSEX_CONTINUE 0xF7
|
||||
#define MIDI_META_EVENT 0xFF
|
||||
#define MIDI_END_OF_TRACK 0x2F
|
||||
#define MIDI_HOLD1 0x40
|
||||
#define MIDI_SOSTENUTO 0x42
|
||||
#define MIDI_TEMPO_CHANGE 0x51
|
||||
#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_ALL_NOTES_OFF 0x7b
|
||||
#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_Installed;
|
||||
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)
|
||||
{
|
||||
|
|
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 int midiLastDivision;
|
||||
#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 {
|
||||
struct MidiBuffer *next;
|
||||
|
@ -79,7 +79,6 @@ static volatile MidiBuffer activeMidiBuffers;
|
|||
static volatile MidiBuffer spareMidiBuffers;
|
||||
static MidiBuffer *currentMidiBuffer;
|
||||
|
||||
|
||||
#define MIDI_NOTE_OFF 0x80
|
||||
#define MIDI_NOTE_ON 0x90
|
||||
#define MIDI_POLY_AFTER_TCH 0xA0
|
||||
|
@ -94,8 +93,6 @@ static MidiBuffer *currentMidiBuffer;
|
|||
#define MIDI_ALL_NOTES_OFF 0x7B
|
||||
|
||||
|
||||
|
||||
|
||||
int WinMMDrv_GetError(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int datalen;
|
||||
unsigned int datalen;
|
||||
MidiBuffer * node;
|
||||
|
||||
// determine the space to alloc.
|
||||
|
@ -646,6 +643,8 @@ static DWORD midi_get_tick(void)
|
|||
|
||||
static DWORD WINAPI midiDataThread(LPVOID lpParameter)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lpParameter);
|
||||
|
||||
DWORD waitret;
|
||||
DWORD sequenceTime;
|
||||
DWORD sleepAmount = 100 / THREAD_QUEUE_INTERVAL;
|
||||
|
@ -677,7 +676,7 @@ static DWORD WINAPI midiDataThread(LPVOID lpParameter)
|
|||
sequenceTime = midi_get_tick();
|
||||
|
||||
sleepAmount = 100 / THREAD_QUEUE_INTERVAL;
|
||||
if ((int)(midiThreadTimer - sequenceTime) > midiThreadQueueTicks) {
|
||||
if ((midiThreadTimer - sequenceTime) > midiThreadQueueTicks) {
|
||||
// we're running ahead, so sleep for half the usual
|
||||
// amount and try again
|
||||
sleepAmount /= 2;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "drivers.h"
|
||||
|
||||
#include "driver_nosound.h"
|
||||
#include "driver_adlib.h"
|
||||
|
||||
#ifdef RENDERTYPESDL
|
||||
# include "driver_sdl.h"
|
||||
|
@ -141,50 +142,23 @@ static struct {
|
|||
#else
|
||||
UNSUPPORTED_COMPLETELY
|
||||
#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",
|
||||
WinMMDrv_GetError,
|
||||
WinMMDrv_ErrorString,
|
||||
"Nuked OPL3",
|
||||
AdlibDrv_GetError,
|
||||
AdlibDrv_ErrorString,
|
||||
|
||||
UNSUPPORTED_PCM,
|
||||
|
||||
WinMMDrv_MIDI_Init,
|
||||
WinMMDrv_MIDI_Shutdown,
|
||||
WinMMDrv_MIDI_StartPlayback,
|
||||
WinMMDrv_MIDI_HaltPlayback,
|
||||
WinMMDrv_MIDI_SetTempo,
|
||||
WinMMDrv_MIDI_Lock,
|
||||
WinMMDrv_MIDI_Unlock,
|
||||
AdlibDrv_MIDI_Init,
|
||||
AdlibDrv_MIDI_Shutdown,
|
||||
AdlibDrv_MIDI_StartPlayback,
|
||||
AdlibDrv_MIDI_HaltPlayback,
|
||||
AdlibDrv_MIDI_SetTempo,
|
||||
AdlibDrv_MIDI_Lock,
|
||||
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 "_multivc.h"
|
||||
#include "al_midi.h"
|
||||
#include "compat.h"
|
||||
#include "mpu401.h"
|
||||
#include "multivoc.h"
|
||||
#include "music.h"
|
||||
#include "pragmas.h"
|
||||
#include "sndcards.h"
|
||||
#include "windows_inc.h"
|
||||
|
||||
extern int MV_MixRate;
|
||||
extern int ASS_MIDISoundDriver;
|
||||
|
@ -87,11 +86,10 @@ static midifuncs *_MIDI_Funcs;
|
|||
|
||||
static int _MIDI_Reset;
|
||||
|
||||
int MIDI_Tempo = 120;
|
||||
static int MIDI_Tempo = 120;
|
||||
|
||||
static int _MIDI_PlayRoutine = -1;
|
||||
static int _MIDI_MixRate = 44100;
|
||||
static int _MIDI_MixTimer;
|
||||
int MV_MIDIRenderTempo = -1;
|
||||
int MV_MIDIRenderTimer;
|
||||
|
||||
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)
|
||||
{
|
||||
SoundDriver_MIDI_Lock();
|
||||
|
||||
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, 0x78, 0);
|
||||
_MIDI_SendControlChange(channel, MIDI_ALL_SOUNDS_OFF, 0);
|
||||
}
|
||||
|
||||
SoundDriver_MIDI_Unlock();
|
||||
|
||||
return MIDI_Ok;
|
||||
}
|
||||
|
||||
|
@ -554,6 +557,8 @@ int MIDI_Reset(void)
|
|||
{
|
||||
MIDI_AllNotesOff();
|
||||
|
||||
SoundDriver_MIDI_Lock();
|
||||
|
||||
for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++)
|
||||
{
|
||||
_MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0);
|
||||
|
@ -566,6 +571,8 @@ int MIDI_Reset(void)
|
|||
|
||||
_MIDI_SendChannelVolumes();
|
||||
|
||||
SoundDriver_MIDI_Unlock();
|
||||
|
||||
_MIDI_Reset = TRUE;
|
||||
|
||||
return MIDI_Ok;
|
||||
|
@ -615,8 +622,6 @@ void MIDI_ContinueSong(void)
|
|||
return;
|
||||
|
||||
_MIDI_SongActive = TRUE;
|
||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
||||
MPU_Unpause();
|
||||
}
|
||||
|
||||
void MIDI_PauseSong(void)
|
||||
|
@ -626,8 +631,6 @@ void MIDI_PauseSong(void)
|
|||
|
||||
_MIDI_SongActive = FALSE;
|
||||
MIDI_AllNotesOff();
|
||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
||||
MPU_Pause();
|
||||
}
|
||||
|
||||
void MIDI_SetMidiFuncs(midifuncs *funcs) { _MIDI_Funcs = funcs; }
|
||||
|
@ -637,15 +640,11 @@ void MIDI_StopSong(void)
|
|||
if (!_MIDI_SongLoaded)
|
||||
return;
|
||||
|
||||
SoundDriver_MIDI_HaltPlayback();
|
||||
|
||||
_MIDI_SongActive = FALSE;
|
||||
_MIDI_SongLoaded = FALSE;
|
||||
|
||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
||||
{
|
||||
MPU_Reset();
|
||||
MPU_Init(ASS_MIDISoundDriver);
|
||||
}
|
||||
|
||||
MIDI_Reset();
|
||||
_MIDI_ResetTracks();
|
||||
|
||||
|
@ -658,10 +657,6 @@ void MIDI_StopSong(void)
|
|||
_MIDI_TotalTicks = 0;
|
||||
_MIDI_TotalBeats = 0;
|
||||
_MIDI_TotalMeasures = 0;
|
||||
|
||||
if (ASS_MIDISoundDriver == ASS_OPL3)
|
||||
MV_UnhookMusicRoutine();
|
||||
|
||||
}
|
||||
|
||||
int MIDI_PlaySong(char *song, int loopflag)
|
||||
|
@ -728,16 +723,6 @@ int MIDI_PlaySong(char *song, int loopflag)
|
|||
if (_MIDI_SongLoaded)
|
||||
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_NumTracks = My_MIDI_NumTracks;
|
||||
|
@ -753,59 +738,34 @@ int MIDI_PlaySong(char *song, int loopflag)
|
|||
|
||||
_MIDI_Reset = FALSE;
|
||||
|
||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
||||
if (ASS_MIDISoundDriver == ASS_OPL3)
|
||||
{
|
||||
MIDI_SetDivision(_MIDI_Division);
|
||||
//MIDI_SetTempo( 120 );
|
||||
MV_MIDIRenderTempo = 100;
|
||||
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_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;
|
||||
}
|
||||
|
||||
void MIDI_SetTempo(int tempo)
|
||||
{
|
||||
int tickspersecond;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
if (ASS_MIDISoundDriver == ASS_MPU401)
|
||||
MPU_SetDivision(division);
|
||||
UNREFERENCED_PARAMETER(division);
|
||||
}
|
||||
|
||||
int MIDI_GetTempo(void) { return MIDI_Tempo; }
|
||||
|
@ -816,9 +776,6 @@ static void _MIDI_InitEMIDI(void)
|
|||
|
||||
switch (ASS_MIDISoundDriver)
|
||||
{
|
||||
case ASS_MPU401:
|
||||
type = EMIDI_GeneralMIDI;
|
||||
break;
|
||||
case ASS_OPL3:
|
||||
type = EMIDI_Adlib;
|
||||
break;
|
||||
|
@ -1026,21 +983,21 @@ static void _MIDI_InitEMIDI(void)
|
|||
_MIDI_ResetTracks();
|
||||
}
|
||||
|
||||
void MIDI_MusicMix(char *buffer, int length)
|
||||
void MV_RenderMIDI(void)
|
||||
{
|
||||
int16_t * buffer16 = (int16_t *)buffer;
|
||||
int const samples = length >> 2;
|
||||
int16_t * buffer16 = (int16_t *)MV_MusicBuffer;
|
||||
int const samples = MV_BufferSize >> 2;
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
{
|
||||
Bit16s buf[2];
|
||||
while (_MIDI_MixTimer >= _MIDI_MixRate)
|
||||
while (MV_MIDIRenderTimer >= MV_MixRate)
|
||||
{
|
||||
if (_MIDI_PlayRoutine >= 0)
|
||||
if (MV_MIDIRenderTempo >= 0)
|
||||
_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);
|
||||
*buffer16++ = clamp(buf[0]<<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)
|
||||
{
|
||||
if (!_MIDI_SongLoaded || !_MIDI_SongActive) return;
|
||||
while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -54,20 +54,20 @@ enum MIDI_Errors
|
|||
|
||||
#define MIDI_MaxVolume 255
|
||||
|
||||
int MIDI_AllNotesOff(void);
|
||||
int MIDI_Reset(void);
|
||||
int MIDI_SetVolume(int volume);
|
||||
int MIDI_GetVolume(void);
|
||||
void MIDI_SetMidiFuncs(midifuncs *funcs);
|
||||
void MIDI_SetLoopFlag(int loopflag);
|
||||
void MIDI_ContinueSong(void);
|
||||
void MIDI_PauseSong(void);
|
||||
void MIDI_StopSong(void);
|
||||
int MIDI_PlaySong(char *song, int loopflag);
|
||||
void MIDI_SetTempo(int tempo);
|
||||
int MIDI_GetTempo(void);
|
||||
void MIDI_MusicMix(char *buffer, int length);
|
||||
void MIDI_UpdateMusic(void);
|
||||
void MIDI_SetDivision(int division);
|
||||
int MIDI_AllNotesOff(void);
|
||||
int MIDI_Reset(void);
|
||||
int MIDI_SetVolume(int volume);
|
||||
int MIDI_GetVolume(void);
|
||||
void MIDI_SetMidiFuncs(midifuncs *funcs);
|
||||
void MIDI_SetLoopFlag(int loopflag);
|
||||
void MIDI_ContinueSong(void);
|
||||
void MIDI_PauseSong(void);
|
||||
void MIDI_StopSong(void);
|
||||
int MIDI_PlaySong(char *song, int loopflag);
|
||||
void MIDI_SetTempo(int tempo);
|
||||
int MIDI_GetTempo(void);
|
||||
void MV_RenderMIDI(void);
|
||||
void MIDI_UpdateMusic(void);
|
||||
void MIDI_SetDivision(int division);
|
||||
|
||||
#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_MaxVoices = 1;
|
||||
|
||||
static int MV_BufferSize = MV_MIXBUFFERSIZE;
|
||||
int MV_BufferSize = MV_MIXBUFFERSIZE;
|
||||
static int MV_BufferLength;
|
||||
|
||||
static int MV_NumberOfBuffers = MV_NUMBEROFBUFFERS;
|
||||
|
@ -92,8 +92,8 @@ float MV_VolumeSmooth = 1.f;
|
|||
|
||||
int MV_Locked;
|
||||
|
||||
static char *MV_MusicBuffer;
|
||||
static void (*MV_MusicCallback)(char *buffer, int length) = NULL;
|
||||
char *MV_MusicBuffer;
|
||||
static void (*MV_MusicCallback)(void);
|
||||
static int MV_MixMusic = FALSE;
|
||||
|
||||
static bool MV_Mix(VoiceNode * const voice, int const buffer)
|
||||
|
@ -269,10 +269,10 @@ static void MV_ServiceVoc(void)
|
|||
|
||||
if (MV_MixMusic)
|
||||
{
|
||||
MV_MusicCallback(MV_MusicBuffer, MV_BufferSize);
|
||||
MV_MusicCallback();
|
||||
int16_t *source = (int16_t*)MV_MusicBuffer;
|
||||
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 sr = *source++;
|
||||
|
@ -716,7 +716,7 @@ static int MV_StartPlayback(void)
|
|||
|
||||
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_Ok;
|
||||
|
@ -789,7 +789,7 @@ int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initd
|
|||
MV_SetErrorCode(MV_Ok);
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -845,6 +845,8 @@ int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initd
|
|||
ptr += MV_BufferSize;
|
||||
}
|
||||
|
||||
MV_MusicBuffer = ptr;
|
||||
|
||||
// Calculate pan table
|
||||
MV_CalcPanTable();
|
||||
|
||||
|
@ -894,7 +896,7 @@ int MV_Shutdown(void)
|
|||
return MV_Ok;
|
||||
}
|
||||
|
||||
void MV_HookMusicRoutine(void(*callback)(char *buffer, int length))
|
||||
void MV_HookMusicRoutine(void(*callback)(void))
|
||||
{
|
||||
MV_Lock();
|
||||
MV_MusicCallback = callback;
|
||||
|
@ -904,10 +906,13 @@ void MV_HookMusicRoutine(void(*callback)(char *buffer, int length))
|
|||
|
||||
void MV_UnhookMusicRoutine(void)
|
||||
{
|
||||
MV_Lock();
|
||||
MV_MusicCallback = NULL;
|
||||
MV_MixMusic = FALSE;
|
||||
MV_Unlock();
|
||||
if (MV_MusicCallback)
|
||||
{
|
||||
MV_Lock();
|
||||
MV_MusicCallback = NULL;
|
||||
MV_MixMusic = FALSE;
|
||||
MV_Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
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 **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 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 );
|
||||
#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 );
|
||||
|
||||
#ifndef EDUKE32_SIMPLE_MENU
|
||||
|
@ -1190,6 +1207,7 @@ static MenuEntry_t *MEL_ADVSOUND[] = {
|
|||
&ME_SOUND_NUMVOICES,
|
||||
&ME_Space2_Redfont,
|
||||
#endif
|
||||
&ME_SOUND_MUSICDEVICE,
|
||||
&ME_SOUND_RESTART,
|
||||
};
|
||||
|
||||
|
@ -3219,6 +3237,7 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry)
|
|||
{
|
||||
snd_mixrate = soundrate;
|
||||
snd_numvoices = soundvoices;
|
||||
ud.config.MusicDevice = musicdevice;
|
||||
|
||||
S_SoundShutdown();
|
||||
S_MusicShutdown();
|
||||
|
@ -4241,6 +4260,7 @@ static void Menu_AboutToStartDisplaying(Menu_t * m)
|
|||
case MENU_ADVSOUND:
|
||||
soundrate = snd_mixrate;
|
||||
soundvoices = snd_numvoices;
|
||||
musicdevice = ud.config.MusicDevice;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -112,7 +112,7 @@ void S_SoundShutdown(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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue