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,7 +22,15 @@
#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;
@ -32,9 +40,7 @@ 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

@ -33,7 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#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" {
@ -44,7 +44,6 @@ 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,
}; };
@ -58,16 +57,16 @@ enum FX_LOOP_HOW
#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, void * initdata ); int32_t FX_Init(int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, unsigned mixrate,
void *initdata);
int32_t FX_Shutdown(void); int32_t FX_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);
@ -79,45 +78,18 @@ 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);
#if 0
int32_t FX_PlayVOC( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayLoopedVOC( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayWAV( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayLoopedWAV( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayVOC3D( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayWAV3D( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t angle, int32_t distance,
int32_t priority, uint32_t callbackval );
int32_t FX_PlayRaw( char *ptr, uint32_t length, unsigned rate,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority,
uint32_t callbackval );
int32_t FX_PlayLoopedRaw( char *ptr, uint32_t length, char *loopstart,
char *loopend, unsigned rate, int32_t pitchoffset, int32_t vol, int32_t left,
int32_t right, int32_t priority, uint32_t callbackval );
#endif
int32_t FX_PlayAuto(char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t 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 priority, uint32_t callbackval);
int32_t FX_PlayLoopedAuto( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t FX_PlayLoopedAuto(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval);
uint32_t callbackval ); int32_t FX_PlayAuto3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t FX_PlayAuto3D( char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle, int32_t distance, int32_t distance, int32_t priority, uint32_t callbackval);
int32_t priority, uint32_t callbackval );
int32_t FX_Pan3D(int32_t handle, int32_t angle, int32_t distance); int32_t FX_Pan3D(int32_t handle, int32_t angle, int32_t distance);
int32_t FX_SoundActive(int32_t handle); int32_t FX_SoundActive(int32_t handle);
int32_t FX_SoundsPlaying(void); int32_t FX_SoundsPlaying(void);
int32_t FX_StopSound(int32_t handle); int32_t FX_StopSound(int32_t handle);
int32_t FX_StopAllSounds(void); 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_SetVoiceCallback(int32_t handle, uint32_t callbackval);
int32_t FX_SetPrintf(void(*function)(const char *, ...)); int32_t FX_SetPrintf(void(*function)(const char *, ...));

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
@ -102,19 +100,25 @@ typedef struct VoiceNode
struct VoiceNode *next; struct VoiceNode *next;
struct VoiceNode *prev; struct VoiceNode *prev;
wavedata wavetype;
char bits;
char channels;
playbackstatus (*GetSound)(struct VoiceNode *voice); playbackstatus (*GetSound)(struct VoiceNode *voice);
void ( *mix )( uint32_t position, uint32_t rate, void (*mix)(uint32_t position, uint32_t rate, const char *start, uint32_t length);
const char *start, uint32_t length );
const char *sound;
const int16_t *LeftVolume;
const int16_t *RightVolume;
const void *rawdataptr;
const uint8_t *rawdataptr;
const char *NextBlock; const char *NextBlock;
const char *LoopStart; const char *LoopStart;
const char *LoopEnd; const char *LoopEnd;
wavefmt_t wavetype;
char bits;
char channels;
unsigned LoopCount; unsigned LoopCount;
uint32_t LoopSize; uint32_t LoopSize;
uint32_t BlockLength; uint32_t BlockLength;
@ -124,7 +128,6 @@ typedef struct VoiceNode
uint32_t PitchScale; uint32_t PitchScale;
uint32_t FixedPointBufferSize; uint32_t FixedPointBufferSize;
const char *sound;
uint32_t length; uint32_t length;
uint32_t SamplingRate; uint32_t SamplingRate;
uint32_t RateScale; uint32_t RateScale;
@ -135,53 +138,15 @@ typedef struct VoiceNode
int32_t handle; int32_t handle;
int32_t priority; int32_t priority;
void ( *DemandFeed )( char **ptr, uint32_t *length );
void *extra;
const int16_t *LeftVolume;
const int16_t *RightVolume;
uint32_t callbackval; uint32_t callbackval;
} VoiceNode; } VoiceNode;
typedef struct
{
VoiceNode *start;
VoiceNode *end;
} VList;
typedef struct typedef struct
{ {
uint8_t left; uint8_t left;
uint8_t right; uint8_t right;
} Pan; } Pan;
typedef int16_t MONO16;
typedef int8_t MONO8;
typedef struct
{
MONO16 left;
MONO16 right;
// uint16_t left;
// uint16_t right;
} STEREO16;
typedef struct
{
MONO16 left;
MONO16 right;
} SIGNEDSTEREO16;
typedef struct
{
// MONO8 left;
// MONO8 right;
char left;
char right;
} STEREO8;
typedef struct typedef struct
{ {
char RIFF[4]; char RIFF[4];
@ -207,17 +172,13 @@ typedef struct
uint32_t size; uint32_t size;
} data_header; } 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;
extern int32_t MV_Installed; 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);
@ -239,67 +200,26 @@ 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_Mix8BitMono8Stereo( 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 ); 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_Mix8BitStereo8Stereo( uint32_t position, void MV_Mix8BitMono16Stereo(uint32_t position, uint32_t rate, const char *start, uint32_t length);
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_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_HarshClipTable;
extern char *MV_MixDestination; // pointer to the next output sample extern char *MV_MixDestination; // pointer to the next output sample

View file

@ -276,4 +276,3 @@ void SDLDrv_PCM_Unlock(void)
SDL_UnlockMutex(EffectFence); SDL_UnlockMutex(EffectFence);
} }

View file

@ -39,7 +39,8 @@ 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); int32_t (*GetError)(void);
const char *(*ErrorString)(int32_t); const char *(*ErrorString)(int32_t);
int32_t (*Init)(int32_t *, int32_t *, int32_t *, void *); int32_t (*Init)(int32_t *, int32_t *, int32_t *, void *);
@ -52,27 +53,15 @@ static struct {
// 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,
NoSoundDrv_PCM_StopPlayback,
NoSoundDrv_PCM_Lock,
NoSoundDrv_PCM_Unlock,
}, },
// Simple DirectMedia Layer // 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
@ -81,13 +70,8 @@ static struct {
// 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_Shutdown,
DirectSoundDrv_PCM_BeginPlayback,
DirectSoundDrv_PCM_StopPlayback,
DirectSoundDrv_PCM_Lock,
DirectSoundDrv_PCM_Unlock, DirectSoundDrv_PCM_Unlock,
}, },
#else #else
@ -96,28 +80,22 @@ static struct {
}; };
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);
} }
@ -126,29 +104,16 @@ int32_t SoundDriver_Init(int32_t *mixrate, int32_t *numchannels, int32_t *sample
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

@ -44,7 +44,8 @@
#include "_multivc.h" #include "_multivc.h"
typedef struct { typedef struct
{
void *ptr; void *ptr;
size_t length; size_t length;
size_t pos; size_t pos;
@ -68,13 +69,16 @@ static size_t read_flac(void * ptr, size_t size, size_t nmemb, FLAC__IOHandle da
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; bytes = flac->length - flac->pos;
if (size < bytes) { if (size < bytes)
{
bytes = size; bytes = size;
} }
@ -82,7 +86,8 @@ static size_t read_flac(void * ptr, size_t size, size_t nmemb, FLAC__IOHandle da
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++; nread++;
break; break;
} }
@ -105,7 +110,8 @@ static int32_t seek_flac(FLAC__IOHandle datasource, FLAC__int64 offset, int32_t
{ {
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_SET: flac->pos = 0; break;
case SEEK_CUR: break; case SEEK_CUR: break;
case SEEK_END: flac->pos = flac->length; break; case SEEK_END: flac->pos = flac->length; break;
@ -113,7 +119,8 @@ static int32_t seek_flac(FLAC__IOHandle datasource, FLAC__int64 offset, int32_t
flac->pos += offset; flac->pos += offset;
if (flac->pos > flac->length) { if (flac->pos > flac->length)
{
flac->pos = flac->length; flac->pos = flac->length;
} }
@ -148,21 +155,18 @@ static int32_t close_flac(FLAC__IOHandle datasource)
} }
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); *bytes = read_flac(buffer, sizeof(FLAC__byte), *bytes, client_data);
if (errno) if (errno)
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
@ -175,7 +179,8 @@ FLAC__StreamDecoderReadStatus read_flac_stream(const FLAC__StreamDecoder *decode
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
} }
FLAC__StreamDecoderSeekStatus seek_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) FLAC__StreamDecoderSeekStatus seek_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset,
void *client_data)
{ {
UNREFERENCED_PARAMETER(decoder); 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)
@ -184,14 +189,16 @@ FLAC__StreamDecoderSeekStatus seek_flac_stream(const FLAC__StreamDecoder *decode
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);
@ -204,7 +211,8 @@ FLAC__bool eof_flac_stream(const FLAC__StreamDecoder *decoder, void *client_data
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;
@ -221,7 +229,8 @@ 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))
@ -266,8 +275,7 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
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);
} }
} }
@ -286,7 +294,7 @@ void error_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderEr
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,13 +314,10 @@ 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;
@ -378,17 +383,8 @@ 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;
@ -431,19 +427,8 @@ 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;
@ -459,7 +444,8 @@ int32_t MV_PlayFLAC
} }
fd = (flac_data *)calloc(1, sizeof(flac_data)); fd = (flac_data *)calloc(1, sizeof(flac_data));
if (!fd) { if (!fd)
{
MV_SetErrorCode(MV_InvalidFLACFile); MV_SetErrorCode(MV_InvalidFLACFile);
return MV_Error; return MV_Error;
} }
@ -476,16 +462,11 @@ int32_t MV_PlayFLAC
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,
write_flac_stream,
/*metadata_flac_stream*/ NULL,
error_flac_stream,
(void*) fd) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
MV_Printf("MV_PlayFLAC: %s\n", FLAC__stream_decoder_get_resolved_state_string(fd->stream)); MV_Printf("MV_PlayFLAC: %s\n", FLAC__stream_decoder_get_resolved_state_string(fd->stream));
MV_SetErrorCode(MV_InvalidFLACFile); MV_SetErrorCode(MV_InvalidFLACFile);
return MV_Error; return MV_Error;
@ -504,11 +485,10 @@ int32_t MV_PlayFLAC
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);
@ -526,8 +506,10 @@ int32_t MV_PlayFLAC
// 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)
{ {
@ -550,7 +532,8 @@ 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_object_delete(tags);
FLAC__metadata_iterator_delete(metadata_iterator); FLAC__metadata_iterator_delete(metadata_iterator);
// FLAC__metadata_chain_delete(metadata_chain); // FLAC__metadata_chain_delete(metadata_chain);
@ -580,24 +563,27 @@ int32_t MV_PlayFLAC
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)
{ {
@ -640,15 +626,15 @@ 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);
@ -660,9 +646,10 @@ int32_t MV_PlayFLAC
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;
} }
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 #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,24 +196,20 @@ 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;
} }
} }
} }
}
break; break;
case 8 : case 8 :
@ -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
)
{
MV_SetVolume(volume);
}
/*---------------------------------------------------------------------
Function: FX_GetVolume
Returns the volume of the current sound device.
---------------------------------------------------------------------*/
int32_t FX_GetVolume
(
void
)
{
int32_t volume;
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 FX_Pan3D(int32_t handle, int32_t angle, int32_t distance)
{ {
int32_t status; return FX_CheckMVErr(MV_Pan3D(handle, angle, distance));
status = MV_Pan3D(handle, angle, distance);
if (status != MV_Ok)
{
FX_SetErrorCode(FX_MultiVocError);
status = FX_Warning;
} }
return status; int32_t FX_SoundActive(int32_t handle) { return MV_VoicePlaying(handle); }
}
int32_t FX_SoundsPlaying(void) { return MV_VoicesPlaying(); }
/*--------------------------------------------------------------------- int32_t FX_StopSound(int32_t handle) { return FX_CheckMVErr(MV_Kill(handle)); }
Function: FX_SoundActive
Tests if the specified sound is currently playing. int32_t FX_StopAllSounds(void) { return FX_CheckMVErr(MV_KillAllVoices()); }
---------------------------------------------------------------------*/
int32_t FX_SoundActive(int32_t handle) static wavefmt_t FX_AutoDetectFormat(const char *ptr, uint32_t length)
{ {
return MV_VoicePlaying(handle); wavefmt_t fmt = FMT_UNKNOWN;
}
/*---------------------------------------------------------------------
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;
case 'O' + ('g' << 8) + ('g' << 16) + ('S' << 24): // OggS
fmt = FMT_VORBIS;
break; break;
case 'R' + ('I' << 8) + ('F' << 16) + ('F' << 24): // RIFF case 'R' + ('I' << 8) + ('F' << 16) + ('F' << 24): // RIFF
switch (LITTLE32(*(int32_t *)(ptr + 8))) switch (LITTLE32(*(int32_t *)(ptr + 8)))
{ {
case 'C' + ('D' << 8) + ('X' << 16) + ('A' << 24): // CDXA case 'C' + ('D' << 8) + ('X' << 16) + ('A' << 24): // CDXA
return XA; fmt = FMT_XA;
break;
default:
return WAV;
break; break;
default: fmt = FMT_WAV; break;
} }
break; break;
case 'O'+('g'<<8)+('g'<<16)+('S'<<24): // OggS
return Vorbis;
break;
case 'f' + ('L' << 8) + ('a' << 16) + ('C' << 24): // fLaC case 'f' + ('L' << 8) + ('a' << 16) + ('C' << 24): // fLaC
return FLAC; fmt = FMT_FLAC;
break; break;
default: default:
switch (LITTLE32(*(int32_t *)(ptr + 8))) switch (LITTLE32(*(int32_t *)(ptr + 8)))
{ {
case 'W' + ('A' << 8) + ('V' << 16) + ('E' << 24): // WAVE case 'W' + ('A' << 8) + ('V' << 16) + ('E' << 24): // WAVE
return WAV; fmt = FMT_WAV;
break; break;
} }
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;
} }
@ -135,26 +133,27 @@ static void MV_GetVorbisCommentLoops(VoiceNode *voice, vorbis_comment *vc)
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; errno = 0;
if (vorb->length == vorb->pos) { if (vorb->length == vorb->pos)
return 0; return 0;
}
for (; nmemb > 0; nmemb--, nread++) { size_t nread = 0;
bytes = vorb->length - vorb->pos;
if (size < bytes) { for (; nmemb > 0; nmemb--, nread++)
{
size_t bytes = vorb->length - vorb->pos;
if (size < bytes)
bytes = size; bytes = size;
}
memcpy(ptr, (uint8_t *)vorb->ptr + vorb->pos, bytes); memcpy(ptr, (uint8_t *)vorb->ptr + vorb->pos, bytes);
vorb->pos += bytes; vorb->pos += bytes;
ptr = (uint8_t *)ptr + bytes; ptr = (uint8_t *)ptr + bytes;
if (vorb->length == vorb->pos) { if (vorb->length == vorb->pos)
{
nread++; nread++;
break; break;
} }
@ -168,7 +167,8 @@ 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) { switch (whence)
{
case SEEK_SET: vorb->pos = 0; break; case SEEK_SET: vorb->pos = 0; break;
case SEEK_CUR: break; case SEEK_CUR: break;
case SEEK_END: vorb->pos = vorb->length; break; case SEEK_END: vorb->pos = vorb->length; break;
@ -176,9 +176,8 @@ static int32_t seek_vorbis(void * datasource, ogg_int64_t offset, int32_t whence
vorb->pos += offset; vorb->pos += offset;
if (vorb->pos > vorb->length) { if (vorb->pos > vorb->length)
vorb->pos = vorb->length; vorb->pos = vorb->length;
}
return vorb->pos; return vorb->pos;
} }
@ -196,24 +195,19 @@ static long tell_vorbis(void * 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,72 +218,84 @@ 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; ogg_int64_t currentPosition;
bytesread += bytes; bytesread += bytes;
if ((ogg_int64_t)(intptr_t)voice->LoopEnd > 0 if ((ogg_int64_t)(intptr_t)voice->LoopEnd > 0 &&
&& (currentPosition = ov_pcm_tell(&vd->vf)) >= (ogg_int64_t)(intptr_t)voice->LoopEnd) { (currentPosition = ov_pcm_tell(&vd->vf)) >= (ogg_int64_t)(intptr_t)voice->LoopEnd)
bytesread -= (currentPosition - (ogg_int64_t)(intptr_t)voice->LoopEnd) * voice->channels * 2; // (voice->bits>>3) {
err = ov_pcm_seek(&vd->vf,(ogg_int64_t)(intptr_t)voice->LoopStart); bytesread -=
if (err != 0) { (currentPosition - (ogg_int64_t)(intptr_t)voice->LoopEnd) * voice->channels * 2; // (voice->bits>>3)
int const err = ov_pcm_seek(&vd->vf, (ogg_int64_t)(intptr_t)voice->LoopStart);
if (err != 0)
{
MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, LOOP_END %l, err %d\n", 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); (ogg_int64_t)(intptr_t)voice->LoopStart, (ogg_int64_t)(intptr_t)voice->LoopEnd, err);
} else {
continue;
} }
} }
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)
{
int const err = ov_pcm_seek(&vd->vf, (ogg_int64_t)(intptr_t)voice->LoopStart);
if (err != 0)
{
MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, err %d\n", MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, err %d\n",
(ogg_int64_t)(intptr_t)voice->LoopStart, err); (ogg_int64_t)(intptr_t)voice->LoopStart, err);
} else { }
else
continue; continue;
} }
} else { else
{
break; break;
} }
} else if (bytes < 0) { }
else if (bytes < 0)
{
MV_Printf("MV_GetNextVorbisBlock ov_read: err %d\n", bytes); MV_Printf("MV_GetNextVorbisBlock ov_read: err %d\n", bytes);
voice->Playing = FALSE; voice->Playing = FALSE;
return NoMoreData; return NoMoreData;
} }
} while (bytesread < BLOCKSIZE); } while (bytesread < BLOCKSIZE);
if (bytesread == 0) { if (bytesread == 0)
{
voice->Playing = FALSE; voice->Playing = FALSE;
return NoMoreData; return NoMoreData;
} }
if (bitstream != vd->lastbitstream) { if (bitstream != vd->lastbitstream)
{
vorbis_info *vi = 0; vorbis_info *vi = 0;
vi = ov_info(&vd->vf, -1); vi = ov_info(&vd->vf, -1);
if (!vi || (vi->channels != 1 && vi->channels != 2)) { if (!vi || (vi->channels != 1 && vi->channels != 2))
{
voice->Playing = FALSE; voice->Playing = FALSE;
return NoMoreData; return NoMoreData;
} }
@ -310,13 +316,11 @@ static playbackstatus MV_GetNextVorbisBlock
voice->length = bytesread << 16; // ???: Should the literal 16 be voice->bits? 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,25 +334,9 @@ 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;
int32_t right;
int32_t mid;
int32_t volume;
int32_t status;
if (!MV_Installed) if (!MV_Installed)
{ {
MV_SetErrorCode(MV_NotInstalled); MV_SetErrorCode(MV_NotInstalled);
@ -361,18 +349,13 @@ int32_t MV_PlayVorbis3D
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_PlayVorbis(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_PlayVorbis(ptr, ptrlength, loophow, -1, pitchoffset, mid, left, right, priority, callbackval);
return status;
} }
@ -383,26 +366,9 @@ 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)
@ -411,8 +377,10 @@ int32_t MV_PlayVorbis
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) {
if (!vd)
{
MV_SetErrorCode(MV_InvalidVorbisFile); MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error; return MV_Error;
} }
@ -422,22 +390,27 @@ int32_t MV_PlayVorbis
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) {
if (status < 0)
{
MV_Printf("MV_PlayVorbis: err %d\n", status); MV_Printf("MV_PlayVorbis: err %d\n", status);
MV_SetErrorCode(MV_InvalidVorbisFile); MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error; return MV_Error;
} }
vi = ov_info(&vd->vf, 0); vorbis_info *vi = ov_info(&vd->vf, 0);
if (!vi) {
if (!vi)
{
ov_clear(&vd->vf); ov_clear(&vd->vf);
free(vd); free(vd);
MV_SetErrorCode(MV_InvalidVorbisFile); MV_SetErrorCode(MV_InvalidVorbisFile);
return MV_Error; return MV_Error;
} }
if (vi->channels != 1 && vi->channels != 2) { if (vi->channels != 1 && vi->channels != 2)
{
ov_clear(&vd->vf); ov_clear(&vd->vf);
free(vd); free(vd);
MV_SetErrorCode(MV_InvalidVorbisFile); MV_SetErrorCode(MV_InvalidVorbisFile);
@ -445,7 +418,8 @@ int32_t MV_PlayVorbis
} }
// 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)
{ {
ov_clear(&vd->vf); ov_clear(&vd->vf);
@ -454,13 +428,12 @@ int32_t MV_PlayVorbis
return MV_Error; return MV_Error;
} }
voice->wavetype = Vorbis; 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)
if (voice->wavetype != Vorbis) {
return; return;
}
vorbis_data *vd = (vorbis_data *)voice->rawdataptr;
ov_clear(&vd->vf); ov_clear(&vd->vf);
free(vd); free(vd);
voice->extra = 0; voice->rawdataptr = 0;
}
#else
int32_t MV_PlayVorbis(char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset,
int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval)
{
MV_Printf("MV_PlayVorbis: OggVorbis support not included in this binary.\n");
return -1;
} }
int32_t MV_PlayVorbis3D(char *ptr, uint32_t ptrlength, int32_t loophow, int32_t pitchoffset, int32_t angle,
int32_t distance, int32_t priority, uint32_t callbackval)
{
MV_Printf("MV_PlayVorbis: OggVorbis support not included in this binary.\n");
return -1;
}
#endif //HAVE_VORBIS #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;
} }