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 #define DRIVERS_H
#include "inttypes.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; extern int32_t ASS_SoundDriver;
int32_t SoundDriver_IsSupported(int32_t driver); int32_t SoundDriver_IsSupported(int32_t driver);
int32_t SoundDriver_GetError(void); int32_t SoundDriver_GetError(void);
const char * SoundDriver_ErrorString( int32_t ErrorNumber ); const char *SoundDriver_ErrorString(int32_t 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);
void SoundDriver_Shutdown(void); void SoundDriver_Shutdown(void);
int32_t SoundDriver_BeginPlayback( char *BufferStart, int32_t SoundDriver_BeginPlayback(char *BufferStart, int32_t BufferSize, int32_t NumDivisions, void(*CallBackFunc)(void));
int32_t BufferSize, int32_t NumDivisions,
void ( *CallBackFunc )( void ) );
void SoundDriver_StopPlayback(void); void SoundDriver_StopPlayback(void);
void SoundDriver_Lock(void); void SoundDriver_Lock(void);
void SoundDriver_Unlock(void); void SoundDriver_Unlock(void);

View file

@ -1,132 +1,104 @@
/* /*
Copyright (C) 1994-1995 Apogee Software, Ltd. Copyright (C) 1994-1995 Apogee Software, Ltd.
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
/********************************************************************** /**********************************************************************
module: FX_MAN.H module: FX_MAN.H
author: James R. Dose author: James R. Dose
date: March 17, 1994 date: March 17, 1994
Public header for FX_MAN.C Public header for FX_MAN.C
(c) Copyright 1994 James R. Dose. All Rights Reserved. (c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/ **********************************************************************/
#ifndef FX_MAN_H_ #ifndef FX_MAN_H_
#define FX_MAN_H_ #define FX_MAN_H_
#include "inttypes.h" #include "inttypes.h"
#include "limits.h" #include "limits.h"
#include "sndcards.h" #include "drivers.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
enum FX_ERRORS enum FX_ERRORS
{ {
FX_Warning = -2, FX_Warning = -2,
FX_Error = -1, FX_Error = -1,
FX_Ok = 0, FX_Ok = 0,
FX_SoundCardError, FX_InvalidCard,
FX_InvalidCard, FX_MultiVocError,
FX_MultiVocError, };
};
enum FX_LOOP_HOW
enum FX_LOOP_HOW {
{ FX_ONESHOT = -1,
FX_ONESHOT = -1, FX_LOOP = 0,
FX_LOOP = 0, };
};
#define FX_MUSIC_PRIORITY INT_MAX
#define FX_MUSIC_PRIORITY INT_MAX
const char *FX_ErrorString(int32_t ErrorNumber);
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,
int32_t FX_Init( int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, unsigned mixrate, void * initdata ); void *initdata);
int32_t FX_Shutdown( void ); int32_t FX_Shutdown(void);
int32_t FX_SetCallBack( void ( *function )( uint32_t ) ); void FX_SetCallBack(void(*function)(uint32_t));
void FX_SetVolume( int32_t volume ); void FX_SetVolume(int32_t volume);
int32_t FX_GetVolume( void ); int32_t FX_GetVolume(void);
void FX_SetReverseStereo( int32_t setting ); void FX_SetReverseStereo(int32_t setting);
int32_t FX_GetReverseStereo( void ); int32_t FX_GetReverseStereo(void);
void FX_SetReverb( int32_t reverb ); void FX_SetReverb(int32_t reverb);
void FX_SetFastReverb( int32_t reverb ); int32_t FX_GetMaxReverbDelay(void);
int32_t FX_GetMaxReverbDelay( void ); int32_t FX_GetReverbDelay(void);
int32_t FX_GetReverbDelay( void ); void FX_SetReverbDelay(int32_t delay);
void FX_SetReverbDelay( int32_t delay );
int32_t FX_PauseVoice(int32_t handle, int32_t pause);
int32_t FX_PauseVoice ( int32_t handle, int32_t pause ); int32_t FX_VoiceAvailable(int32_t priority);
int32_t FX_VoiceAvailable( int32_t priority ); int32_t FX_EndLooping(int32_t handle);
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_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_SetPitch( int32_t handle, int32_t pitchoffset ); int32_t FX_SetFrequency(int32_t handle, int32_t frequency);
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,
#if 0 int32_t priority, uint32_t callbackval);
int32_t FX_PlayVOC( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t FX_PlayLoopedAuto(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t priority, uint32_t callbackval ); 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 FX_PlayAuto3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, int32_t distance, int32_t priority, uint32_t callbackval);
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 FX_Pan3D(int32_t handle, int32_t angle, int32_t distance);
int32_t priority, uint32_t callbackval ); int32_t FX_SoundActive(int32_t handle);
int32_t FX_PlayLoopedWAV( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t FX_SoundsPlaying(void);
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, int32_t FX_StopSound(int32_t handle);
uint32_t callbackval ); int32_t FX_StopAllSounds(void);
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_SetVoiceCallback(int32_t handle, uint32_t callbackval);
int32_t FX_PlayWAV3D( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t angle, int32_t distance, int32_t FX_SetPrintf(void(*function)(const char *, ...));
int32_t priority, uint32_t callbackval );
int32_t FX_PlayRaw( char *ptr, uint32_t length, unsigned rate, int32_t FX_GetPosition(int32_t handle, int32_t *position);
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, int32_t FX_SetPosition(int32_t handle, int32_t position);
uint32_t callbackval );
int32_t FX_PlayLoopedRaw( char *ptr, uint32_t length, char *loopstart, #ifdef __cplusplus
char *loopend, unsigned rate, int32_t pitchoffset, int32_t vol, int32_t left, }
int32_t right, int32_t priority, uint32_t callbackval ); #endif
#endif
#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

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

View file

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

View file

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

View file

@ -27,9 +27,9 @@
#define FLAC__NO_DLL #define FLAC__NO_DLL
#ifdef __APPLE__ #ifdef __APPLE__
# include <FLAC/all.h> #include <FLAC/all.h>
#else #else
# include "FLAC/all.h" #include "FLAC/all.h"
#endif #endif
#include <stdlib.h> #include <stdlib.h>
@ -44,154 +44,161 @@
#include "_multivc.h" #include "_multivc.h"
typedef struct { typedef struct
void * ptr; {
size_t length; void *ptr;
size_t pos; size_t length;
size_t pos;
FLAC__StreamDecoder* stream; FLAC__StreamDecoder *stream;
FLAC__uint64 sample_pos; FLAC__uint64 sample_pos;
char *block; char *block;
size_t blocksize; size_t blocksize;
VoiceNode *owner; VoiceNode *owner;
} flac_data; } flac_data;
// callbacks, round 1 // 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; flac_data *flac = (flac_data *)datasource;
size_t nread = 0; size_t nread = 0;
size_t bytes; size_t bytes;
errno = 0; errno = 0;
if (flac->length == flac->pos) { if (flac->length == flac->pos)
return 0; {
} return 0;
}
for (; nmemb > 0; nmemb--, nread++) { for (; nmemb > 0; nmemb--, nread++)
bytes = flac->length - flac->pos; {
if (size < bytes) { bytes = flac->length - flac->pos;
bytes = size; if (size < bytes)
} {
bytes = size;
}
memcpy(ptr, (uint8_t *)flac->ptr + flac->pos, bytes); memcpy(ptr, (uint8_t *)flac->ptr + flac->pos, bytes);
flac->pos += bytes; flac->pos += bytes;
ptr = (uint8_t *)ptr + bytes; ptr = (uint8_t *)ptr + bytes;
if (flac->length == flac->pos) { if (flac->length == flac->pos)
nread++; {
break; 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(ptr);
UNREFERENCED_PARAMETER(size); UNREFERENCED_PARAMETER(size);
UNREFERENCED_PARAMETER(nmemb); UNREFERENCED_PARAMETER(nmemb);
UNREFERENCED_PARAMETER(datasource); UNREFERENCED_PARAMETER(datasource);
return 0; return 0;
} }
static int32_t seek_flac(FLAC__IOHandle datasource, FLAC__int64 offset, int32_t whence) 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) { switch (whence)
case SEEK_SET: flac->pos = 0; break; {
case SEEK_CUR: break; case SEEK_SET: flac->pos = 0; break;
case SEEK_END: flac->pos = flac->length; break; case SEEK_CUR: break;
} case SEEK_END: flac->pos = flac->length; break;
}
flac->pos += offset; flac->pos += offset;
if (flac->pos > flac->length) { if (flac->pos > flac->length)
flac->pos = flac->length; {
} flac->pos = flac->length;
}
return 0; return 0;
} }
static FLAC__int64 tell_flac(FLAC__IOHandle datasource) 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) 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) 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) static int32_t close_flac(FLAC__IOHandle datasource)
{ {
UNREFERENCED_PARAMETER(datasource); UNREFERENCED_PARAMETER(datasource);
return 0; return 0;
} }
static FLAC__IOCallbacks flac_callbacks = { static FLAC__IOCallbacks flac_callbacks = {
read_flac, read_flac, write_flac, seek_flac, tell_flac, eof_flac, close_flac,
write_flac,
seek_flac,
tell_flac,
eof_flac,
close_flac,
}; };
// callbacks, round 2 // 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); UNREFERENCED_PARAMETER(decoder);
if(*bytes > 0) { if (*bytes > 0)
*bytes = read_flac(buffer, sizeof(FLAC__byte), *bytes, client_data); {
if(errno) *bytes = read_flac(buffer, sizeof(FLAC__byte), *bytes, client_data);
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; if (errno)
else if(*bytes == 0) return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; else if (*bytes == 0)
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
else else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
else
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); UNREFERENCED_PARAMETER(decoder);
if(seek_flac(client_data, absolute_byte_offset, SEEK_SET) < 0) if (seek_flac(client_data, absolute_byte_offset, SEEK_SET) < 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
else else
return FLAC__STREAM_DECODER_SEEK_STATUS_OK; 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); UNREFERENCED_PARAMETER(decoder);
*absolute_byte_offset = tell_flac(client_data); *absolute_byte_offset = tell_flac(client_data);
return FLAC__STREAM_DECODER_TELL_STATUS_OK; 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); UNREFERENCED_PARAMETER(decoder);
*stream_length = length_flac(client_data); *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) FLAC__bool eof_flac_stream(const FLAC__StreamDecoder *decoder, void *client_data)
{ {
UNREFERENCED_PARAMETER(decoder); UNREFERENCED_PARAMETER(decoder);
return eof_flac(client_data); 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; VoiceNode *voice = fd->owner;
FLAC__uint64 samples = frame->header.blocksize; FLAC__uint64 samples = frame->header.blocksize;
UNREFERENCED_PARAMETER(decoder); UNREFERENCED_PARAMETER(decoder);
voice->channels = frame->header.channels; voice->channels = frame->header.channels;
voice->bits = frame->header.bits_per_sample; voice->bits = frame->header.bits_per_sample;
voice->SamplingRate = frame->header.sample_rate; voice->SamplingRate = frame->header.sample_rate;
if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) 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) else if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER)
fd->sample_pos = frame->header.number.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; samples = (FLAC__uint64)(uintptr_t)voice->LoopEnd - fd->sample_pos;
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart)) 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", 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->length = ((samples * (voice->bits / 8)) / 2) << voice->bits;
voice->position = 0; voice->position = 0;
voice->BlockLength = 0; voice->BlockLength = 0;
// CODEDUP multivoc.c MV_SetVoicePitch // CODEDUP multivoc.c MV_SetVoicePitch
voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate;
voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) - voice->RateScale; voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale;
MV_SetVoiceMixMode( voice ); 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) if (size > fd->blocksize)
{ {
fd->blocksize = size; fd->blocksize = size;
fd->block = (char*)realloc(fd->block, sizeof(char) * size); fd->block = (char *)realloc(fd->block, sizeof(char) * size);
} }
} }
if (!fd->block) if (!fd->block)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
voice->sound = fd->block; voice->sound = fd->block;
{ {
char *obuffer = fd->block; char *obuffer = fd->block;
@ -257,17 +266,16 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
uint8_t channel; uint8_t channel;
// this loop is adapted from code in ov_read_filter() in vorbisfile.c in libvorbis // this loop is adapted from code in ov_read_filter() in vorbisfile.c in libvorbis
for(sample=0; sample < samples; ++sample) for (sample = 0; sample < samples; ++sample)
for(channel=0; channel < frame->header.channels; ++channel) for (channel = 0; channel < frame->header.channels; ++channel)
{ {
int8_t byte; int8_t byte;
FLAC__int32 val=ibuffer[channel][sample]; FLAC__int32 val = ibuffer[channel][sample];
if(val>(1<<(voice->bits-1))-1) if (val > (1 << (voice->bits - 1)) - 1)
val=(1<<(voice->bits-1))-1; val = (1 << (voice->bits - 1)) - 1;
else if(val<-(1<<(voice->bits-1))) else if (val < -(1 << (voice->bits - 1)))
val=-(1<<(voice->bits-1)); val = -(1 << (voice->bits - 1));
for (byte = 0; byte < voice->bits; byte += 8) for (byte = 0; byte < voice->bits; byte += 8) *obuffer++ = ((val >> byte) & 0x000000FF);
*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) 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(client_data);
UNREFERENCED_PARAMETER(decoder); UNREFERENCED_PARAMETER(decoder);
MV_Printf("%s\n", FLAC__StreamDecoderErrorStatusString[status]); 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) int32_t MV_GetFLACPosition(VoiceNode *voice)
{ {
FLAC__uint64 position = 0; 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); 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) 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); FLAC__stream_decoder_seek_absolute(fd->stream, position);
} }
@ -306,34 +314,31 @@ Function: MV_GetNextFLACBlock
Controls playback of FLAC data Controls playback of FLAC data
---------------------------------------------------------------------*/ ---------------------------------------------------------------------*/
static playbackstatus MV_GetNextFLACBlock static playbackstatus MV_GetNextFLACBlock(VoiceNode *voice)
(
VoiceNode *voice
)
{ {
flac_data * fd = (flac_data *) voice->extra; flac_data *fd = (flac_data *)voice->rawdataptr;
FLAC__StreamDecoderState decode_state; FLAC__StreamDecoderState decode_state;
// FLAC__bool decode_status; // FLAC__bool decode_status;
voice->Playing = TRUE; voice->Playing = TRUE;
if ((FLAC__uint64)(uintptr_t)voice->LoopEnd > 0 && fd->sample_pos >= (FLAC__uint64)(uintptr_t)voice->LoopEnd) 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)) 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", 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); decode_state = FLAC__stream_decoder_get_state(fd->stream);
/* /*
if (!decode_status) if (!decode_status)
{ {
MV_Printf("MV_GetNextFLACBlock: %s\n", FLAC__StreamDecoderStateString[decode_state]); MV_Printf("MV_GetNextFLACBlock: %s\n", FLAC__StreamDecoderStateString[decode_state]);
voice->Playing = FALSE; voice->Playing = FALSE;
return NoMoreData; return NoMoreData;
} }
*/ */
if (decode_state == FLAC__STREAM_DECODER_SEEK_ERROR) 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)) 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", 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 else
{ {
@ -378,49 +383,40 @@ Begin playback of sound data at specified angle and distance
from listener. from listener.
---------------------------------------------------------------------*/ ---------------------------------------------------------------------*/
int32_t MV_PlayFLAC3D 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)
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 left;
int32_t right; int32_t right;
int32_t mid; int32_t mid;
int32_t volume; int32_t volume;
int32_t status; int32_t status;
if ( !MV_Installed ) if (!MV_Installed)
{ {
MV_SetErrorCode( MV_NotInstalled ); MV_SetErrorCode(MV_NotInstalled);
return MV_Error; return MV_Error;
} }
if ( distance < 0 ) if (distance < 0)
{ {
distance = -distance; distance = -distance;
angle += MV_NUMPANPOSITIONS / 2; angle += MV_NUMPANPOSITIONS / 2;
} }
volume = MIX_VOLUME( distance ); volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127 // Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION; angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left; left = MV_PanTable[angle][volume].left;
right = MV_PanTable[ angle ][ volume ].right; right = MV_PanTable[angle][volume].right;
mid = max( 0, 255 - distance ); 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. priority.
---------------------------------------------------------------------*/ ---------------------------------------------------------------------*/
int32_t MV_PlayFLAC 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)
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; VoiceNode *voice;
flac_data * fd = 0; flac_data *fd = 0;
FLAC__Metadata_Chain* metadata_chain; FLAC__Metadata_Chain *metadata_chain;
UNREFERENCED_PARAMETER(loopend); UNREFERENCED_PARAMETER(loopend);
if ( !MV_Installed ) if (!MV_Installed)
{ {
MV_SetErrorCode( MV_NotInstalled ); MV_SetErrorCode(MV_NotInstalled);
return MV_Error; return MV_Error;
} }
fd = (flac_data *) calloc( 1, sizeof(flac_data) ); fd = (flac_data *)calloc(1, sizeof(flac_data));
if (!fd) { if (!fd)
MV_SetErrorCode( MV_InvalidFLACFile ); {
return MV_Error; MV_SetErrorCode(MV_InvalidFLACFile);
} return MV_Error;
}
fd->ptr = ptr; fd->ptr = ptr;
fd->pos = 0; fd->pos = 0;
fd->blocksize = 0; fd->blocksize = 0;
fd->length = ptrlength; fd->length = ptrlength;
fd->block = NULL; fd->block = NULL;
fd->stream = FLAC__stream_decoder_new(); fd->stream = FLAC__stream_decoder_new();
fd->sample_pos = 0; fd->sample_pos = 0;
FLAC__stream_decoder_set_metadata_ignore_all(fd->stream); FLAC__stream_decoder_set_metadata_ignore_all(fd->stream);
if (FLAC__stream_decoder_init_stream(fd->stream, if (FLAC__stream_decoder_init_stream(fd->stream, read_flac_stream, seek_flac_stream, tell_flac_stream,
read_flac_stream, length_flac_stream, eof_flac_stream, write_flac_stream,
seek_flac_stream, /*metadata_flac_stream*/ NULL, error_flac_stream,
tell_flac_stream, (void *)fd) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
length_flac_stream, {
eof_flac_stream, MV_Printf("MV_PlayFLAC: %s\n", FLAC__stream_decoder_get_resolved_state_string(fd->stream));
write_flac_stream, MV_SetErrorCode(MV_InvalidFLACFile);
/*metadata_flac_stream*/ NULL, return MV_Error;
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 // Request a voice from the voice pool
voice = MV_AllocVoice( priority ); voice = MV_AllocVoice(priority);
if ( voice == NULL ) if (voice == NULL)
{ {
FLAC__stream_decoder_finish(fd->stream); FLAC__stream_decoder_finish(fd->stream);
FLAC__stream_decoder_delete(fd->stream); FLAC__stream_decoder_delete(fd->stream);
free(fd); free(fd);
MV_SetErrorCode( MV_NoVoices ); MV_SetErrorCode(MV_NoVoices);
return MV_Error; return MV_Error;
} }
fd->owner = voice; fd->owner = voice;
voice->wavetype = FLAC; voice->wavetype = FMT_FLAC;
voice->extra = (void*)fd; voice->rawdataptr = (void *)fd;
voice->GetSound = MV_GetNextFLACBlock; voice->GetSound = MV_GetNextFLACBlock;
voice->NextBlock = fd->block; voice->NextBlock = fd->block;
voice->DemandFeed = NULL; voice->LoopCount = 0;
voice->LoopCount = 0; voice->BlockLength = 0;
voice->BlockLength = 0; voice->PitchScale = PITCH_GetScale(pitchoffset);
voice->PitchScale = PITCH_GetScale( pitchoffset ); voice->next = NULL;
voice->next = NULL; voice->prev = NULL;
voice->prev = NULL; voice->priority = priority;
voice->priority = priority; voice->callbackval = callbackval;
voice->callbackval = callbackval;
voice->Playing = TRUE; voice->Playing = TRUE;
voice->Paused = FALSE; voice->Paused = FALSE;
voice->LoopStart = 0; voice->LoopStart = 0;
voice->LoopEnd = 0; voice->LoopEnd = 0;
voice->LoopSize = (loopstart >= 0 ? 1 : 0); voice->LoopSize = (loopstart >= 0 ? 1 : 0);
// parse metadata // parse metadata
// loop parsing designed with multiple repetitions in mind // loop parsing designed with multiple repetitions in mind
// In retrospect, it may be possible to MV_GetVorbisCommentLoops(voice, (vorbis_comment *) &tags->data.vorbis_comment) // In retrospect, it may be possible to MV_GetVorbisCommentLoops(voice, (vorbis_comment *)
// but libvorbisfile may be confused by the signedness of char* vs FLAC__byte* and this code does not depend on HAVE_VORBIS. // &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(); metadata_chain = FLAC__metadata_chain_new();
if (metadata_chain != NULL) if (metadata_chain != NULL)
{ {
if (FLAC__metadata_chain_read_with_callbacks(metadata_chain, fd, flac_callbacks)) 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) if (metadata_iterator != NULL)
{ {
char *vc_loopstart = NULL; char *vc_loopstart = NULL;
@ -550,19 +532,20 @@ int32_t MV_PlayFLAC
{ {
const FLAC__StreamMetadata_StreamInfo *info = &tags->data.stream_info; const FLAC__StreamMetadata_StreamInfo *info = &tags->data.stream_info;
if (info->channels != 1 && info->channels != 2) { if (info->channels != 1 && info->channels != 2)
FLAC__metadata_object_delete(tags); {
FLAC__metadata_iterator_delete(metadata_iterator); FLAC__metadata_object_delete(tags);
// FLAC__metadata_chain_delete(metadata_chain); FLAC__metadata_iterator_delete(metadata_iterator);
FLAC__stream_decoder_finish(fd->stream); // FLAC__metadata_chain_delete(metadata_chain);
FLAC__stream_decoder_delete(fd->stream); FLAC__stream_decoder_finish(fd->stream);
free(fd); FLAC__stream_decoder_delete(fd->stream);
MV_SetErrorCode( MV_InvalidFLACFile ); free(fd);
return MV_Error; MV_SetErrorCode(MV_InvalidFLACFile);
return MV_Error;
} }
voice->channels = info->channels; voice->channels = info->channels;
voice->bits = info->bits_per_sample; voice->bits = info->bits_per_sample;
voice->SamplingRate = info->sample_rate; voice->SamplingRate = info->sample_rate;
} }
@ -573,39 +556,42 @@ int32_t MV_PlayFLAC
uint8_t loopTagCount; uint8_t loopTagCount;
for (comment = 0; comment < tags->data.vorbis_comment.num_comments; ++comment) 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') if (entry != NULL && entry[0] != '\0')
{ {
const char *value = strchr(entry,'='); const char *value = strchr(entry, '=');
const size_t field = value-entry; const size_t field = value - entry;
value += 1; 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) if (strncasecmp(entry, loopStartTags[loopTagCount], field) == 0)
vc_loopstart = strdup(value); 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) if (strncasecmp(entry, loopEndTags[loopTagCount], field) == 0)
vc_loopend = strdup(value); 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) if (strncasecmp(entry, loopLengthTags[loopTagCount], field) == 0)
vc_looplength = strdup(value); vc_looplength = strdup(value);
} }
} }
} }
FLAC__metadata_object_delete(tags); // If it were not for this, I would assign pointers instead of strdup(). 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)); } while (FLAC__metadata_iterator_next(metadata_iterator));
if (vc_loopstart != NULL) if (vc_loopstart != NULL)
{ {
{ {
const FLAC__int64 flac_loopstart = atol(vc_loopstart); 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; voice->LoopSize = 1;
} }
} }
@ -616,8 +602,8 @@ int32_t MV_PlayFLAC
if (voice->LoopSize > 0) if (voice->LoopSize > 0)
{ {
const FLAC__int64 flac_loopend = atol(vc_loopend); const FLAC__int64 flac_loopend = atol(vc_loopend);
if (flac_loopend > 0) // a loop ending at 0 is invalid if (flac_loopend > 0) // a loop ending at 0 is invalid
voice->LoopEnd = (const char *) (intptr_t) flac_loopend; voice->LoopEnd = (const char *)(intptr_t)flac_loopend;
} }
free(vc_loopend); free(vc_loopend);
} }
@ -626,8 +612,8 @@ int32_t MV_PlayFLAC
if (voice->LoopSize > 0 && voice->LoopEnd == 0) if (voice->LoopSize > 0 && voice->LoopEnd == 0)
{ {
const FLAC__int64 flac_looplength = atol(vc_looplength); const FLAC__int64 flac_looplength = atol(vc_looplength);
if (flac_looplength > 0) // a loop of length 0 is invalid if (flac_looplength > 0) // a loop of length 0 is invalid
voice->LoopEnd = (const char *) ((intptr_t) flac_looplength + (intptr_t) voice->LoopStart); voice->LoopEnd = (const char *)((intptr_t)flac_looplength + (intptr_t)voice->LoopStart);
} }
free(vc_looplength); free(vc_looplength);
} }
@ -640,29 +626,30 @@ int32_t MV_PlayFLAC
else else
MV_Printf("%s\n", FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(metadata_chain)]); 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 else
MV_Printf("Error allocating FLAC__Metadata_Chain!\n"); MV_Printf("Error allocating FLAC__Metadata_Chain!\n");
// CODEDUP multivoc.c MV_SetVoicePitch // CODEDUP multivoc.c MV_SetVoicePitch
voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate;
voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale;
voice->RateScale; MV_SetVoiceMixMode(voice);
MV_SetVoiceMixMode( voice );
MV_SetVoiceVolume( voice, vol, left, right ); MV_SetVoiceVolume(voice, vol, left, right);
MV_PlayVoice( voice ); 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; return;
} }
@ -675,7 +662,20 @@ void MV_ReleaseFLACVoice( VoiceNode * voice )
free(fd->block); free(fd->block);
free(fd); 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) 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 This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License 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> #include <stdlib.h>
@ -33,46 +35,6 @@
#include "multivoc.h" #include "multivoc.h"
#include "_multivc.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) static playbackstatus MV_GetNextWAVBlock(VoiceNode *voice)
{ {
if (voice->BlockLength <= 0) if (voice->BlockLength <= 0)
@ -99,24 +61,11 @@ static playbackstatus MV_GetNextWAVBlock(VoiceNode *voice)
return KeepPlaying; return KeepPlaying;
} }
/*---------------------------------------------------------------------
Function: MV_GetNextVOCBlock
Interpret the information of a VOC format sound file.
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice) static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
{ {
const uint8_t *ptr;
int32_t blocktype;
int32_t lastblocktype;
size_t blocklength = 0; size_t blocklength = 0;
uint32_t samplespeed = 0; // XXX: compiler-happy on synthesis uint32_t samplespeed = 0; // XXX: compiler-happy on synthesis
uint32_t tc = 0; uint32_t tc = 0;
int32_t packtype;
int32_t voicemode;
int32_t done;
unsigned BitsPerSample; unsigned BitsPerSample;
unsigned Channels; unsigned Channels;
unsigned Format; unsigned Format;
@ -131,16 +80,17 @@ static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
return KeepPlaying; return KeepPlaying;
} }
ptr = (uint8_t *)voice->NextBlock; const uint8_t *ptr = (uint8_t *)voice->NextBlock;
voice->Playing = TRUE; voice->Playing = TRUE;
voice->Paused = FALSE; voice->Paused = FALSE;
voicemode = 0; int voicemode = 0;
lastblocktype = 0; int blocktype = 0;
packtype = 0; int lastblocktype = 0;
int packtype = 0;
done = FALSE; int done = FALSE;
do do
{ {
@ -155,7 +105,7 @@ static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
// terminator is not mandatory according to // terminator is not mandatory according to
// http://wiki.multimedia.cx/index.php?title=Creative_Voice // 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 blocktype = 0; // fake a terminator
else else
blocktype = *ptr; blocktype = *ptr;
@ -206,14 +156,11 @@ end_of_data:
// Skip packed or stereo data // Skip packed or stereo data
if ((packtype != 0) || (voicemode != 0 && voicemode != 1)) if ((packtype != 0) || (voicemode != 0 && voicemode != 1))
{
ptr += blocklength; ptr += blocklength;
}
else else
{
done = TRUE; done = TRUE;
}
if (ptr - voice->rawdataptr >= voice->ptrlength) if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
goto end_of_data; goto end_of_data;
voicemode = 0; voicemode = 0;
@ -227,19 +174,11 @@ end_of_data:
case 3 : case 3 :
// Silence // Silence
// Not implimented.
ptr += blocklength;
break;
case 4 : case 4 :
// Marker // Marker
// Not implimented.
ptr += blocklength;
break;
case 5 : case 5 :
// ASCII string // ASCII string
// Not implimented. // All not implemented.
ptr += blocklength; ptr += blocklength;
break; break;
@ -257,21 +196,17 @@ end_of_data:
// Repeat end // Repeat end
ptr += blocklength; ptr += blocklength;
if (lastblocktype == 6) if (lastblocktype == 6)
{
voice->LoopCount = 0; voice->LoopCount = 0;
}
else else
{ {
if ((voice->LoopCount > 0) && (voice->LoopStart != NULL)) if ((voice->LoopCount > 0) && (voice->LoopStart != NULL))
{ {
ptr = (uint8_t *) voice->LoopStart; ptr = (uint8_t *) voice->LoopStart;
if (voice->LoopCount < 0xffff) if (voice->LoopCount < 0xffff)
{ {
voice->LoopCount--; if (--voice->LoopCount == 0)
if (voice->LoopCount == 0)
{
voice->LoopStart = NULL; voice->LoopStart = NULL;
}
} }
} }
} }
@ -294,8 +229,7 @@ end_of_data:
Channels = (unsigned)*(ptr + 5); Channels = (unsigned)*(ptr + 5);
Format = (unsigned)LITTLE16(*(uint16_t *)(ptr + 6)); Format = (unsigned)LITTLE16(*(uint16_t *)(ptr + 6));
if ((BitsPerSample == 8) && (Channels == 1 || Channels == 2) && if ((BitsPerSample == 8) && (Channels == 1 || Channels == 2) && (Format == VOC_8BIT))
(Format == VOC_8BIT))
{ {
ptr += 12; ptr += 12;
blocklength -= 12; blocklength -= 12;
@ -303,8 +237,7 @@ end_of_data:
voice->channels = Channels; voice->channels = Channels;
done = TRUE; done = TRUE;
} }
else if ((BitsPerSample == 16) && (Channels == 1 || Channels == 2) && else if ((BitsPerSample == 16) && (Channels == 1 || Channels == 2) && (Format == VOC_16BIT))
(Format == VOC_16BIT))
{ {
ptr += 12; ptr += 12;
blocklength -= 12; blocklength -= 12;
@ -320,7 +253,7 @@ end_of_data:
// CAUTION: // CAUTION:
// SNAKRM.VOC is corrupt! blocklength gets us beyond the // SNAKRM.VOC is corrupt! blocklength gets us beyond the
// end of the file. // end of the file.
if (ptr - voice->rawdataptr >= voice->ptrlength) if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
goto end_of_data; goto end_of_data;
break; break;
@ -380,137 +313,11 @@ end_of_data:
return NoMoreData; return NoMoreData;
} }
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)
Function: MV_GetNextDemandFeedBlock
Controls playback of demand fed data.
---------------------------------------------------------------------*/
static playbackstatus MV_GetNextDemandFeedBlock(VoiceNode *voice)
{ {
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) if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error; 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) if (distance < 0)
{ {
@ -518,67 +325,33 @@ int32_t MV_PlayWAV3D
angle += MV_NUMPANPOSITIONS / 2; angle += MV_NUMPANPOSITIONS / 2;
} }
volume = MIX_VOLUME(distance); int const volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127 // Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION; angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left; return MV_PlayWAV(ptr, length, loophow, -1, pitchoffset, max(0, 255 - distance),
right = MV_PanTable[ angle ][ volume ].right; MV_PanTable[ angle ][ volume ].left, MV_PanTable[ angle ][ volume ].right, priority, callbackval);
mid = max(0, 255 - distance);
status = MV_PlayWAV(ptr, length, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
} }
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)
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
)
{ {
riff_header riff;
format_header format;
data_header data;
VoiceNode *voice;
int32_t length;
if (!MV_Installed) if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error; return MV_Error;
}
riff_header riff;
memcpy(&riff, ptr, sizeof(riff_header)); memcpy(&riff, ptr, sizeof(riff_header));
riff.file_size = LITTLE32(riff.file_size); riff.file_size = LITTLE32(riff.file_size);
riff.format_size = LITTLE32(riff.format_size); riff.format_size = LITTLE32(riff.format_size);
if ((memcmp(riff.RIFF, "RIFF", 4) != 0) || if ((memcmp(riff.RIFF, "RIFF", 4) != 0) || (memcmp(riff.WAVE, "WAVE", 4) != 0) || (memcmp(riff.fmt, "fmt ", 4) != 0))
(memcmp(riff.WAVE, "WAVE", 4) != 0) ||
(memcmp(riff.fmt, "fmt ", 4) != 0))
{ {
MV_SetErrorCode(MV_InvalidWAVFile); MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error; return MV_Error;
} }
format_header format;
memcpy(&format, ptr + sizeof(riff_header), sizeof(format_header)); memcpy(&format, ptr + sizeof(riff_header), sizeof(format_header));
format.wFormatTag = LITTLE16(format.wFormatTag); format.wFormatTag = LITTLE16(format.wFormatTag);
format.nChannels = LITTLE16(format.nChannels); format.nChannels = LITTLE16(format.nChannels);
@ -587,54 +360,41 @@ int32_t MV_PlayWAV
format.nBlockAlign = LITTLE16(format.nBlockAlign); format.nBlockAlign = LITTLE16(format.nBlockAlign);
format.nBitsPerSample = LITTLE16(format.nBitsPerSample); format.nBitsPerSample = LITTLE16(format.nBitsPerSample);
data_header data;
memcpy(&data, ptr + sizeof(riff_header) + riff.format_size, sizeof(data_header)); memcpy(&data, ptr + sizeof(riff_header) + riff.format_size, sizeof(data_header));
data.size = LITTLE32(data.size); data.size = LITTLE32(data.size);
// Check if it's PCM data. // Check if it's PCM data.
if (format.wFormatTag != 1) 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;
}
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)
{ {
MV_SetErrorCode(MV_InvalidWAVFile); MV_SetErrorCode(MV_InvalidWAVFile);
return MV_Error; return MV_Error;
} }
// Request a voice from the voice pool // Request a voice from the voice pool
voice = MV_AllocVoice(priority);
VoiceNode *voice = MV_AllocVoice(priority);
if (voice == NULL) if (voice == NULL)
{ {
MV_SetErrorCode(MV_NoVoices); MV_SetErrorCode(MV_NoVoices);
return MV_Error; return MV_Error;
} }
voice->wavetype = WAV; voice->wavetype = FMT_WAV;
voice->bits = format.nBitsPerSample; voice->bits = format.nBitsPerSample;
voice->channels = format.nChannels; voice->channels = format.nChannels;
voice->GetSound = MV_GetNextWAVBlock; voice->GetSound = MV_GetNextWAVBlock;
length = data.size; int32_t length = data.size;
if (voice->bits == 16) if (voice->bits == 16)
{ {
data.size &= ~1; data.size &= ~1;
length /= 2; length /= 2;
} }
if (voice->channels == 2) if (voice->channels == 2)
{ {
data.size &= ~1; data.size &= ~1;
@ -645,7 +405,6 @@ int32_t MV_PlayWAV
voice->ptrlength = ptrlength; voice->ptrlength = ptrlength;
voice->Playing = TRUE; voice->Playing = TRUE;
voice->Paused = FALSE; voice->Paused = FALSE;
voice->DemandFeed = NULL;
voice->LoopCount = 0; voice->LoopCount = 0;
voice->position = 0; voice->position = 0;
voice->length = 0; voice->length = 0;
@ -666,38 +425,11 @@ int32_t MV_PlayWAV
return voice->handle; return voice->handle;
} }
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)
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 left;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
if (!MV_Installed) if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error; return MV_Error;
}
if (distance < 0) if (distance < 0)
{ {
@ -705,62 +437,31 @@ int32_t MV_PlayVOC3D
angle += MV_NUMPANPOSITIONS / 2; angle += MV_NUMPANPOSITIONS / 2;
} }
volume = MIX_VOLUME(distance); int const volume = MIX_VOLUME(distance);
// Ensure angle is within 0 - 127 // Ensure angle is within 0 - 127
angle &= MV_MAXPANPOSITION; angle &= MV_MAXPANPOSITION;
left = MV_PanTable[ angle ][ volume ].left; return MV_PlayVOC(ptr, ptrlength, loophow, -1, pitchoffset, max(0, 255 - distance),
right = MV_PanTable[ angle ][ volume ].right; MV_PanTable[ angle ][ volume ].left, MV_PanTable[ angle ][ volume ].right, priority, callbackval);
mid = max(0, 255 - distance);
status = MV_PlayVOC(ptr, ptrlength, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
} }
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)
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
)
{ {
VoiceNode *voice;
int32_t status;
if (!MV_Installed) if (!MV_Installed)
{
MV_SetErrorCode(MV_NotInstalled);
return MV_Error; return MV_Error;
}
// Make sure it looks like a valid VOC file. // Make sure it looks like a valid VOC file.
status = memcmp(ptr, "Creative Voice File", 19); if (memcmp(ptr, "Creative Voice File", 19) != 0)
if (status != 0)
{ {
MV_SetErrorCode(MV_InvalidVOCFile); MV_SetErrorCode(MV_InvalidVOCFile);
return MV_Error; return MV_Error;
} }
// Request a voice from the voice pool // Request a voice from the voice pool
voice = MV_AllocVoice(priority); VoiceNode *voice = MV_AllocVoice(priority);
if (voice == NULL) if (voice == NULL)
{ {
MV_SetErrorCode(MV_NoVoices); MV_SetErrorCode(MV_NoVoices);
@ -771,12 +472,11 @@ int32_t MV_PlayVOC
voice->ptrlength = ptrlength; voice->ptrlength = ptrlength;
voice->Playing = TRUE; voice->Playing = TRUE;
voice->Paused = FALSE; voice->Paused = FALSE;
voice->wavetype = VOC; voice->wavetype = FMT_VOC;
voice->bits = 8; voice->bits = 8;
voice->channels = 1; voice->channels = 1;
voice->GetSound = MV_GetNextVOCBlock; voice->GetSound = MV_GetNextVOCBlock;
voice->NextBlock = ptr + LITTLE16(*(uint16_t *)(ptr + 0x14)); voice->NextBlock = ptr + LITTLE16(*(uint16_t *)(ptr + 0x14));
voice->DemandFeed = NULL;
voice->LoopCount = 0; voice->LoopCount = 0;
voice->BlockLength = 0; voice->BlockLength = 0;
voice->PitchScale = PITCH_GetScale(pitchoffset); voice->PitchScale = PITCH_GetScale(pitchoffset);
@ -795,63 +495,3 @@ int32_t MV_PlayVOC
return voice->handle; 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) 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 This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License 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. (c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/ **********************************************************************/
#include "compat.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "sndcards.h"
#include "drivers.h" #include "drivers.h"
#include "multivoc.h" #include "multivoc.h"
#include "fx_man.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_ErrorCode = FX_Ok;
int32_t FX_Installed = FALSE; int32_t FX_Installed = FALSE;
#define FX_SetErrorCode( status ) \ #define FX_SetErrorCode(status) FX_ErrorCode = (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
)
const char *FX_ErrorString(int32_t ErrorNumber)
{ {
const char *ErrorString; const char *ErrorString;
switch (ErrorNumber) switch (ErrorNumber)
{ {
case FX_Warning : case FX_Warning:
case FX_Error : case FX_Error: ErrorString = FX_ErrorString(FX_ErrorCode); break;
ErrorString = FX_ErrorString(FX_ErrorCode);
break;
case FX_Ok : case FX_Ok: ErrorString = "Fx ok."; break;
ErrorString = "Fx ok.";
break;
case FX_SoundCardError : case FX_InvalidCard: ErrorString = "Invalid Sound Fx device."; break;
ErrorString = SoundDriver_ErrorString(SoundDriver_GetError());
break;
case FX_InvalidCard : case FX_MultiVocError: ErrorString = MV_ErrorString(MV_Error); break;
ErrorString = "Invalid Sound Fx device.";
break;
case FX_MultiVocError : default: ErrorString = "Unknown Fx error code."; break;
ErrorString = MV_ErrorString(MV_Error);
break;
default :
ErrorString = "Unknown Fx error code.";
break;
} }
return ErrorString; return ErrorString;
} }
static inline int32_t FX_CheckMVErr(int32_t status)
/*---------------------------------------------------------------------
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
)
{ {
int32_t status; if (status != MV_Ok)
int32_t devicestatus;
if (FX_Installed)
{ {
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 (SoundCard == ASS_AutoDetect)
{ {
#if defined HAVE_DS #if defined HAVE_DS
@ -130,8 +95,7 @@ int32_t FX_Init
if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards) if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards)
{ {
FX_SetErrorCode(FX_InvalidCard); FX_SetErrorCode(FX_InvalidCard);
status = FX_Error; return FX_Error;
return status;
} }
if (SoundDriver_IsSupported(SoundCard) == 0) if (SoundDriver_IsSupported(SoundCard) == 0)
@ -140,43 +104,27 @@ int32_t FX_Init
SoundCard = ASS_NoSound; SoundCard = ASS_NoSound;
} }
status = FX_Ok; int status = FX_Ok;
devicestatus = MV_Init(SoundCard, mixrate, numvoices, numchannels, samplebits, initdata);
if (devicestatus != MV_Ok) if (MV_Init(SoundCard, mixrate, numvoices, numchannels, samplebits, initdata) != MV_Ok)
{ {
FX_SetErrorCode(FX_MultiVocError); FX_SetErrorCode(FX_MultiVocError);
status = FX_Error; status = FX_Error;
} }
if (status == FX_Ok) if (status == FX_Ok)
{
FX_Installed = TRUE; FX_Installed = TRUE;
}
return status; return status;
} }
int32_t FX_Shutdown(void)
/*---------------------------------------------------------------------
Function: FX_Shutdown
Terminates use of sound device.
---------------------------------------------------------------------*/
int32_t FX_Shutdown
(
void
)
{ {
int32_t status;
if (!FX_Installed) if (!FX_Installed)
{
return FX_Ok; return FX_Ok;
}
status = MV_Shutdown(); int status = MV_Shutdown();
if (status != MV_Ok) if (status != MV_Ok)
{ {
FX_SetErrorCode(FX_MultiVocError); FX_SetErrorCode(FX_MultiVocError);
@ -188,569 +136,116 @@ int32_t FX_Shutdown
return status; return status;
} }
void FX_SetCallBack(void (*function)(uint32_t)) { MV_SetCallBack(function); }
/*--------------------------------------------------------------------- void FX_SetVolume(int32_t volume) { MV_SetVolume(volume); }
Function: FX_SetCallback
Sets the function to call when a voice is done. int32_t FX_GetVolume(void) { return MV_GetVolume(); }
---------------------------------------------------------------------*/
int32_t FX_SetCallBack void FX_SetReverseStereo(int32_t setting) { MV_SetReverseStereo(setting); }
(
void (*function)(uint32_t)
)
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; return FX_CheckMVErr(MV_SetPan(handle, vol, left, right));
status = FX_Ok;
MV_SetCallBack(function);
return status;
} }
int32_t FX_SetPitch(int32_t handle, int32_t pitchoffset) { return FX_CheckMVErr(MV_SetPitch(handle, pitchoffset)); }
/*--------------------------------------------------------------------- int32_t FX_SetFrequency(int32_t handle, int32_t frequency) { return FX_CheckMVErr(MV_SetFrequency(handle, frequency)); }
Function: FX_SetVolume
Sets the volume of the current sound device.
---------------------------------------------------------------------*/
void FX_SetVolume
(
int32_t volume
)
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); }
/*--------------------------------------------------------------------- int32_t FX_SoundsPlaying(void) { return MV_VoicesPlaying(); }
Function: FX_GetVolume
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 int32_t FX_StopAllSounds(void) { return FX_CheckMVErr(MV_KillAllVoices()); }
(
void
)
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) if (length < 12)
return Unknown; return fmt;
switch (LITTLE32(*(int32_t *)ptr)) switch (LITTLE32(*(int32_t *)ptr))
{ {
case 'C'+('r'<<8)+('e'<<16)+('a'<<24): // Crea case 'C' + ('r' << 8) + ('e' << 16) + ('a' << 24): // Crea
return VOC; fmt = FMT_VOC;
break; break;
case 'R'+('I'<<8)+('F'<<16)+('F'<<24): // RIFF case 'O' + ('g' << 8) + ('g' << 16) + ('S' << 24): // OggS
switch (LITTLE32(*(int32_t *)(ptr + 8))) fmt = FMT_VORBIS;
{ break;
case 'C'+('D'<<8)+('X'<<16)+('A'<<24): // CDXA case 'R' + ('I' << 8) + ('F' << 16) + ('F' << 24): // RIFF
return XA; 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; break;
default: default:
return WAV; switch (LITTLE32(*(int32_t *)(ptr + 8)))
{
case 'W' + ('A' << 8) + ('V' << 16) + ('E' << 24): // WAVE
fmt = FMT_WAV;
break;
}
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 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) 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); return FX_PlayLoopedAuto(ptr, length, -1, -1, pitchoffset, vol, left, right, priority, callbackval);
} }
/*--------------------------------------------------------------------- int32_t FX_PlayLoopedAuto(char *ptr, uint32_t length, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
Function: FX_PlayLoopedAuto int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
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 handle = -1; int32_t handle = -1;
switch (FX_AutoDetectFormat(ptr, length)) EDUKE32_STATIC_ASSERT(FMT_MAX == 7);
{
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;
}
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) if (handle <= MV_Ok)
{ {
@ -761,46 +256,20 @@ int32_t FX_PlayLoopedAuto(char *ptr, uint32_t length, int32_t loopstart, int32_t
return handle; return handle;
} }
/*--------------------------------------------------------------------- int32_t FX_PlayAuto3D(char *ptr, uint32_t length, int32_t loophow, int32_t pitchoffset, int32_t angle, int32_t distance,
Function: FX_PlayAuto3D int32_t priority, uint32_t callbackval)
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 handle = -1; int32_t handle = -1;
switch (FX_AutoDetectFormat(ptr, length)) EDUKE32_STATIC_ASSERT(FMT_MAX == 7);
{
case VOC: static int32_t (*const func[FMT_MAX])(char *, uint32_t, int32_t, int32_t, int32_t, int32_t, int32_t, uint32_t) =
handle = MV_PlayVOC3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval); { NULL, NULL, MV_PlayVOC3D, MV_PlayWAV3D, MV_PlayVorbis3D, MV_PlayFLAC3D, MV_PlayXA3D };
break;
case WAV: wavefmt_t const fmt = FX_AutoDetectFormat(ptr, length);
handle = MV_PlayWAV3D(ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
break; if (func[fmt])
case Vorbis: handle = func[fmt](ptr, length, loophow, pitchoffset, angle, distance, priority, callbackval);
#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;
}
if (handle <= MV_Ok) 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 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) if (status != MV_Ok)
{ {
FX_SetErrorCode(FX_MultiVocError); FX_SetErrorCode(FX_MultiVocError);

View file

@ -27,7 +27,7 @@ extern "C" {
#define NewNode(type) ((type *)Bmalloc(sizeof(type))) #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) = NewNode(type); \
(rootnode)->prev = (rootnode); \ (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)->next = (rootnode); \
(newnode)->prev = (rootnode)->prev; \ (newnode)->prev = (rootnode)->prev; \
@ -58,18 +58,16 @@ extern "C" {
#define LL_ReverseList(root, type, next, prev) \ #define LL_ReverseList(root, type, next, prev) \
{ \ { \
type *newend, *trav, *tprev; \ type *newend = (root)->next, *trav, *tprev; \
\
newend = (root)->next; \
for (trav = (root)->prev; trav != newend; trav = tprev) \ for (trav = (root)->prev; trav != newend; trav = tprev) \
{ \ { \
tprev = trav->prev; \ 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)->prev->next = (node)->next; \
(node)->next->prev = (node)->prev; \ (node)->next->prev = (node)->prev; \
@ -80,31 +78,24 @@ extern "C" {
#define LL_SortedInsertion(rootnode, insertnode, next, prev, type, sortparm) \ #define LL_SortedInsertion(rootnode, insertnode, next, prev, type, sortparm) \
{ \ { \
type *hoya; \ type *hoya = (rootnode)->next; \
\
hoya = (rootnode)->next; \
while ((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \ while ((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \
{ \ { \
hoya = hoya->next; \ 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_Remove((node), next, prev); \
LL_AddNode((newroot), (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_Free(list) Bfree(list)
#define LL_Reset(list, next, prev) (list)->next = (list)->prev = (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 #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" #include "_multivc.h"
void ClearBuffer_DW( void *ptr, unsigned data, int32_t length )
{
unsigned *ptrdw = (unsigned *)ptr;
while (length--) {
*(ptrdw++) = data;
}
}
/* /*
JBF: JBF:
@ -39,10 +30,9 @@ void ClearBuffer_DW( void *ptr, unsigned data, int32_t length )
*/ */
// 8-bit mono source, 8-bit mono output // 8-bit mono source, 8-bit mono output
void MV_Mix8BitMono( uint32_t position, uint32_t rate, void MV_Mix8BitMono(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0; int32_t sample0;
@ -63,10 +53,9 @@ void MV_Mix8BitMono( uint32_t position, uint32_t rate,
} }
// 8-bit mono source, 8-bit stereo output // 8-bit mono source, 8-bit stereo output
void MV_Mix8BitStereo( uint32_t position, uint32_t rate, void MV_Mix8BitStereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 8-bit mono source, 16-bit mono output
void MV_Mix16BitMono( uint32_t position, uint32_t rate, void MV_Mix16BitMono(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0; int32_t sample0;
@ -116,10 +104,9 @@ void MV_Mix16BitMono( uint32_t position, uint32_t rate,
} }
// 8-bit mono source, 16-bit stereo output // 8-bit mono source, 16-bit stereo output
void MV_Mix16BitStereo( uint32_t position, uint32_t rate, void MV_Mix16BitStereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 16-bit mono source, 16-bit mono output
void MV_Mix16BitMono16( uint32_t position, uint32_t rate, void MV_Mix16BitMono16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0; 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 // 16-bit mono source, 8-bit mono output
void MV_Mix8BitMono16( uint32_t position, uint32_t rate, void MV_Mix8BitMono16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0; int32_t sample0;
@ -204,10 +189,9 @@ void MV_Mix8BitMono16( uint32_t position, uint32_t rate,
} }
// 16-bit mono source, 8-bit stereo output // 16-bit mono source, 8-bit stereo output
void MV_Mix8BitStereo16( uint32_t position, uint32_t rate, void MV_Mix8BitStereo16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 16-bit mono source, 16-bit stereo output
void MV_Mix16BitStereo16( uint32_t position, uint32_t rate, void MV_Mix16BitStereo16(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0; int32_t sample0l, sample0h, sample0;
int32_t sample1l, sample1h, sample1; int32_t sample1l, sample1h, sample1;
@ -274,14 +257,14 @@ void MV_Mix16BitStereo16( uint32_t position, uint32_t rate,
MV_MixDestination = (char *) dest; 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 * output = (int16_t *) dest;
int16_t sample0l, sample0h, sample0; int16_t sample0l, sample0h, sample0;
do { do {
sample0 = *input; sample0 = *input++;
#if 0 //def BIGENDIAN #if 0 //def BIGENDIAN
sample0l = sample0 >> 8; sample0l = sample0 >> 8;
sample0h = (sample0 & 255) ^ 128; 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; sample0l = ((int16_t *) volume)[sample0l] >> 8;
sample0h = ((int16_t *) volume)[sample0h]; sample0h = ((int16_t *) volume)[sample0h];
*output = (int16_t) (sample0l + sample0h + 128); *output++ = (int16_t) (sample0l + sample0h + 128);
input++;
output++;
} while (--count > 0); } 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; uint8_t * output = (uint8_t *) dest;
do { do {
*output = ((int16_t *) volume)[*input] + 128; *output++ = ((int16_t *) volume)[*input++] + 128;
input++;
output++;
} while (--count > 0); } 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 // 8-bit stereo source, 8-bit mono output
void MV_Mix8BitMono8Stereo( uint32_t position, uint32_t rate, void MV_Mix8BitMono8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 8-bit stereo source, 8-bit stereo output
void MV_Mix8BitStereo8Stereo( uint32_t position, uint32_t rate, void MV_Mix8BitStereo8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 8-bit stereo source, 16-bit mono output
void MV_Mix16BitMono8Stereo( uint32_t position, uint32_t rate, void MV_Mix16BitMono8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 8-bit stereo source, 16-bit stereo output
void MV_Mix16BitStereo8Stereo( uint32_t position, uint32_t rate, void MV_Mix16BitStereo8Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 16-bit stereo source, 16-bit mono output
void MV_Mix16BitMono16Stereo( uint32_t position, uint32_t rate, void MV_Mix16BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0; int32_t sample0l, sample0h, sample0;
int32_t sample1l, sample1h, sample1; 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 // 16-bit stereo source, 8-bit mono output
void MV_Mix8BitMono16Stereo( uint32_t position, uint32_t rate, void MV_Mix8BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 16-bit stereo source, 8-bit stereo output
void MV_Mix8BitStereo16Stereo( uint32_t position, uint32_t rate, void MV_Mix8BitStereo16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; uint8_t *dest = (uint8_t *) MV_MixDestination;
int32_t sample0, sample1; 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 // 16-bit stereo source, 16-bit stereo output
void MV_Mix16BitStereo16Stereo( uint32_t position, uint32_t rate, void MV_Mix16BitStereo16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length)
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; int16_t *dest = (int16_t *) MV_MixDestination;
int32_t sample0l, sample0h, sample0; int32_t sample0l, sample0h, sample0;
int32_t sample1l, sample1h, sample1; 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_ #ifndef MULTIVOC_H_
#define MULTIVOC_H_ #define MULTIVOC_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef UNREFERENCED_PARAMETER #ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(x) x = x #define UNREFERENCED_PARAMETER(x) x = x
#endif #endif
@ -76,15 +80,15 @@ static inline uint32_t SWAP32(uint32_t s)
typedef enum typedef enum
{ {
Unknown, FMT_UNKNOWN,
Raw, FMT_RAW,
VOC, FMT_VOC,
DemandFeed, FMT_WAV,
WAV, FMT_VORBIS,
Vorbis, FMT_FLAC,
FLAC, FMT_XA,
XA, FMT_MAX
} wavedata; } wavefmt_t;
#define MV_MINVOICEHANDLE 1 #define MV_MINVOICEHANDLE 1
@ -95,7 +99,6 @@ enum MV_Errors
MV_Warning = -2, MV_Warning = -2,
MV_Error = -1, MV_Error = -1,
MV_Ok = 0, MV_Ok = 0,
MV_UnsupportedCard,
MV_NotInstalled, MV_NotInstalled,
MV_DriverError, MV_DriverError,
MV_NoVoices, MV_NoVoices,
@ -106,8 +109,6 @@ enum MV_Errors
MV_InvalidVorbisFile, MV_InvalidVorbisFile,
MV_InvalidFLACFile, MV_InvalidFLACFile,
MV_InvalidXAFile, MV_InvalidXAFile,
MV_InvalidMixMode,
MV_NullRecordFunction
}; };
extern void (*MV_Printf)(const char *fmt, ...); 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_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); int32_t MV_Pan3D(int32_t handle, int32_t angle, int32_t distance);
void MV_SetReverb(int32_t reverb); void MV_SetReverb(int32_t reverb);
void MV_SetFastReverb(int32_t reverb);
int32_t MV_GetMaxReverbDelay(void); int32_t MV_GetMaxReverbDelay(void);
int32_t MV_GetReverbDelay(void); int32_t MV_GetReverbDelay(void);
void MV_SetReverbDelay(int32_t delay); void MV_SetReverbDelay(int32_t delay);
// int32_t MV_SetMixMode( int32_t numchannels, int32_t samplebits ); // int32_t MV_SetMixMode( int32_t numchannels, int32_t samplebits );
// int32_t MV_StartPlayback( void ); // int32_t MV_StartPlayback( void );
// void MV_StopPlayback( 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 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 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, 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); int32_t MV_SetVoiceCallback(int32_t handle, uint32_t callbackval);
void MV_SetPrintf(void (*function)(const char *fmt, ...)); void MV_SetPrintf(void (*function)(const char *fmt, ...));
#ifdef __cplusplus
}
#endif
#endif #endif

View file

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

View file

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