- manual update of audiolib

This commit is contained in:
Christoph Oelckers 2019-10-24 19:59:09 +02:00
parent df415605ae
commit 082fcfeef0
10 changed files with 1990 additions and 40 deletions

View file

@ -0,0 +1,45 @@
/*
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __AL_MIDI_H
#define __AL_MIDI_H
#include "opl3.h"
#include <inttypes.h>
typedef struct
{
uint8_t SAVEK[2];
uint8_t Level[2];
uint8_t Env1[2];
uint8_t Env2[2];
uint8_t Wave[2];
uint8_t Feedback;
int8_t Transpose;
int8_t Velocity;
} AdLibTimbre;
extern AdLibTimbre ADLIB_TimbreBank[256];
opl3_chip *AL_GetChip(void);
void AL_RegisterTimbreBank(uint8_t *timbres);
void AL_SetStereo(int const stereo);
#endif

View file

@ -0,0 +1,160 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 2013-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.
*/
//-------------------------------------------------------------------------
//
// Nuked OPL3 emulator.
// Thanks:
// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
// Feedback and Rhythm part calculation information.
// forums.submarine.org.uk(carbon14, opl3):
// Tremolo and phase generator calculation information.
// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
// OPL2 ROMs.
// siliconpr0n.org(John McMaster, digshadow):
// YMF262 and VRC VII decaps and die shots.
//
// version: 1.8
//
#ifndef OPL_OPL3_H
#define OPL_OPL3_H
#include <inttypes.h>
#define OPL_WRITEBUF_SIZE 1024
#define OPL_WRITEBUF_DELAY 2
typedef uintptr_t Bitu;
typedef intptr_t Bits;
typedef uint64_t Bit64u;
typedef int64_t Bit64s;
typedef uint32_t Bit32u;
typedef int32_t Bit32s;
typedef uint16_t Bit16u;
typedef int16_t Bit16s;
typedef uint8_t Bit8u;
typedef int8_t Bit8s;
typedef struct _opl3_slot opl3_slot;
typedef struct _opl3_channel opl3_channel;
typedef struct _opl3_chip opl3_chip;
struct _opl3_slot {
opl3_channel *channel;
opl3_chip *chip;
Bit16s out;
Bit16s fbmod;
Bit16s *mod;
Bit16s prout;
Bit16s eg_rout;
Bit16s eg_out;
Bit8u eg_inc;
Bit8u eg_gen;
Bit8u eg_rate;
Bit8u eg_ksl;
Bit8u *trem;
Bit8u reg_vib;
Bit8u reg_type;
Bit8u reg_ksr;
Bit8u reg_mult;
Bit8u reg_ksl;
Bit8u reg_tl;
Bit8u reg_ar;
Bit8u reg_dr;
Bit8u reg_sl;
Bit8u reg_rr;
Bit8u reg_wf;
Bit8u key;
Bit32u pg_reset;
Bit32u pg_phase;
Bit16u pg_phase_out;
Bit8u slot_num;
};
struct _opl3_channel {
opl3_slot *slots[2];
opl3_channel *pair;
opl3_chip *chip;
Bit16s *out[4];
Bit8u chtype;
Bit16u f_num;
Bit8u block;
Bit8u fb;
Bit8u con;
Bit8u alg;
Bit8u ksv;
Bit16u cha, chb;
Bit32s leftpan;
Bit32s rightpan;
Bit8u ch_num;
};
typedef struct _opl3_writebuf {
Bit64u time;
Bit16u reg;
Bit8u data;
} opl3_writebuf;
struct _opl3_chip {
opl3_channel channel[18];
opl3_slot slot[36];
Bit16u timer;
Bit64u eg_timer;
Bit8u eg_timerrem;
Bit8u eg_state;
Bit8u eg_add;
Bit8u newm;
Bit8u nts;
Bit8u rhy;
Bit8u vibpos;
Bit8u vibshift;
Bit8u tremolo;
Bit8u tremolopos;
Bit8u tremoloshift;
Bit32u noise;
Bit16s zeromod;
Bit32s mixbuff[2];
Bit8u rm_hh_bit2;
Bit8u rm_hh_bit3;
Bit8u rm_hh_bit7;
Bit8u rm_hh_bit8;
Bit8u rm_tc_bit3;
Bit8u rm_tc_bit5;
Bit8u stereoext;
Bit32s rateratio;
Bit32s samplecnt;
Bit16s oldsamples[2];
Bit16s samples[2];
Bit64u writebuf_samplecnt;
Bit32u writebuf_cur;
Bit32u writebuf_last;
Bit64u writebuf_lasttime;
opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
};
void OPL3_Generate(opl3_chip *chip, Bit16s *buf);
void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf);
void OPL3_Reset(opl3_chip *chip, Bit32u samplerate);
void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v);
void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v);
void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples);
#endif

View file

@ -0,0 +1,94 @@
//-------------------------------------------------------------------------
/*
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.
*/
//-------------------------------------------------------------------------
#ifndef __MIDI_H
#define __MIDI_H
namespace OPLMusic {
enum MIDI_Errors
{
MIDI_Warning = -2,
MIDI_Error = -1,
MIDI_Ok = 0,
MIDI_NullMidiModule,
MIDI_InvalidMidiFile,
MIDI_UnknownMidiFormat,
MIDI_NoTracks,
MIDI_InvalidTrack,
MIDI_NoMemory,
MIDI_DPMI_Error
};
#define MIDI_PASS_THROUGH 1
#define MIDI_DONT_PLAY 0
#define MIDI_MaxVolume 255
extern char MIDI_PatchMap[ 128 ];
typedef struct
{
void (*NoteOff)(int32_t channel, int32_t key, int32_t velocity);
void (*NoteOn)(int32_t channel, int32_t key, int32_t velocity);
void (*PolyAftertouch)(int32_t channel, int32_t key, int32_t pressure);
void (*ControlChange)(int32_t channel, int32_t number, int32_t value);
void (*ProgramChange)(int32_t channel, int32_t program);
void (*ChannelAftertouch)(int32_t channel, int32_t pressure);
void (*PitchBend)(int32_t channel, int32_t lsb, int32_t msb);
void (*FinishBuffer)(void);
} midifuncs;
void MIDI_RerouteMidiChannel( int32_t channel, int32_t ( *function )( int32_t event, int32_t c1, int32_t c2 ) );
int32_t MIDI_AllNotesOff( void );
void MIDI_SetUserChannelVolume( int32_t channel, int32_t volume );
void MIDI_ResetUserChannelVolume( void );
int32_t MIDI_Reset( void );
int32_t MIDI_SetVolume( int32_t volume );
int32_t MIDI_GetVolume( void );
void MIDI_SetMidiFuncs( midifuncs *funcs );
void MIDI_SetContext( int32_t context );
int32_t MIDI_GetContext( void );
void MIDI_SetLoopFlag( int32_t loopflag );
void MIDI_ContinueSong( void );
void MIDI_PauseSong( void );
int32_t MIDI_SongPlaying( void );
void MIDI_StopSong( void );
int32_t MIDI_PlaySong( char *song, int32_t loopflag );
void MIDI_SetTempo( int32_t tempo );
int32_t MIDI_GetTempo( void );
void MIDI_SetSongTick( uint32_t PositionInTicks );
void MIDI_SetSongTime( uint32_t milliseconds );
void MIDI_SetSongPosition( int32_t measure, int32_t beat, int32_t tick );
void MIDI_GetSongPosition( songposition *pos );
void MIDI_GetSongLength( songposition *pos );
void MIDI_LoadTimbres( void );
void MIDI_MusicMix( char *buffer, int length );
void MIDI_UpdateMusic(void);
void MIDI_SetDivision( int32_t division );
int32_t MUSIC_InitMidi(int32_t card, midifuncs *Funcs, int32_t Address);
}
#endif

View file

@ -0,0 +1,126 @@
/*
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ___AL_MIDI_H
#define ___AL_MIDI_H
#include <inttypes.h>
#define STEREO_DETUNE 5
#define lobyte(num) ((uint32_t)*((char *)&(num)))
#define hibyte(num) ((uint32_t)*(((char *)&(num)) + 1))
#define AL_MaxVolume 127
#define AL_DefaultChannelVolume 90
#define AL_DefaultPitchBendRange 200
#define AL_VoiceNotFound -1
#define ADLIB_PORT 0x388
/* Number of slots for the voices on the chip */
#define AL_NumChipSlots 18
#define NUMADLIBVOICES 9
#define NUMADLIBCHANNELS 16
#define NOTE_ON 0x2000 /* Used to turn note on or toggle note */
#define NOTE_OFF 0x0000
#define MAX_VELOCITY 0x7f
#define MAX_OCTAVE 7
#define MAX_NOTE (MAX_OCTAVE * 12 + 11)
#define FINETUNE_MAX 31
#define FINETUNE_RANGE (FINETUNE_MAX + 1)
#define PITCHBEND_CENTER 1638400
#define MIDI_VOLUME 7
#define MIDI_PAN 10
#define MIDI_DETUNE 94
#define MIDI_ALL_NOTES_OFF 0x7B
#define MIDI_RESET_ALL_CONTROLLERS 0x79
#define MIDI_RPN_MSB 100
#define MIDI_RPN_LSB 101
#define MIDI_DATAENTRY_MSB 6
#define MIDI_DATAENTRY_LSB 38
#define MIDI_PITCHBEND_RPN 0
/* Definition of octave information to be ORed onto F-Number */
enum octaves
{
OCTAVE_0 = 0x0000,
OCTAVE_1 = 0x0400,
OCTAVE_2 = 0x0800,
OCTAVE_3 = 0x0C00,
OCTAVE_4 = 0x1000,
OCTAVE_5 = 0x1400,
OCTAVE_6 = 0x1800,
OCTAVE_7 = 0x1C00
};
typedef struct AdLibVoice
{
struct AdLibVoice *next;
struct AdLibVoice *prev;
uint32_t num;
uint32_t key;
uint32_t velocity;
uint32_t channel;
uint32_t pitchleft;
uint32_t pitchright;
int timbre;
int port;
uint32_t status;
} AdLibVoice;
typedef struct
{
AdLibVoice *start;
AdLibVoice *end;
} AdLibVoiceList;
typedef struct
{
AdLibVoiceList Voices;
int Timbre;
int Pitchbend;
int KeyOffset;
uint32_t KeyDetune;
uint32_t Volume;
uint32_t EffectiveVolume;
int Pan;
int Detune;
uint32_t RPN;
int16_t PitchBendRange;
int16_t PitchBendSemiTones;
int16_t PitchBendHundreds;
} AdLibChannel;
static int AL_Init(int rate);
static void AL_NoteOff(int channel, int key, int velocity);
static void AL_NoteOn(int channel, int key, int vel);
static void AL_ControlChange(int channel, int type, int data);
static void AL_ProgramChange(int channel, int patch);
static void AL_SetPitchBend(int channel, int lsb, int msb);
#endif

View file

@ -0,0 +1,151 @@
//-------------------------------------------------------------------------
/*
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.
*/
//-------------------------------------------------------------------------
#ifndef ___MIDI_H
#define ___MIDI_H
#include "compat.h"
namespace OPLMusic {
#define RELATIVE_BEAT( measure, beat, tick ) \
( ( tick ) + ( ( beat ) << 9 ) + ( ( measure ) << 16 ) )
//Bobby Prince thinks this may be 100
//#define GENMIDI_DefaultVolume 100
#define GENMIDI_DefaultVolume 90
#define MAX_FORMAT 1
#define NUM_MIDI_CHANNELS 16
#define TIME_PRECISION 16
#define MIDI_HEADER_SIGNATURE 0x6468544d // "MThd"
#define MIDI_TRACK_SIGNATURE 0x6b72544d // "MTrk"
#define MIDI_VOLUME 7
#define MIDI_PAN 10
#define MIDI_DETUNE 94
#define MIDI_RHYTHM_CHANNEL 9
#define MIDI_RPN_MSB 100
#define MIDI_RPN_LSB 101
#define MIDI_DATAENTRY_MSB 6
#define MIDI_DATAENTRY_LSB 38
#define MIDI_PITCHBEND_MSB 0
#define MIDI_PITCHBEND_LSB 0
#define MIDI_RUNNING_STATUS 0x80
#define MIDI_NOTE_OFF 0x8
#define MIDI_NOTE_ON 0x9
#define MIDI_POLY_AFTER_TCH 0xA
#define MIDI_CONTROL_CHANGE 0xB
#define MIDI_PROGRAM_CHANGE 0xC
#define MIDI_AFTER_TOUCH 0xD
#define MIDI_PITCH_BEND 0xE
#define MIDI_SPECIAL 0xF
#define MIDI_SYSEX 0xF0
#define MIDI_SYSEX_CONTINUE 0xF7
#define MIDI_META_EVENT 0xFF
#define MIDI_END_OF_TRACK 0x2F
#define MIDI_TEMPO_CHANGE 0x51
#define MIDI_TIME_SIGNATURE 0x58
#define MIDI_RESET_ALL_CONTROLLERS 0x79
#define MIDI_ALL_NOTES_OFF 0x7b
#define MIDI_MONO_MODE_ON 0x7E
#define MIDI_SYSTEM_RESET 0xFF
#define GET_NEXT_EVENT( track, data ) do { \
( data ) = *( track )->pos; \
( track )->pos += 1; \
} while (0)
#define GET_MIDI_CHANNEL( event ) ( ( event ) & 0xf )
#define GET_MIDI_COMMAND( event ) ( ( event ) >> 4 )
#define EMIDI_INFINITE -1
#define EMIDI_END_LOOP_VALUE 127
#define EMIDI_ALL_CARDS 127
#define EMIDI_INCLUDE_TRACK 110
#define EMIDI_EXCLUDE_TRACK 111
#define EMIDI_PROGRAM_CHANGE 112
#define EMIDI_VOLUME_CHANGE 113
#define EMIDI_CONTEXT_START 114
#define EMIDI_CONTEXT_END 115
#define EMIDI_LOOP_START 116
#define EMIDI_LOOP_END 117
#define EMIDI_SONG_LOOP_START 118
#define EMIDI_SONG_LOOP_END 119
#define EMIDI_GeneralMIDI 0
#define EMIDI_SoundBlaster 4
#define EMIDI_AffectsCurrentCard(c, type) (((c) == EMIDI_ALL_CARDS) || ((c) == (type)))
#define EMIDI_NUM_CONTEXTS 7
typedef struct
{
char *pos;
char *loopstart;
int16_t loopcount;
int16_t RunningStatus;
unsigned time;
int32_t FPSecondsPerTick;
int16_t tick;
int16_t beat;
int16_t measure;
int16_t BeatsPerMeasure;
int16_t TicksPerBeat;
int16_t TimeBase;
int32_t delay;
int16_t active;
} songcontext;
typedef struct
{
char *start;
char *pos;
int32_t delay;
int16_t active;
int16_t RunningStatus;
int16_t currentcontext;
songcontext context[EMIDI_NUM_CONTEXTS];
char EMIDI_IncludeTrack;
char EMIDI_ProgramChange;
char EMIDI_VolumeChange;
} track;
static int32_t _MIDI_ReadNumber(void *from, size_t size);
static int32_t _MIDI_ReadDelta(track *ptr);
static void _MIDI_ResetTracks(void);
static void _MIDI_AdvanceTick(void);
static void _MIDI_MetaEvent(track *Track);
static void _MIDI_SysEx(track *Track);
static int32_t _MIDI_InterpretControllerInfo(track *Track, int32_t TimeSet, int32_t channel, int32_t c1, int32_t c2);
static int32_t _MIDI_SendControlChange(int32_t channel, int32_t c1, int32_t c2);
static void _MIDI_SetChannelVolume(int32_t channel, int32_t volume);
static void _MIDI_SendChannelVolumes(void);
static void _MIDI_InitEMIDI(void);
}
#endif

View file

@ -212,9 +212,9 @@ int SDLDrv_PCM_Init(int *mixrate, int *numchannels, void * initdata)
if (actual.freq == 0 || actual.channels == 0) {
// hack for when SDL said it opened the audio, but clearly didn't
SDL_CloseAudio();
ErrorCode = SDLErr_OpenAudio;
return SDLErr_Error;
}
ErrorCode = SDLErr_OpenAudio;
return SDLErr_Error;
}
#endif
err = 0;

View file

@ -98,9 +98,7 @@ static int MV_MixMusic = FALSE;
static bool MV_Mix(VoiceNode * const voice, int const buffer)
{
/* cheap fix for a crash under 64-bit linux */
/* v v v v */
if (voice->length == 0 && (voice->GetSound == NULL || voice->GetSound(voice) != KeepPlaying))
if (voice->length == 0 && voice->GetSound(voice) != KeepPlaying)
return false;
float const gv = MV_GlobalVolume;
@ -288,7 +286,7 @@ static VoiceNode *MV_GetVoice(int handle)
{
if (handle < MV_MINVOICEHANDLE || handle > MV_MaxVoices)
{
MV_Printf("MV_GetVoice(): bad handle (%d)!\n", handle);
MV_Printf("MV_GetVoice(): bad handle (%d)!\n", handle);
return nullptr;
}

1398
source/audiolib/src/opl3.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -289,7 +289,7 @@ static playbackstatus MV_GetNextVorbisBlock(VoiceNode *voice)
if (!vi || (vi->channels != 1 && vi->channels != 2))
return NoMoreData;
voice->channels = vi->channels;
voice->channels = vi->channels;
voice->SamplingRate = vi->rate;
voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate);
@ -359,11 +359,13 @@ int MV_PlayVorbis(char *ptr, uint32_t length, int loopstart, int loopend, int pi
if (!MV_Installed)
return MV_SetErrorCode(MV_NotInstalled);
auto vd = (vorbis_data *)Xcalloc(1, sizeof(vorbis_data));
VoiceNode *voice = MV_AllocVoice(priority);
if (voice == nullptr)
return MV_SetErrorCode(MV_NoVoices);
auto vd = (vorbis_data *)Xcalloc(1, sizeof(vorbis_data));
vd->ptr = ptr;
vd->pos = 0;
vd->length = length;
@ -371,43 +373,19 @@ int MV_PlayVorbis(char *ptr, uint32_t length, int loopstart, int loopend, int pi
vd->lastbitstream = -1;
int status = ov_open_callbacks((void *)vd, &vd->vf, 0, 0, vorbis_callbacks);
vorbis_info *vi;
if (status < 0)
if (status < 0 || ((vi = ov_info(&vd->vf, 0)) == nullptr) || vi->channels < 1 || vi->channels > 2)
{
Xfree(vd);
MV_Printf("MV_PlayVorbis: err %d\n", status);
MV_SetErrorCode(MV_InvalidFile);
return MV_Error;
}
if (status == 0)
ov_clear(&vd->vf);
else
MV_Printf("MV_PlayVorbis: err %d\n", status);
vorbis_info *vi = ov_info(&vd->vf, 0);
if (!vi)
{
ov_clear(&vd->vf);
Xfree(vd);
return MV_SetErrorCode(MV_InvalidFile);
}
if (vi->channels != 1 && vi->channels != 2)
{
ov_clear(&vd->vf);
Xfree(vd);
MV_SetErrorCode(MV_InvalidFile);
return MV_Error;
}
// Request a voice from the voice pool
VoiceNode *voice = MV_AllocVoice(priority);
if (voice == NULL)
{
ov_clear(&vd->vf);
Xfree(vd);
MV_SetErrorCode(MV_NoVoices);
return MV_Error;
}
voice->wavetype = FMT_VORBIS;
voice->bits = 16;
voice->channels = vi->channels;
@ -448,7 +426,6 @@ void MV_ReleaseVorbisVoice( VoiceNode * voice )
auto vd = (vorbis_data *)voice->rawdataptr;
voice->rawdataptr = 0;
voice->length = 0;
voice->sound = nullptr;
ov_clear(&vd->vf);

View file

@ -8,6 +8,7 @@
#include "pitch.h"
#include "pragmas.h"
#define BUILDING_STATIC
#include "libxmp-lite/xmp.h"
typedef struct {