Rework audiolib, interim commit before removing 8-bit output support. DONT_BUILD.

git-svn-id: https://svn.eduke32.com/eduke32@5270 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2015-07-08 03:33:56 +00:00
parent f1bc3ea23b
commit 08b101eaed
17 changed files with 1355 additions and 3280 deletions

View file

@ -22,19 +22,25 @@
#define DRIVERS_H
#include "inttypes.h"
#include "sndcards.h"
typedef enum
{
ASS_NoSound,
ASS_SDL,
ASS_DirectSound,
ASS_NumSoundCards,
ASS_AutoDetect = -2
} soundcardnames;
extern int32_t ASS_SoundDriver;
int32_t SoundDriver_IsSupported(int32_t driver);
int32_t SoundDriver_GetError(void);
const char * SoundDriver_ErrorString( int32_t ErrorNumber );
int32_t SoundDriver_Init(int32_t *mixrate, int32_t *numchannels, int32_t *samplebits, void * initdata);
const char *SoundDriver_ErrorString(int32_t ErrorNumber);
int32_t SoundDriver_Init(int32_t *mixrate, int32_t *numchannels, int32_t *samplebits, void *initdata);
void SoundDriver_Shutdown(void);
int32_t SoundDriver_BeginPlayback( char *BufferStart,
int32_t BufferSize, int32_t NumDivisions,
void ( *CallBackFunc )( void ) );
int32_t SoundDriver_BeginPlayback(char *BufferStart, int32_t BufferSize, int32_t NumDivisions, void(*CallBackFunc)(void));
void SoundDriver_StopPlayback(void);
void SoundDriver_Lock(void);
void SoundDriver_Unlock(void);

View file

@ -1,132 +1,104 @@
/*
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.
*/
/**********************************************************************
module: FX_MAN.H
author: James R. Dose
date: March 17, 1994
Public header for FX_MAN.C
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef FX_MAN_H_
#define FX_MAN_H_
#include "inttypes.h"
#include "limits.h"
#include "sndcards.h"
#ifdef __cplusplus
extern "C" {
#endif
enum FX_ERRORS
{
FX_Warning = -2,
FX_Error = -1,
FX_Ok = 0,
FX_SoundCardError,
FX_InvalidCard,
FX_MultiVocError,
};
enum FX_LOOP_HOW
{
FX_ONESHOT = -1,
FX_LOOP = 0,
};
#define FX_MUSIC_PRIORITY INT_MAX
const char *FX_ErrorString( int32_t ErrorNumber );
int32_t FX_Init( int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, unsigned mixrate, void * initdata );
int32_t FX_Shutdown( void );
int32_t FX_SetCallBack( void ( *function )( uint32_t ) );
void FX_SetVolume( int32_t volume );
int32_t FX_GetVolume( void );
void FX_SetReverseStereo( int32_t setting );
int32_t FX_GetReverseStereo( void );
void FX_SetReverb( int32_t reverb );
void FX_SetFastReverb( int32_t reverb );
int32_t FX_GetMaxReverbDelay( void );
int32_t FX_GetReverbDelay( void );
void FX_SetReverbDelay( int32_t delay );
int32_t FX_PauseVoice ( int32_t handle, int32_t pause );
int32_t FX_VoiceAvailable( int32_t priority );
int32_t FX_EndLooping( int32_t handle );
int32_t FX_SetPan( int32_t handle, int32_t vol, int32_t left, int32_t right );
int32_t FX_SetPitch( int32_t handle, int32_t pitchoffset );
int32_t FX_SetFrequency( int32_t handle, int32_t frequency );
#if 0
int32_t FX_PlayVOC( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayLoopedVOC( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayWAV( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayLoopedWAV( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayVOC3D( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayWAV3D( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayRaw( char *ptr, uint32_t length, unsigned rate,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayLoopedRaw( char *ptr, uint32_t length, char *loopstart,
char *loopend, unsigned rate, int32_t pitchoffset, int32_t vol, int32_t left,
int32_t right, int32_t priority, uint32_t callbackval );
#endif
int32_t FX_PlayAuto( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayLoopedAuto( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayAuto3D( char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_Pan3D( int32_t handle, int32_t angle, int32_t distance );
int32_t FX_SoundActive( int32_t handle );
int32_t FX_SoundsPlaying( void );
int32_t FX_StopSound( int32_t handle );
int32_t FX_StopAllSounds( void );
int32_t FX_StartDemandFeedPlayback( void ( *function )( char **ptr, uint32_t *length ),
int32_t rate, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval );
int32_t FX_SetVoiceCallback(int32_t handle, uint32_t callbackval);
int32_t FX_SetPrintf(void (*function)(const char *, ...));
int32_t FX_GetPosition(int32_t handle, int32_t *position);
int32_t FX_SetPosition(int32_t handle, int32_t position);
#ifdef __cplusplus
}
#endif
#endif
/*
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.
*/
/**********************************************************************
module: FX_MAN.H
author: James R. Dose
date: March 17, 1994
Public header for FX_MAN.C
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef FX_MAN_H_
#define FX_MAN_H_
#include "inttypes.h"
#include "limits.h"
#include "drivers.h"
#ifdef __cplusplus
extern "C" {
#endif
enum FX_ERRORS
{
FX_Warning = -2,
FX_Error = -1,
FX_Ok = 0,
FX_InvalidCard,
FX_MultiVocError,
};
enum FX_LOOP_HOW
{
FX_ONESHOT = -1,
FX_LOOP = 0,
};
#define FX_MUSIC_PRIORITY INT_MAX
const char *FX_ErrorString(int32_t ErrorNumber);
int32_t FX_Init(int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, unsigned mixrate,
void *initdata);
int32_t FX_Shutdown(void);
void FX_SetCallBack(void(*function)(uint32_t));
void FX_SetVolume(int32_t volume);
int32_t FX_GetVolume(void);
void FX_SetReverseStereo(int32_t setting);
int32_t FX_GetReverseStereo(void);
void FX_SetReverb(int32_t reverb);
int32_t FX_GetMaxReverbDelay(void);
int32_t FX_GetReverbDelay(void);
void FX_SetReverbDelay(int32_t delay);
int32_t FX_PauseVoice(int32_t handle, int32_t pause);
int32_t FX_VoiceAvailable(int32_t priority);
int32_t FX_EndLooping(int32_t handle);
int32_t FX_SetPan(int32_t handle, int32_t vol, int32_t left, int32_t right);
int32_t FX_SetPitch(int32_t handle, int32_t pitchoffset);
int32_t FX_SetFrequency(int32_t handle, int32_t frequency);
int32_t FX_PlayAuto(char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval);
int32_t FX_PlayLoopedAuto(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval);
int32_t FX_PlayAuto3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval);
int32_t FX_Pan3D(int32_t handle, int32_t angle, int32_t distance);
int32_t FX_SoundActive(int32_t handle);
int32_t FX_SoundsPlaying(void);
int32_t FX_StopSound(int32_t handle);
int32_t FX_StopAllSounds(void);
int32_t FX_SetVoiceCallback(int32_t handle, uint32_t callbackval);
int32_t FX_SetPrintf(void(*function)(const char *, ...));
int32_t FX_GetPosition(int32_t handle, int32_t *position);
int32_t FX_SetPosition(int32_t handle, int32_t position);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,43 +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.
*/
/**********************************************************************
module: SNDCARDS.H
author: James R. Dose
date: March 31, 1994
Contains enumerated type definitions for sound cards.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef SNDCARDS_H_
#define SNDCARDS_H_
typedef enum
{
ASS_NoSound,
ASS_SDL,
ASS_DirectSound,
ASS_NumSoundCards,
ASS_AutoDetect = -2
} soundcardnames;
#endif

View file

@ -62,9 +62,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// mirrors FX_MUSIC_PRIORITY from fx_man.h
#define MV_MUSIC_PRIORITY INT_MAX
#define MIX_VOLUME( volume ) \
( ( max( 0, min( ( volume ), 255 ) ) * ( MV_MAXVOLUME + 1 ) ) >> 8 )
// ( ( max( 0, min( ( volume ), 255 ) ) ) >> 2 )
#define MIX_VOLUME(volume) ((max(0, min((volume), 255)) * (MV_MAXVOLUME + 1)) >> 8)
#define STEREO 1
#define SIXTEEN_BIT 2
@ -91,124 +89,88 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//#define PI 3.1415926536
typedef enum
{
NoMoreData,
KeepPlaying
} playbackstatus;
{
NoMoreData,
KeepPlaying
} playbackstatus;
typedef struct VoiceNode
{
struct VoiceNode *next;
struct VoiceNode *prev;
{
struct VoiceNode *next;
struct VoiceNode *prev;
wavedata wavetype;
char bits;
char channels;
playbackstatus (*GetSound)(struct VoiceNode *voice);
playbackstatus ( *GetSound )( struct VoiceNode *voice );
void (*mix)(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void ( *mix )( uint32_t position, uint32_t rate,
const char *start, uint32_t length );
const char *sound;
const uint8_t *rawdataptr;
const char *NextBlock;
const char *LoopStart;
const char *LoopEnd;
unsigned LoopCount;
uint32_t LoopSize;
uint32_t BlockLength;
const int16_t *LeftVolume;
const int16_t *RightVolume;
int32_t ptrlength; // ptrlength-1 is the max permissible index for rawdataptr
const void *rawdataptr;
uint32_t PitchScale;
uint32_t FixedPointBufferSize;
const char *NextBlock;
const char *LoopStart;
const char *LoopEnd;
const char *sound;
uint32_t length;
uint32_t SamplingRate;
uint32_t RateScale;
uint32_t position;
int32_t Playing;
int32_t Paused;
wavefmt_t wavetype;
char bits;
char channels;
int32_t handle;
int32_t priority;
unsigned LoopCount;
uint32_t LoopSize;
uint32_t BlockLength;
void ( *DemandFeed )( char **ptr, uint32_t *length );
void *extra;
int32_t ptrlength; // ptrlength-1 is the max permissible index for rawdataptr
const int16_t *LeftVolume;
const int16_t *RightVolume;
uint32_t PitchScale;
uint32_t FixedPointBufferSize;
uint32_t callbackval;
uint32_t length;
uint32_t SamplingRate;
uint32_t RateScale;
uint32_t position;
int32_t Playing;
int32_t Paused;
} VoiceNode;
int32_t handle;
int32_t priority;
uint32_t callbackval;
} VoiceNode;
typedef struct
{
VoiceNode *start;
VoiceNode *end;
} VList;
{
uint8_t left;
uint8_t right;
} Pan;
typedef struct
{
uint8_t left;
uint8_t right;
} Pan;
typedef int16_t MONO16;
typedef int8_t MONO8;
{
char RIFF[4];
uint32_t file_size;
char WAVE[4];
char fmt[4];
uint32_t format_size;
} riff_header;
typedef struct
{
MONO16 left;
MONO16 right;
// uint16_t left;
// uint16_t right;
} STEREO16;
{
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t nBitsPerSample;
} format_header;
typedef struct
{
MONO16 left;
MONO16 right;
} SIGNEDSTEREO16;
typedef struct
{
// MONO8 left;
// MONO8 right;
char left;
char right;
} STEREO8;
typedef struct
{
char RIFF[ 4 ];
uint32_t file_size;
char WAVE[ 4 ];
char fmt[ 4 ];
uint32_t format_size;
} riff_header;
typedef struct
{
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t nBitsPerSample;
} format_header;
typedef struct
{
uint8_t DATA[ 4 ];
uint32_t size;
} data_header;
typedef MONO8 VOLUME8[ 256 ];
typedef MONO16 VOLUME16[ 256 ];
{
uint8_t DATA[4];
uint32_t size;
} data_header;
extern Pan MV_PanTable[ MV_NUMPANPOSITIONS ][ MV_MAXVOLUME + 1 ];
extern int32_t MV_ErrorCode;
@ -216,16 +178,15 @@ extern int32_t MV_Installed;
extern int32_t MV_MixRate;
typedef char HARSH_CLIP_TABLE_8[ MV_NUMVOICES * 256 ];
#define MV_SetErrorCode( status ) \
MV_ErrorCode = ( status );
#define MV_SetErrorCode(status) MV_ErrorCode = (status);
void MV_PlayVoice( VoiceNode *voice );
void MV_PlayVoice(VoiceNode *voice);
VoiceNode *MV_AllocVoice( int32_t priority );
VoiceNode *MV_AllocVoice(int32_t priority);
void MV_SetVoiceMixMode( VoiceNode *voice );
void MV_SetVoiceVolume ( VoiceNode *voice, int32_t vol, int32_t left, int32_t right );
void MV_SetVoicePitch ( VoiceNode *voice, uint32_t rate, int32_t pitchoffset );
void MV_SetVoiceMixMode(VoiceNode *voice);
void MV_SetVoiceVolume(VoiceNode *voice, int32_t vol, int32_t left, int32_t right);
void MV_SetVoicePitch(VoiceNode *voice, uint32_t rate, int32_t pitchoffset);
int32_t MV_GetVorbisPosition(VoiceNode *voice);
void MV_SetVorbisPosition(VoiceNode *voice, int32_t position);
@ -234,80 +195,39 @@ void MV_SetFLACPosition(VoiceNode *voice, int32_t position);
int32_t MV_GetXAPosition(VoiceNode *voice);
void MV_SetXAPosition(VoiceNode *voice, int32_t position);
void MV_ReleaseVorbisVoice( VoiceNode * voice );
void MV_ReleaseFLACVoice( VoiceNode * voice );
void MV_ReleaseXAVoice( VoiceNode * voice );
void MV_ReleaseVorbisVoice(VoiceNode *voice);
void MV_ReleaseFLACVoice(VoiceNode *voice);
void MV_ReleaseXAVoice(VoiceNode *voice);
// implemented in mix.c
void ClearBuffer_DW( void *ptr, unsigned data, int32_t length );
void MV_Mix8BitMono( uint32_t position, uint32_t rate,
const char *start, uint32_t length );
void MV_Mix8BitStereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitMono( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitStereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitMono16( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix8BitMono16( uint32_t position, uint32_t rate,
const char *start, uint32_t length );
void MV_Mix8BitStereo16( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitStereo16( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_16BitReverb( char *src, char *dest, VOLUME16 *volume, int32_t count );
void MV_8BitReverb( int8_t *src, int8_t *dest, VOLUME16 *volume, int32_t count );
void MV_16BitReverbFast( char *src, char *dest, int32_t count, int32_t shift );
void MV_8BitReverbFast( int8_t *src, int8_t *dest, int32_t count, int32_t shift );
void MV_Mix8BitMono(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitStereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitMono(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitStereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitMono16(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitMono16(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitStereo16(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitStereo16(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_16BitReverb( char const *src, char *dest, int16_t *volume, int32_t count );
void MV_8BitReverb( int8_t *src, int8_t *dest, int16_t *volume, int32_t count );
// implemented in mixst.c
void ClearBuffer_DW( void *ptr, unsigned data, int32_t length );
void MV_Mix8BitMono8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitStereo8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitMono8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitStereo8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitStereo16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix16BitStereo16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
void MV_Mix8BitMono8Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length );
void MV_Mix8BitStereo8Stereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitMono8Stereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitStereo8Stereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitMono16Stereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix8BitMono16Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length );
void MV_Mix8BitStereo16Stereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
void MV_Mix16BitStereo16Stereo( uint32_t position,
uint32_t rate, const char *start, uint32_t length );
extern char *MV_HarshClipTable;
extern char *MV_MixDestination; // pointer to the next output sample
extern uint32_t MV_MixPosition; // return value of where the source pointer got to
extern char *MV_HarshClipTable;
extern char *MV_MixDestination; // pointer to the next output sample
extern uint32_t MV_MixPosition; // return value of where the source pointer got to
extern const int16_t *MV_LeftVolume;
extern const int16_t *MV_RightVolume;
extern int32_t MV_SampleSize;
extern int32_t MV_RightChannelOffset;
extern int32_t MV_SampleSize;
extern int32_t MV_RightChannelOffset;
#define loopStartTagCount 2
extern const char *loopStartTags[loopStartTagCount];

View file

@ -263,17 +263,16 @@ void SDLDrv_PCM_StopPlayback(void)
void SDLDrv_PCM_Lock(void)
{
if (InterruptsDisabled++)
return;
SDL_LockMutex(EffectFence);
if (InterruptsDisabled++)
return;
SDL_LockMutex(EffectFence);
}
void SDLDrv_PCM_Unlock(void)
{
if (--InterruptsDisabled)
return;
SDL_UnlockMutex(EffectFence);
}
if (--InterruptsDisabled)
return;
SDL_UnlockMutex(EffectFence);
}

View file

@ -39,116 +39,81 @@ int32_t ASS_SoundDriver = -1;
#define UNSUPPORTED { 0,0,0,0,0,0,0,0, },
static struct {
int32_t (* GetError)(void);
const char * (* ErrorString)(int32_t);
int32_t (* Init)(int32_t *, int32_t *, int32_t *, void *);
void (* Shutdown)(void);
int32_t (* BeginPlayback)(char *, int32_t, int32_t, void ( * )(void) );
void (* StopPlayback)(void);
void (* Lock)(void);
void (* Unlock)(void);
static struct
{
int32_t (*GetError)(void);
const char *(*ErrorString)(int32_t);
int32_t (*Init)(int32_t *, int32_t *, int32_t *, void *);
void (*Shutdown)(void);
int32_t (*BeginPlayback)(char *, int32_t, int32_t, void (*)(void));
void (*StopPlayback)(void);
void (*Lock)(void);
void (*Unlock)(void);
} SoundDrivers[ASS_NumSoundCards] = {
// Everyone gets the "no sound" driver
{
NoSoundDrv_GetError,
NoSoundDrv_ErrorString,
NoSoundDrv_PCM_Init,
NoSoundDrv_PCM_Shutdown,
NoSoundDrv_PCM_BeginPlayback,
NoSoundDrv_PCM_StopPlayback,
NoSoundDrv_PCM_Lock,
NoSoundDrv_PCM_Unlock,
},
// Simple DirectMedia Layer
// Everyone gets the "no sound" driver
{
NoSoundDrv_GetError, NoSoundDrv_ErrorString, NoSoundDrv_PCM_Init, NoSoundDrv_PCM_Shutdown,
NoSoundDrv_PCM_BeginPlayback, NoSoundDrv_PCM_StopPlayback, NoSoundDrv_PCM_Lock, NoSoundDrv_PCM_Unlock,
},
// Simple DirectMedia Layer
#ifdef HAVE_SDL
{
SDLDrv_GetError,
SDLDrv_ErrorString,
SDLDrv_PCM_Init,
SDLDrv_PCM_Shutdown,
SDLDrv_PCM_BeginPlayback,
SDLDrv_PCM_StopPlayback,
SDLDrv_PCM_Lock,
SDLDrv_PCM_Unlock,
},
{
SDLDrv_GetError, SDLDrv_ErrorString, SDLDrv_PCM_Init, SDLDrv_PCM_Shutdown,
SDLDrv_PCM_BeginPlayback, SDLDrv_PCM_StopPlayback, SDLDrv_PCM_Lock, SDLDrv_PCM_Unlock,
},
#else
UNSUPPORTED
UNSUPPORTED
#endif
// Windows DirectSound
#ifdef HAVE_DS
{
DirectSoundDrv_GetError,
DirectSoundDrv_ErrorString,
DirectSoundDrv_PCM_Init,
DirectSoundDrv_PCM_Shutdown,
DirectSoundDrv_PCM_BeginPlayback,
DirectSoundDrv_PCM_StopPlayback,
DirectSoundDrv_PCM_Lock,
DirectSoundDrv_PCM_Unlock,
},
{
DirectSoundDrv_GetError, DirectSoundDrv_ErrorString, DirectSoundDrv_PCM_Init, DirectSoundDrv_PCM_Shutdown,
DirectSoundDrv_PCM_BeginPlayback, DirectSoundDrv_PCM_StopPlayback, DirectSoundDrv_PCM_Lock,
DirectSoundDrv_PCM_Unlock,
},
#else
UNSUPPORTED
UNSUPPORTED
#endif
};
int32_t SoundDriver_IsSupported(int32_t driver)
{
return (SoundDrivers[driver].GetError != 0);
}
int32_t SoundDriver_IsSupported(int32_t driver) { return (SoundDrivers[driver].GetError != 0); }
int32_t SoundDriver_GetError(void)
{
if (!SoundDriver_IsSupported(ASS_SoundDriver)) {
return -1;
}
return SoundDrivers[ASS_SoundDriver].GetError();
return SoundDriver_IsSupported(ASS_SoundDriver) ? SoundDrivers[ASS_SoundDriver].GetError() : -1;
}
const char * SoundDriver_ErrorString( int32_t ErrorNumber )
{
if (ASS_SoundDriver < 0 || ASS_SoundDriver >= ASS_NumSoundCards) {
return "No sound driver selected.";
}
if (!SoundDriver_IsSupported(ASS_SoundDriver)) {
return "Unsupported sound driver selected.";
}
return SoundDrivers[ASS_SoundDriver].ErrorString(ErrorNumber);
if (ASS_SoundDriver < 0 || ASS_SoundDriver >= ASS_NumSoundCards)
return "No sound driver selected.";
if (!SoundDriver_IsSupported(ASS_SoundDriver))
return "Unsupported sound driver selected.";
return SoundDrivers[ASS_SoundDriver].ErrorString(ErrorNumber);
}
int32_t SoundDriver_Init(int32_t *mixrate, int32_t *numchannels, int32_t *samplebits, void * initdata)
int32_t SoundDriver_Init(int32_t *mixrate, int32_t *numchannels, int32_t *samplebits, void *initdata)
{
return SoundDrivers[ASS_SoundDriver].Init(mixrate, numchannels, samplebits, initdata);
return SoundDrivers[ASS_SoundDriver].Init(mixrate, numchannels, samplebits, initdata);
}
void SoundDriver_Shutdown(void)
void SoundDriver_Shutdown(void) { SoundDrivers[ASS_SoundDriver].Shutdown(); }
int32_t SoundDriver_BeginPlayback(char *BufferStart, int32_t BufferSize, int32_t NumDivisions,
void (*CallBackFunc)(void))
{
SoundDrivers[ASS_SoundDriver].Shutdown();
return SoundDrivers[ASS_SoundDriver].BeginPlayback(BufferStart, BufferSize, NumDivisions, CallBackFunc);
}
int32_t SoundDriver_BeginPlayback(char *BufferStart, int32_t BufferSize,
int32_t NumDivisions, void ( *CallBackFunc )( void ) )
{
return SoundDrivers[ASS_SoundDriver].BeginPlayback(BufferStart,
BufferSize, NumDivisions, CallBackFunc);
}
void SoundDriver_StopPlayback(void) { SoundDrivers[ASS_SoundDriver].StopPlayback(); }
void SoundDriver_StopPlayback(void)
{
SoundDrivers[ASS_SoundDriver].StopPlayback();
}
void SoundDriver_Lock(void) { SoundDrivers[ASS_SoundDriver].Lock(); }
void SoundDriver_Lock(void)
{
SoundDrivers[ASS_SoundDriver].Lock();
}
void SoundDriver_Unlock(void)
{
SoundDrivers[ASS_SoundDriver].Unlock();
}
void SoundDriver_Unlock(void) { SoundDrivers[ASS_SoundDriver].Unlock(); }

View file

@ -27,9 +27,9 @@
#define FLAC__NO_DLL
#ifdef __APPLE__
# include <FLAC/all.h>
#include <FLAC/all.h>
#else
# include "FLAC/all.h"
#include "FLAC/all.h"
#endif
#include <stdlib.h>
@ -44,154 +44,161 @@
#include "_multivc.h"
typedef struct {
void * ptr;
size_t length;
size_t pos;
typedef struct
{
void *ptr;
size_t length;
size_t pos;
FLAC__StreamDecoder* stream;
FLAC__uint64 sample_pos;
FLAC__StreamDecoder *stream;
FLAC__uint64 sample_pos;
char *block;
size_t blocksize;
char *block;
size_t blocksize;
VoiceNode *owner;
VoiceNode *owner;
} flac_data;
// callbacks, round 1
static size_t read_flac(void * ptr, size_t size, size_t nmemb, FLAC__IOHandle datasource)
static size_t read_flac(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle datasource)
{
flac_data * flac = (flac_data *) datasource;
size_t nread = 0;
size_t bytes;
flac_data *flac = (flac_data *)datasource;
size_t nread = 0;
size_t bytes;
errno = 0;
errno = 0;
if (flac->length == flac->pos) {
return 0;
}
if (flac->length == flac->pos)
{
return 0;
}
for (; nmemb > 0; nmemb--, nread++) {
bytes = flac->length - flac->pos;
if (size < bytes) {
bytes = size;
}
for (; nmemb > 0; nmemb--, nread++)
{
bytes = flac->length - flac->pos;
if (size < bytes)
{
bytes = size;
}
memcpy(ptr, (uint8_t *)flac->ptr + flac->pos, bytes);
flac->pos += bytes;
ptr = (uint8_t *)ptr + bytes;
memcpy(ptr, (uint8_t *)flac->ptr + flac->pos, bytes);
flac->pos += bytes;
ptr = (uint8_t *)ptr + bytes;
if (flac->length == flac->pos) {
nread++;
break;
}
}
if (flac->length == flac->pos)
{
nread++;
break;
}
}
return nread;
return nread;
}
static size_t write_flac(const void * ptr, size_t size, size_t nmemb, FLAC__IOHandle datasource)
static size_t write_flac(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle datasource)
{
UNREFERENCED_PARAMETER(ptr);
UNREFERENCED_PARAMETER(size);
UNREFERENCED_PARAMETER(nmemb);
UNREFERENCED_PARAMETER(datasource);
return 0;
return 0;
}
static int32_t seek_flac(FLAC__IOHandle datasource, FLAC__int64 offset, int32_t whence)
{
flac_data * flac = (flac_data *) datasource;
flac_data *flac = (flac_data *)datasource;
switch (whence) {
case SEEK_SET: flac->pos = 0; break;
case SEEK_CUR: break;
case SEEK_END: flac->pos = flac->length; break;
}
switch (whence)
{
case SEEK_SET: flac->pos = 0; break;
case SEEK_CUR: break;
case SEEK_END: flac->pos = flac->length; break;
}
flac->pos += offset;
flac->pos += offset;
if (flac->pos > flac->length) {
flac->pos = flac->length;
}
if (flac->pos > flac->length)
{
flac->pos = flac->length;
}
return 0;
return 0;
}
static FLAC__int64 tell_flac(FLAC__IOHandle datasource)
{
flac_data * flac = (flac_data *) datasource;
flac_data *flac = (flac_data *)datasource;
return flac->pos;
return flac->pos;
}
static FLAC__int64 length_flac(FLAC__IOHandle datasource)
{
flac_data * flac = (flac_data *) datasource;
flac_data *flac = (flac_data *)datasource;
return flac->length;
return flac->length;
}
static int32_t eof_flac(FLAC__IOHandle datasource)
{
flac_data * flac = (flac_data *) datasource;
flac_data *flac = (flac_data *)datasource;
return (flac->pos == flac->length);
return (flac->pos == flac->length);
}
static int32_t close_flac(FLAC__IOHandle datasource)
{
UNREFERENCED_PARAMETER(datasource);
return 0;
UNREFERENCED_PARAMETER(datasource);
return 0;
}
static FLAC__IOCallbacks flac_callbacks = {
read_flac,
write_flac,
seek_flac,
tell_flac,
eof_flac,
close_flac,
read_flac, write_flac, seek_flac, tell_flac, eof_flac, close_flac,
};
// callbacks, round 2
FLAC__StreamDecoderReadStatus read_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
FLAC__StreamDecoderReadStatus read_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes,
void *client_data)
{
UNREFERENCED_PARAMETER(decoder);
if(*bytes > 0) {
*bytes = read_flac(buffer, sizeof(FLAC__byte), *bytes, client_data);
if(errno)
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
else if(*bytes == 0)
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
UNREFERENCED_PARAMETER(decoder);
if (*bytes > 0)
{
*bytes = read_flac(buffer, sizeof(FLAC__byte), *bytes, client_data);
if (errno)
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
else if (*bytes == 0)
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
else
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
FLAC__StreamDecoderSeekStatus seek_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
FLAC__StreamDecoderSeekStatus seek_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset,
void *client_data)
{
UNREFERENCED_PARAMETER(decoder);
if(seek_flac(client_data, absolute_byte_offset, SEEK_SET) < 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
else
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
UNREFERENCED_PARAMETER(decoder);
if (seek_flac(client_data, absolute_byte_offset, SEEK_SET) < 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
else
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
FLAC__StreamDecoderTellStatus tell_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
FLAC__StreamDecoderTellStatus tell_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset,
void *client_data)
{
UNREFERENCED_PARAMETER(decoder);
*absolute_byte_offset = tell_flac(client_data);
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
FLAC__StreamDecoderLengthStatus length_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
FLAC__StreamDecoderLengthStatus length_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length,
void *client_data)
{
UNREFERENCED_PARAMETER(decoder);
*stream_length = length_flac(client_data);
@ -200,20 +207,21 @@ FLAC__StreamDecoderLengthStatus length_flac_stream(const FLAC__StreamDecoder *de
FLAC__bool eof_flac_stream(const FLAC__StreamDecoder *decoder, void *client_data)
{
UNREFERENCED_PARAMETER(decoder);
return eof_flac(client_data);
UNREFERENCED_PARAMETER(decoder);
return eof_flac(client_data);
}
FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const ibuffer[], void *client_data)
FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
const FLAC__int32 *const ibuffer[], void *client_data)
{
flac_data * fd = (flac_data *) client_data;
flac_data *fd = (flac_data *)client_data;
VoiceNode *voice = fd->owner;
FLAC__uint64 samples = frame->header.blocksize;
UNREFERENCED_PARAMETER(decoder);
voice->channels = frame->header.channels;
voice->bits = frame->header.bits_per_sample;
voice->channels = frame->header.channels;
voice->bits = frame->header.bits_per_sample;
voice->SamplingRate = frame->header.sample_rate;
if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER)
@ -221,35 +229,36 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
else if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER)
fd->sample_pos = frame->header.number.sample_number;
if ((FLAC__uint64)(uintptr_t)voice->LoopEnd > 0 && fd->sample_pos + samples >= (FLAC__uint64)(uintptr_t)voice->LoopEnd)
if ((FLAC__uint64)(uintptr_t)voice->LoopEnd > 0 &&
fd->sample_pos + samples >= (FLAC__uint64)(uintptr_t)voice->LoopEnd)
{
samples = (FLAC__uint64)(uintptr_t)voice->LoopEnd - fd->sample_pos;
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart))
MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul, LOOP_END %ul\n",
(FLAC__uint64)(uintptr_t)voice->LoopStart, (FLAC__uint64)(uintptr_t)voice->LoopEnd);
(FLAC__uint64)(uintptr_t)voice->LoopStart, (FLAC__uint64)(uintptr_t)voice->LoopEnd);
}
voice->length = ((samples * (voice->bits/8))/2)<<voice->bits;
voice->position = 0;
voice->BlockLength = 0;
voice->length = ((samples * (voice->bits / 8)) / 2) << voice->bits;
voice->position = 0;
voice->BlockLength = 0;
// CODEDUP multivoc.c MV_SetVoicePitch
voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) - voice->RateScale;
MV_SetVoiceMixMode( voice );
voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate;
voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale;
MV_SetVoiceMixMode(voice);
{
const size_t size = samples * voice->channels * (voice->bits/8);
const size_t size = samples * voice->channels * (voice->bits / 8);
if (size > fd->blocksize)
{
fd->blocksize = size;
fd->block = (char*)realloc(fd->block, sizeof(char) * size);
fd->block = (char *)realloc(fd->block, sizeof(char) * size);
}
}
if (!fd->block)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
voice->sound = fd->block;
voice->sound = fd->block;
{
char *obuffer = fd->block;
@ -257,17 +266,16 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
uint8_t channel;
// this loop is adapted from code in ov_read_filter() in vorbisfile.c in libvorbis
for(sample=0; sample < samples; ++sample)
for(channel=0; channel < frame->header.channels; ++channel)
for (sample = 0; sample < samples; ++sample)
for (channel = 0; channel < frame->header.channels; ++channel)
{
int8_t byte;
FLAC__int32 val=ibuffer[channel][sample];
if(val>(1<<(voice->bits-1))-1)
val=(1<<(voice->bits-1))-1;
else if(val<-(1<<(voice->bits-1)))
val=-(1<<(voice->bits-1));
for (byte = 0; byte < voice->bits; byte += 8)
*obuffer++=((val>>byte)&0x000000FF);
FLAC__int32 val = ibuffer[channel][sample];
if (val > (1 << (voice->bits - 1)) - 1)
val = (1 << (voice->bits - 1)) - 1;
else if (val < -(1 << (voice->bits - 1)))
val = -(1 << (voice->bits - 1));
for (byte = 0; byte < voice->bits; byte += 8) *obuffer++ = ((val >> byte) & 0x000000FF);
}
}
@ -276,17 +284,17 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
void error_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
// flac_data * fd = (flac_data *) client_data;
// flac_data * fd = (flac_data *) client_data;
UNREFERENCED_PARAMETER(client_data);
UNREFERENCED_PARAMETER(decoder);
MV_Printf("%s\n", FLAC__StreamDecoderErrorStatusString[status]);
// FLAC__stream_decoder_flush(fd->stream);
// FLAC__stream_decoder_flush(fd->stream);
}
int32_t MV_GetFLACPosition(VoiceNode *voice)
{
FLAC__uint64 position = 0;
flac_data * fd = (flac_data *) voice->extra;
flac_data *fd = (flac_data *)voice->rawdataptr;
FLAC__stream_decoder_get_decode_position(fd->stream, &position);
@ -295,7 +303,7 @@ int32_t MV_GetFLACPosition(VoiceNode *voice)
void MV_SetFLACPosition(VoiceNode *voice, int32_t position)
{
flac_data * fd = (flac_data *) voice->extra;
flac_data *fd = (flac_data *)voice->rawdataptr;
FLAC__stream_decoder_seek_absolute(fd->stream, position);
}
@ -306,34 +314,31 @@ Function: MV_GetNextFLACBlock
Controls playback of FLAC data
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextFLACBlock
(
VoiceNode *voice
)
static playbackstatus MV_GetNextFLACBlock(VoiceNode *voice)
{
flac_data * fd = (flac_data *) voice->extra;
flac_data *fd = (flac_data *)voice->rawdataptr;
FLAC__StreamDecoderState decode_state;
// FLAC__bool decode_status;
// FLAC__bool decode_status;
voice->Playing = TRUE;
if ((FLAC__uint64)(uintptr_t)voice->LoopEnd > 0 && fd->sample_pos >= (FLAC__uint64)(uintptr_t)voice->LoopEnd)
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart))
MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul, LOOP_END %ul\n",
(FLAC__uint64)(uintptr_t)voice->LoopStart, (FLAC__uint64)(uintptr_t)voice->LoopEnd);
(FLAC__uint64)(uintptr_t)voice->LoopStart, (FLAC__uint64)(uintptr_t)voice->LoopEnd);
/*decode_status =*/ FLAC__stream_decoder_process_single(fd->stream);
/*decode_status =*/FLAC__stream_decoder_process_single(fd->stream);
decode_state = FLAC__stream_decoder_get_state(fd->stream);
/*
if (!decode_status)
{
MV_Printf("MV_GetNextFLACBlock: %s\n", FLAC__StreamDecoderStateString[decode_state]);
voice->Playing = FALSE;
return NoMoreData;
}
*/
/*
if (!decode_status)
{
MV_Printf("MV_GetNextFLACBlock: %s\n", FLAC__StreamDecoderStateString[decode_state]);
voice->Playing = FALSE;
return NoMoreData;
}
*/
if (decode_state == FLAC__STREAM_DECODER_SEEK_ERROR)
{
@ -347,7 +352,7 @@ static playbackstatus MV_GetNextFLACBlock
{
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart))
MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul\n",
(FLAC__uint64)(uintptr_t)voice->LoopStart);
(FLAC__uint64)(uintptr_t)voice->LoopStart);
}
else
{
@ -378,49 +383,40 @@ Begin playback of sound data at specified angle and distance
from listener.
---------------------------------------------------------------------*/
int32_t MV_PlayFLAC3D
(
char *ptr,
uint32_t ptrlength,
int32_t loophow,
int32_t pitchoffset,
int32_t angle,
int32_t distance,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayFLAC3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
{
int32_t left;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
int32_t left;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
if ( !MV_Installed )
{
MV_SetErrorCode( MV_NotInstalled );
return MV_Error;
}
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
if ( distance < 0 )
{
distance = -distance;
angle += MV_NUMPANPOSITIONS / 2;
}
if (distance < 0)
{
distance = -distance;
angle += MV_NUMPANPOSITIONS / 2;
}
volume = MIX_VOLUME( distance );
volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION;
// Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left;
right = MV_PanTable[ angle ][ volume ].right;
mid = max( 0, 255 - distance );
left = MV_PanTable[angle][volume].left;
right = MV_PanTable[angle][volume].right;
mid = max(0, 255 - distance);
status = MV_PlayFLAC(ptr, ptrlength, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
status = MV_PlayFLAC(ptr, ptrlength, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
return status;
}
@ -431,109 +427,95 @@ Begin playback of sound data with the given sound levels and
priority.
---------------------------------------------------------------------*/
int32_t MV_PlayFLAC
(
char *ptr,
uint32_t ptrlength,
int32_t loopstart,
int32_t loopend,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayFLAC(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset, int32_t vol,
int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
VoiceNode *voice;
flac_data * fd = 0;
FLAC__Metadata_Chain* metadata_chain;
VoiceNode *voice;
flac_data *fd = 0;
FLAC__Metadata_Chain *metadata_chain;
UNREFERENCED_PARAMETER(loopend);
UNREFERENCED_PARAMETER(loopend);
if ( !MV_Installed )
{
MV_SetErrorCode( MV_NotInstalled );
return MV_Error;
}
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
fd = (flac_data *) calloc( 1, sizeof(flac_data) );
if (!fd) {
MV_SetErrorCode( MV_InvalidFLACFile );
return MV_Error;
}
fd = (flac_data *)calloc(1, sizeof(flac_data));
if (!fd)
{
MV_SetErrorCode(MV_InvalidFLACFile);
return MV_Error;
}
fd->ptr = ptr;
fd->pos = 0;
fd->blocksize = 0;
fd->length = ptrlength;
fd->ptr = ptr;
fd->pos = 0;
fd->blocksize = 0;
fd->length = ptrlength;
fd->block = NULL;
fd->block = NULL;
fd->stream = FLAC__stream_decoder_new();
fd->sample_pos = 0;
fd->stream = FLAC__stream_decoder_new();
fd->sample_pos = 0;
FLAC__stream_decoder_set_metadata_ignore_all(fd->stream);
if (FLAC__stream_decoder_init_stream(fd->stream,
read_flac_stream,
seek_flac_stream,
tell_flac_stream,
length_flac_stream,
eof_flac_stream,
write_flac_stream,
/*metadata_flac_stream*/ NULL,
error_flac_stream,
(void*) fd) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
MV_Printf("MV_PlayFLAC: %s\n", FLAC__stream_decoder_get_resolved_state_string(fd->stream));
MV_SetErrorCode( MV_InvalidFLACFile );
return MV_Error;
}
if (FLAC__stream_decoder_init_stream(fd->stream, read_flac_stream, seek_flac_stream, tell_flac_stream,
length_flac_stream, eof_flac_stream, write_flac_stream,
/*metadata_flac_stream*/ NULL, error_flac_stream,
(void *)fd) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
{
MV_Printf("MV_PlayFLAC: %s\n", FLAC__stream_decoder_get_resolved_state_string(fd->stream));
MV_SetErrorCode(MV_InvalidFLACFile);
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice( priority );
if ( voice == NULL )
{
FLAC__stream_decoder_finish(fd->stream);
FLAC__stream_decoder_delete(fd->stream);
free(fd);
MV_SetErrorCode( MV_NoVoices );
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice(priority);
if (voice == NULL)
{
FLAC__stream_decoder_finish(fd->stream);
FLAC__stream_decoder_delete(fd->stream);
free(fd);
MV_SetErrorCode(MV_NoVoices);
return MV_Error;
}
fd->owner = voice;
fd->owner = voice;
voice->wavetype = FLAC;
voice->extra = (void*)fd;
voice->GetSound = MV_GetNextFLACBlock;
voice->NextBlock = fd->block;
voice->DemandFeed = NULL;
voice->LoopCount = 0;
voice->BlockLength = 0;
voice->PitchScale = PITCH_GetScale( pitchoffset );
voice->next = NULL;
voice->prev = NULL;
voice->priority = priority;
voice->callbackval = callbackval;
voice->wavetype = FMT_FLAC;
voice->rawdataptr = (void *)fd;
voice->GetSound = MV_GetNextFLACBlock;
voice->NextBlock = fd->block;
voice->LoopCount = 0;
voice->BlockLength = 0;
voice->PitchScale = PITCH_GetScale(pitchoffset);
voice->next = NULL;
voice->prev = NULL;
voice->priority = priority;
voice->callbackval = callbackval;
voice->Playing = TRUE;
voice->Paused = FALSE;
voice->Playing = TRUE;
voice->Paused = FALSE;
voice->LoopStart = 0;
voice->LoopEnd = 0;
voice->LoopSize = (loopstart >= 0 ? 1 : 0);
voice->LoopStart = 0;
voice->LoopEnd = 0;
voice->LoopSize = (loopstart >= 0 ? 1 : 0);
// parse metadata
// loop parsing designed with multiple repetitions in mind
// In retrospect, it may be possible to MV_GetVorbisCommentLoops(voice, (vorbis_comment *) &tags->data.vorbis_comment)
// but libvorbisfile may be confused by the signedness of char* vs FLAC__byte* and this code does not depend on HAVE_VORBIS.
// In retrospect, it may be possible to MV_GetVorbisCommentLoops(voice, (vorbis_comment *)
// &tags->data.vorbis_comment)
// but libvorbisfile may be confused by the signedness of char* vs FLAC__byte* and this code does not depend on
// HAVE_VORBIS.
metadata_chain = FLAC__metadata_chain_new();
if (metadata_chain != NULL)
{
if (FLAC__metadata_chain_read_with_callbacks(metadata_chain, fd, flac_callbacks))
{
FLAC__Metadata_Iterator* metadata_iterator = FLAC__metadata_iterator_new();
FLAC__Metadata_Iterator *metadata_iterator = FLAC__metadata_iterator_new();
if (metadata_iterator != NULL)
{
char *vc_loopstart = NULL;
@ -550,19 +532,20 @@ int32_t MV_PlayFLAC
{
const FLAC__StreamMetadata_StreamInfo *info = &tags->data.stream_info;
if (info->channels != 1 && info->channels != 2) {
FLAC__metadata_object_delete(tags);
FLAC__metadata_iterator_delete(metadata_iterator);
// FLAC__metadata_chain_delete(metadata_chain);
FLAC__stream_decoder_finish(fd->stream);
FLAC__stream_decoder_delete(fd->stream);
free(fd);
MV_SetErrorCode( MV_InvalidFLACFile );
return MV_Error;
if (info->channels != 1 && info->channels != 2)
{
FLAC__metadata_object_delete(tags);
FLAC__metadata_iterator_delete(metadata_iterator);
// FLAC__metadata_chain_delete(metadata_chain);
FLAC__stream_decoder_finish(fd->stream);
FLAC__stream_decoder_delete(fd->stream);
free(fd);
MV_SetErrorCode(MV_InvalidFLACFile);
return MV_Error;
}
voice->channels = info->channels;
voice->bits = info->bits_per_sample;
voice->channels = info->channels;
voice->bits = info->bits_per_sample;
voice->SamplingRate = info->sample_rate;
}
@ -573,39 +556,42 @@ int32_t MV_PlayFLAC
uint8_t loopTagCount;
for (comment = 0; comment < tags->data.vorbis_comment.num_comments; ++comment)
{
const char *entry = (const char *) tags->data.vorbis_comment.comments[comment].entry;
const char *entry = (const char *)tags->data.vorbis_comment.comments[comment].entry;
if (entry != NULL && entry[0] != '\0')
{
const char *value = strchr(entry,'=');
const size_t field = value-entry;
const char *value = strchr(entry, '=');
const size_t field = value - entry;
value += 1;
for (loopTagCount = 0; loopTagCount < loopStartTagCount && vc_loopstart == NULL; ++loopTagCount)
for (loopTagCount = 0; loopTagCount < loopStartTagCount && vc_loopstart == NULL;
++loopTagCount)
if (strncasecmp(entry, loopStartTags[loopTagCount], field) == 0)
vc_loopstart = strdup(value);
for (loopTagCount = 0; loopTagCount < loopEndTagCount && vc_loopend == NULL; ++loopTagCount)
for (loopTagCount = 0; loopTagCount < loopEndTagCount && vc_loopend == NULL;
++loopTagCount)
if (strncasecmp(entry, loopEndTags[loopTagCount], field) == 0)
vc_loopend = strdup(value);
for (loopTagCount = 0; loopTagCount < loopLengthTagCount && vc_looplength == NULL; ++loopTagCount)
for (loopTagCount = 0; loopTagCount < loopLengthTagCount && vc_looplength == NULL;
++loopTagCount)
if (strncasecmp(entry, loopLengthTags[loopTagCount], field) == 0)
vc_looplength = strdup(value);
}
}
}
FLAC__metadata_object_delete(tags); // If it were not for this, I would assign pointers instead of strdup().
}
while (FLAC__metadata_iterator_next(metadata_iterator));
FLAC__metadata_object_delete(
tags); // If it were not for this, I would assign pointers instead of strdup().
} while (FLAC__metadata_iterator_next(metadata_iterator));
if (vc_loopstart != NULL)
{
{
const FLAC__int64 flac_loopstart = atol(vc_loopstart);
if (flac_loopstart >= 0) // a loop starting at 0 is valid
if (flac_loopstart >= 0) // a loop starting at 0 is valid
{
voice->LoopStart = (const char *) (intptr_t) flac_loopstart;
voice->LoopStart = (const char *)(intptr_t)flac_loopstart;
voice->LoopSize = 1;
}
}
@ -616,8 +602,8 @@ int32_t MV_PlayFLAC
if (voice->LoopSize > 0)
{
const FLAC__int64 flac_loopend = atol(vc_loopend);
if (flac_loopend > 0) // a loop ending at 0 is invalid
voice->LoopEnd = (const char *) (intptr_t) flac_loopend;
if (flac_loopend > 0) // a loop ending at 0 is invalid
voice->LoopEnd = (const char *)(intptr_t)flac_loopend;
}
free(vc_loopend);
}
@ -626,8 +612,8 @@ int32_t MV_PlayFLAC
if (voice->LoopSize > 0 && voice->LoopEnd == 0)
{
const FLAC__int64 flac_looplength = atol(vc_looplength);
if (flac_looplength > 0) // a loop of length 0 is invalid
voice->LoopEnd = (const char *) ((intptr_t) flac_looplength + (intptr_t) voice->LoopStart);
if (flac_looplength > 0) // a loop of length 0 is invalid
voice->LoopEnd = (const char *)((intptr_t)flac_looplength + (intptr_t)voice->LoopStart);
}
free(vc_looplength);
}
@ -640,29 +626,30 @@ int32_t MV_PlayFLAC
else
MV_Printf("%s\n", FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(metadata_chain)]);
// FLAC__metadata_chain_delete(metadata_chain); // when run with GDB, this throws SIGTRAP about freed heap memory being modified
// FLAC__metadata_chain_delete(metadata_chain); // when run with GDB, this throws SIGTRAP about freed heap
// memory being modified
}
else
MV_Printf("Error allocating FLAC__Metadata_Chain!\n");
// CODEDUP multivoc.c MV_SetVoicePitch
voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) -
voice->RateScale;
MV_SetVoiceMixMode( voice );
// CODEDUP multivoc.c MV_SetVoicePitch
voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate;
voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale;
MV_SetVoiceMixMode(voice);
MV_SetVoiceVolume( voice, vol, left, right );
MV_PlayVoice( voice );
MV_SetVoiceVolume(voice, vol, left, right);
MV_PlayVoice(voice);
return voice->handle;
return voice->handle;
}
void MV_ReleaseFLACVoice( VoiceNode * voice )
void MV_ReleaseFLACVoice(VoiceNode *voice)
{
flac_data * fd = (flac_data *) voice->extra;
flac_data *fd = (flac_data *)voice->rawdataptr;
if (voice->wavetype != FLAC) {
if (voice->wavetype != FMT_FLAC)
{
return;
}
@ -675,7 +662,20 @@ void MV_ReleaseFLACVoice( VoiceNode * voice )
free(fd->block);
free(fd);
voice->extra = 0;
voice->rawdataptr = 0;
}
#else
int32_t MV_PlayFLAC(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
MV_Printf("MV_PlayFLAC: FLAC support not included in this binary.\n");
return -1;
}
#endif //HAVE_FLAC
int32_t MV_PlayFLAC3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
{
MV_Printf("MV_PlayFLAC: FLAC support not included in this binary.\n");
return -1;
}
#endif // HAVE_FLAC

View file

@ -1,5 +1,7 @@
/*
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
Copyright (C) 2015 EDuke32 developers
Copyright (C) 2015 Voidpoint, LLC
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -19,7 +21,7 @@
*/
/**
* Raw, DemandFeed, WAV, and VOC source support for MultiVoc
* Raw, WAV, and VOC source support for MultiVoc
*/
#include <stdlib.h>
@ -33,46 +35,6 @@
#include "multivoc.h"
#include "_multivc.h"
/*---------------------------------------------------------------------
Function: MV_GetNextRawBlock
Controls playback of demand fed data.
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextRawBlock(VoiceNode *voice)
{
if (voice->BlockLength <= 0)
{
if (voice->LoopStart == NULL)
{
voice->Playing = FALSE;
return NoMoreData;
}
voice->BlockLength = voice->LoopSize;
voice->NextBlock = voice->LoopStart;
voice->length = 0;
voice->position = 0;
}
voice->sound = voice->NextBlock;
voice->position -= voice->length;
voice->length = min(voice->BlockLength, 0x8000);
voice->NextBlock += voice->length * (voice->channels * voice->bits / 8);
voice->BlockLength -= voice->length;
voice->length <<= 16;
return KeepPlaying;
}
/*---------------------------------------------------------------------
Function: MV_GetNextWAVBlock
Controls playback of demand fed data.
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextWAVBlock(VoiceNode *voice)
{
if (voice->BlockLength <= 0)
@ -99,24 +61,11 @@ static playbackstatus MV_GetNextWAVBlock(VoiceNode *voice)
return KeepPlaying;
}
/*---------------------------------------------------------------------
Function: MV_GetNextVOCBlock
Interpret the information of a VOC format sound file.
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
{
const uint8_t *ptr;
int32_t blocktype;
int32_t lastblocktype;
size_t blocklength = 0;
uint32_t samplespeed = 0; // XXX: compiler-happy on synthesis
uint32_t tc = 0;
int32_t packtype;
int32_t voicemode;
int32_t done;
unsigned BitsPerSample;
unsigned Channels;
unsigned Format;
@ -131,16 +80,17 @@ static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
return KeepPlaying;
}
ptr = (uint8_t *)voice->NextBlock;
const uint8_t *ptr = (uint8_t *)voice->NextBlock;
voice->Playing = TRUE;
voice->Paused = FALSE;
voicemode = 0;
lastblocktype = 0;
packtype = 0;
int voicemode = 0;
int blocktype = 0;
int lastblocktype = 0;
int packtype = 0;
done = FALSE;
int done = FALSE;
do
{
@ -155,7 +105,7 @@ static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
// terminator is not mandatory according to
// http://wiki.multimedia.cx/index.php?title=Creative_Voice
if (ptr - voice->rawdataptr >= voice->ptrlength)
if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
blocktype = 0; // fake a terminator
else
blocktype = *ptr;
@ -206,14 +156,11 @@ end_of_data:
// Skip packed or stereo data
if ((packtype != 0) || (voicemode != 0 && voicemode != 1))
{
ptr += blocklength;
}
else
{
done = TRUE;
}
if (ptr - voice->rawdataptr >= voice->ptrlength)
if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
goto end_of_data;
voicemode = 0;
@ -227,19 +174,11 @@ end_of_data:
case 3 :
// Silence
// Not implimented.
ptr += blocklength;
break;
case 4 :
// Marker
// Not implimented.
ptr += blocklength;
break;
case 5 :
// ASCII string
// Not implimented.
// All not implemented.
ptr += blocklength;
break;
@ -257,21 +196,17 @@ end_of_data:
// Repeat end
ptr += blocklength;
if (lastblocktype == 6)
{
voice->LoopCount = 0;
}
else
{
if ((voice->LoopCount > 0) && (voice->LoopStart != NULL))
{
ptr = (uint8_t *) voice->LoopStart;
if (voice->LoopCount < 0xffff)
{
voice->LoopCount--;
if (voice->LoopCount == 0)
{
if (--voice->LoopCount == 0)
voice->LoopStart = NULL;
}
}
}
}
@ -294,8 +229,7 @@ end_of_data:
Channels = (unsigned)*(ptr + 5);
Format = (unsigned)LITTLE16(*(uint16_t *)(ptr + 6));
if ((BitsPerSample == 8) && (Channels == 1 || Channels == 2) &&
(Format == VOC_8BIT))
if ((BitsPerSample == 8) && (Channels == 1 || Channels == 2) && (Format == VOC_8BIT))
{
ptr += 12;
blocklength -= 12;
@ -303,8 +237,7 @@ end_of_data:
voice->channels = Channels;
done = TRUE;
}
else if ((BitsPerSample == 16) && (Channels == 1 || Channels == 2) &&
(Format == VOC_16BIT))
else if ((BitsPerSample == 16) && (Channels == 1 || Channels == 2) && (Format == VOC_16BIT))
{
ptr += 12;
blocklength -= 12;
@ -320,7 +253,7 @@ end_of_data:
// CAUTION:
// SNAKRM.VOC is corrupt! blocklength gets us beyond the
// end of the file.
if (ptr - voice->rawdataptr >= voice->ptrlength)
if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
goto end_of_data;
break;
@ -380,137 +313,11 @@ end_of_data:
return NoMoreData;
}
/*---------------------------------------------------------------------
Function: MV_GetNextDemandFeedBlock
Controls playback of demand fed data.
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextDemandFeedBlock(VoiceNode *voice)
int32_t MV_PlayWAV3D(char *ptr, uint32_t length, int32_t loophow, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval)
{
if (voice->BlockLength > 0)
{
voice->position -= voice->length;
voice->sound += voice->length >> 16;
voice->length = min(voice->BlockLength, 0x8000);
voice->BlockLength -= voice->length;
voice->length <<= 16;
return KeepPlaying;
}
if (voice->DemandFeed == NULL)
return NoMoreData;
voice->position = 0;
// TODO: learn how to properly attach the 'const' in pointer-pointers :O
(voice->DemandFeed)((char **)&voice->sound, &voice->BlockLength);
voice->length = min(voice->BlockLength, 0x8000);
voice->BlockLength -= voice->length;
voice->length <<= 16;
return ((voice->length > 0) && (voice->sound != NULL) ? KeepPlaying : NoMoreData);
}
/*---------------------------------------------------------------------
Function: MV_PlayRaw
Begin playback of sound data with the given sound levels and
priority.
---------------------------------------------------------------------*/
int32_t MV_PlayRaw
(
char *ptr,
uint32_t length,
char *loopstart,
char *loopend,
unsigned rate,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
{
VoiceNode *voice;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice(priority);
if (voice == NULL)
{
MV_SetErrorCode(MV_NoVoices);
return MV_Error;
}
voice->wavetype = Raw;
voice->bits = 8;
voice->channels = 1;
voice->GetSound = MV_GetNextRawBlock;
voice->Playing = TRUE;
voice->Paused = FALSE;
voice->NextBlock = ptr;
voice->position = 0;
voice->BlockLength = length;
voice->length = 0;
voice->next = NULL;
voice->prev = NULL;
voice->priority = priority;
voice->callbackval = callbackval;
voice->LoopStart = loopstart;
voice->LoopEnd = loopend;
voice->LoopSize = loopend > (char*) 0 ? (uintptr_t) loopend - (uintptr_t) loopstart + 1 : length;
MV_SetVoicePitch(voice, rate, pitchoffset);
MV_SetVoiceVolume(voice, vol, left, right);
MV_PlayVoice(voice);
return voice->handle;
}
/*---------------------------------------------------------------------
Function: MV_PlayWAV3D
Begin playback of sound data at specified angle and distance
from listener.
---------------------------------------------------------------------*/
int32_t MV_PlayWAV3D
(
char *ptr,
uint32_t length,
int32_t loophow,
int32_t pitchoffset,
int32_t angle,
int32_t distance,
int32_t priority,
uint32_t callbackval
)
{
int32_t left;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
if (distance < 0)
{
@ -518,67 +325,33 @@ int32_t MV_PlayWAV3D
angle += MV_NUMPANPOSITIONS / 2;
}
volume = MIX_VOLUME(distance);
int const volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left;
right = MV_PanTable[ angle ][ volume ].right;
mid = max(0, 255 - distance);
status = MV_PlayWAV(ptr, length, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
return MV_PlayWAV(ptr, length, loophow, -1, pitchoffset, max(0, 255 - distance),
MV_PanTable[ angle ][ volume ].left, MV_PanTable[ angle ][ volume ].right, priority, callbackval);
}
/*---------------------------------------------------------------------
Function: MV_PlayWAV
Begin playback of sound data with the given sound levels and
priority.
---------------------------------------------------------------------*/
int32_t MV_PlayWAV
(
char *ptr,
uint32_t ptrlength,
int32_t loopstart,
int32_t loopend,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayWAV(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset, int32_t vol,
int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
riff_header riff;
format_header format;
data_header data;
VoiceNode *voice;
int32_t length;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
riff_header riff;
memcpy(&riff, ptr, sizeof(riff_header));
riff.file_size = LITTLE32(riff.file_size);
riff.format_size = LITTLE32(riff.format_size);
if ((memcmp(riff.RIFF, "RIFF", 4) != 0) ||
(memcmp(riff.WAVE, "WAVE", 4) != 0) ||
(memcmp(riff.fmt, "fmt ", 4) != 0))
if ((memcmp(riff.RIFF, "RIFF", 4) != 0) || (memcmp(riff.WAVE, "WAVE", 4) != 0) || (memcmp(riff.fmt, "fmt ", 4) != 0))
{
MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error;
}
format_header format;
memcpy(&format, ptr + sizeof(riff_header), sizeof(format_header));
format.wFormatTag = LITTLE16(format.wFormatTag);
format.nChannels = LITTLE16(format.nChannels);
@ -587,54 +360,41 @@ int32_t MV_PlayWAV
format.nBlockAlign = LITTLE16(format.nBlockAlign);
format.nBitsPerSample = LITTLE16(format.nBitsPerSample);
data_header data;
memcpy(&data, ptr + sizeof(riff_header) + riff.format_size, sizeof(data_header));
data.size = LITTLE32(data.size);
// Check if it's PCM data.
if (format.wFormatTag != 1)
{
MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error;
}
if (format.nChannels != 1 && format.nChannels != 2)
{
MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error;
}
if ((format.nBitsPerSample != 8) &&
(format.nBitsPerSample != 16))
{
MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error;
}
if (memcmp(data.DATA, "data", 4) != 0)
if (format.wFormatTag != 1 || (format.nChannels != 1 && format.nChannels != 2) ||
((format.nBitsPerSample != 8) && (format.nBitsPerSample != 16)) || memcmp(data.DATA, "data", 4) != 0)
{
MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice(priority);
VoiceNode *voice = MV_AllocVoice(priority);
if (voice == NULL)
{
MV_SetErrorCode(MV_NoVoices);
return MV_Error;
}
voice->wavetype = WAV;
voice->wavetype = FMT_WAV;
voice->bits = format.nBitsPerSample;
voice->channels = format.nChannels;
voice->GetSound = MV_GetNextWAVBlock;
length = data.size;
int32_t length = data.size;
if (voice->bits == 16)
{
data.size &= ~1;
length /= 2;
}
if (voice->channels == 2)
{
data.size &= ~1;
@ -645,7 +405,6 @@ int32_t MV_PlayWAV
voice->ptrlength = ptrlength;
voice->Playing = TRUE;
voice->Paused = FALSE;
voice->DemandFeed = NULL;
voice->LoopCount = 0;
voice->position = 0;
voice->length = 0;
@ -666,38 +425,11 @@ int32_t MV_PlayWAV
return voice->handle;
}
/*---------------------------------------------------------------------
Function: MV_PlayVOC3D
Begin playback of sound data at specified angle and distance
from listener.
---------------------------------------------------------------------*/
int32_t MV_PlayVOC3D
(
char *ptr,
uint32_t ptrlength,
int32_t loophow,
int32_t pitchoffset,
int32_t angle,
int32_t distance,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayVOC3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
{
int32_t left;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
if (distance < 0)
{
@ -705,62 +437,31 @@ int32_t MV_PlayVOC3D
angle += MV_NUMPANPOSITIONS / 2;
}
volume = MIX_VOLUME(distance);
int const volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left;
right = MV_PanTable[ angle ][ volume ].right;
mid = max(0, 255 - distance);
status = MV_PlayVOC(ptr, ptrlength, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
return MV_PlayVOC(ptr, ptrlength, loophow, -1, pitchoffset, max(0, 255 - distance),
MV_PanTable[ angle ][ volume ].left, MV_PanTable[ angle ][ volume ].right, priority, callbackval);
}
/*---------------------------------------------------------------------
Function: MV_PlayVOC
Begin playback of sound data with the given sound levels and
priority.
---------------------------------------------------------------------*/
int32_t MV_PlayVOC
(
char *ptr,
uint32_t ptrlength,
int32_t loopstart,
int32_t loopend,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayVOC(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset, int32_t vol,
int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
VoiceNode *voice;
int32_t status;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
// Make sure it looks like a valid VOC file.
status = memcmp(ptr, "Creative Voice File", 19);
if (status != 0)
if (memcmp(ptr, "Creative Voice File", 19) != 0)
{
MV_SetErrorCode(MV_InvalidVOCFile);
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice(priority);
VoiceNode *voice = MV_AllocVoice(priority);
if (voice == NULL)
{
MV_SetErrorCode(MV_NoVoices);
@ -771,12 +472,11 @@ int32_t MV_PlayVOC
voice->ptrlength = ptrlength;
voice->Playing = TRUE;
voice->Paused = FALSE;
voice->wavetype = VOC;
voice->wavetype = FMT_VOC;
voice->bits = 8;
voice->channels = 1;
voice->GetSound = MV_GetNextVOCBlock;
voice->NextBlock = ptr + LITTLE16(*(uint16_t *)(ptr + 0x14));
voice->DemandFeed = NULL;
voice->LoopCount = 0;
voice->BlockLength = 0;
voice->PitchScale = PITCH_GetScale(pitchoffset);
@ -795,63 +495,3 @@ int32_t MV_PlayVOC
return voice->handle;
}
/*---------------------------------------------------------------------
Function: MV_StartDemandFeedPlayback
Plays a digitized sound from a user controlled buffering system.
---------------------------------------------------------------------*/
int32_t MV_StartDemandFeedPlayback
(
void (*function)(char **ptr, uint32_t *length),
int32_t rate,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
{
VoiceNode *voice;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice(priority);
if (voice == NULL)
{
MV_SetErrorCode(MV_NoVoices);
return MV_Error;
}
voice->wavetype = DemandFeed;
voice->bits = 8;
voice->channels = 1;
voice->GetSound = MV_GetNextDemandFeedBlock;
voice->NextBlock = NULL;
voice->DemandFeed = function;
voice->LoopStart = NULL;
voice->LoopCount = 0;
voice->position = 0;
voice->sound = NULL;
voice->length = 0;
voice->BlockLength = 0;
voice->Playing = TRUE;
voice->next = NULL;
voice->prev = NULL;
voice->priority = priority;
voice->callbackval = callbackval;
MV_SetVoicePitch(voice, rate, pitchoffset);
MV_SetVoiceVolume(voice, vol, left, right);
MV_PlayVoice(voice);
return voice->handle;
}

View file

@ -1,5 +1,7 @@
/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
Copyright (C) 2015 EDuke32 developers
Copyright (C) 2015 Voidpoint, LLC
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -28,10 +30,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#include "compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndcards.h"
#include "drivers.h"
#include "multivoc.h"
#include "fx_man.h"
@ -39,82 +41,45 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
int32_t FX_ErrorCode = FX_Ok;
int32_t FX_Installed = FALSE;
#define FX_SetErrorCode( status ) \
FX_ErrorCode = ( status );
/*---------------------------------------------------------------------
Function: FX_ErrorString
Returns a pointer to the error message associated with an error
number. A -1 returns a pointer the current error.
---------------------------------------------------------------------*/
const char *FX_ErrorString
(
int32_t ErrorNumber
)
#define FX_SetErrorCode(status) FX_ErrorCode = (status);
const char *FX_ErrorString(int32_t ErrorNumber)
{
const char *ErrorString;
switch (ErrorNumber)
{
case FX_Warning :
case FX_Error :
ErrorString = FX_ErrorString(FX_ErrorCode);
break;
case FX_Warning:
case FX_Error: ErrorString = FX_ErrorString(FX_ErrorCode); break;
case FX_Ok :
ErrorString = "Fx ok.";
break;
case FX_Ok: ErrorString = "Fx ok."; break;
case FX_SoundCardError :
ErrorString = SoundDriver_ErrorString(SoundDriver_GetError());
break;
case FX_InvalidCard: ErrorString = "Invalid Sound Fx device."; break;
case FX_InvalidCard :
ErrorString = "Invalid Sound Fx device.";
break;
case FX_MultiVocError: ErrorString = MV_ErrorString(MV_Error); break;
case FX_MultiVocError :
ErrorString = MV_ErrorString(MV_Error);
break;
default :
ErrorString = "Unknown Fx error code.";
break;
default: ErrorString = "Unknown Fx error code."; break;
}
return ErrorString;
}
/*---------------------------------------------------------------------
Function: FX_Init
Selects which sound device to use.
---------------------------------------------------------------------*/
int32_t FX_Init
(
int32_t SoundCard,
int32_t numvoices,
int32_t numchannels,
int32_t samplebits,
unsigned mixrate,
void * initdata
)
static inline int32_t FX_CheckMVErr(int32_t status)
{
int32_t status;
int32_t devicestatus;
if (FX_Installed)
if (status != MV_Ok)
{
FX_Shutdown();
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
int32_t FX_Init(int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, unsigned mixrate, void *initdata)
{
if (FX_Installed)
FX_Shutdown();
if (SoundCard == ASS_AutoDetect)
{
#if defined HAVE_DS
@ -130,8 +95,7 @@ int32_t FX_Init
if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards)
{
FX_SetErrorCode(FX_InvalidCard);
status = FX_Error;
return status;
return FX_Error;
}
if (SoundDriver_IsSupported(SoundCard) == 0)
@ -140,43 +104,27 @@ int32_t FX_Init
SoundCard = ASS_NoSound;
}
status = FX_Ok;
devicestatus = MV_Init(SoundCard, mixrate, numvoices, numchannels, samplebits, initdata);
if (devicestatus != MV_Ok)
int status = FX_Ok;
if (MV_Init(SoundCard, mixrate, numvoices, numchannels, samplebits, initdata) != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Error;
}
if (status == FX_Ok)
{
FX_Installed = TRUE;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_Shutdown
Terminates use of sound device.
---------------------------------------------------------------------*/
int32_t FX_Shutdown
(
void
)
int32_t FX_Shutdown(void)
{
int32_t status;
if (!FX_Installed)
{
return FX_Ok;
}
status = MV_Shutdown();
int status = MV_Shutdown();
if (status != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
@ -188,569 +136,116 @@ int32_t FX_Shutdown
return status;
}
void FX_SetCallBack(void (*function)(uint32_t)) { MV_SetCallBack(function); }
/*---------------------------------------------------------------------
Function: FX_SetCallback
void FX_SetVolume(int32_t volume) { MV_SetVolume(volume); }
Sets the function to call when a voice is done.
---------------------------------------------------------------------*/
int32_t FX_GetVolume(void) { return MV_GetVolume(); }
int32_t FX_SetCallBack
(
void (*function)(uint32_t)
)
void FX_SetReverseStereo(int32_t setting) { MV_SetReverseStereo(setting); }
int32_t FX_GetReverseStereo(void) { return MV_GetReverseStereo(); }
void FX_SetReverb(int32_t reverb) { MV_SetReverb(reverb); }
int32_t FX_GetMaxReverbDelay(void) { return MV_GetMaxReverbDelay(); }
int32_t FX_GetReverbDelay(void) { return MV_GetReverbDelay(); }
void FX_SetReverbDelay(int32_t delay) { MV_SetReverbDelay(delay); }
int32_t FX_VoiceAvailable(int32_t priority) { return MV_VoiceAvailable(priority); }
int32_t FX_PauseVoice(int32_t handle, int32_t pause) { return FX_CheckMVErr(MV_PauseVoice(handle, pause)); }
int32_t FX_GetPosition(int32_t handle, int32_t *position) { return FX_CheckMVErr(MV_GetPosition(handle, position)); }
int32_t FX_SetPosition(int32_t handle, int32_t position) { return FX_CheckMVErr(MV_SetPosition(handle, position)); }
int32_t FX_EndLooping(int32_t handle) { return FX_CheckMVErr(MV_EndLooping(handle)); }
int32_t FX_SetPan(int32_t handle, int32_t vol, int32_t left, int32_t right)
{
int32_t status;
status = FX_Ok;
MV_SetCallBack(function);
return status;
return FX_CheckMVErr(MV_SetPan(handle, vol, left, right));
}
int32_t FX_SetPitch(int32_t handle, int32_t pitchoffset) { return FX_CheckMVErr(MV_SetPitch(handle, pitchoffset)); }
/*---------------------------------------------------------------------
Function: FX_SetVolume
Sets the volume of the current sound device.
---------------------------------------------------------------------*/
void FX_SetVolume
(
int32_t volume
)
int32_t FX_SetFrequency(int32_t handle, int32_t frequency) { return FX_CheckMVErr(MV_SetFrequency(handle, frequency)); }
int32_t FX_Pan3D(int32_t handle, int32_t angle, int32_t distance)
{
MV_SetVolume(volume);
return FX_CheckMVErr(MV_Pan3D(handle, angle, distance));
}
int32_t FX_SoundActive(int32_t handle) { return MV_VoicePlaying(handle); }
/*---------------------------------------------------------------------
Function: FX_GetVolume
int32_t FX_SoundsPlaying(void) { return MV_VoicesPlaying(); }
Returns the volume of the current sound device.
---------------------------------------------------------------------*/
int32_t FX_StopSound(int32_t handle) { return FX_CheckMVErr(MV_Kill(handle)); }
int32_t FX_GetVolume
(
void
)
int32_t FX_StopAllSounds(void) { return FX_CheckMVErr(MV_KillAllVoices()); }
static wavefmt_t FX_AutoDetectFormat(const char *ptr, uint32_t length)
{
int32_t volume;
wavefmt_t fmt = FMT_UNKNOWN;
volume = MV_GetVolume();
return volume;
}
/*---------------------------------------------------------------------
Function: FX_SetReverseStereo
Set the orientation of the left and right channels.
---------------------------------------------------------------------*/
void FX_SetReverseStereo
(
int32_t setting
)
{
MV_SetReverseStereo(setting);
}
/*---------------------------------------------------------------------
Function: FX_GetReverseStereo
Returns the orientation of the left and right channels.
---------------------------------------------------------------------*/
int32_t FX_GetReverseStereo
(
void
)
{
return MV_GetReverseStereo();
}
/*---------------------------------------------------------------------
Function: FX_SetReverb
Sets the reverb level.
---------------------------------------------------------------------*/
void FX_SetReverb
(
int32_t reverb
)
{
MV_SetReverb(reverb);
}
/*---------------------------------------------------------------------
Function: FX_SetFastReverb
Sets the reverb level.
---------------------------------------------------------------------*/
void FX_SetFastReverb
(
int32_t reverb
)
{
MV_SetFastReverb(reverb);
}
/*---------------------------------------------------------------------
Function: FX_GetMaxReverbDelay
Returns the maximum delay time for reverb.
---------------------------------------------------------------------*/
int32_t FX_GetMaxReverbDelay
(
void
)
{
return MV_GetMaxReverbDelay();
}
/*---------------------------------------------------------------------
Function: FX_GetReverbDelay
Returns the current delay time for reverb.
---------------------------------------------------------------------*/
int32_t FX_GetReverbDelay
(
void
)
{
return MV_GetReverbDelay();
}
/*---------------------------------------------------------------------
Function: FX_SetReverbDelay
Sets the delay level of reverb to add to mix.
---------------------------------------------------------------------*/
void FX_SetReverbDelay
(
int32_t delay
)
{
MV_SetReverbDelay(delay);
}
/*---------------------------------------------------------------------
Function: FX_VoiceAvailable
Checks if a voice can be play at the specified priority.
---------------------------------------------------------------------*/
int32_t FX_VoiceAvailable
(
int32_t priority
)
{
return MV_VoiceAvailable(priority);
}
/*---------------------------------------------------------------------
Function: FX_PauseVoice
Stops the voice associated with the specified handle from looping
without stoping the sound.
---------------------------------------------------------------------*/
int32_t FX_PauseVoice
(
int32_t handle,
int32_t pause
)
{
int32_t status;
status = MV_PauseVoice(handle, pause);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
int32_t FX_GetPosition(int32_t handle, int32_t *position)
{
int32_t status;
status = MV_GetPosition(handle, position);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
int32_t FX_SetPosition(int32_t handle, int32_t position)
{
int32_t status;
status = MV_SetPosition(handle, position);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_EndLooping
Stops the voice associated with the specified handle from looping
without stoping the sound.
---------------------------------------------------------------------*/
int32_t FX_EndLooping
(
int32_t handle
)
{
int32_t status;
status = MV_EndLooping(handle);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_SetPan
Sets the stereo and mono volume level of the voice associated
with the specified handle.
---------------------------------------------------------------------*/
int32_t FX_SetPan
(
int32_t handle,
int32_t vol,
int32_t left,
int32_t right
)
{
int32_t status;
status = MV_SetPan(handle, vol, left, right);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_SetPitch
Sets the pitch of the voice associated with the specified handle.
---------------------------------------------------------------------*/
int32_t FX_SetPitch
(
int32_t handle,
int32_t pitchoffset
)
{
int32_t status;
status = MV_SetPitch(handle, pitchoffset);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_SetFrequency
Sets the frequency of the voice associated with the specified handle.
---------------------------------------------------------------------*/
int32_t FX_SetFrequency
(
int32_t handle,
int32_t frequency
)
{
int32_t status;
status = MV_SetFrequency(handle, frequency);
if (status == MV_Error)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_Pan3D
Set the angle and distance from the listener of the voice associated
with the specified handle.
---------------------------------------------------------------------*/
int32_t FX_Pan3D(int32_t handle,int32_t angle,int32_t distance)
{
int32_t status;
status = MV_Pan3D(handle, angle, distance);
if (status != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
}
return status;
}
/*---------------------------------------------------------------------
Function: FX_SoundActive
Tests if the specified sound is currently playing.
---------------------------------------------------------------------*/
int32_t FX_SoundActive(int32_t handle)
{
return MV_VoicePlaying(handle);
}
/*---------------------------------------------------------------------
Function: FX_SoundsPlaying
Reports the number of voices playing.
---------------------------------------------------------------------*/
int32_t FX_SoundsPlaying(void)
{
return MV_VoicesPlaying();
}
/*---------------------------------------------------------------------
Function: FX_StopSound
Halts playback of a specific voice
---------------------------------------------------------------------*/
int32_t FX_StopSound(int32_t handle)
{
int32_t status;
status = MV_Kill(handle);
if (status != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
return FX_Warning;
}
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_StopAllSounds
Halts playback of all sounds.
---------------------------------------------------------------------*/
int32_t FX_StopAllSounds
(
void
)
{
int32_t status;
status = MV_KillAllVoices();
if (status != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
return FX_Warning;
}
return FX_Ok;
}
/*---------------------------------------------------------------------
Function: FX_StartDemandFeedPlayback
Plays a digitized sound from a user controlled buffering system.
---------------------------------------------------------------------*/
int32_t FX_StartDemandFeedPlayback
(
void (*function)(char **ptr, uint32_t *length),
int32_t rate,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
{
int32_t handle;
handle = MV_StartDemandFeedPlayback(function, rate,
pitchoffset, vol, left, right, priority, callbackval);
if (handle < MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
handle = FX_Warning;
}
return handle;
}
static wavedata FX_AutoDetectFormat(const char *ptr, uint32_t length)
{
if (length < 12)
return Unknown;
return fmt;
switch (LITTLE32(*(int32_t *)ptr))
{
case 'C'+('r'<<8)+('e'<<16)+('a'<<24): // Crea
return VOC;
break;
case 'R'+('I'<<8)+('F'<<16)+('F'<<24): // RIFF
switch (LITTLE32(*(int32_t *)(ptr + 8)))
{
case 'C'+('D'<<8)+('X'<<16)+('A'<<24): // CDXA
return XA;
case 'C' + ('r' << 8) + ('e' << 16) + ('a' << 24): // Crea
fmt = FMT_VOC;
break;
case 'O' + ('g' << 8) + ('g' << 16) + ('S' << 24): // OggS
fmt = FMT_VORBIS;
break;
case 'R' + ('I' << 8) + ('F' << 16) + ('F' << 24): // RIFF
switch (LITTLE32(*(int32_t *)(ptr + 8)))
{
case 'C' + ('D' << 8) + ('X' << 16) + ('A' << 24): // CDXA
fmt = FMT_XA;
break;
default: fmt = FMT_WAV; break;
}
break;
case 'f' + ('L' << 8) + ('a' << 16) + ('C' << 24): // fLaC
fmt = FMT_FLAC;
break;
default:
return WAV;
switch (LITTLE32(*(int32_t *)(ptr + 8)))
{
case 'W' + ('A' << 8) + ('V' << 16) + ('E' << 24): // WAVE
fmt = FMT_WAV;
break;
}
break;
}
break;
case 'O'+('g'<<8)+('g'<<16)+('S'<<24): // OggS
return Vorbis;
break;
case 'f'+('L'<<8)+('a'<<16)+('C'<<24): // fLaC
return FLAC;
break;
default:
switch (LITTLE32(*(int32_t *)(ptr + 8)))
{
case 'W'+('A'<<8)+('V'<<16)+('E'<<24): // WAVE
return WAV;
break;
}
break;
}
return Unknown;
return fmt;
}
/*---------------------------------------------------------------------
Function: FX_PlayAuto
Play a sound, autodetecting the format.
---------------------------------------------------------------------*/
int32_t FX_PlayAuto(char *ptr, uint32_t length, int32_t pitchoffset, int32_t vol,
int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
return FX_PlayLoopedAuto(ptr, length, -1, -1, pitchoffset, vol, left, right, priority, callbackval);
}
/*---------------------------------------------------------------------
Function: FX_PlayLoopedAuto
Play a looped sound, autodetecting the format.
---------------------------------------------------------------------*/
int32_t FX_PlayLoopedAuto(char *ptr, uint32_t length, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval)
int32_t FX_PlayLoopedAuto(char *ptr, uint32_t length, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
int32_t handle = -1;
switch (FX_AutoDetectFormat(ptr, length))
{
case VOC:
handle = MV_PlayVOC(ptr, length, loopstart, loopend, pitchoffset, vol, left, right, priority, callbackval);
break;
case WAV:
handle = MV_PlayWAV(ptr, length, loopstart, loopend, pitchoffset, vol, left, right, priority, callbackval);
break;
case Vorbis:
#ifdef HAVE_VORBIS
handle = MV_PlayVorbis(ptr, length, loopstart, loopend, pitchoffset, vol, left, right, priority, callbackval);
#else
MV_Printf("FX_PlayLoopedAuto: OggVorbis support not included in this binary.\n");
#endif
break;
case FLAC:
#ifdef HAVE_FLAC
handle = MV_PlayFLAC(ptr, length, loopstart, loopend, pitchoffset, vol, left, right, priority, callbackval);
#else
MV_Printf("FX_PlayLoopedAuto: FLAC support not included in this binary.\n");
#endif
break;
case XA:
handle = MV_PlayXA(ptr, length, loopstart, loopend, pitchoffset, vol, left, right, priority, callbackval);
break;
default:
MV_Printf("FX_PlayLoopedAuto: Unknown or unsupported format.\n");
break;
}
EDUKE32_STATIC_ASSERT(FMT_MAX == 7);
static int32_t(*const func[FMT_MAX])(char *, uint32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, uint32_t) =
{ NULL, NULL, MV_PlayVOC, MV_PlayWAV, MV_PlayVorbis, MV_PlayFLAC, MV_PlayXA };
wavefmt_t const fmt = FX_AutoDetectFormat(ptr, length);
if (func[fmt])
handle = func[fmt](ptr, length, loopstart, loopend, pitchoffset, vol, left, right, priority, callbackval);
if (handle <= MV_Ok)
{
@ -761,46 +256,20 @@ int32_t FX_PlayLoopedAuto(char *ptr, uint32_t length, int32_t loopstart, int32_t
return handle;
}
/*---------------------------------------------------------------------
Function: FX_PlayAuto3D
Play a positioned sound, autodetecting the format.
<loophow>: one of FX_LOOP or FX_ONESHOT.
---------------------------------------------------------------------*/
int32_t FX_PlayAuto3D(char *ptr, uint32_t length, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
int32_t FX_PlayAuto3D(char *ptr, uint32_t length, int32_t loophow, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval)
{
int32_t handle = -1;
switch (FX_AutoDetectFormat(ptr, length))
{
case VOC:
handle = MV_PlayVOC3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
break;
case WAV:
handle = MV_PlayWAV3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
break;
case Vorbis:
#ifdef HAVE_VORBIS
handle = MV_PlayVorbis3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
#else
MV_Printf("FX_PlayAuto3D: OggVorbis support not included in this binary.\n");
#endif
break;
case FLAC:
#ifdef HAVE_FLAC
handle = MV_PlayFLAC3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
#else
MV_Printf("FX_PlayAuto3D: FLAC support not included in this binary.\n");
#endif
break;
case XA:
handle = MV_PlayXA3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
break;
default:
MV_Printf("FX_PlayAuto3D: Unknown or unsupported format.\n");
break;
}
EDUKE32_STATIC_ASSERT(FMT_MAX == 7);
static int32_t (*const func[FMT_MAX])(char *, uint32_t, int32_t, int32_t, int32_t, int32_t, int32_t, uint32_t) =
{ NULL, NULL, MV_PlayVOC3D, MV_PlayWAV3D, MV_PlayVorbis3D, MV_PlayFLAC3D, MV_PlayXA3D };
wavefmt_t const fmt = FX_AutoDetectFormat(ptr, length);
if (func[fmt])
handle = func[fmt](ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
if (handle <= MV_Ok)
{
@ -813,9 +282,8 @@ int32_t FX_PlayAuto3D(char *ptr, uint32_t length, int32_t loophow, int32_t pitch
int32_t FX_SetVoiceCallback(int32_t handle, uint32_t callbackval)
{
int32_t status;
int32_t status = MV_SetVoiceCallback(handle, callbackval);
status = MV_SetVoiceCallback(handle, callbackval);
if (status != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);

View file

@ -27,7 +27,7 @@ extern "C" {
#define NewNode(type) ((type *)Bmalloc(sizeof(type)))
#define LL_CreateNewLinkedList(rootnode, type, next, prev) \
#define LL_New(rootnode, type, next, prev) \
{ \
(rootnode) = NewNode(type); \
(rootnode)->prev = (rootnode); \
@ -35,7 +35,7 @@ extern "C" {
}
#define LL_AddNode(rootnode, newnode, next, prev) \
#define LL_Add(rootnode, newnode, next, prev) \
{ \
(newnode)->next = (rootnode); \
(newnode)->prev = (rootnode)->prev; \
@ -58,18 +58,16 @@ extern "C" {
#define LL_ReverseList(root, type, next, prev) \
{ \
type *newend, *trav, *tprev; \
\
newend = (root)->next; \
type *newend = (root)->next, *trav, *tprev; \
for (trav = (root)->prev; trav != newend; trav = tprev) \
{ \
tprev = trav->prev; \
LL_MoveNode(trav, newend, next, prev); \
LL_Move(trav, newend, next, prev); \
} \
}
#define LL_RemoveNode(node, next, prev) \
#define LL_Remove(node, next, prev) \
{ \
(node)->prev->next = (node)->next; \
(node)->next->prev = (node)->prev; \
@ -80,31 +78,24 @@ extern "C" {
#define LL_SortedInsertion(rootnode, insertnode, next, prev, type, sortparm) \
{ \
type *hoya; \
\
hoya = (rootnode)->next; \
type *hoya = (rootnode)->next; \
while ((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \
{ \
hoya = hoya->next; \
} \
LL_AddNode(hoya, (insertnode), next, prev); \
LL_Add(hoya, (insertnode), next, prev); \
}
#define LL_MoveNode(node, newroot, next, prev) \
#define LL_Move(node, newroot, next, prev) \
{ \
LL_RemoveNode((node), next, prev); \
LL_AddNode((newroot), (node), next, prev); \
LL_Remove((node), next, prev); \
LL_Add((newroot), (node), next, prev); \
}
#define LL_ListEmpty(list, next, prev) (((list)->next == (list)) && ((list)->prev == (list)))
#define LL_Empty(list, next, prev) (((list)->next == (list)) && ((list)->prev == (list)))
#define LL_Free(list) Bfree(list)
#define LL_Reset(list, next, prev) (list)->next = (list)->prev = (list)
#define LL_New LL_CreateNewLinkedList
#define LL_Remove LL_RemoveNode
#define LL_Add LL_AddNode
#define LL_Empty LL_ListEmpty
#define LL_Move LL_MoveNode
#ifdef __cplusplus

View file

@ -1,67 +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.
*/
/**********************************************************************
module: LL_MAN.H
author: James R. Dose
date: February 4, 1994
Public header for LL_MAN.C. Linked list management routines.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#ifndef LL_MAN_H_
#define LL_MAN_H_
enum LL_Errors
{
LL_Warning = -2,
LL_Error = -1,
LL_Ok = 0
};
typedef struct list
{
void *start;
void *end;
} list;
void LL_AddNode(char *node, char **head, char **tail, int32_t next, int32_t prev);
void LL_RemoveNode(char *node, char **head, char **tail, int32_t next, int32_t prev);
void LL_UnlockMemory(void);
int32_t LL_LockMemory(void);
#define LL_AddToHead(type, listhead, node) \
LL_AddNode((char *)(node), (char **)&((listhead)->start), (char **)&((listhead)->end), \
(int32_t) & ((type *)0)->next, (int32_t) & ((type *)0)->prev)
#define LL_AddToTail(type, listhead, node) \
LL_AddNode((char *)(node), (char **)&((listhead)->end), (char **)&((listhead)->start), \
(int32_t) & ((type *)0)->prev, (int32_t) & ((type *)0)->next)
#define LL_Remove(type, listhead, node) \
LL_RemoveNode((char *)(node), (char **)&((listhead)->start), (char **)&((listhead)->end), \
(int32_t) & ((type *)0)->next, (int32_t) & ((type *)0)->prev)
#define LL_NextNode(node) ((node)->next)
#define LL_PreviousNode(node) ((node)->prev)
#endif

View file

@ -20,15 +20,6 @@
#include "_multivc.h"
void ClearBuffer_DW( void *ptr, unsigned data, int32_t length )
{
unsigned *ptrdw = (unsigned *)ptr;
while (length--) {
*(ptrdw++) = data;
}
}
/*
JBF:
@ -39,10 +30,9 @@ void ClearBuffer_DW( void *ptr, unsigned data, int32_t length )
*/
// 8-bit mono source, 8-bit mono output
void MV_Mix8BitMono( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitMono(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0;
@ -63,10 +53,9 @@ void MV_Mix8BitMono( uint32_t position, uint32_t rate,
}
// 8-bit mono source, 8-bit stereo output
void MV_Mix8BitStereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitStereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -91,10 +80,9 @@ void MV_Mix8BitStereo( uint32_t position, uint32_t rate,
}
// 8-bit mono source, 16-bit mono output
void MV_Mix16BitMono( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitMono(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0;
@ -116,10 +104,9 @@ void MV_Mix16BitMono( uint32_t position, uint32_t rate,
}
// 8-bit mono source, 16-bit stereo output
void MV_Mix16BitStereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitStereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -146,10 +133,9 @@ void MV_Mix16BitStereo( uint32_t position, uint32_t rate,
}
// 16-bit mono source, 16-bit mono output
void MV_Mix16BitMono16( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitMono16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint16_t *source = (uint16_t *) start;
uint16_t const * const source = (uint16_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0;
@ -180,10 +166,9 @@ void MV_Mix16BitMono16( uint32_t position, uint32_t rate,
}
// 16-bit mono source, 8-bit mono output
void MV_Mix8BitMono16( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitMono16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
int8_t *source = (int8_t *) start + 1;
int8_t const * const source = (int8_t *) start + 1;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0;
@ -204,10 +189,9 @@ void MV_Mix8BitMono16( uint32_t position, uint32_t rate,
}
// 16-bit mono source, 8-bit stereo output
void MV_Mix8BitStereo16( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitStereo16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
int8_t *source = (int8_t *) start + 1;
int8_t const * const source = (int8_t *) start + 1;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -232,10 +216,9 @@ void MV_Mix8BitStereo16( uint32_t position, uint32_t rate,
}
// 16-bit mono source, 16-bit stereo output
void MV_Mix16BitStereo16( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitStereo16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint16_t *source = (uint16_t *) start;
uint16_t const * const source = (uint16_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0;
int32_t sample1l, sample1h, sample1;
@ -274,14 +257,14 @@ void MV_Mix16BitStereo16( uint32_t position, uint32_t rate,
MV_MixDestination = (char *) dest;
}
void MV_16BitReverb( char *src, char *dest, VOLUME16 *volume, int32_t count )
void MV_16BitReverb(char const *src, char *dest, int16_t *volume, int32_t count)
{
uint16_t * input = (uint16_t *) src;
uint16_t const * input = (uint16_t *) src;
int16_t * output = (int16_t *) dest;
int16_t sample0l, sample0h, sample0;
do {
sample0 = *input;
sample0 = *input++;
#if 0 //def BIGENDIAN
sample0l = sample0 >> 8;
sample0h = (sample0 & 255) ^ 128;
@ -292,51 +275,16 @@ void MV_16BitReverb( char *src, char *dest, VOLUME16 *volume, int32_t count )
sample0l = ((int16_t *) volume)[sample0l] >> 8;
sample0h = ((int16_t *) volume)[sample0h];
*output = (int16_t) (sample0l + sample0h + 128);
input++;
output++;
*output++ = (int16_t) (sample0l + sample0h + 128);
} while (--count > 0);
}
void MV_8BitReverb( int8_t *src, int8_t *dest, VOLUME16 *volume, int32_t count )
void MV_8BitReverb(int8_t *src, int8_t *dest, int16_t *volume, int32_t count)
{
uint8_t * input = (uint8_t *) src;
uint8_t const * input = (uint8_t *) src;
uint8_t * output = (uint8_t *) dest;
do {
*output = ((int16_t *) volume)[*input] + 128;
input++;
output++;
*output++ = ((int16_t *) volume)[*input++] + 128;
} while (--count > 0);
}
void MV_16BitReverbFast( char *src, char *dest, int32_t count, int32_t shift )
{
int16_t * input = (int16_t *) src;
int16_t * output = (int16_t *) dest;
do {
*output = *input >> shift;
input++;
output++;
} while (--count > 0);
}
void MV_8BitReverbFast( int8_t *src, int8_t *dest, int32_t count, int32_t shift )
{
uint8_t sample0, c;
c = 128 - (128 >> shift);
do {
sample0 = *((uint8_t *) src) >> shift;
*dest = sample0 + c + ((sample0 ^ 128) >> 7);
src++;
dest++;
} while (--count > 0);
}

View file

@ -31,10 +31,9 @@
*/
// 8-bit stereo source, 8-bit mono output
void MV_Mix8BitMono8Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitMono8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -56,10 +55,9 @@ void MV_Mix8BitMono8Stereo( uint32_t position, uint32_t rate,
}
// 8-bit stereo source, 8-bit stereo output
void MV_Mix8BitStereo8Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitStereo8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -84,10 +82,9 @@ void MV_Mix8BitStereo8Stereo( uint32_t position, uint32_t rate,
}
// 8-bit stereo source, 16-bit mono output
void MV_Mix16BitMono8Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitMono8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -110,10 +107,9 @@ void MV_Mix16BitMono8Stereo( uint32_t position, uint32_t rate,
}
// 8-bit stereo source, 16-bit stereo output
void MV_Mix16BitStereo8Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitStereo8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint8_t *source = (uint8_t *) start;
uint8_t const * const source = (uint8_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -140,10 +136,9 @@ void MV_Mix16BitStereo8Stereo( uint32_t position, uint32_t rate,
}
// 16-bit stereo source, 16-bit mono output
void MV_Mix16BitMono16Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint16_t *source = (uint16_t *) start;
uint16_t const * const source = (uint16_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0;
int32_t sample1l, sample1h, sample1;
@ -185,10 +180,9 @@ void MV_Mix16BitMono16Stereo( uint32_t position, uint32_t rate,
}
// 16-bit stereo source, 8-bit mono output
void MV_Mix8BitMono16Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
int8_t *source = (int8_t *) start + 1;
int8_t const * const source = (int8_t *) start + 1;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -212,10 +206,9 @@ void MV_Mix8BitMono16Stereo( uint32_t position, uint32_t rate,
}
// 16-bit stereo source, 8-bit stereo output
void MV_Mix8BitStereo16Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix8BitStereo16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
int8_t *source = (int8_t *) start + 1;
int8_t const * const source = (int8_t *) start + 1;
uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1;
@ -240,10 +233,9 @@ void MV_Mix8BitStereo16Stereo( uint32_t position, uint32_t rate,
}
// 16-bit stereo source, 16-bit stereo output
void MV_Mix16BitStereo16Stereo( uint32_t position, uint32_t rate,
const char *start, uint32_t length )
void MV_Mix16BitStereo16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
{
uint16_t *source = (uint16_t *) start;
uint16_t const * const source = (uint16_t *) start;
int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0;
int32_t sample1l, sample1h, sample1;

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef MULTIVOC_H_
#define MULTIVOC_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(x) x = x
#endif
@ -76,15 +80,15 @@ static inline uint32_t SWAP32(uint32_t s)
typedef enum
{
Unknown,
Raw,
VOC,
DemandFeed,
WAV,
Vorbis,
FLAC,
XA,
} wavedata;
FMT_UNKNOWN,
FMT_RAW,
FMT_VOC,
FMT_WAV,
FMT_VORBIS,
FMT_FLAC,
FMT_XA,
FMT_MAX
} wavefmt_t;
#define MV_MINVOICEHANDLE 1
@ -95,7 +99,6 @@ enum MV_Errors
MV_Warning = -2,
MV_Error = -1,
MV_Ok = 0,
MV_UnsupportedCard,
MV_NotInstalled,
MV_DriverError,
MV_NoVoices,
@ -106,8 +109,6 @@ enum MV_Errors
MV_InvalidVorbisFile,
MV_InvalidFLACFile,
MV_InvalidXAFile,
MV_InvalidMixMode,
MV_NullRecordFunction
};
extern void (*MV_Printf)(const char *fmt, ...);
@ -124,17 +125,12 @@ int32_t MV_EndLooping(int32_t handle);
int32_t MV_SetPan(int32_t handle, int32_t vol, int32_t left, int32_t right);
int32_t MV_Pan3D(int32_t handle, int32_t angle, int32_t distance);
void MV_SetReverb(int32_t reverb);
void MV_SetFastReverb(int32_t reverb);
int32_t MV_GetMaxReverbDelay(void);
int32_t MV_GetReverbDelay(void);
void MV_SetReverbDelay(int32_t delay);
// int32_t MV_SetMixMode( int32_t numchannels, int32_t samplebits );
// int32_t MV_StartPlayback( void );
// void MV_StopPlayback( void );
int32_t MV_StartDemandFeedPlayback(void (*function)(char **ptr, uint32_t *length), int32_t rate, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval);
int32_t MV_PlayRaw(char *ptr, uint32_t length, char *loopstart, char *loopend, unsigned rate, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval);
int32_t MV_PlayWAV3D(char *ptr, uint32_t length, int32_t loophow, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval);
int32_t MV_PlayWAV(char *ptr, uint32_t length, int32_t loopstart, int32_t loopend, int32_t pitchoffset, int32_t vol,
@ -171,4 +167,8 @@ int32_t MV_Shutdown(void);
int32_t MV_SetVoiceCallback(int32_t handle, uint32_t callbackval);
void MV_SetPrintf(void (*function)(const char *fmt, ...));
#ifdef __cplusplus
}
#endif
#endif

View file

@ -63,37 +63,35 @@ typedef struct {
// designed with multiple calls in mind
static void MV_GetVorbisCommentLoops(VoiceNode *voice, vorbis_comment *vc)
{
int32_t comment;
uint8_t loopTagCount;
if (vc == NULL)
return;
const char *vc_loopstart = NULL;
const char *vc_loopend = NULL;
const char *vc_looplength = NULL;
if (vc == NULL)
return;
for (comment = 0; comment < vc->comments; ++comment)
for (int comment = 0; comment < vc->comments; ++comment)
{
const char *entry = (const char *) vc->user_comments[comment];
const char *entry = (const char *)vc->user_comments[comment];
if (entry != NULL && entry[0] != '\0')
{
const char *value = strchr(entry,'=');
const char *value = strchr(entry, '=');
if (!value) continue;
if (!value)
continue;
const size_t field = value-entry;
const size_t field = value - entry;
value += 1;
for (loopTagCount = 0; loopTagCount < loopStartTagCount && vc_loopstart == NULL; ++loopTagCount)
for (uint8_t loopTagCount = 0; loopTagCount < loopStartTagCount && vc_loopstart == NULL; ++loopTagCount)
if (strncasecmp(entry, loopStartTags[loopTagCount], field) == 0)
vc_loopstart = value;
for (loopTagCount = 0; loopTagCount < loopEndTagCount && vc_loopend == NULL; ++loopTagCount)
for (uint8_t loopTagCount = 0; loopTagCount < loopEndTagCount && vc_loopend == NULL; ++loopTagCount)
if (strncasecmp(entry, loopEndTags[loopTagCount], field) == 0)
vc_loopend = value;
for (loopTagCount = 0; loopTagCount < loopLengthTagCount && vc_looplength == NULL; ++loopTagCount)
for (uint8_t loopTagCount = 0; loopTagCount < loopLengthTagCount && vc_looplength == NULL; ++loopTagCount)
if (strncasecmp(entry, loopLengthTags[loopTagCount], field) == 0)
vc_looplength = value;
}
@ -132,88 +130,84 @@ static void MV_GetVorbisCommentLoops(VoiceNode *voice, vorbis_comment *vc)
// callbacks
static size_t read_vorbis(void * ptr, size_t size, size_t nmemb, void * datasource)
static size_t read_vorbis(void *ptr, size_t size, size_t nmemb, void *datasource)
{
vorbis_data * vorb = (vorbis_data *) datasource;
size_t nread = 0;
size_t bytes;
errno = 0;
vorbis_data *vorb = (vorbis_data *)datasource;
if (vorb->length == vorb->pos) {
return 0;
}
for (; nmemb > 0; nmemb--, nread++) {
bytes = vorb->length - vorb->pos;
if (size < bytes) {
bytes = size;
}
memcpy(ptr, (uint8_t *)vorb->ptr + vorb->pos, bytes);
vorb->pos += bytes;
ptr = (uint8_t *)ptr + bytes;
if (vorb->length == vorb->pos) {
nread++;
break;
}
}
return nread;
errno = 0;
if (vorb->length == vorb->pos)
return 0;
size_t nread = 0;
for (; nmemb > 0; nmemb--, nread++)
{
size_t bytes = vorb->length - vorb->pos;
if (size < bytes)
bytes = size;
memcpy(ptr, (uint8_t *)vorb->ptr + vorb->pos, bytes);
vorb->pos += bytes;
ptr = (uint8_t *)ptr + bytes;
if (vorb->length == vorb->pos)
{
nread++;
break;
}
}
return nread;
}
static int32_t seek_vorbis(void * datasource, ogg_int64_t offset, int32_t whence)
static int32_t seek_vorbis(void *datasource, ogg_int64_t offset, int32_t whence)
{
vorbis_data * vorb = (vorbis_data *) datasource;
switch (whence) {
case SEEK_SET: vorb->pos = 0; break;
case SEEK_CUR: break;
case SEEK_END: vorb->pos = vorb->length; break;
}
vorb->pos += offset;
vorbis_data *vorb = (vorbis_data *)datasource;
if (vorb->pos > vorb->length) {
vorb->pos = vorb->length;
}
return vorb->pos;
switch (whence)
{
case SEEK_SET: vorb->pos = 0; break;
case SEEK_CUR: break;
case SEEK_END: vorb->pos = vorb->length; break;
}
vorb->pos += offset;
if (vorb->pos > vorb->length)
vorb->pos = vorb->length;
return vorb->pos;
}
static int32_t close_vorbis(void * datasource)
static int32_t close_vorbis(void *datasource)
{
UNREFERENCED_PARAMETER(datasource);
return 0;
return 0;
}
static long tell_vorbis(void * datasource)
static long tell_vorbis(void *datasource)
{
vorbis_data * vorb = (vorbis_data *) datasource;
return vorb->pos;
vorbis_data *vorb = (vorbis_data *)datasource;
return vorb->pos;
}
static ov_callbacks vorbis_callbacks = {
read_vorbis,
seek_vorbis,
close_vorbis,
tell_vorbis
};
static ov_callbacks vorbis_callbacks = { read_vorbis, seek_vorbis, close_vorbis, tell_vorbis };
int32_t MV_GetVorbisPosition(VoiceNode *voice)
{
vorbis_data * vd = (vorbis_data *) voice->extra;
vorbis_data * vd = (vorbis_data *) voice->rawdataptr;
return ov_pcm_tell(&vd->vf);
}
void MV_SetVorbisPosition(VoiceNode *voice, int32_t position)
{
vorbis_data * vd = (vorbis_data *) voice->extra;
vorbis_data * vd = (vorbis_data *) voice->rawdataptr;
ov_pcm_seek(&vd->vf, position);
}
@ -224,102 +218,112 @@ Function: MV_GetNextVorbisBlock
Controls playback of OggVorbis data
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextVorbisBlock
(
VoiceNode *voice
)
static playbackstatus MV_GetNextVorbisBlock(VoiceNode *voice)
{
vorbis_data * vd = (vorbis_data *) voice->extra;
int32_t bytes, bytesread;
int32_t bitstream, err;
int32_t bitstream;
voice->Playing = TRUE;
bytesread = 0;
do {
voice->Playing = TRUE;
int32_t bytesread = 0;
vorbis_data *vd = (vorbis_data *)voice->rawdataptr;
do
{
#ifdef USING_TREMOR
bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, &bitstream);
int32_t bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, &bitstream);
#else
bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, 0, 2, 1, &bitstream);
int32_t bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, 0, 2, 1, &bitstream);
#endif
//fprintf(stderr, "ov_read = %d\n", bytes);
if (bytes > 0) {
ogg_int64_t currentPosition;
bytesread += bytes;
if ((ogg_int64_t)(intptr_t)voice->LoopEnd > 0
&& (currentPosition = ov_pcm_tell(&vd->vf)) >= (ogg_int64_t)(intptr_t)voice->LoopEnd) {
bytesread -= (currentPosition - (ogg_int64_t)(intptr_t)voice->LoopEnd) * voice->channels * 2; // (voice->bits>>3)
err = ov_pcm_seek(&vd->vf,(ogg_int64_t)(intptr_t)voice->LoopStart);
if (err != 0) {
MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, LOOP_END %l, err %d\n",
(ogg_int64_t)(intptr_t)voice->LoopStart, (ogg_int64_t)(intptr_t)voice->LoopEnd, err);
} else {
continue;
}
}
// fprintf(stderr, "ov_read = %d\n", bytes);
if (bytes > 0)
{
ogg_int64_t currentPosition;
bytesread += bytes;
if ((ogg_int64_t)(intptr_t)voice->LoopEnd > 0 &&
(currentPosition = ov_pcm_tell(&vd->vf)) >= (ogg_int64_t)(intptr_t)voice->LoopEnd)
{
bytesread -=
(currentPosition - (ogg_int64_t)(intptr_t)voice->LoopEnd) * voice->channels * 2; // (voice->bits>>3)
int const err = ov_pcm_seek(&vd->vf, (ogg_int64_t)(intptr_t)voice->LoopStart);
if (err != 0)
{
MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, LOOP_END %l, err %d\n",
(ogg_int64_t)(intptr_t)voice->LoopStart, (ogg_int64_t)(intptr_t)voice->LoopEnd, err);
}
}
continue;
}
else if (bytes == OV_HOLE) continue;
else if (bytes == 0) {
if (voice->LoopSize > 0) {
err = ov_pcm_seek(&vd->vf,(ogg_int64_t)(intptr_t)voice->LoopStart);
if (err != 0) {
MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, err %d\n",
(ogg_int64_t)(intptr_t)voice->LoopStart, err);
} else {
continue;
}
} else {
break;
}
} else if (bytes < 0) {
MV_Printf("MV_GetNextVorbisBlock ov_read: err %d\n", bytes);
voice->Playing = FALSE;
return NoMoreData;
}
} while (bytesread < BLOCKSIZE);
}
else if (bytes == OV_HOLE)
continue;
else if (bytes == 0)
{
if (voice->LoopSize > 0)
{
int const err = ov_pcm_seek(&vd->vf, (ogg_int64_t)(intptr_t)voice->LoopStart);
if (bytesread == 0) {
voice->Playing = FALSE;
return NoMoreData;
}
if (bitstream != vd->lastbitstream) {
vorbis_info * vi = 0;
vi = ov_info(&vd->vf, -1);
if (!vi || (vi->channels != 1 && vi->channels != 2)) {
voice->Playing = FALSE;
return NoMoreData;
}
voice->channels = vi->channels;
voice->SamplingRate = vi->rate;
voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) - voice->RateScale;
MV_SetVoiceMixMode( voice );
vd->lastbitstream = bitstream;
}
if (err != 0)
{
MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, err %d\n",
(ogg_int64_t)(intptr_t)voice->LoopStart, err);
}
else
continue;
}
else
{
break;
}
}
else if (bytes < 0)
{
MV_Printf("MV_GetNextVorbisBlock ov_read: err %d\n", bytes);
voice->Playing = FALSE;
return NoMoreData;
}
} while (bytesread < BLOCKSIZE);
bytesread /= 2 * voice->channels;
voice->position = 0;
voice->sound = vd->block;
voice->BlockLength = 0;
voice->length = bytesread << 16; // ???: Should the literal 16 be voice->bits?
if (bytesread == 0)
{
voice->Playing = FALSE;
return NoMoreData;
}
if (bitstream != vd->lastbitstream)
{
vorbis_info *vi = 0;
vi = ov_info(&vd->vf, -1);
if (!vi || (vi->channels != 1 && vi->channels != 2))
{
voice->Playing = FALSE;
return NoMoreData;
}
voice->channels = vi->channels;
voice->SamplingRate = vi->rate;
voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate;
voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale;
MV_SetVoiceMixMode(voice);
vd->lastbitstream = bitstream;
}
bytesread /= 2 * voice->channels;
voice->position = 0;
voice->sound = vd->block;
voice->BlockLength = 0;
voice->length = bytesread << 16; // ???: Should the literal 16 be voice->bits?
#ifdef GEKKO
{
// If libtremor had the three additional ov_read() parameters that libvorbis has,
// this would be better handled using the endianness parameter.
int16_t *data = (int16_t*)(voice->sound); // assumes signed 16-bit
for (bytesread = 0; bytesread < BLOCKSIZE / 2; ++bytesread)
data[bytesread] = (data[bytesread] & 0xff) << 8 | ((data[bytesread] & 0xff00) >> 8);
}
// If libtremor had the three additional ov_read() parameters that libvorbis has,
// this would be better handled using the endianness parameter.
int16_t *data = (int16_t *)(voice->sound); // assumes signed 16-bit
for (bytesread = 0; bytesread < BLOCKSIZE / 2; ++bytesread)
data[bytesread] = (data[bytesread] & 0xff) << 8 | ((data[bytesread] & 0xff00) >> 8);
#endif
return KeepPlaying;
return KeepPlaying;
}
@ -330,49 +334,28 @@ Begin playback of sound data at specified angle and distance
from listener.
---------------------------------------------------------------------*/
int32_t MV_PlayVorbis3D
(
char *ptr,
uint32_t ptrlength,
int32_t loophow,
int32_t pitchoffset,
int32_t angle,
int32_t distance,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayVorbis3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
{
int32_t left;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
if ( !MV_Installed )
{
MV_SetErrorCode( MV_NotInstalled );
return MV_Error;
}
if ( distance < 0 )
{
distance = -distance;
angle += MV_NUMPANPOSITIONS / 2;
}
volume = MIX_VOLUME( distance );
// Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left;
right = MV_PanTable[ angle ][ volume ].right;
mid = max( 0, 255 - distance );
status = MV_PlayVorbis(ptr, ptrlength, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
if (distance < 0)
{
distance = -distance;
angle += MV_NUMPANPOSITIONS / 2;
}
int const volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION;
return MV_PlayVorbis(ptr, ptrlength, loophow, -1, pitchoffset, max(0, 255 - distance),
MV_PanTable[angle][volume].left, MV_PanTable[angle][volume].right, priority, callbackval);
}
@ -383,84 +366,74 @@ Begin playback of sound data with the given sound levels and
priority.
---------------------------------------------------------------------*/
int32_t MV_PlayVorbis
(
char *ptr,
uint32_t ptrlength,
int32_t loopstart,
int32_t loopend,
int32_t pitchoffset,
int32_t vol,
int32_t left,
int32_t right,
int32_t priority,
uint32_t callbackval
)
int32_t MV_PlayVorbis(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
VoiceNode *voice;
int32_t status;
vorbis_data * vd = 0;
vorbis_info * vi = 0;
UNREFERENCED_PARAMETER(loopend);
if ( !MV_Installed )
if (!MV_Installed)
{
MV_SetErrorCode( MV_NotInstalled );
return MV_Error;
MV_SetErrorCode(MV_NotInstalled);
return MV_Error;
}
vd = (vorbis_data *) calloc( 1, sizeof(vorbis_data) );
if (!vd) {
MV_SetErrorCode( MV_InvalidVorbisFile );
return MV_Error;
vorbis_data *vd = (vorbis_data *)calloc(1, sizeof(vorbis_data));
if (!vd)
{
MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error;
}
vd->ptr = ptr;
vd->pos = 0;
vd->length = ptrlength;
vd->lastbitstream = -1;
status = ov_open_callbacks((void *) vd, &vd->vf, 0, 0, vorbis_callbacks);
if (status < 0) {
MV_Printf("MV_PlayVorbis: err %d\n", status);
MV_SetErrorCode( MV_InvalidVorbisFile );
return MV_Error;
}
vi = ov_info(&vd->vf, 0);
if (!vi) {
ov_clear(&vd->vf);
free(vd);
MV_SetErrorCode( MV_InvalidVorbisFile );
return MV_Error;
}
if (vi->channels != 1 && vi->channels != 2) {
ov_clear(&vd->vf);
free(vd);
MV_SetErrorCode( MV_InvalidVorbisFile );
return MV_Error;
}
// Request a voice from the voice pool
voice = MV_AllocVoice( priority );
if ( voice == NULL )
int32_t status = ov_open_callbacks((void *)vd, &vd->vf, 0, 0, vorbis_callbacks);
if (status < 0)
{
ov_clear(&vd->vf);
free(vd);
MV_SetErrorCode( MV_NoVoices );
return MV_Error;
MV_Printf("MV_PlayVorbis: err %d\n", status);
MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error;
}
voice->wavetype = Vorbis;
vorbis_info *vi = ov_info(&vd->vf, 0);
if (!vi)
{
ov_clear(&vd->vf);
free(vd);
MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error;
}
if (vi->channels != 1 && vi->channels != 2)
{
ov_clear(&vd->vf);
free(vd);
MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error;
}
// Request a voice from the voice pool
VoiceNode *voice = MV_AllocVoice(priority);
if (voice == NULL)
{
ov_clear(&vd->vf);
free(vd);
MV_SetErrorCode(MV_NoVoices);
return MV_Error;
}
voice->wavetype = FMT_VORBIS;
voice->bits = 16;
voice->channels = vi->channels;
voice->extra = (void *) vd;
voice->rawdataptr = (void *) vd;
voice->GetSound = MV_GetNextVorbisBlock;
voice->NextBlock = vd->block;
voice->DemandFeed = NULL;
voice->LoopCount = 0;
voice->BlockLength = 0;
voice->length = 0;
@ -490,16 +463,28 @@ int32_t MV_PlayVorbis
void MV_ReleaseVorbisVoice( VoiceNode * voice )
{
vorbis_data * vd = (vorbis_data *) voice->extra;
if (voice->wavetype != Vorbis) {
return;
}
ov_clear(&vd->vf);
free(vd);
voice->extra = 0;
if (voice->wavetype != FMT_VORBIS)
return;
vorbis_data *vd = (vorbis_data *)voice->rawdataptr;
ov_clear(&vd->vf);
free(vd);
voice->rawdataptr = 0;
}
#else
int32_t MV_PlayVorbis(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
MV_Printf("MV_PlayVorbis: OggVorbis support not included in this binary.\n");
return -1;
}
int32_t MV_PlayVorbis3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
{
MV_Printf("MV_PlayVorbis: OggVorbis support not included in this binary.\n");
return -1;
}
#endif //HAVE_VORBIS

View file

@ -288,13 +288,13 @@ static void decodeSoundSectStereo(XASector *ssct, xa_data * xad)
int32_t MV_GetXAPosition(VoiceNode *voice)
{
xa_data * xad = (xa_data *) voice->extra;
xa_data * xad = (xa_data *) voice->rawdataptr;
return xad->pos;
}
void MV_SetXAPosition(VoiceNode *voice, int32_t position)
{
xa_data * xad = (xa_data *) voice->extra;
xa_data * xad = (xa_data *) voice->rawdataptr;
if (position < XA_DATA_START || (size_t)position >= xad->length)
position = XA_DATA_START;
@ -314,7 +314,7 @@ static playbackstatus MV_GetNextXABlock
)
{
xa_data * xad = (xa_data *) voice->extra;
xa_data * xad = (xa_data *) voice->rawdataptr;
XASector ssct;
int coding;
@ -483,11 +483,10 @@ int32_t MV_PlayXA
xad->owner = voice;
voice->wavetype = XA;
voice->extra = (void*)xad;
voice->wavetype = FMT_XA;
voice->rawdataptr = (void*)xad;
voice->GetSound = MV_GetNextXABlock;
voice->NextBlock = xad->block;
voice->DemandFeed = NULL;
voice->LoopCount = 0;
voice->BlockLength = 0;
voice->PitchScale = PITCH_GetScale( pitchoffset );
@ -516,9 +515,9 @@ int32_t MV_PlayXA
void MV_ReleaseXAVoice( VoiceNode * voice )
{
xa_data * xad = (xa_data *) voice->extra;
xa_data * xad = (xa_data *) voice->rawdataptr;
if (voice->wavetype != XA) {
if (voice->wavetype != FMT_XA) {
return;
}
@ -526,5 +525,5 @@ void MV_ReleaseXAVoice( VoiceNode * voice )
free(xad->block);
free(xad);
voice->extra = 0;
voice->rawdataptr = 0;
}