From 4f10a9e4771ee6f0a8b0268f7cc5e529ed516d3f Mon Sep 17 00:00:00 2001 From: terminx Date: Mon, 27 Jul 2009 05:47:50 +0000 Subject: [PATCH] Initial working commit of JonoF's audiolib re-port... I think git-svn-id: https://svn.eduke32.com/eduke32@1471 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/jaudiolib/Makefile | 47 + .../eduke32/source/jaudiolib/include/fx_man.h | 113 + .../eduke32/source/jaudiolib/include/music.h | 93 + .../source/jaudiolib/include/sndcards.h | 46 + .../jfaudiolib.xcodeproj/project.pbxproj | 307 ++ .../eduke32/source/jaudiolib/src/_multivc.h | 320 ++ .../source/jaudiolib/src/driver_coreaudio.c | 339 ++ .../source/jaudiolib/src/driver_coreaudio.h | 29 + .../source/jaudiolib/src/driver_directsound.c | 487 +++ .../source/jaudiolib/src/driver_directsound.h | 31 + .../source/jaudiolib/src/driver_nosound.c | 62 + .../source/jaudiolib/src/driver_nosound.h | 30 + .../eduke32/source/jaudiolib/src/driver_sdl.c | 231 ++ .../eduke32/source/jaudiolib/src/driver_sdl.h | 30 + .../eduke32/source/jaudiolib/src/drivers.c | 174 + .../eduke32/source/jaudiolib/src/drivers.h | 42 + polymer/eduke32/source/jaudiolib/src/fx_man.c | 1069 ++++++ .../eduke32/source/jaudiolib/src/linklist.h | 118 + polymer/eduke32/source/jaudiolib/src/ll_man.h | 76 + polymer/eduke32/source/jaudiolib/src/mix.c | 353 ++ polymer/eduke32/source/jaudiolib/src/mixst.c | 297 ++ .../eduke32/source/jaudiolib/src/multivoc.c | 2910 +++++++++++++++++ .../eduke32/source/jaudiolib/src/multivoc.h | 119 + polymer/eduke32/source/jaudiolib/src/pitch.c | 187 ++ polymer/eduke32/source/jaudiolib/src/pitch.h | 47 + polymer/eduke32/source/jaudiolib/src/vorbis.c | 424 +++ .../source/jaudiolib/third-party/README.txt | 13 + .../mingw32/include/ogg/config_types.h | 11 + .../third-party/mingw32/include/ogg/ogg.h | 208 ++ .../mingw32/include/ogg/os_types.h | 139 + .../mingw32/include/vorbis/codec.h | 243 ++ .../mingw32/include/vorbis/vorbisfile.h | 206 ++ .../third-party/ogg.framework/Headers | 1 + .../third-party/ogg.framework/Resources | 1 + .../ogg.framework/Versions/A/Headers/ogg.h | 202 ++ .../Versions/A/Headers/os_types.h | 127 + .../Resources/English.lproj/InfoPlist.strings | Bin 0 -> 204 bytes .../Versions/A/Resources/Info.plist | 22 + .../third-party/ogg.framework/Versions/A/ogg | Bin 0 -> 48348 bytes .../ogg.framework/Versions/Current | 1 + .../jaudiolib/third-party/ogg.framework/ogg | 1 + .../third-party/vorbis.framework/Headers | 1 + .../third-party/vorbis.framework/Resources | 1 + .../Versions/A/Headers/codec.h | 240 ++ .../Versions/A/Headers/vorbisenc.h | 112 + .../Versions/A/Headers/vorbisfile.h | 143 + .../Resources/English.lproj/InfoPlist.strings | Bin 0 -> 204 bytes .../Versions/A/Resources/Info.plist | 22 + .../vorbis.framework/Versions/A/vorbis | Bin 0 -> 2639520 bytes .../vorbis.framework/Versions/Current | 1 + .../third-party/vorbis.framework/vorbis | 1 + 51 files changed, 9677 insertions(+) create mode 100644 polymer/eduke32/source/jaudiolib/Makefile create mode 100644 polymer/eduke32/source/jaudiolib/include/fx_man.h create mode 100644 polymer/eduke32/source/jaudiolib/include/music.h create mode 100644 polymer/eduke32/source/jaudiolib/include/sndcards.h create mode 100644 polymer/eduke32/source/jaudiolib/jfaudiolib.xcodeproj/project.pbxproj create mode 100644 polymer/eduke32/source/jaudiolib/src/_multivc.h create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_coreaudio.c create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_coreaudio.h create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_directsound.c create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_directsound.h create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_nosound.c create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_nosound.h create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_sdl.c create mode 100644 polymer/eduke32/source/jaudiolib/src/driver_sdl.h create mode 100644 polymer/eduke32/source/jaudiolib/src/drivers.c create mode 100644 polymer/eduke32/source/jaudiolib/src/drivers.h create mode 100644 polymer/eduke32/source/jaudiolib/src/fx_man.c create mode 100644 polymer/eduke32/source/jaudiolib/src/linklist.h create mode 100644 polymer/eduke32/source/jaudiolib/src/ll_man.h create mode 100644 polymer/eduke32/source/jaudiolib/src/mix.c create mode 100644 polymer/eduke32/source/jaudiolib/src/mixst.c create mode 100644 polymer/eduke32/source/jaudiolib/src/multivoc.c create mode 100644 polymer/eduke32/source/jaudiolib/src/multivoc.h create mode 100644 polymer/eduke32/source/jaudiolib/src/pitch.c create mode 100644 polymer/eduke32/source/jaudiolib/src/pitch.h create mode 100644 polymer/eduke32/source/jaudiolib/src/vorbis.c create mode 100644 polymer/eduke32/source/jaudiolib/third-party/README.txt create mode 100644 polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/config_types.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/ogg.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/os_types.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/codec.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/vorbisfile.h create mode 120000 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Headers create mode 120000 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Resources create mode 100644 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/ogg.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/os_types.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/English.lproj/InfoPlist.strings create mode 100644 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/Info.plist create mode 100755 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/ogg create mode 120000 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/Current create mode 120000 polymer/eduke32/source/jaudiolib/third-party/ogg.framework/ogg create mode 120000 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Headers create mode 120000 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Resources create mode 100644 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/codec.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisenc.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisfile.h create mode 100644 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/English.lproj/InfoPlist.strings create mode 100644 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/Info.plist create mode 100755 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/vorbis create mode 120000 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/Current create mode 120000 polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/vorbis diff --git a/polymer/eduke32/source/jaudiolib/Makefile b/polymer/eduke32/source/jaudiolib/Makefile new file mode 100644 index 000000000..1e025e339 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/Makefile @@ -0,0 +1,47 @@ +CC=gcc +OBJ=obj +OBJNAME?=libjfaudiolib.a +PRETTY_OUTPUT?=1 +EROOT?=build +SRC=src + +include ../../$(EROOT)/Makefile.shared + +CFLAGS=-g -O2 -Wall +CPPFLAGS=-Iinclude -Isrc -DHAVE_VORBIS + +OBJECTS=$(OBJ)/drivers.o \ + $(OBJ)/fx_man.o \ + $(OBJ)/multivoc.o \ + $(OBJ)/mix.o \ + $(OBJ)/mixst.o \ + $(OBJ)/pitch.o \ + $(OBJ)/vorbis.o \ + $(OBJ)/driver_nosound.o + +ifeq ($(PLATFORM),WINDOWS) + CPPFLAGS+= -I/z/sdks/directx/dx7/include -Ithird-party/mingw32/include + OBJECTS+= $(OBJ)/driver_directsound.o + OBJNAME=libjfaudiolib_win32.a + OBJ=obj_win +else + CPPFLAGS+= -DHAVE_SDL + OBJECTS+= $(OBJ)/driver_sdl.o +endif + +# OBJECTS=$(SOURCES:%.c=$(OBJ)/%.o) + +$(OBJNAME): $(OBJECTS) + ar cr $@ $^ + +$(OBJECTS): $(OBJ)/%.o: $(SRC)/%.c + -mkdir -p $(OBJ) + $(COMPILE_STATUS) + if $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@; then $(COMPILE_OK); else $(COMPILE_FAILED); fi + +ifeq ($(PRETTY_OUTPUT),1) +.SILENT: +endif +.PHONY: clean +clean: + -rm -f $(OBJECTS) $(OBJNAME) diff --git a/polymer/eduke32/source/jaudiolib/include/fx_man.h b/polymer/eduke32/source/jaudiolib/include/fx_man.h new file mode 100644 index 000000000..161ed3159 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/include/fx_man.h @@ -0,0 +1,113 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + module: FX_MAN.H + + author: James R. Dose + date: March 17, 1994 + + Public header for FX_MAN.C + + (c) Copyright 1994 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#ifndef __FX_MAN_H +#define __FX_MAN_H + +#include "inttypes.h" +#include "limits.h" +#include "sndcards.h" + +enum FX_ERRORS + { + FX_Warning = -2, + FX_Error = -1, + FX_Ok = 0, + FX_ASSVersion, + FX_SoundCardError, + FX_InvalidCard, + FX_MultiVocError, + }; + +#define FX_MUSIC_PRIORITY INT_MAX + +const char *FX_ErrorString( int32_t ErrorNumber ); +int32_t FX_Init( int32_t SoundCard, int32_t numvoices, int32_t numchannels, int32_t samplebits, unsigned mixrate, void * initdata ); +int32_t FX_Shutdown( void ); +int32_t FX_SetCallBack( void ( *function )( uint32_t ) ); +void FX_SetVolume( int32_t volume ); +int32_t FX_GetVolume( void ); + +void FX_SetReverseStereo( int32_t setting ); +int32_t FX_GetReverseStereo( void ); +void FX_SetReverb( int32_t reverb ); +void FX_SetFastReverb( int32_t reverb ); +int32_t FX_GetMaxReverbDelay( void ); +int32_t FX_GetReverbDelay( void ); +void FX_SetReverbDelay( int32_t delay ); + +int32_t FX_PauseVoice ( int32_t handle, int32_t pause ); +int32_t FX_VoiceAvailable( int32_t priority ); +int32_t FX_EndLooping( int32_t handle ); +int32_t FX_SetPan( int32_t handle, int32_t vol, int32_t left, int32_t right ); +int32_t FX_SetPitch( int32_t handle, int32_t pitchoffset ); +int32_t FX_SetFrequency( int32_t handle, int32_t frequency ); + +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_PlayAuto( char *ptr, uint32_t ptrlength, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, + int32_t priority, uint32_t callbackval ); +int32_t FX_PlayLoopedAuto( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, + int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, + uint32_t callbackval ); +int32_t FX_PlayAuto3D( char *ptr, uint32_t ptrlength, int32_t 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 ); +int32_t FX_Pan3D( int32_t handle, int32_t angle, int32_t distance ); +int32_t FX_SoundActive( int32_t handle ); +int32_t FX_SoundsPlaying( void ); +int32_t FX_StopSound( int32_t handle ); +int32_t FX_StopAllSounds( void ); +int32_t FX_StartDemandFeedPlayback( void ( *function )( char **ptr, uint32_t *length ), + int32_t rate, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, + int32_t priority, uint32_t callbackval ); +int32_t FX_StartRecording( int32_t MixRate, void ( *function )( char *ptr, int32_t length ) ); +void FX_StopRecord( void ); + +#endif diff --git a/polymer/eduke32/source/jaudiolib/include/music.h b/polymer/eduke32/source/jaudiolib/include/music.h new file mode 100644 index 000000000..56942790d --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/include/music.h @@ -0,0 +1,93 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + module: MUSIC.H + + author: James R. Dose + date: March 25, 1994 + + Public header for MUSIC.C + + (c) Copyright 1994 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#ifndef __MUSIC_H +#define __MUSIC_H + +#include "inttypes.h" +#include "sndcards.h" + +extern int32_t MUSIC_ErrorCode; + +enum MUSIC_ERRORS + { + MUSIC_Warning = -2, + MUSIC_Error = -1, + MUSIC_Ok = 0, + MUSIC_ASSVersion, + MUSIC_SoundCardError, + MUSIC_MPU401Error, + MUSIC_InvalidCard, + MUSIC_MidiError, + MUSIC_TaskManError, + MUSIC_FMNotDetected, + MUSIC_DPMI_Error + }; + +typedef struct + { + uint32_t tickposition; + uint32_t milliseconds; + uint32_t measure; + uint32_t beat; + uint32_t tick; + } songposition; + +#define MUSIC_LoopSong ( 1 == 1 ) +#define MUSIC_PlayOnce ( !MUSIC_LoopSong ) + +char *MUSIC_ErrorString( int32_t ErrorNumber ); +int32_t MUSIC_Init( int32_t SoundCard, int32_t Address ); +int32_t MUSIC_Shutdown( void ); +void MUSIC_SetMaxFMMidiChannel( int32_t channel ); +void MUSIC_SetVolume( int32_t volume ); +void MUSIC_SetMidiChannelVolume( int32_t channel, int32_t volume ); +void MUSIC_ResetMidiChannelVolumes( void ); +int32_t MUSIC_GetVolume( void ); +void MUSIC_SetLoopFlag( int32_t loopflag ); +int32_t MUSIC_SongPlaying( void ); +void MUSIC_Continue( void ); +void MUSIC_Pause( void ); +int32_t MUSIC_StopSong( void ); +int32_t MUSIC_PlaySong( uint8_t *song, int32_t loopflag ); +void MUSIC_SetContext( int32_t context ); +int32_t MUSIC_GetContext( void ); +void MUSIC_SetSongTick( uint32_t PositionInTicks ); +void MUSIC_SetSongTime( uint32_t milliseconds ); +void MUSIC_SetSongPosition( int32_t measure, int32_t beat, int32_t tick ); +void MUSIC_GetSongPosition( songposition *pos ); +void MUSIC_GetSongLength( songposition *pos ); +int32_t MUSIC_FadeVolume( int32_t tovolume, int32_t milliseconds ); +int32_t MUSIC_FadeActive( void ); +void MUSIC_StopFade( void ); +void MUSIC_RerouteMidiChannel( int32_t channel, int32_t ( *function )( int32_t event, int32_t c1, int32_t c2 ) ); +void MUSIC_RegisterTimbreBank( uint8_t *timbres ); + +#endif diff --git a/polymer/eduke32/source/jaudiolib/include/sndcards.h b/polymer/eduke32/source/jaudiolib/include/sndcards.h new file mode 100644 index 000000000..31cd6a858 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/include/sndcards.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + 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 + +#define ASS_VERSION_STRING "JonoF 20090718" + +typedef enum + { + ASS_NoSound, + ASS_SDL, + ASS_CoreAudio, + ASS_DirectSound, + ASS_NumSoundCards, + ASS_AutoDetect = -2 + } soundcardnames; + +#endif diff --git a/polymer/eduke32/source/jaudiolib/jfaudiolib.xcodeproj/project.pbxproj b/polymer/eduke32/source/jaudiolib/jfaudiolib.xcodeproj/project.pbxproj new file mode 100644 index 000000000..88ded1e65 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/jfaudiolib.xcodeproj/project.pbxproj @@ -0,0 +1,307 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + AB2E9E5F1011E65900DD2F1F /* _multivc.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E4D1011E65900DD2F1F /* _multivc.h */; }; + AB2E9E601011E65900DD2F1F /* driver_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2E9E4E1011E65900DD2F1F /* driver_coreaudio.c */; }; + AB2E9E611011E65900DD2F1F /* driver_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E4F1011E65900DD2F1F /* driver_coreaudio.h */; }; + AB2E9E641011E65900DD2F1F /* driver_nosound.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2E9E521011E65900DD2F1F /* driver_nosound.c */; }; + AB2E9E651011E65900DD2F1F /* driver_nosound.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E531011E65900DD2F1F /* driver_nosound.h */; }; + AB2E9E681011E65900DD2F1F /* drivers.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2E9E561011E65900DD2F1F /* drivers.c */; }; + AB2E9E691011E65900DD2F1F /* drivers.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E571011E65900DD2F1F /* drivers.h */; }; + AB2E9E6A1011E65900DD2F1F /* fx_man.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2E9E581011E65900DD2F1F /* fx_man.c */; }; + AB2E9E6B1011E65900DD2F1F /* linklist.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E591011E65900DD2F1F /* linklist.h */; }; + AB2E9E6C1011E65900DD2F1F /* ll_man.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E5A1011E65900DD2F1F /* ll_man.h */; }; + AB2E9E6D1011E65900DD2F1F /* multivoc.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2E9E5B1011E65900DD2F1F /* multivoc.c */; }; + AB2E9E6E1011E65900DD2F1F /* multivoc.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E5C1011E65900DD2F1F /* multivoc.h */; }; + AB2E9E6F1011E65900DD2F1F /* pitch.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2E9E5D1011E65900DD2F1F /* pitch.c */; }; + AB2E9E701011E65900DD2F1F /* pitch.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E5E1011E65900DD2F1F /* pitch.h */; }; + AB2E9E741011E66100DD2F1F /* fx_man.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E711011E66100DD2F1F /* fx_man.h */; }; + AB2E9E751011E66100DD2F1F /* music.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E721011E66100DD2F1F /* music.h */; }; + AB2E9E761011E66100DD2F1F /* sndcards.h in Headers */ = {isa = PBXBuildFile; fileRef = AB2E9E731011E66100DD2F1F /* sndcards.h */; }; + AB2EA0831012029200DD2F1F /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB2EA0821012029200DD2F1F /* AudioUnit.framework */; }; + AB2EA17710121AA900DD2F1F /* mix.c in Sources */ = {isa = PBXBuildFile; fileRef = AB2EA17610121AA900DD2F1F /* mix.c */; }; + AB8C5612101A077700B42306 /* mixst.c in Sources */ = {isa = PBXBuildFile; fileRef = AB8C5611101A077700B42306 /* mixst.c */; }; + AB8C5828101B6B7100B42306 /* ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C5826101B6B7100B42306 /* ogg.framework */; }; + AB8C5829101B6B7100B42306 /* vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C5827101B6B7100B42306 /* vorbis.framework */; }; + AB8C5868101B6D7500B42306 /* vorbis.c in Sources */ = {isa = PBXBuildFile; fileRef = AB8C5867101B6D7500B42306 /* vorbis.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + AB2E9E421011E61700DD2F1F /* libjfaudiolib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjfaudiolib.a; sourceTree = BUILT_PRODUCTS_DIR; }; + AB2E9E4D1011E65900DD2F1F /* _multivc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _multivc.h; sourceTree = ""; }; + AB2E9E4E1011E65900DD2F1F /* driver_coreaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = driver_coreaudio.c; sourceTree = ""; }; + AB2E9E4F1011E65900DD2F1F /* driver_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = driver_coreaudio.h; sourceTree = ""; }; + AB2E9E521011E65900DD2F1F /* driver_nosound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = driver_nosound.c; sourceTree = ""; }; + AB2E9E531011E65900DD2F1F /* driver_nosound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = driver_nosound.h; sourceTree = ""; }; + AB2E9E561011E65900DD2F1F /* drivers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = drivers.c; sourceTree = ""; }; + AB2E9E571011E65900DD2F1F /* drivers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drivers.h; sourceTree = ""; }; + AB2E9E581011E65900DD2F1F /* fx_man.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fx_man.c; sourceTree = ""; }; + AB2E9E591011E65900DD2F1F /* linklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linklist.h; sourceTree = ""; }; + AB2E9E5A1011E65900DD2F1F /* ll_man.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ll_man.h; sourceTree = ""; }; + AB2E9E5B1011E65900DD2F1F /* multivoc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = multivoc.c; sourceTree = ""; }; + AB2E9E5C1011E65900DD2F1F /* multivoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multivoc.h; sourceTree = ""; }; + AB2E9E5D1011E65900DD2F1F /* pitch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pitch.c; sourceTree = ""; }; + AB2E9E5E1011E65900DD2F1F /* pitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pitch.h; sourceTree = ""; }; + AB2E9E711011E66100DD2F1F /* fx_man.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fx_man.h; sourceTree = ""; }; + AB2E9E721011E66100DD2F1F /* music.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music.h; sourceTree = ""; }; + AB2E9E731011E66100DD2F1F /* sndcards.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sndcards.h; sourceTree = ""; }; + AB2EA0821012029200DD2F1F /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = ""; }; + AB2EA17610121AA900DD2F1F /* mix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mix.c; sourceTree = ""; }; + AB8C5611101A077700B42306 /* mixst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mixst.c; sourceTree = ""; }; + AB8C5826101B6B7100B42306 /* ogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ogg.framework; path = "third-party/ogg.framework"; sourceTree = ""; }; + AB8C5827101B6B7100B42306 /* vorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = vorbis.framework; path = "third-party/vorbis.framework"; sourceTree = ""; }; + AB8C5867101B6D7500B42306 /* vorbis.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + AB2E9E401011E61600DD2F1F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2EA0831012029200DD2F1F /* AudioUnit.framework in Frameworks */, + AB8C5828101B6B7100B42306 /* ogg.framework in Frameworks */, + AB8C5829101B6B7100B42306 /* vorbis.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + AB2E9E301011E60300DD2F1F = { + isa = PBXGroup; + children = ( + AB8C582E101B6B7900B42306 /* Linked frameworks */, + AB2E9E481011E63F00DD2F1F /* include */, + AB2E9E471011E63900DD2F1F /* src */, + AB2E9E431011E61700DD2F1F /* Products */, + ); + sourceTree = ""; + }; + AB2E9E431011E61700DD2F1F /* Products */ = { + isa = PBXGroup; + children = ( + AB2E9E421011E61700DD2F1F /* libjfaudiolib.a */, + ); + name = Products; + sourceTree = ""; + }; + AB2E9E471011E63900DD2F1F /* src */ = { + isa = PBXGroup; + children = ( + AB2E9E4D1011E65900DD2F1F /* _multivc.h */, + AB2E9E4E1011E65900DD2F1F /* driver_coreaudio.c */, + AB2E9E4F1011E65900DD2F1F /* driver_coreaudio.h */, + AB2E9E521011E65900DD2F1F /* driver_nosound.c */, + AB2E9E531011E65900DD2F1F /* driver_nosound.h */, + AB2E9E561011E65900DD2F1F /* drivers.c */, + AB2E9E571011E65900DD2F1F /* drivers.h */, + AB2E9E581011E65900DD2F1F /* fx_man.c */, + AB2E9E591011E65900DD2F1F /* linklist.h */, + AB2E9E5A1011E65900DD2F1F /* ll_man.h */, + AB2E9E5B1011E65900DD2F1F /* multivoc.c */, + AB2E9E5C1011E65900DD2F1F /* multivoc.h */, + AB2E9E5D1011E65900DD2F1F /* pitch.c */, + AB2E9E5E1011E65900DD2F1F /* pitch.h */, + AB2EA17610121AA900DD2F1F /* mix.c */, + AB8C5611101A077700B42306 /* mixst.c */, + AB8C5867101B6D7500B42306 /* vorbis.c */, + ); + path = src; + sourceTree = ""; + }; + AB2E9E481011E63F00DD2F1F /* include */ = { + isa = PBXGroup; + children = ( + AB2E9E711011E66100DD2F1F /* fx_man.h */, + AB2E9E721011E66100DD2F1F /* music.h */, + AB2E9E731011E66100DD2F1F /* sndcards.h */, + ); + path = include; + sourceTree = ""; + }; + AB8C582E101B6B7900B42306 /* Linked frameworks */ = { + isa = PBXGroup; + children = ( + AB2EA0821012029200DD2F1F /* AudioUnit.framework */, + AB8C5827101B6B7100B42306 /* vorbis.framework */, + AB8C5826101B6B7100B42306 /* ogg.framework */, + ); + name = "Linked frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + AB2E9E3E1011E61600DD2F1F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2E9E5F1011E65900DD2F1F /* _multivc.h in Headers */, + AB2E9E611011E65900DD2F1F /* driver_coreaudio.h in Headers */, + AB2E9E651011E65900DD2F1F /* driver_nosound.h in Headers */, + AB2E9E691011E65900DD2F1F /* drivers.h in Headers */, + AB2E9E6B1011E65900DD2F1F /* linklist.h in Headers */, + AB2E9E6C1011E65900DD2F1F /* ll_man.h in Headers */, + AB2E9E6E1011E65900DD2F1F /* multivoc.h in Headers */, + AB2E9E701011E65900DD2F1F /* pitch.h in Headers */, + AB2E9E741011E66100DD2F1F /* fx_man.h in Headers */, + AB2E9E751011E66100DD2F1F /* music.h in Headers */, + AB2E9E761011E66100DD2F1F /* sndcards.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + AB2E9E411011E61600DD2F1F /* jfaudiolib */ = { + isa = PBXNativeTarget; + buildConfigurationList = AB2E9E441011E61900DD2F1F /* Build configuration list for PBXNativeTarget "jfaudiolib" */; + buildPhases = ( + AB2E9E3E1011E61600DD2F1F /* Headers */, + AB2E9E3F1011E61600DD2F1F /* Sources */, + AB2E9E401011E61600DD2F1F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = jfaudiolib; + productName = jfaudiolib; + productReference = AB2E9E421011E61700DD2F1F /* libjfaudiolib.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + AB2E9E321011E60300DD2F1F /* Project object */ = { + isa = PBXProject; + buildConfigurationList = AB2E9E331011E60300DD2F1F /* Build configuration list for PBXProject "jfaudiolib" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 0; + mainGroup = AB2E9E301011E60300DD2F1F; + productRefGroup = AB2E9E431011E61700DD2F1F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + AB2E9E411011E61600DD2F1F /* jfaudiolib */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + AB2E9E3F1011E61600DD2F1F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2E9E601011E65900DD2F1F /* driver_coreaudio.c in Sources */, + AB2E9E641011E65900DD2F1F /* driver_nosound.c in Sources */, + AB2E9E681011E65900DD2F1F /* drivers.c in Sources */, + AB2E9E6A1011E65900DD2F1F /* fx_man.c in Sources */, + AB2E9E6D1011E65900DD2F1F /* multivoc.c in Sources */, + AB2E9E6F1011E65900DD2F1F /* pitch.c in Sources */, + AB2EA17710121AA900DD2F1F /* mix.c in Sources */, + AB8C5612101A077700B42306 /* mixst.c in Sources */, + AB8C5868101B6D7500B42306 /* vorbis.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + AB2E9E341011E60300DD2F1F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "third-party"; + GCC_PREPROCESSOR_DEFINITIONS = __MACOSX__; + GCC_VERSION_i386 = 4.0; + GCC_VERSION_ppc = 4.0; + MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; + MACOSX_DEPLOYMENT_TARGET_ppc = 10.3; + SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk; + SDKROOT_ppc = /Developer/SDKs/MacOSX10.3.9.sdk; + }; + name = Debug; + }; + AB2E9E351011E60300DD2F1F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = "third-party"; + GCC_PREPROCESSOR_DEFINITIONS = __MACOSX__; + GCC_VERSION_i386 = 4.0; + GCC_VERSION_ppc = 4.0; + MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; + MACOSX_DEPLOYMENT_TARGET_ppc = 10.3; + SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk; + SDKROOT_ppc = /Developer/SDKs/MacOSX10.3.9.sdk; + }; + name = Release; + }; + AB2E9E451011E61900DD2F1F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + PREBINDING = NO; + PRODUCT_NAME = jfaudiolib; + ZERO_LINK = YES; + }; + name = Debug; + }; + AB2E9E461011E61900DD2F1F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + PREBINDING = NO; + PRODUCT_NAME = jfaudiolib; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + AB2E9E331011E60300DD2F1F /* Build configuration list for PBXProject "jfaudiolib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB2E9E341011E60300DD2F1F /* Debug */, + AB2E9E351011E60300DD2F1F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AB2E9E441011E61900DD2F1F /* Build configuration list for PBXNativeTarget "jfaudiolib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AB2E9E451011E61900DD2F1F /* Debug */, + AB2E9E461011E61900DD2F1F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = AB2E9E321011E60300DD2F1F /* Project object */; +} diff --git a/polymer/eduke32/source/jaudiolib/src/_multivc.h b/polymer/eduke32/source/jaudiolib/src/_multivc.h new file mode 100644 index 000000000..d05675f78 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/_multivc.h @@ -0,0 +1,320 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + file: _MULTIVC.H + + author: James R. Dose + date: December 20, 1993 + + Private header for MULTIVOC.C + + (c) Copyright 1993 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#include "limits.h" +#include "inttypes.h" + +#ifndef ___MULTIVC_H +#define ___MULTIVC_H + +#define TRUE ( 1 == 1 ) +#define FALSE ( !TRUE ) + +#define VOC_8BIT 0x0 +#define VOC_CT4_ADPCM 0x1 +#define VOC_CT3_ADPCM 0x2 +#define VOC_CT2_ADPCM 0x3 +#define VOC_16BIT 0x4 +#define VOC_ALAW 0x6 +#define VOC_MULAW 0x7 +#define VOC_CREATIVE_ADPCM 0x200 + +#define T_SIXTEENBIT_STEREO 0 +#define T_8BITS 1 +#define T_MONO 2 +#define T_16BITSOURCE 4 +#define T_STEREOSOURCE 8 +#define T_LEFTQUIET 16 +#define T_RIGHTQUIET 32 +#define T_DEFAULT T_SIXTEENBIT_STEREO + +#define MV_MaxPanPosition 127 +#define MV_NumPanPositions ( MV_MaxPanPosition + 1 ) +#define MV_MaxTotalVolume 255 +//#define MV_MaxVolume 63 +#define MV_NumVoices 8 + +// mirrors FX_MUSIC_PRIORITY from fx_man.h +#define MV_MUSIC_PRIORITY INT_MAX + +#define MIX_VOLUME( volume ) \ + ( ( max( 0, min( ( volume ), 255 ) ) * ( MV_MaxVolume + 1 ) ) >> 8 ) +// ( ( max( 0, min( ( volume ), 255 ) ) ) >> 2 ) + +#define STEREO 1 +#define SIXTEEN_BIT 2 + +#define MONO_8BIT 0 +#define STEREO_8BIT ( STEREO ) +#define MONO_16BIT ( SIXTEEN_BIT ) +#define STEREO_16BIT ( STEREO | SIXTEEN_BIT ) + +#define MONO_8BIT_SAMPLE_SIZE 1 +#define MONO_16BIT_SAMPLE_SIZE 2 +#define STEREO_8BIT_SAMPLE_SIZE ( 2 * MONO_8BIT_SAMPLE_SIZE ) +#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE ) + +//#define SILENCE_16BIT 0x80008000 +#define SILENCE_16BIT 0 +#define SILENCE_8BIT 0x80808080 +//#define SILENCE_16BIT_PAS 0 + +#define MixBufferSize 256 + +#define NumberOfBuffers 16 +#define TotalBufferSize ( MixBufferSize * NumberOfBuffers ) + +#define PI 3.1415926536 + +typedef enum + { + Raw, + VOC, + DemandFeed, + WAV, + Vorbis + } wavedata; + +typedef enum + { + NoMoreData, + KeepPlaying + } playbackstatus; + + +typedef struct VoiceNode + { + struct VoiceNode *next; + struct VoiceNode *prev; + + wavedata wavetype; + char bits; + char channels; + + playbackstatus ( *GetSound )( struct VoiceNode *voice ); + + void ( *mix )( uint32_t position, uint32_t rate, + char *start, uint32_t length ); + + char *NextBlock; + char *LoopStart; + char *LoopEnd; + unsigned LoopCount; + uint32_t LoopSize; + uint32_t BlockLength; + + uint32_t PitchScale; + uint32_t FixedPointBufferSize; + + char *sound; + uint32_t length; + uint32_t SamplingRate; + uint32_t RateScale; + uint32_t position; + int32_t Playing; + int32_t Paused; + + int32_t handle; + int32_t priority; + + void ( *DemandFeed )( char **ptr, uint32_t *length ); + void *extra; + + int16_t *LeftVolume; + int16_t *RightVolume; + + uint32_t callbackval; + + } VoiceNode; + +typedef struct + { + VoiceNode *start; + VoiceNode *end; + } VList; + +typedef struct + { + uint8_t left; + uint8_t right; + } 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 + { + char RIFF[ 4 ]; + uint32_t file_size; + char WAVE[ 4 ]; + char fmt[ 4 ]; + uint32_t format_size; + } riff_header; + +typedef struct + { + uint16_t wFormatTag; + uint16_t nChannels; + uint32_t nSamplesPerSec; + uint32_t nAvgBytesPerSec; + uint16_t nBlockAlign; + uint16_t nBitsPerSample; + } format_header; + +typedef struct + { + uint8_t DATA[ 4 ]; + uint32_t size; + } data_header; + +typedef MONO8 VOLUME8[ 256 ]; +typedef MONO16 VOLUME16[ 256 ]; + +extern Pan MV_PanTable[ MV_NumPanPositions ][ 255 + 1 ]; +extern int32_t MV_ErrorCode; +extern int32_t MV_Installed; +extern int32_t MV_MaxVolume; +extern int32_t MV_MixRate; +typedef char HARSH_CLIP_TABLE_8[ MV_NumVoices * 256 ]; + +#define MV_SetErrorCode( status ) \ + MV_ErrorCode = ( status ); + +static void MV_Mix( VoiceNode *voice, int32_t buffer ); +void MV_PlayVoice( VoiceNode *voice ); +static void MV_StopVoice( VoiceNode *voice ); +static void MV_ServiceVoc( void ); + +static playbackstatus MV_GetNextVOCBlock( VoiceNode *voice ); +static playbackstatus MV_GetNextDemandFeedBlock( VoiceNode *voice ); +static playbackstatus MV_GetNextRawBlock( VoiceNode *voice ); +static playbackstatus MV_GetNextWAVBlock( VoiceNode *voice ); +static playbackstatus MV_GetNextVorbisBlock( VoiceNode *voice ); + +static void MV_ServiceRecord( void ); +static VoiceNode *MV_GetVoice( int32_t handle ); +VoiceNode *MV_AllocVoice( int32_t priority ); + +static int16_t *MV_GetVolumeTable( int32_t vol ); + +void MV_SetVoiceMixMode( VoiceNode *voice ); +void MV_SetVoiceVolume ( VoiceNode *voice, int32_t vol, int32_t left, int32_t right ); + +static void MV_SetVoicePitch( VoiceNode *voice, uint32_t rate, int32_t pitchoffset ); +static void MV_CalcVolume( int32_t MaxLevel ); +static void MV_CalcPanTable( void ); + +void MV_ReleaseVorbisVoice( VoiceNode * voice ); + +// implemented in mix.c +void ClearBuffer_DW( void *ptr, unsigned data, int32_t length ); + +void MV_Mix8BitMono( uint32_t position, uint32_t rate, + char *start, uint32_t length ); + +void MV_Mix8BitStereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitMono( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitStereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitMono16( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix8BitMono16( uint32_t position, uint32_t rate, + char *start, uint32_t length ); + +void MV_Mix8BitStereo16( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitStereo16( uint32_t position, + uint32_t rate, 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 +void ClearBuffer_DW( void *ptr, unsigned data, int32_t length ); + +void MV_Mix8BitMono8Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ); + +void MV_Mix8BitStereo8Stereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitMono8Stereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitStereo8Stereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitMono16Stereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix8BitMono16Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ); + +void MV_Mix8BitStereo16Stereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +void MV_Mix16BitStereo16Stereo( uint32_t position, + uint32_t rate, char *start, uint32_t length ); + +#endif diff --git a/polymer/eduke32/source/jaudiolib/src/driver_coreaudio.c b/polymer/eduke32/source/jaudiolib/src/driver_coreaudio.c new file mode 100644 index 000000000..6aee6ba24 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_coreaudio.c @@ -0,0 +1,339 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +/** + * CoreAudio output driver for MultiVoc + * + * Inspired by the example set by the Audiere sound library available at + * https://audiere.svn.sourceforge.net/svnroot/audiere/trunk/audiere/ + * + */ + +#include +#include +#include "driver_coreaudio.h" + +enum { + CAErr_Warning = -2, + CAErr_Error = -1, + CAErr_Ok = 0, + CAErr_Uninitialised, + CAErr_FindNextComponent, + CAErr_OpenAComponent, + CAErr_AudioUnitInitialize, + CAErr_AudioUnitSetProperty, + CAErr_Mutex +}; + +static int32_t ErrorCode = CAErr_Ok; +static int32_t Initialised = 0; +static int32_t Playing = 0; +static ComponentInstance output_audio_unit; +static pthread_mutex_t mutex; + +static char *MixBuffer = 0; +static int32_t MixBufferSize = 0; +static int32_t MixBufferCount = 0; +static int32_t MixBufferCurrent = 0; +static int32_t MixBufferUsed = 0; +static void ( *MixCallBack )( void ) = 0; + +static OSStatus fillInput( + void *inRefCon, + AudioUnitRenderActionFlags inActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + AudioBuffer *ioData) +{ + UInt32 remaining, len; + char *ptr, *sptr; + + remaining = ioData->mDataByteSize; + ptr = ioData->mData; + + while (remaining > 0) { + if (MixBufferUsed == MixBufferSize) { + CoreAudioDrv_Lock(); + MixCallBack(); + CoreAudioDrv_Unlock(); + + MixBufferUsed = 0; + MixBufferCurrent++; + if (MixBufferCurrent >= MixBufferCount) { + MixBufferCurrent -= MixBufferCount; + } + } + + while (remaining > 0 && MixBufferUsed < MixBufferSize) { + sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed; + + len = MixBufferSize - MixBufferUsed; + if (remaining < len) { + len = remaining; + } + + memcpy(ptr, sptr, len); + + ptr += len; + MixBufferUsed += len; + remaining -= len; + } + } + + return noErr; +} + +int32_t CoreAudioDrv_GetError(void) +{ + return ErrorCode; +} + +const char *CoreAudioDrv_ErrorString( int32_t ErrorNumber ) +{ + const char *ErrorString; + + switch( ErrorNumber ) + { + case CAErr_Warning : + case CAErr_Error : + ErrorString = CoreAudioDrv_ErrorString( ErrorCode ); + break; + + case CAErr_Ok : + ErrorString = "CoreAudio ok."; + break; + + case CAErr_Uninitialised: + ErrorString = "CoreAudio uninitialised."; + break; + + case CAErr_FindNextComponent: + ErrorString = "CoreAudio error: FindNextComponent returned NULL."; + break; + + case CAErr_OpenAComponent: + ErrorString = "CoreAudio error: OpenAComponent failed."; + break; + + case CAErr_AudioUnitInitialize: + ErrorString = "CoreAudio error: AudioUnitInitialize failed."; + break; + + case CAErr_AudioUnitSetProperty: + ErrorString = "CoreAudio error: AudioUnitSetProperty failed."; + break; + + case CAErr_Mutex: + ErrorString = "CoreAudio error: could not initialise mutex."; + break; + + default: + ErrorString = "Unknown CoreAudio error code."; + break; + } + + return ErrorString; +} + +/* +int32_t CoreAudioDrv_InitMIDI() +{ + AudioStreamBasicDescription requestedDesc; + + requestedDesc.mFormatID = kAudioFormatMIDIStream; +} + */ + +int32_t CoreAudioDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata) +{ + OSStatus result = noErr; + Component comp; + ComponentDescription desc; + AudioStreamBasicDescription requestedDesc; + struct AudioUnitInputCallback callback; + + if (Initialised) { + CoreAudioDrv_Shutdown(); + } + + if (pthread_mutex_init(&mutex, 0) < 0) { + ErrorCode = CAErr_Mutex; + return CAErr_Error; + } + + // Setup a AudioStreamBasicDescription with the requested format + requestedDesc.mFormatID = kAudioFormatLinearPCM; + requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; + requestedDesc.mChannelsPerFrame = numchannels; + requestedDesc.mSampleRate = mixrate; + + requestedDesc.mBitsPerChannel = samplebits; + if (samplebits == 16) { + requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; +#ifdef __POWERPC__ + requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; +#endif + } + + requestedDesc.mFramesPerPacket = 1; + requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * \ + requestedDesc.mChannelsPerFrame / 8; + requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * \ + requestedDesc.mFramesPerPacket; + + // Locate the default output audio unit + desc.componentType = kAudioUnitComponentType; + desc.componentSubType = kAudioUnitSubType_Output; + desc.componentManufacturer = kAudioUnitID_DefaultOutput; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + comp = FindNextComponent(NULL, &desc); + if (comp == NULL) { + ErrorCode = CAErr_FindNextComponent; + pthread_mutex_destroy(&mutex); + return CAErr_Error; + } + + // Open & initialize the default output audio unit + result = OpenAComponent(comp, &output_audio_unit); + if (result != noErr) { + ErrorCode = CAErr_OpenAComponent; + CloseComponent(output_audio_unit); + pthread_mutex_destroy(&mutex); + return CAErr_Error; + } + + result = AudioUnitInitialize(output_audio_unit); + if (result != noErr) { + ErrorCode = CAErr_AudioUnitInitialize; + CloseComponent(output_audio_unit); + pthread_mutex_destroy(&mutex); + return CAErr_Error; + } + + // Set the input format of the audio unit. + result = AudioUnitSetProperty(output_audio_unit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &requestedDesc, + sizeof(requestedDesc)); + if (result != noErr) { + ErrorCode = CAErr_AudioUnitSetProperty; + CloseComponent(output_audio_unit); + pthread_mutex_destroy(&mutex); + return CAErr_Error; + } + + // Set the audio callback + callback.inputProc = fillInput; + callback.inputProcRefCon = 0; + AudioUnitSetProperty(output_audio_unit, + kAudioUnitProperty_SetInputCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)); + + Initialised = 1; + + return CAErr_Ok; +} + +void CoreAudioDrv_Shutdown(void) +{ + OSStatus result; + struct AudioUnitInputCallback callback; + + if (!Initialised) { + return; + } + + // stop processing the audio unit + CoreAudioDrv_StopPlayback(); + + // Remove the input callback + callback.inputProc = 0; + callback.inputProcRefCon = 0; + result = AudioUnitSetProperty(output_audio_unit, + kAudioUnitProperty_SetInputCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)); + result = CloseComponent(output_audio_unit); + + pthread_mutex_destroy(&mutex); + + Initialised = 0; +} + +int32_t CoreAudioDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ) +{ + if (!Initialised) { + ErrorCode = CAErr_Uninitialised; + return CAErr_Error; + } + + if (Playing) { + CoreAudioDrv_StopPlayback(); + } + + MixBuffer = BufferStart; + MixBufferSize = BufferSize; + MixBufferCount = NumDivisions; + MixBufferCurrent = 0; + MixBufferUsed = 0; + MixCallBack = CallBackFunc; + + // prime the buffer + MixCallBack(); + + AudioOutputUnitStart(output_audio_unit); + + Playing = 1; + + return CAErr_Ok; +} + +void CoreAudioDrv_StopPlayback(void) +{ + if (!Initialised || !Playing) { + return; + } + + CoreAudioDrv_Lock(); + AudioOutputUnitStop(output_audio_unit); + CoreAudioDrv_Unlock(); + + Playing = 0; +} + +void CoreAudioDrv_Lock(void) +{ + pthread_mutex_lock(&mutex); +} + +void CoreAudioDrv_Unlock(void) +{ + pthread_mutex_unlock(&mutex); +} diff --git a/polymer/eduke32/source/jaudiolib/src/driver_coreaudio.h b/polymer/eduke32/source/jaudiolib/src/driver_coreaudio.h new file mode 100644 index 000000000..48df3e352 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_coreaudio.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +int32_t CoreAudioDrv_GetError(void); +const char *CoreAudioDrv_ErrorString( int32_t ErrorNumber ); +int32_t CoreAudioDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata); +void CoreAudioDrv_Shutdown(void); +int32_t CoreAudioDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ); +void CoreAudioDrv_StopPlayback(void); +void CoreAudioDrv_Lock(void); +void CoreAudioDrv_Unlock(void); \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/src/driver_directsound.c b/polymer/eduke32/source/jaudiolib/src/driver_directsound.c new file mode 100644 index 000000000..9a413564f --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_directsound.c @@ -0,0 +1,487 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +/** + * DirectSound output driver for MultiVoc + */ + +#define WIN32_LEAN_AND_MEAN +#define DIRECTSOUND_VERSION 0x0700 +#include +#include +#include +#include +#include + +#include "driver_directsound.h" + +enum { + DSErr_Warning = -2, + DSErr_Error = -1, + DSErr_Ok = 0, + DSErr_Uninitialised, + DSErr_DirectSoundCreate, + DSErr_SetCooperativeLevel, + DSErr_CreateSoundBuffer, + DSErr_CreateSoundBufferSecondary, + DSErr_SetFormat, + DSErr_SetFormatSecondary, + DSErr_Notify, + DSErr_NotifyEvents, + DSErr_SetNotificationPositions, + DSErr_Play, + DSErr_PlaySecondary, + DSErr_CreateThread, + DSErr_CreateMutex +}; + +static int32_t ErrorCode = DSErr_Ok; +static int32_t Initialised = 0; +static int32_t Playing = 0; + +static char *MixBuffer = 0; +static int32_t MixBufferSize = 0; +static int32_t MixBufferCount = 0; +static int32_t MixBufferCurrent = 0; +static int32_t MixBufferUsed = 0; +static void ( *MixCallBack )( void ) = 0; + +static LPDIRECTSOUND lpds = 0; +static LPDIRECTSOUNDBUFFER lpdsbprimary = 0, lpdsbsec = 0; +static LPDIRECTSOUNDNOTIFY lpdsnotify = 0; +static DSBPOSITIONNOTIFY notifyPositions[3] = { { 0,0 }, { 0,0 }, { 0,0 } }; +static HANDLE mixThread = 0; +static HANDLE mutex = 0; + + +static void FillBufferPortion(char * ptr, int32_t remaining) +{ + int32_t len; + char *sptr; + + while (remaining > 0) { + if (MixBufferUsed == MixBufferSize) { + MixCallBack(); + + MixBufferUsed = 0; + MixBufferCurrent++; + if (MixBufferCurrent >= MixBufferCount) { + MixBufferCurrent -= MixBufferCount; + } + } + + while (remaining > 0 && MixBufferUsed < MixBufferSize) { + sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed; + + len = MixBufferSize - MixBufferUsed; + if (remaining < len) { + len = remaining; + } + + memcpy(ptr, sptr, len); + + ptr += len; + MixBufferUsed += len; + remaining -= len; + } + } +} + +static void FillBuffer(int32_t bufnum) +{ + HRESULT err; + LPVOID ptr, ptr2; + DWORD remaining, remaining2; + int32_t retries = 1; + + //fprintf(stderr, "DirectSound FillBuffer: filling %d\n", bufnum); + + do { + err = IDirectSoundBuffer_Lock(lpdsbsec, + notifyPositions[bufnum].dwOffset, + notifyPositions[1].dwOffset, + &ptr, &remaining, + &ptr2, &remaining2, + 0); + if (FAILED(err)) { + if (err == DSERR_BUFFERLOST) { + err = IDirectSoundBuffer_Restore(lpdsbsec); + if (FAILED(err)) { + return; + } + + if (retries-- > 0) { + continue; + } + } + fprintf(stderr, "DirectSound FillBuffer: err %x\n", (uint32_t) err); + return; + } + break; + } while (1); + + if (ptr) { + FillBufferPortion((char *) ptr, remaining); + } + if (ptr2) { + FillBufferPortion((char *) ptr2, remaining2); + } + + IDirectSoundBuffer_Unlock(lpdsbsec, ptr, remaining, ptr2, remaining2); +} + +static DWORD WINAPI fillDataThread(LPVOID lpParameter) +{ + HANDLE handles[3]; + DWORD waitret, waitret2; + + handles[0] = notifyPositions[0].hEventNotify; + handles[1] = notifyPositions[1].hEventNotify; + handles[2] = notifyPositions[2].hEventNotify; + + do { + waitret = WaitForMultipleObjects(3, handles, FALSE, INFINITE); + switch (waitret) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0+1: + waitret2 = WaitForSingleObject(mutex, INFINITE); + if (waitret2 == WAIT_OBJECT_0) { + FillBuffer(WAIT_OBJECT_0 + 1 - waitret); + ReleaseMutex(mutex); + } else { + fprintf(stderr, "DirectSound fillDataThread: wfso err %d\n", (int32_t) waitret2); + } + break; + case WAIT_OBJECT_0+2: + fprintf(stderr, "DirectSound fillDataThread: exiting\n"); + ExitThread(0); + break; + default: + fprintf(stderr, "DirectSound fillDataThread: wfmo err %d\n", (int32_t) waitret); + break; + } + } while (1); + + return 0; +} + + +int32_t DirectSoundDrv_GetError(void) +{ + return ErrorCode; +} + +const char *DirectSoundDrv_ErrorString( int32_t ErrorNumber ) +{ + const char *ErrorString; + + switch( ErrorNumber ) + { + case DSErr_Warning : + case DSErr_Error : + ErrorString = DirectSoundDrv_ErrorString( ErrorCode ); + break; + + case DSErr_Ok : + ErrorString = "DirectSound ok."; + break; + + case DSErr_Uninitialised: + ErrorString = "DirectSound uninitialised."; + break; + + case DSErr_DirectSoundCreate: + ErrorString = "DirectSound error: DirectSoundCreate failed."; + break; + + case DSErr_SetCooperativeLevel: + ErrorString = "DirectSound error: SetCooperativeLevel failed."; + break; + + case DSErr_CreateSoundBuffer: + ErrorString = "DirectSound error: primary CreateSoundBuffer failed."; + break; + + case DSErr_CreateSoundBufferSecondary: + ErrorString = "DirectSound error: secondary CreateSoundBuffer failed."; + break; + + case DSErr_SetFormat: + ErrorString = "DirectSound error: primary buffer SetFormat failed."; + break; + + case DSErr_SetFormatSecondary: + ErrorString = "DirectSound error: secondary buffer SetFormat failed."; + break; + + case DSErr_Notify: + ErrorString = "DirectSound error: failed querying secondary buffer for notify interface."; + break; + + case DSErr_NotifyEvents: + ErrorString = "DirectSound error: failed creating notify events."; + break; + + case DSErr_SetNotificationPositions: + ErrorString = "DirectSound error: failed setting notification positions."; + break; + + case DSErr_Play: + ErrorString = "DirectSound error: primary buffer Play failed."; + break; + + case DSErr_PlaySecondary: + ErrorString = "DirectSound error: secondary buffer Play failed."; + break; + + case DSErr_CreateThread: + ErrorString = "DirectSound error: failed creating mix thread."; + break; + + case DSErr_CreateMutex: + ErrorString = "DirectSound error: failed creating mix mutex."; + break; + + default: + ErrorString = "Unknown DirectSound error code."; + break; + } + + return ErrorString; + +} + + +static void TeardownDSound(HRESULT err) +{ + if (FAILED(err)) { + fprintf(stderr, "Dying error: %x\n", (uint32_t) err); + } + + if (lpdsnotify) IDirectSoundNotify_Release(lpdsnotify); + if (notifyPositions[0].hEventNotify) CloseHandle(notifyPositions[0].hEventNotify); + if (notifyPositions[1].hEventNotify) CloseHandle(notifyPositions[1].hEventNotify); + if (notifyPositions[2].hEventNotify) CloseHandle(notifyPositions[2].hEventNotify); + if (mutex) CloseHandle(mutex); + if (lpdsbsec) IDirectSoundBuffer_Release(lpdsbsec); + if (lpdsbprimary) IDirectSoundBuffer_Release(lpdsbprimary); + if (lpds) IDirectSound_Release(lpds); + notifyPositions[0].hEventNotify = + notifyPositions[1].hEventNotify = + notifyPositions[2].hEventNotify = 0; + mutex = 0; + lpdsnotify = 0; + lpdsbsec = 0; + lpdsbprimary = 0; + lpds = 0; +} + +int32_t DirectSoundDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata) +{ + HRESULT err; + DSBUFFERDESC bufdesc; + WAVEFORMATEX wfex; + + if (Initialised) { + DirectSoundDrv_Shutdown(); + } + + err = DirectSoundCreate(0, &lpds, 0); + if (FAILED( err )) { + ErrorCode = DSErr_DirectSoundCreate; + return DSErr_Error; + } + + err = IDirectSound_SetCooperativeLevel(lpds, (HWND) initdata, DSSCL_PRIORITY); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_SetCooperativeLevel; + return DSErr_Error; + } + + memset(&bufdesc, 0, sizeof(DSBUFFERDESC)); + bufdesc.dwSize = sizeof(DSBUFFERDESC); + bufdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + + err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_CreateSoundBuffer; + return DSErr_Error; + } + + memset(&wfex, 0, sizeof(WAVEFORMATEX)); + wfex.wFormatTag = WAVE_FORMAT_PCM; + wfex.nChannels = numchannels; + wfex.nSamplesPerSec = mixrate; + wfex.wBitsPerSample = samplebits; + wfex.nBlockAlign = wfex.nChannels * wfex.wBitsPerSample / 8; + wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; + + err = IDirectSoundBuffer_SetFormat(lpdsbprimary, &wfex); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_SetFormat; + return DSErr_Error; + } + + bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + bufdesc.dwBufferBytes = wfex.nBlockAlign * 2048 * 2; + bufdesc.lpwfxFormat = &wfex; + + err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_SetFormatSecondary; + return DSErr_Error; + } + + err = IDirectSoundBuffer_QueryInterface(lpdsbsec, &IID_IDirectSoundNotify, + (LPVOID *) &lpdsnotify); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_Notify; + return DSErr_Error; + } + + notifyPositions[0].dwOffset = 0; + notifyPositions[0].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL); + notifyPositions[1].dwOffset = bufdesc.dwBufferBytes / 2; + notifyPositions[1].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL); + notifyPositions[2].dwOffset = DSBPN_OFFSETSTOP; + notifyPositions[2].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!notifyPositions[0].hEventNotify || + !notifyPositions[1].hEventNotify || + !notifyPositions[2].hEventNotify) { + TeardownDSound(DS_OK); + ErrorCode = DSErr_NotifyEvents; + return DSErr_Error; + } + + err = IDirectSoundNotify_SetNotificationPositions(lpdsnotify, 3, notifyPositions); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_SetNotificationPositions; + return DSErr_Error; + } + + err = IDirectSoundBuffer_Play(lpdsbprimary, 0, 0, DSBPLAY_LOOPING); + if (FAILED( err )) { + TeardownDSound(err); + ErrorCode = DSErr_Play; + return DSErr_Error; + } + + mutex = CreateMutex(0, FALSE, 0); + if (!mutex) { + TeardownDSound(DS_OK); + ErrorCode = DSErr_CreateMutex; + return DSErr_Error; + } + + Initialised = 1; + + fprintf(stderr, "DirectSound Init: yay\n"); + + return DSErr_Ok; +} + +void DirectSoundDrv_Shutdown(void) +{ + if (!Initialised) { + return; + } + + DirectSoundDrv_StopPlayback(); + + TeardownDSound(DS_OK); + + Initialised = 0; +} + +int32_t DirectSoundDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ) +{ + HRESULT err; + + if (!Initialised) { + ErrorCode = DSErr_Uninitialised; + return DSErr_Error; + } + + DirectSoundDrv_StopPlayback(); + + MixBuffer = BufferStart; + MixBufferSize = BufferSize; + MixBufferCount = NumDivisions; + MixBufferCurrent = 0; + MixBufferUsed = 0; + MixCallBack = CallBackFunc; + + // prime the buffer + FillBuffer(0); + + mixThread = CreateThread(NULL, 0, fillDataThread, 0, 0, 0); + if (!mixThread) { + ErrorCode = DSErr_CreateThread; + return DSErr_Error; + } + + SetThreadPriority(mixThread, THREAD_PRIORITY_HIGHEST); + + err = IDirectSoundBuffer_Play(lpdsbsec, 0, 0, DSBPLAY_LOOPING); + if (FAILED( err )) { + ErrorCode = DSErr_PlaySecondary; + return DSErr_Error; + } + + Playing = 1; + + return DSErr_Ok; +} + +void DirectSoundDrv_StopPlayback(void) +{ + if (!Playing) { + return; + } + + IDirectSoundBuffer_Stop(lpdsbsec); + IDirectSoundBuffer_SetCurrentPosition(lpdsbsec, 0); + + Playing = 0; +} + +void DirectSoundDrv_Lock(void) +{ + DWORD err; + + err = WaitForSingleObject(mutex, INFINITE); + if (err != WAIT_OBJECT_0) { + fprintf(stderr, "DirectSound lock: wfso %d\n", (int32_t) err); + } +} + +void DirectSoundDrv_Unlock(void) +{ + ReleaseMutex(mutex); +} diff --git a/polymer/eduke32/source/jaudiolib/src/driver_directsound.h b/polymer/eduke32/source/jaudiolib/src/driver_directsound.h new file mode 100644 index 000000000..33dfe7d7c --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_directsound.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "inttypes.h" + +int32_t DirectSoundDrv_GetError(void); +const char *DirectSoundDrv_ErrorString( int32_t ErrorNumber ); +int32_t DirectSoundDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata); +void DirectSoundDrv_Shutdown(void); +int32_t DirectSoundDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ); +void DirectSoundDrv_StopPlayback(void); +void DirectSoundDrv_Lock(void); +void DirectSoundDrv_Unlock(void); diff --git a/polymer/eduke32/source/jaudiolib/src/driver_nosound.c b/polymer/eduke32/source/jaudiolib/src/driver_nosound.c new file mode 100644 index 000000000..55818c8b2 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_nosound.c @@ -0,0 +1,62 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +/** + * Stub driver for no output + */ + +#include "inttypes.h" + +int32_t NoSoundDrv_GetError(void) +{ + return 0; +} + +const char *NoSoundDrv_ErrorString( int32_t ErrorNumber ) +{ + return "No sound, Ok."; +} + +int32_t NoSoundDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata) +{ + return 0; +} + +void NoSoundDrv_Shutdown(void) +{ +} + +int32_t NoSoundDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ) +{ + return 0; +} + +void NoSoundDrv_StopPlayback(void) +{ +} + +void NoSoundDrv_Lock(void) +{ +} + +void NoSoundDrv_Unlock(void) +{ +} diff --git a/polymer/eduke32/source/jaudiolib/src/driver_nosound.h b/polymer/eduke32/source/jaudiolib/src/driver_nosound.h new file mode 100644 index 000000000..fcba11bbe --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_nosound.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +int NoSoundDrv_GetError(void); +const char *NoSoundDrv_ErrorString( int ErrorNumber ); +int NoSoundDrv_Init(int mixrate, int numchannels, int samplebits, void * initdata); +void NoSoundDrv_Shutdown(void); +int NoSoundDrv_BeginPlayback(char *BufferStart, int BufferSize, + int NumDivisions, void ( *CallBackFunc )( void ) ); +void NoSoundDrv_StopPlayback(void); +void NoSoundDrv_Lock(void); +void NoSoundDrv_Unlock(void); diff --git a/polymer/eduke32/source/jaudiolib/src/driver_sdl.c b/polymer/eduke32/source/jaudiolib/src/driver_sdl.c new file mode 100644 index 000000000..3c8e8e0eb --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_sdl.c @@ -0,0 +1,231 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +/** + * libSDL output driver for MultiVoc + */ + + +#include +#include "driver_sdl.h" + +enum { + SDLErr_Warning = -2, + SDLErr_Error = -1, + SDLErr_Ok = 0, + SDLErr_Uninitialised, + SDLErr_InitSubSystem, + SDLErr_OpenAudio +}; + +static int32_t ErrorCode = SDLErr_Ok; +static int32_t Initialised = 0; +static int32_t Playing = 0; +static int32_t StartedSDL = -1; + +static char *MixBuffer = 0; +static int32_t MixBufferSize = 0; +static int32_t MixBufferCount = 0; +static int32_t MixBufferCurrent = 0; +static int32_t MixBufferUsed = 0; +static void ( *MixCallBack )( void ) = 0; + +static void fillData(void * userdata, Uint8 * ptr, int32_t remaining) +{ + int32_t len; + char *sptr; + + while (remaining > 0) { + if (MixBufferUsed == MixBufferSize) { + MixCallBack(); + + MixBufferUsed = 0; + MixBufferCurrent++; + if (MixBufferCurrent >= MixBufferCount) { + MixBufferCurrent -= MixBufferCount; + } + } + + while (remaining > 0 && MixBufferUsed < MixBufferSize) { + sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed; + + len = MixBufferSize - MixBufferUsed; + if (remaining < len) { + len = remaining; + } + + memcpy(ptr, sptr, len); + + ptr += len; + MixBufferUsed += len; + remaining -= len; + } + } +} + + +int32_t SDLDrv_GetError(void) +{ + return ErrorCode; +} + +const char *SDLDrv_ErrorString( int32_t ErrorNumber ) +{ + const char *ErrorString; + + switch( ErrorNumber ) { + case SDLErr_Warning : + case SDLErr_Error : + ErrorString = SDLDrv_ErrorString( ErrorCode ); + break; + + case SDLErr_Ok : + ErrorString = "SDL Audio ok."; + break; + + case SDLErr_Uninitialised: + ErrorString = "SDL Audio uninitialised."; + break; + + case SDLErr_InitSubSystem: + ErrorString = "SDL Audio: error in Init or InitSubSystem."; + break; + + case SDLErr_OpenAudio: + ErrorString = "SDL Audio: error in OpenAudio."; + break; + + default: + ErrorString = "Unknown SDL Audio error code."; + break; + } + + return ErrorString; +} + +int32_t SDLDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata) +{ + Uint32 inited; + Uint32 err = 0; + SDL_AudioSpec spec; + + if (Initialised) { + SDLDrv_Shutdown(); + } + + inited = SDL_WasInit(SDL_INIT_EVERYTHING); + + if (inited == 0) { + // nothing was initialised + err = SDL_Init(SDL_INIT_AUDIO); + StartedSDL = 0; + } else if (inited & SDL_INIT_AUDIO) { + err = SDL_InitSubSystem(SDL_INIT_AUDIO); + StartedSDL = 1; + } + + if (err < 0) { + ErrorCode = SDLErr_InitSubSystem; + return SDLErr_Error; + } + + spec.freq = mixrate; + spec.format = (samplebits == 8) ? AUDIO_U8 : AUDIO_S16SYS; + spec.channels = numchannels; + spec.samples = 256; + spec.callback = fillData; + spec.userdata = 0; + + err = SDL_OpenAudio(&spec, NULL); + if (err < 0) { + ErrorCode = SDLErr_OpenAudio; + return SDLErr_Error; + } + + Initialised = 1; + + return SDLErr_Ok; +} + +void SDLDrv_Shutdown(void) +{ + if (!Initialised) { + return; + } + + if (StartedSDL > 0) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } else if (StartedSDL == 0) { + SDL_Quit(); + } + + StartedSDL = -1; +} + +int32_t SDLDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ) +{ + if (!Initialised) { + ErrorCode = SDLErr_Uninitialised; + return SDLErr_Error; + } + + if (Playing) { + SDLDrv_StopPlayback(); + } + + MixBuffer = BufferStart; + MixBufferSize = BufferSize; + MixBufferCount = NumDivisions; + MixBufferCurrent = 0; + MixBufferUsed = 0; + MixCallBack = CallBackFunc; + + // prime the buffer + MixCallBack(); + + SDL_PauseAudio(0); + + Playing = 1; + + return SDLErr_Ok; +} + +void SDLDrv_StopPlayback(void) +{ + if (!Initialised || !Playing) { + return; + } + + SDL_PauseAudio(1); + + Playing = 0; +} + +void SDLDrv_Lock(void) +{ + SDL_LockAudio(); +} + +void SDLDrv_Unlock(void) +{ + SDL_UnlockAudio(); +} + diff --git a/polymer/eduke32/source/jaudiolib/src/driver_sdl.h b/polymer/eduke32/source/jaudiolib/src/driver_sdl.h new file mode 100644 index 000000000..36c04ec2c --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/driver_sdl.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +int32_t SDLDrv_GetError(void); +const char *SDLDrv_ErrorString( int32_t ErrorNumber ); +int32_t SDLDrv_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata); +void SDLDrv_Shutdown(void); +int32_t SDLDrv_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ); +void SDLDrv_StopPlayback(void); +void SDLDrv_Lock(void); +void SDLDrv_Unlock(void); diff --git a/polymer/eduke32/source/jaudiolib/src/drivers.c b/polymer/eduke32/source/jaudiolib/src/drivers.c new file mode 100644 index 000000000..a8f394cdb --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/drivers.c @@ -0,0 +1,174 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +/** + * Abstraction layer for hiding the various supported sound devices + * behind a common and opaque interface called on by MultiVoc. + */ + +#include "drivers.h" + +#include "driver_nosound.h" + +#ifdef HAVE_SDL +# include "driver_sdl.h" +#endif + +#ifdef __APPLE__ +# include "driver_coreaudio.h" +#endif + +#ifdef WIN32 +# include "driver_directsound.h" +#endif + +int32_t ASS_SoundDriver = -1; + +#define UNSUPPORTED { 0,0,0,0,0,0,0,0, }, + +static struct { + int32_t (* GetError)(void); + const char * (* ErrorString)(int32_t); + int32_t (* Init)(int32_t, int32_t, int32_t, void *); + void (* Shutdown)(void); + int32_t (* BeginPlayback)(char *, int32_t, int32_t, void ( * )(void) ); + void (* StopPlayback)(void); + void (* Lock)(void); + void (* Unlock)(void); +} SoundDrivers[ASS_NumSoundCards] = { + + // Everyone gets the "no sound" driver + { + NoSoundDrv_GetError, + NoSoundDrv_ErrorString, + NoSoundDrv_Init, + NoSoundDrv_Shutdown, + NoSoundDrv_BeginPlayback, + NoSoundDrv_StopPlayback, + NoSoundDrv_Lock, + NoSoundDrv_Unlock, + }, + + // Simple DirectMedia Layer + #ifdef HAVE_SDL + { + SDLDrv_GetError, + SDLDrv_ErrorString, + SDLDrv_Init, + SDLDrv_Shutdown, + SDLDrv_BeginPlayback, + SDLDrv_StopPlayback, + SDLDrv_Lock, + SDLDrv_Unlock, + }, + #else + UNSUPPORTED + #endif + + // OS X CoreAudio + #ifdef __APPLE__ + { + CoreAudioDrv_GetError, + CoreAudioDrv_ErrorString, + CoreAudioDrv_Init, + CoreAudioDrv_Shutdown, + CoreAudioDrv_BeginPlayback, + CoreAudioDrv_StopPlayback, + CoreAudioDrv_Lock, + CoreAudioDrv_Unlock, + }, + #else + UNSUPPORTED + #endif + + // Windows DirectSound + #ifdef WIN32 + { + DirectSoundDrv_GetError, + DirectSoundDrv_ErrorString, + DirectSoundDrv_Init, + DirectSoundDrv_Shutdown, + DirectSoundDrv_BeginPlayback, + DirectSoundDrv_StopPlayback, + DirectSoundDrv_Lock, + DirectSoundDrv_Unlock, + }, + #else + UNSUPPORTED + #endif +}; + + +int32_t SoundDriver_IsSupported(int32_t driver) +{ + return (SoundDrivers[driver].GetError != 0); +} + + +int32_t SoundDriver_GetError(void) +{ + if (!SoundDriver_IsSupported(ASS_SoundDriver)) { + return -1; + } + return SoundDrivers[ASS_SoundDriver].GetError(); +} + +const char * SoundDriver_ErrorString( int32_t ErrorNumber ) +{ + if (ASS_SoundDriver < 0 || ASS_SoundDriver >= ASS_NumSoundCards) { + return "No sound driver selected."; + } + if (!SoundDriver_IsSupported(ASS_SoundDriver)) { + return "Unsupported sound driver selected."; + } + return SoundDrivers[ASS_SoundDriver].ErrorString(ErrorNumber); +} + +int32_t SoundDriver_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata) +{ + return SoundDrivers[ASS_SoundDriver].Init(mixrate, numchannels, samplebits, initdata); +} + +void SoundDriver_Shutdown(void) +{ + SoundDrivers[ASS_SoundDriver].Shutdown(); +} + +int32_t SoundDriver_BeginPlayback(char *BufferStart, int32_t BufferSize, + int32_t NumDivisions, void ( *CallBackFunc )( void ) ) +{ + return SoundDrivers[ASS_SoundDriver].BeginPlayback(BufferStart, + BufferSize, NumDivisions, CallBackFunc); +} + +void SoundDriver_StopPlayback(void) +{ + SoundDrivers[ASS_SoundDriver].StopPlayback(); +} + +void SoundDriver_Lock(void) +{ + SoundDrivers[ASS_SoundDriver].Lock(); +} + +void SoundDriver_Unlock(void) +{ + SoundDrivers[ASS_SoundDriver].Unlock(); +} diff --git a/polymer/eduke32/source/jaudiolib/src/drivers.h b/polymer/eduke32/source/jaudiolib/src/drivers.h new file mode 100644 index 000000000..4a25f68cf --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/drivers.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef DRIVERS_H +#define DRIVERS_H + +#include "inttypes.h" +#include "sndcards.h" + +extern int32_t ASS_SoundDriver; + +int32_t SoundDriver_IsSupported(int32_t driver); + +int32_t SoundDriver_GetError(void); +const char * SoundDriver_ErrorString( int32_t ErrorNumber ); +int32_t SoundDriver_Init(int32_t mixrate, int32_t numchannels, int32_t samplebits, void * initdata); +void SoundDriver_Shutdown(void); +int32_t SoundDriver_BeginPlayback( char *BufferStart, + int32_t BufferSize, int32_t NumDivisions, + void ( *CallBackFunc )( void ) ); +void SoundDriver_StopPlayback(void); +void SoundDriver_Lock(void); +void SoundDriver_Unlock(void); + +#endif diff --git a/polymer/eduke32/source/jaudiolib/src/fx_man.c b/polymer/eduke32/source/jaudiolib/src/fx_man.c new file mode 100644 index 000000000..fe71f8be4 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/fx_man.c @@ -0,0 +1,1069 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + module: FX_MAN.C + + author: James R. Dose + date: March 17, 1994 + + Device independant sound effect routines. + + (c) Copyright 1994 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#include +#include +#include "sndcards.h" +#include "drivers.h" +#include "multivoc.h" +#include "fx_man.h" + +#define TRUE ( 1 == 1 ) +#define FALSE ( !TRUE ) + +int32_t FX_ErrorCode = FX_Ok; +int32_t FX_Installed = FALSE; + +#define FX_SetErrorCode( status ) \ + FX_ErrorCode = ( status ); + + +/*--------------------------------------------------------------------- + Function: FX_ErrorString + + Returns a pointer to the error message associated with an error + number. A -1 returns a pointer the current error. +---------------------------------------------------------------------*/ + +const char *FX_ErrorString +( + int32_t ErrorNumber +) + +{ + const char *ErrorString; + + switch (ErrorNumber) + { + case FX_Warning : + case FX_Error : + ErrorString = FX_ErrorString(FX_ErrorCode); + break; + + case FX_Ok : + ErrorString = "Fx ok."; + break; + + case FX_ASSVersion : + ErrorString = "Apogee Sound System Version " ASS_VERSION_STRING " " + "Programmed by Jim Dose\n" + "(c) Copyright 1995 James R. Dose. All Rights Reserved.\n"; + break; + + case FX_SoundCardError : + ErrorString = SoundDriver_ErrorString(SoundDriver_GetError()); + break; + + case FX_InvalidCard : + ErrorString = "Invalid Sound Fx device."; + break; + + case FX_MultiVocError : + ErrorString = MV_ErrorString(MV_Error); + break; + + default : + ErrorString = "Unknown Fx error code."; + break; + } + + return(ErrorString); +} + + +/*--------------------------------------------------------------------- + Function: FX_Init + + Selects which sound device to use. +---------------------------------------------------------------------*/ + +int32_t FX_Init +( + int32_t SoundCard, + int32_t numvoices, + int32_t numchannels, + int32_t samplebits, + unsigned mixrate, + void * initdata +) + +{ + int32_t status; + int32_t devicestatus; + + if (FX_Installed) + { + FX_Shutdown(); + } + + if (SoundCard == ASS_AutoDetect) + { +#if defined __APPLE__ + SoundCard = ASS_CoreAudio; +#elif defined WIN32 + SoundCard = ASS_DirectSound; +#elif defined HAVE_SDL + SoundCard = ASS_SDL; +#else + SoundCard = ASS_NoSound; +#endif + } + + if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards) + { + FX_SetErrorCode(FX_InvalidCard); + status = FX_Error; + return status; + } + + if (SoundDriver_IsSupported(SoundCard) == 0) + { + // unsupported cards fall back to no sound + SoundCard = ASS_NoSound; + } + + status = FX_Ok; + devicestatus = MV_Init(SoundCard, mixrate, numvoices, numchannels, samplebits, initdata); + if (devicestatus != MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + status = FX_Error; + } + + if (status == FX_Ok) + { + FX_Installed = TRUE; + } + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: FX_Shutdown + + Terminates use of sound device. +---------------------------------------------------------------------*/ + +int32_t FX_Shutdown +( + void +) + +{ + int32_t status; + + if (!FX_Installed) + { + return(FX_Ok); + } + + status = MV_Shutdown(); + if (status != MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + status = FX_Error; + } + + FX_Installed = FALSE; + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: FX_SetCallback + + Sets the function to call when a voice is done. +---------------------------------------------------------------------*/ + +int32_t FX_SetCallBack +( + void (*function)(uint32_t) +) + +{ + int32_t status; + + status = FX_Ok; + + MV_SetCallBack(function); + + return(status); +} + + +/*--------------------------------------------------------------------- + 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); +} + + +/*--------------------------------------------------------------------- + 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_PlayVOC + + Begin playback of sound data with the given volume and priority. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayVOC(ptr, ptrlength, pitchoffset, vol, left, right, + priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayLoopedVOC + + Begin playback of sound data with the given volume and priority. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayLoopedVOC(ptr, ptrlength, loopstart, loopend, pitchoffset, + vol, left, right, priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayWAV + + Begin playback of sound data with the given volume and priority. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayWAV(ptr, ptrlength, pitchoffset, vol, left, right, + priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayWAV + + Begin playback of sound data with the given volume and priority. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayLoopedWAV(ptr, ptrlength, loopstart, loopend, + pitchoffset, vol, left, right, priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayVOC3D + + Begin playback of sound data at specified angle and distance + from listener. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayVOC3D(ptr, ptrlength, pitchoffset, angle, distance, + priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayWAV3D + + Begin playback of sound data at specified angle and distance + from listener. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayWAV3D(ptr, ptrlength, pitchoffset, angle, distance, + priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayRaw + + Begin playback of raw sound data with the given volume and priority. +---------------------------------------------------------------------*/ + +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 handle; + + handle = MV_PlayRaw(ptr, length, rate, pitchoffset, + vol, left, right, priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayLoopedRaw + + Begin playback of raw sound data with the given volume and priority. +---------------------------------------------------------------------*/ + +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 +) + +{ + int32_t handle; + + handle = MV_PlayLoopedRaw(ptr, length, loopstart, loopend, + rate, pitchoffset, vol, left, right, priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_Pan3D + + Set the angle and distance from the listener of the voice associated + with the specified handle. +---------------------------------------------------------------------*/ + +int32_t FX_Pan3D +( + int32_t handle, + int32_t angle, + int32_t distance +) + +{ + int32_t status; + + status = MV_Pan3D(handle, angle, distance); + if (status != MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + status = FX_Warning; + } + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: FX_SoundActive + + Tests if the specified sound is currently playing. +---------------------------------------------------------------------*/ + +int32_t FX_SoundActive +( + int32_t handle +) + +{ + return(MV_VoicePlaying(handle)); +} + + +/*--------------------------------------------------------------------- + Function: FX_SoundsPlaying + + Reports the number of voices playing. +---------------------------------------------------------------------*/ + +int32_t FX_SoundsPlaying +( + void +) + +{ + return(MV_VoicesPlaying()); +} + + +/*--------------------------------------------------------------------- + Function: FX_StopSound + + Halts playback of a specific voice +---------------------------------------------------------------------*/ + +int32_t FX_StopSound +( + int32_t handle +) + +{ + int32_t status; + + status = MV_Kill(handle); + if (status != MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + return(FX_Warning); + } + + return(FX_Ok); +} + + +/*--------------------------------------------------------------------- + Function: FX_StopAllSounds + + Halts playback of all sounds. +---------------------------------------------------------------------*/ + +int32_t FX_StopAllSounds +( + void +) + +{ + int32_t status; + + status = MV_KillAllVoices(); + if (status != MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + return(FX_Warning); + } + + return(FX_Ok); +} + + +/*--------------------------------------------------------------------- + Function: FX_StartDemandFeedPlayback + + Plays a digitized sound from a user controlled buffering system. +---------------------------------------------------------------------*/ + +int32_t FX_StartDemandFeedPlayback +( + void (*function)(char **ptr, uint32_t *length), + int32_t rate, + int32_t pitchoffset, + int32_t vol, + int32_t left, + int32_t right, + int32_t priority, + uint32_t callbackval +) + +{ + int32_t handle; + + handle = MV_StartDemandFeedPlayback(function, rate, + pitchoffset, vol, left, right, priority, callbackval); + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return(handle); +} + + +/*--------------------------------------------------------------------- + Function: FX_StartRecording + + Starts the sound recording engine. +---------------------------------------------------------------------*/ + +int32_t FX_StartRecording +( + int32_t MixRate, + void (*function)(char *ptr, int32_t length) +) + +{ + int32_t status; + + FX_SetErrorCode(FX_InvalidCard); + status = FX_Warning; + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: FX_StopRecord + + Stops the sound record engine. +---------------------------------------------------------------------*/ + +void FX_StopRecord +( + void +) + +{ +} + + +/*--------------------------------------------------------------------- + Function: FX_PlayAuto + + Play a sound, autodetecting the format. +---------------------------------------------------------------------*/ +int32_t FX_PlayAuto(char *ptr, uint32_t length, int32_t pitchoffset, int32_t vol, + int32_t left, int32_t right, int32_t priority, uint32_t callbackval) +{ + int32_t handle = -1; + + if (!memcmp("Creative Voice File\x1a", ptr, 20)) + { + handle = MV_PlayVOC(ptr, length, pitchoffset, vol, left, right, priority, callbackval); + } + else if (!memcmp("RIFF", ptr, 4) && !memcmp("WAVE", ptr + 8, 4)) + { + handle = MV_PlayWAV(ptr, length, pitchoffset, vol, left, right, priority, callbackval); + } + else if (!memcmp("OggS", ptr, 4)) + { + handle = MV_PlayVorbis(ptr, length, pitchoffset, vol, left, right, priority, callbackval); + } + + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return handle; +} + +/*--------------------------------------------------------------------- + Function: FX_PlayLoopedAuto + + Play a looped sound, autodetecting the format. +---------------------------------------------------------------------*/ +int32_t FX_PlayLoopedAuto(char *ptr, uint32_t length, int32_t loopstart, int32_t loopend, + int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, + uint32_t callbackval) +{ + int32_t handle = -1; + + if (!memcmp("Creative Voice File\x1a", ptr, 20)) + { + handle = MV_PlayLoopedVOC(ptr, length, loopstart, loopend, pitchoffset, + vol, left, right, priority, callbackval); + } + else if (!memcmp("RIFF", ptr, 4) && !memcmp("WAVE", ptr + 8, 4)) + { + handle = MV_PlayLoopedWAV(ptr, length, loopstart, loopend, pitchoffset, + vol, left, right, priority, callbackval); + } + else if (!memcmp("OggS", ptr, 4)) + { + handle = MV_PlayLoopedVorbis(ptr, length, loopstart, loopend, pitchoffset, + vol, left, right, priority, callbackval); + } + + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return handle; +} + +/*--------------------------------------------------------------------- + Function: FX_PlayAuto3D + + Play a positioned sound, autodetecting the format. +---------------------------------------------------------------------*/ +int32_t FX_PlayAuto3D(char *ptr, uint32_t length, int32_t pitchoffset, int32_t angle, + int32_t distance, int32_t priority, uint32_t callbackval) +{ + int32_t handle = -1; + + if (!memcmp("Creative Voice File\x1a", ptr, 20)) + { + handle = MV_PlayVOC3D(ptr, length, pitchoffset, angle, distance, priority, callbackval); + } + else if (!memcmp("RIFF", ptr, 4) && !memcmp("WAVE", ptr + 8, 4)) + { + handle = MV_PlayWAV3D(ptr, length, pitchoffset, angle, distance, priority, callbackval); + } + else if (!memcmp("OggS", ptr, 4)) + { + handle = MV_PlayVorbis3D(ptr, length, pitchoffset, angle, distance, priority, callbackval); + } + + if (handle < MV_Ok) + { + FX_SetErrorCode(FX_MultiVocError); + handle = FX_Warning; + } + + return handle; +} diff --git a/polymer/eduke32/source/jaudiolib/src/linklist.h b/polymer/eduke32/source/jaudiolib/src/linklist.h new file mode 100644 index 000000000..8a7aa5fcc --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/linklist.h @@ -0,0 +1,118 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef __linklist_h +#define __linklist_h +#ifdef __cplusplus +extern "C" { +#endif + + +#define NewNode(type) ((type*)SafeMalloc(sizeof(type))) + + +#define LL_CreateNewLinkedList(rootnode,type,next,prev) \ + { \ + (rootnode) = NewNode(type); \ + (rootnode)->prev = (rootnode); \ + (rootnode)->next = (rootnode); \ + } + + + +#define LL_AddNode(rootnode, newnode, next, prev) \ + { \ + (newnode)->next = (rootnode); \ + (newnode)->prev = (rootnode)->prev; \ + (rootnode)->prev->next = (newnode); \ + (rootnode)->prev = (newnode); \ + } + +#define LL_TransferList(oldroot,newroot,next,prev) \ + { \ + if ((oldroot)->prev != (oldroot)) \ + { \ + (oldroot)->prev->next = (newroot); \ + (oldroot)->next->prev = (newroot)->prev; \ + (newroot)->prev->next = (oldroot)->next; \ + (newroot)->prev = (oldroot)->prev; \ + (oldroot)->next = (oldroot); \ + (oldroot)->prev = (oldroot); \ + } \ + } + +#define LL_ReverseList(root,type,next,prev) \ + { \ + type *newend,*trav,*tprev; \ + \ + newend = (root)->next; \ + for(trav = (root)->prev; trav != newend; trav = tprev) \ + { \ + tprev = trav->prev; \ + LL_MoveNode(trav,newend,next,prev); \ + } \ + } + + +#define LL_RemoveNode(node,next,prev) \ + { \ + (node)->prev->next = (node)->next; \ + (node)->next->prev = (node)->prev; \ + (node)->next = (node); \ + (node)->prev = (node); \ + } + + +#define LL_SortedInsertion(rootnode,insertnode,next,prev,type,sortparm) \ + { \ + type *hoya; \ + \ + hoya = (rootnode)->next; \ + while((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \ + { \ + hoya = hoya->next; \ + } \ + LL_AddNode(hoya,(insertnode),next,prev); \ + } + +#define LL_MoveNode(node,newroot,next,prev) \ + { \ + LL_RemoveNode((node),next,prev); \ + LL_AddNode((newroot),(node),next,prev); \ + } + +#define LL_ListEmpty(list,next,prev) \ + ( \ + ((list)->next == (list)) && \ + ((list)->prev == (list)) \ + ) + +#define LL_Free(list) SafeFree(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 +}; +#endif +#endif diff --git a/polymer/eduke32/source/jaudiolib/src/ll_man.h b/polymer/eduke32/source/jaudiolib/src/ll_man.h new file mode 100644 index 000000000..0fb891ae1 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/ll_man.h @@ -0,0 +1,76 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + 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 diff --git a/polymer/eduke32/source/jaudiolib/src/mix.c b/polymer/eduke32/source/jaudiolib/src/mix.c new file mode 100644 index 000000000..24afcafb6 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/mix.c @@ -0,0 +1,353 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "_multivc.h" + +extern char *MV_HarshClipTable; +extern char *MV_MixDestination; // pointer to the next output sample +extern uint32_t MV_MixPosition; // return value of where the source pointer got to +extern int16_t *MV_LeftVolume; +extern int16_t *MV_RightVolume; +extern int32_t MV_SampleSize; +extern int32_t MV_RightChannelOffset; + +#ifdef __POWERPC__ +# define BIGENDIAN +#endif + +void ClearBuffer_DW( void *ptr, unsigned data, int32_t length ) +{ + unsigned *ptrdw = ptr; + while (length--) { + *(ptrdw++) = data; + } +} + +/* + JBF: + + position = offset of starting sample in start + rate = resampling increment + start = sound data + length = count of samples to mix + */ + +// 8-bit mono source, 8-bit mono output +void MV_Mix8BitMono( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0; + + while (length--) { + sample0 = source[position >> 16]; + position += rate; + + sample0 = MV_LeftVolume[sample0] + *dest; + sample0 = MV_HarshClipTable[sample0 + 128]; + + *dest = sample0 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 8-bit mono source, 8-bit stereo output +void MV_Mix8BitStereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[position >> 16]; + sample1 = sample0; + position += rate; + + sample0 = MV_LeftVolume[sample0] + *dest; + sample1 = MV_RightVolume[sample1] + *(dest + MV_RightChannelOffset); + sample0 = MV_HarshClipTable[sample0 + 128]; + sample1 = MV_HarshClipTable[sample1 + 128]; + + *dest = sample0 & 255; + *(dest + MV_RightChannelOffset) = sample1 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 8-bit mono source, 16-bit mono output +void MV_Mix16BitMono( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0; + + while (length--) { + sample0 = source[position >> 16]; + position += rate; + + sample0 = MV_LeftVolume[sample0] + *dest; + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + + *dest = (int16_t) sample0; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 8-bit mono source, 16-bit stereo output +void MV_Mix16BitStereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[position >> 16]; + sample1 = sample0; + position += rate; + + sample0 = MV_LeftVolume[sample0] + *dest; + sample1 = MV_RightVolume[sample1] + *(dest + MV_RightChannelOffset / 2); + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + if (sample1 < -32768) sample1 = -32768; + else if (sample1 > 32767) sample1 = 32767; + + *dest = (int16_t) sample0; + *(dest + MV_RightChannelOffset/2) = (int16_t) sample1; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit mono source, 16-bit mono output +void MV_Mix16BitMono16( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint16_t *source = (uint16_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0l, sample0h, sample0; + + while (length--) { + sample0 = source[position >> 16]; +#ifdef BIGENDIAN + sample0l = sample0 >> 8; + sample0h = (sample0 & 255) ^ 128; +#else + sample0l = sample0 & 255; + sample0h = (sample0 >> 8) ^ 128; +#endif + position += rate; + + sample0l = MV_LeftVolume[sample0l] >> 8; + sample0h = MV_LeftVolume[sample0h]; + sample0 = sample0l + sample0h + 128 + *dest; + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + + *dest = (int16_t) sample0; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit mono source, 8-bit mono output +void MV_Mix8BitMono16( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + int8_t *source = (int8_t *) start + 1; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + position += rate; + + sample0 = MV_LeftVolume[sample0 + 128] + *dest; + sample0 = MV_HarshClipTable[sample0 + 128]; + + *dest = sample0 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit mono source, 8-bit stereo output +void MV_Mix8BitStereo16( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + int8_t *source = (int8_t *) start + 1; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = sample0; + position += rate; + + sample0 = MV_LeftVolume[sample0 + 128] + *dest; + sample1 = MV_RightVolume[sample1 + 128] + *(dest + MV_RightChannelOffset); + sample0 = MV_HarshClipTable[sample0 + 128]; + sample1 = MV_HarshClipTable[sample1 + 128]; + + *dest = sample0 & 255; + *(dest + MV_RightChannelOffset) = sample1 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit mono source, 16-bit stereo output +void MV_Mix16BitStereo16( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint16_t *source = (uint16_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0l, sample0h, sample0; + int32_t sample1l, sample1h, sample1; + + while (length--) { + sample0 = source[position >> 16]; +#ifdef BIGENDIAN + sample0l = sample0 >> 8; + sample0h = (sample0 & 255) ^ 128; +#else + sample0l = sample0 & 255; + sample0h = (sample0 >> 8) ^ 128; +#endif + sample1l = sample0l; + sample1h = sample0h; + position += rate; + + sample0l = MV_LeftVolume[sample0l] >> 8; + sample0h = MV_LeftVolume[sample0h]; + sample1l = MV_RightVolume[sample1l] >> 8; + sample1h = MV_RightVolume[sample1h]; + sample0 = sample0l + sample0h + 128 + *dest; + sample1 = sample1l + sample1h + 128 + *(dest + MV_RightChannelOffset/2); + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + if (sample1 < -32768) sample1 = -32768; + else if (sample1 > 32767) sample1 = 32767; + + *dest = (int16_t) sample0; + *(dest + MV_RightChannelOffset/2) = (int16_t) sample1; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +void MV_16BitReverb( char *src, char *dest, VOLUME16 *volume, int32_t count ) +{ + uint16_t * input = (uint16_t *) src; + int16_t * output = (int16_t *) dest; + int16_t sample0l, sample0h, sample0; + + do { + sample0 = *input; +#ifdef BIGENDIAN + sample0l = sample0 >> 8; + sample0h = (sample0 & 255) ^ 128; +#else + sample0l = sample0 & 255; + sample0h = (sample0 >> 8) ^ 128; +#endif + + sample0l = ((int16_t *) volume)[sample0l] >> 8; + sample0h = ((int16_t *) volume)[sample0h]; + *output = (int16_t) (sample0l + sample0h + 128); + + input++; + output++; + } while (count-- > 0); +} + +void MV_8BitReverb( int8_t *src, int8_t *dest, VOLUME16 *volume, int32_t count ) +{ + uint8_t * input = (uint8_t *) src; + uint8_t * output = (uint8_t *) dest; + + do { + *output = ((int16_t *) volume)[*input] + 128; + + input++; + output++; + } 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); +} + diff --git a/polymer/eduke32/source/jaudiolib/src/mixst.c b/polymer/eduke32/source/jaudiolib/src/mixst.c new file mode 100644 index 000000000..e9ea69893 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/mixst.c @@ -0,0 +1,297 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "_multivc.h" + +extern char *MV_HarshClipTable; +extern char *MV_MixDestination; // pointer to the next output sample +extern uint32_t MV_MixPosition; // return value of where the source pointer got to +extern int16_t *MV_LeftVolume; +extern int16_t *MV_RightVolume; +extern int32_t MV_SampleSize; +extern int32_t MV_RightChannelOffset; + +#ifdef __POWERPC__ +# define BIGENDIAN +#endif + +/* + JBF: + + position = offset of starting sample in start + rate = resampling increment + start = sound data + length = count of samples to mix + */ + +// 8-bit stereo source, 8-bit mono output +void MV_Mix8BitMono8Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = source[((position >> 16) << 1) + 1]; + position += rate; + + sample0 = (MV_LeftVolume[sample0] + MV_LeftVolume[sample1]) / 2 + *dest; + sample0 = MV_HarshClipTable[sample0 + 128]; + + *dest = sample0 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 8-bit stereo source, 8-bit stereo output +void MV_Mix8BitStereo8Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = source[((position >> 16) << 1) + 1]; + position += rate; + + sample0 = MV_LeftVolume[sample0] + *dest; + sample1 = MV_RightVolume[sample1] + *(dest + MV_RightChannelOffset); + sample0 = MV_HarshClipTable[sample0 + 128]; + sample1 = MV_HarshClipTable[sample1 + 128]; + + *dest = sample0 & 255; + *(dest + MV_RightChannelOffset) = sample1 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 8-bit stereo source, 16-bit mono output +void MV_Mix16BitMono8Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = source[((position >> 16) << 1) + 1]; + position += rate; + + sample0 = (MV_LeftVolume[sample0] + MV_LeftVolume[sample1]) / 2 + *dest; + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + + *dest = (int16_t) sample0; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 8-bit stereo source, 16-bit stereo output +void MV_Mix16BitStereo8Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint8_t *source = (uint8_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = source[((position >> 16) << 1) + 1]; + position += rate; + + sample0 = MV_LeftVolume[sample0] + *dest; + sample1 = MV_RightVolume[sample1] + *(dest + MV_RightChannelOffset / 2); + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + if (sample1 < -32768) sample1 = -32768; + else if (sample1 > 32767) sample1 = 32767; + + *dest = (int16_t) sample0; + *(dest + MV_RightChannelOffset/2) = (int16_t) sample1; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit stereo source, 16-bit mono output +void MV_Mix16BitMono16Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint16_t *source = (uint16_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0l, sample0h, sample0; + int32_t sample1l, sample1h, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = source[((position >> 16) << 1) + 1]; +#ifdef BIGENDIAN + sample0l = sample0 >> 8; + sample0h = (sample0 & 255) ^ 128; + sample1l = sample1 >> 8; + sample1h = (sample1 & 255) ^ 128; +#else + sample0l = sample0 & 255; + sample0h = (sample0 >> 8) ^ 128; + sample1l = sample1 & 255; + sample1h = (sample1 >> 8) ^ 128; +#endif + position += rate; + + sample0l = MV_LeftVolume[sample0l] >> 8; + sample0h = MV_LeftVolume[sample0h]; + sample0 = sample0l + sample0h + 128; + sample1l = MV_LeftVolume[sample1l] >> 8; + sample1h = MV_LeftVolume[sample1h]; + sample1 = sample1l + sample1h + 128; + + sample0 = (sample0 + sample1) / 2 + *dest; + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + + *dest = (int16_t) sample0; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit stereo source, 8-bit mono output +void MV_Mix8BitMono16Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + int8_t *source = (int8_t *) start + 1; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 2]; + sample1 = source[((position >> 16) << 2) + 2]; + position += rate; + + sample0 = MV_LeftVolume[sample0 + 128]; + sample1 = MV_LeftVolume[sample1 + 128]; + sample0 = (sample0 + sample1) / 2 + *dest; + sample0 = MV_HarshClipTable[sample0 + 128]; + + *dest = sample0 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit stereo source, 8-bit stereo output +void MV_Mix8BitStereo16Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + int8_t *source = (int8_t *) start + 1; + uint8_t *dest = (uint8_t *) MV_MixDestination; + int32_t sample0, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 2]; + sample1 = source[((position >> 16) << 2) + 2]; + position += rate; + + sample0 = MV_LeftVolume[sample0 + 128] + *dest; + sample1 = MV_RightVolume[sample1 + 128] + *(dest + MV_RightChannelOffset); + sample0 = MV_HarshClipTable[sample0 + 128]; + sample1 = MV_HarshClipTable[sample1 + 128]; + + *dest = sample0 & 255; + *(dest + MV_RightChannelOffset) = sample1 & 255; + + dest += MV_SampleSize; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} + +// 16-bit stereo source, 16-bit stereo output +void MV_Mix16BitStereo16Stereo( uint32_t position, uint32_t rate, + char *start, uint32_t length ) +{ + uint16_t *source = (uint16_t *) start; + int16_t *dest = (int16_t *) MV_MixDestination; + int32_t sample0l, sample0h, sample0; + int32_t sample1l, sample1h, sample1; + + while (length--) { + sample0 = source[(position >> 16) << 1]; + sample1 = source[((position >> 16) << 1) + 1]; +#ifdef BIGENDIAN + sample0l = sample0 >> 8; + sample0h = (sample0 & 255) ^ 128; + sample1l = sample1 >> 8; + sample1h = (sample1 & 255) ^ 128; +#else + sample0l = sample0 & 255; + sample0h = (sample0 >> 8) ^ 128; + sample1l = sample1 & 255; + sample1h = (sample1 >> 8) ^ 128; +#endif + position += rate; + + sample0l = MV_LeftVolume[sample0l] >> 8; + sample0h = MV_LeftVolume[sample0h]; + sample1l = MV_RightVolume[sample1l] >> 8; + sample1h = MV_RightVolume[sample1h]; + sample0 = sample0l + sample0h + 128 + *dest; + sample1 = sample1l + sample1h + 128 + *(dest + MV_RightChannelOffset/2); + if (sample0 < -32768) sample0 = -32768; + else if (sample0 > 32767) sample0 = 32767; + if (sample1 < -32768) sample1 = -32768; + else if (sample1 > 32767) sample1 = 32767; + + *dest = (int16_t) sample0; + *(dest + MV_RightChannelOffset/2) = (int16_t) sample1; + + dest += MV_SampleSize / 2; + } + + MV_MixPosition = position; + MV_MixDestination = (char *) dest; +} diff --git a/polymer/eduke32/source/jaudiolib/src/multivoc.c b/polymer/eduke32/source/jaudiolib/src/multivoc.c new file mode 100644 index 000000000..f2fad54f2 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/multivoc.c @@ -0,0 +1,2910 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + module: MULTIVOC.C + + author: James R. Dose + date: December 20, 1993 + + Routines to provide multichannel digitized sound playback for + Sound Blaster compatible sound cards. + + (c) Copyright 1993 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#include +#include +#include +#include +#include +#include "linklist.h" +#include "sndcards.h" +#include "drivers.h" +#include "pitch.h" +#include "multivoc.h" +#include "_multivc.h" + +#ifdef __POWERPC__ +#define LITTLE16 SWAP16 +#define LITTLE32 SWAP32 +#else +#define LITTLE16 +#define LITTLE32 +#endif + +static inline uint16_t SWAP16(uint16_t s) +{ + return (s >> 8) | (s << 8); +} + +static inline uint32_t SWAP32(uint32_t s) +{ + return (s >> 24) | (s << 24) | ((s&0xff00) << 8) | ((s & 0xff0000) >> 8); +} + +#define min(x,y) ((x) < (y) ? (x) : (y)) +#define max(x,y) ((x) > (y) ? (x) : (y)) + +#define RoundFixed( fixedval, bits ) \ + ( \ + ( \ + (fixedval) + ( 1 << ( (bits) - 1 ) )\ + ) >> (bits) \ + ) + +#define IS_QUIET( ptr ) ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] ) + +static int32_t MV_ReverbLevel; +static int32_t MV_ReverbDelay; +static VOLUME16 *MV_ReverbTable = NULL; + +//static int16_t MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ]; +static int16_t MV_VolumeTable[ 255 + 1 ][ 256 ]; + +//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ]; +Pan MV_PanTable[ MV_NumPanPositions ][ 255 + 1 ]; + +int32_t MV_Installed = FALSE; +static int32_t MV_TotalVolume = MV_MaxTotalVolume; +static int32_t MV_MaxVoices = 1; +static int32_t MV_Recording; + +static int32_t MV_BufferSize = MixBufferSize; +static int32_t MV_BufferLength; + +static int32_t MV_NumberOfBuffers = NumberOfBuffers; + +static int32_t MV_MixMode = MONO_8BIT; +static int32_t MV_Channels = 1; +static int32_t MV_Bits = 8; + +static int32_t MV_Silence = SILENCE_8BIT; +static int32_t MV_SwapLeftRight = FALSE; + +static int32_t MV_RequestedMixRate; +int32_t MV_MixRate; + +static int32_t MV_BuffShift; + +static int32_t MV_TotalMemory; + +static int32_t MV_BufferEmpty[ NumberOfBuffers ]; +char *MV_MixBuffer[ NumberOfBuffers + 1 ]; + +static VoiceNode *MV_Voices = NULL; + +static volatile VoiceNode VoiceList; +static volatile VoiceNode VoicePool; + +static int32_t MV_MixPage = 0; +static int32_t MV_VoiceHandle = MV_MinVoiceHandle; + +static void (*MV_CallBackFunc)(uint32_t) = NULL; +static void (*MV_RecordFunc)(char *ptr, int32_t length) = NULL; +static void (*MV_MixFunction)(VoiceNode *voice, int32_t buffer); + +int32_t MV_MaxVolume = 255; + +char *MV_HarshClipTable; +char *MV_MixDestination; +int16_t *MV_LeftVolume; +int16_t *MV_RightVolume; +int32_t MV_SampleSize = 1; +int32_t MV_RightChannelOffset; + +uint32_t MV_MixPosition; + +int32_t MV_ErrorCode = MV_Ok; + +static int32_t lockdepth = 0; +static int32_t DisableInterrupts(void) +{ + if (lockdepth++ > 0) + { + return 0; + } + SoundDriver_Lock(); + return 0; +} + +static void RestoreInterrupts(int32_t a) +{ + if (--lockdepth > 0) + { + return; + } + SoundDriver_Unlock(); +} + + +/*--------------------------------------------------------------------- + Function: MV_ErrorString + + Returns a pointer to the error message associated with an error + number. A -1 returns a pointer the current error. +---------------------------------------------------------------------*/ + +const char *MV_ErrorString +( + int32_t ErrorNumber +) + +{ + const char *ErrorString; + + switch (ErrorNumber) + { + case MV_Warning : + case MV_Error : + ErrorString = MV_ErrorString(MV_ErrorCode); + break; + + case MV_Ok : + ErrorString = "Multivoc ok."; + break; + + case MV_UnsupportedCard : + ErrorString = "Selected sound card is not supported by Multivoc."; + break; + + case MV_NotInstalled : + ErrorString = "Multivoc not installed."; + break; + + case MV_DriverError : + ErrorString = SoundDriver_ErrorString(SoundDriver_GetError()); + break; + + case MV_NoVoices : + ErrorString = "No free voices available to Multivoc."; + break; + + case MV_NoMem : + ErrorString = "Out of memory in Multivoc."; + break; + + case MV_VoiceNotFound : + ErrorString = "No voice with matching handle found."; + break; + + case MV_InvalidVOCFile : + ErrorString = "Invalid VOC file passed in to Multivoc."; + break; + + case MV_InvalidWAVFile : + ErrorString = "Invalid WAV file passed in to Multivoc."; + break; + + case MV_InvalidVorbisFile : + ErrorString = "Invalid OggVorbis file passed in to Multivoc."; + break; + + case MV_InvalidMixMode : + ErrorString = "Invalid mix mode request in Multivoc."; + break; + + case MV_NullRecordFunction : + ErrorString = "Null record function passed to MV_StartRecording."; + break; + + default : + ErrorString = "Unknown Multivoc error code."; + break; + } + + return(ErrorString); +} + + +/*--------------------------------------------------------------------- + Function: MV_Mix + + Mixes the sound into the buffer. +---------------------------------------------------------------------*/ + +static void MV_Mix +( + VoiceNode *voice, + int32_t buffer +) + +{ + char *start; + int32_t length; + int32_t voclength; + uint32_t position; + uint32_t rate; + uint32_t FixedPointBufferSize; + + if ((voice->length == 0) && (voice->GetSound(voice) != KeepPlaying)) + { + return; + } + + length = MixBufferSize; + FixedPointBufferSize = voice->FixedPointBufferSize; + + MV_MixDestination = MV_MixBuffer[ buffer ]; + MV_LeftVolume = voice->LeftVolume; + MV_RightVolume = voice->RightVolume; + + if ((MV_Channels == 2) && (IS_QUIET(MV_LeftVolume))) + { + MV_LeftVolume = MV_RightVolume; + MV_MixDestination += MV_RightChannelOffset; + } + + // Add this voice to the mix + while (length > 0) + { + start = voice->sound; + rate = voice->RateScale; + position = voice->position; + + // Check if the last sample in this buffer would be + // beyond the length of the sample block + if ((position + FixedPointBufferSize) >= voice->length) + { + if (position < voice->length) + { + voclength = (voice->length - position + rate - voice->channels) / rate; + } + else + { + voice->GetSound(voice); + return; + } + } + else + { + voclength = length; + } + + if (voice->mix) + { + voice->mix(position, rate, start, voclength); + } + + voice->position = MV_MixPosition; + + length -= voclength; + + if (voice->position >= voice->length) + { + // Get the next block of sound + if (voice->GetSound(voice) != KeepPlaying) + { + return; + } + + if (length > 0) + { + // Get the position of the last sample in the buffer + FixedPointBufferSize = voice->RateScale * (length - voice->channels); + } + } + } +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayVoice + + Adds a voice to the play list. +---------------------------------------------------------------------*/ + +void MV_PlayVoice +( + VoiceNode *voice +) + +{ + int32_t flags; + + flags = DisableInterrupts(); + LL_SortedInsertion(&VoiceList, voice, prev, next, VoiceNode, priority); + + RestoreInterrupts(flags); +} + + +/*--------------------------------------------------------------------- + Function: MV_StopVoice + + Removes the voice from the play list and adds it to the free list. +---------------------------------------------------------------------*/ + +void MV_StopVoice +( + VoiceNode *voice +) + +{ + int32_t flags; + + flags = DisableInterrupts(); + + // move the voice from the play list to the free list + LL_Remove(voice, next, prev); + LL_Add((VoiceNode*) &VoicePool, voice, next, prev); + + RestoreInterrupts(flags); + + if (voice->wavetype == Vorbis) + { + MV_ReleaseVorbisVoice(voice); + } +} + + +/*--------------------------------------------------------------------- + Function: MV_ServiceVoc + + Starts playback of the waiting buffer and mixes the next one. + + JBF: no synchronisation happens inside MV_ServiceVoc nor the + supporting functions it calls. This would cause a deadlock + between the mixer thread in the driver vs the nested + locking in the user-space functions of MultiVoc. The call + to MV_ServiceVoc is synchronised in the driver. + + Known functions called by MV_ServiceVoc and its helpers: + MV_Mix (and its MV_Mix*bit* workers) + MV_GetNextVOCBlock + MV_GetNextWAVBlock + MV_SetVoiceMixMode +---------------------------------------------------------------------*/ +void MV_ServiceVoc +( + void +) + +{ + VoiceNode *voice; + VoiceNode *next; + char *buffer; + //int32_t flags; + + // Toggle which buffer we'll mix next + MV_MixPage++; + if (MV_MixPage >= MV_NumberOfBuffers) + { + MV_MixPage -= MV_NumberOfBuffers; + } + + if (MV_ReverbLevel == 0) + { + // Initialize buffer + //Commented out so that the buffer is always cleared. + //This is so the guys at Echo Speech can mix into the + //buffer even when no sounds are playing. + //if ( !MV_BufferEmpty[ MV_MixPage ] ) + { + ClearBuffer_DW(MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2); + MV_BufferEmpty[ MV_MixPage ] = TRUE; + } + } + else + { + char *end; + char *source; + char *dest; + int32_t count; + int32_t length; + + end = MV_MixBuffer[ 0 ] + MV_BufferLength;; + dest = MV_MixBuffer[ MV_MixPage ]; + source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay; + if (source < MV_MixBuffer[ 0 ]) + { + source += MV_BufferLength; + } + + length = MV_BufferSize; + while (length > 0) + { + count = length; + if (source + count > end) + { + count = end - source; + } + + if (MV_Bits == 16) + { + if (MV_ReverbTable != NULL) + { + MV_16BitReverb(source, dest, MV_ReverbTable, count / 2); + } + else + { + MV_16BitReverbFast(source, dest, count / 2, MV_ReverbLevel); + } + } + else + { + if (MV_ReverbTable != NULL) + { + MV_8BitReverb((int8_t *) source, (int8_t *) dest, MV_ReverbTable, count); + } + else + { + MV_8BitReverbFast((int8_t *) source, (int8_t *) dest, count, MV_ReverbLevel); + } + } + + // if we go through the loop again, it means that we've wrapped around the buffer + source = MV_MixBuffer[ 0 ]; + dest += count; + length -= count; + } + } + + // Play any waiting voices + //flags = DisableInterrupts(); + + if (!VoiceList.next) + return; + + for (voice = VoiceList.next; voice != &VoiceList; voice = next) + { + + MV_BufferEmpty[ MV_MixPage ] = FALSE; + + if (!voice->Paused) + MV_MixFunction(voice, MV_MixPage); + + next = voice->next; + + // Is this voice done? + if (!voice->Playing && !voice->Paused) + { + //JBF: prevent a deadlock caused by MV_StopVoice grabbing the mutex again + //MV_StopVoice( voice ); + LL_Remove(voice, next, prev); + LL_Add((VoiceNode*) &VoicePool, voice, next, prev); + + if (MV_CallBackFunc) + { + MV_CallBackFunc(voice->callbackval); + } + } + } + + //RestoreInterrupts(flags); +} + + +/*--------------------------------------------------------------------- + Function: MV_GetNextVOCBlock + + Interperate the information of a VOC format sound file. +---------------------------------------------------------------------*/ + +playbackstatus MV_GetNextVOCBlock +( + VoiceNode *voice +) + +{ + uint8_t *ptr; + int32_t blocktype; + int32_t lastblocktype; + uint32_t blocklength; + uint32_t samplespeed; + uint32_t tc; + int32_t packtype; + int32_t voicemode; + int32_t done; + unsigned BitsPerSample; + unsigned Channels; + unsigned Format; + + if (voice->BlockLength > 0) + { + voice->position -= voice->length; + voice->sound += (voice->length >> 16) * (voice->channels * voice->bits / 8); + voice->length = min(voice->BlockLength, 0x8000); + voice->BlockLength -= voice->length; + voice->length <<= 16; + return(KeepPlaying); + } + + ptr = (uint8_t *)voice->NextBlock; + + voice->Playing = TRUE; + voice->Paused = FALSE; + + voicemode = 0; + lastblocktype = 0; + packtype = 0; + + done = FALSE; + while (!done) + { + // Stop playing if we get a NULL pointer + if (ptr == NULL) + { + voice->Playing = FALSE; + done = TRUE; + break; + } + + blocktype = (int32_t)*ptr; + blocklength = LITTLE32(*(uint32_t *)(ptr + 1)) & 0x00ffffff; + ptr += 4; + + switch (blocktype) + { + case 0 : + // End of data + if ((voice->LoopStart == NULL) || + ((intptr_t) voice->LoopStart >= ((intptr_t) ptr - 4))) + { + voice->Playing = FALSE; + done = TRUE; + } + else + { + voice->NextBlock = voice->LoopStart; + voice->BlockLength = 0; + voice->position = 0; + return MV_GetNextVOCBlock(voice); + } + break; + + case 1 : + // Sound data block + voice->bits = 8; + voice->channels = voicemode + 1; + if (lastblocktype != 8) + { + tc = (uint32_t)*ptr << 8; + packtype = *(ptr + 1); + } + + ptr += 2; + blocklength -= 2; + + samplespeed = 256000000L / (voice->channels * (65536 - tc)); + + // Skip packed or stereo data + if ((packtype != 0) || (voicemode != 0 && voicemode != 1)) + { + ptr += blocklength; + } + else + { + done = TRUE; + } + voicemode = 0; + break; + + case 2 : + // Sound continuation block + samplespeed = voice->SamplingRate; + done = TRUE; + break; + + case 3 : + // Silence + // Not implimented. + ptr += blocklength; + break; + + case 4 : + // Marker + // Not implimented. + ptr += blocklength; + break; + + case 5 : + // ASCII string + // Not implimented. + ptr += blocklength; + break; + + case 6 : + // Repeat begin + if (voice->LoopEnd == NULL) + { + voice->LoopCount = LITTLE16(*(uint16_t *)ptr); + voice->LoopStart = (char *)((intptr_t) ptr + blocklength); + } + ptr += blocklength; + break; + + case 7 : + // Repeat end + ptr += blocklength; + if (lastblocktype == 6) + { + voice->LoopCount = 0; + } + else + { + if ((voice->LoopCount > 0) && (voice->LoopStart != NULL)) + { + ptr = (uint8_t *) voice->LoopStart; + if (voice->LoopCount < 0xffff) + { + voice->LoopCount--; + if (voice->LoopCount == 0) + { + voice->LoopStart = NULL; + } + } + } + } + break; + + case 8 : + // Extended block + voice->bits = 8; + voice->channels = 1; + tc = LITTLE16(*(uint16_t *)ptr); + packtype = *(ptr + 2); + voicemode = *(ptr + 3); + ptr += blocklength; + break; + + case 9 : + // New sound data block + samplespeed = LITTLE32(*(uint32_t *)ptr); + BitsPerSample = (unsigned)*(ptr + 4); + Channels = (unsigned)*(ptr + 5); + Format = (unsigned)LITTLE16(*(uint16_t *)(ptr + 6)); + + if ((BitsPerSample == 8) && (Channels == 1 || Channels == 2) && + (Format == VOC_8BIT)) + { + ptr += 12; + blocklength -= 12; + voice->bits = 8; + voice->channels = Channels; + done = TRUE; + } + else if ((BitsPerSample == 16) && (Channels == 1 || Channels == 2) && + (Format == VOC_16BIT)) + { + ptr += 12; + blocklength -= 12; + voice->bits = 16; + voice->channels = Channels; + done = TRUE; + } + else + { + ptr += blocklength; + } + break; + + default : + // Unknown data. Probably not a VOC file. + voice->Playing = FALSE; + done = TRUE; + break; + } + + lastblocktype = blocktype; + } + + if (voice->Playing) + { + voice->NextBlock = (char *)ptr + blocklength; + voice->sound = (char *)ptr; + + voice->SamplingRate = samplespeed; + voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate; + + // Multiply by MixBufferSize - 1 + voice->FixedPointBufferSize = (voice->RateScale * MixBufferSize) - + voice->RateScale; + + if (voice->LoopEnd != NULL) + { + if (blocklength > (uint32_t)voice->LoopEnd) + { + blocklength = (uint32_t)voice->LoopEnd; + } + else + { + voice->LoopEnd = (char *)blocklength; + } + + voice->LoopStart = voice->sound + (uint32_t)voice->LoopStart; + voice->LoopEnd = voice->sound + (uint32_t)voice->LoopEnd; + voice->LoopSize = voice->LoopEnd - voice->LoopStart; + } + + if (voice->bits == 16) + { + blocklength /= 2; + } + if (voice->channels == 2) + { + blocklength /= 2; + } + + voice->position = 0; + voice->length = min(blocklength, 0x8000); + voice->BlockLength = blocklength - voice->length; + voice->length <<= 16; + + MV_SetVoiceMixMode(voice); + + return(KeepPlaying); + } + + return(NoMoreData); +} + + +/*--------------------------------------------------------------------- + Function: MV_GetNextDemandFeedBlock + + Controls playback of demand fed data. +---------------------------------------------------------------------*/ + +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; + (voice->DemandFeed)(&voice->sound, &voice->BlockLength); + voice->length = min(voice->BlockLength, 0x8000); + voice->BlockLength -= voice->length; + voice->length <<= 16; + + if ((voice->length > 0) && (voice->sound != NULL)) + { + return(KeepPlaying); + } + return(NoMoreData); +} + + +/*--------------------------------------------------------------------- + Function: MV_GetNextRawBlock + + Controls playback of demand fed data. +---------------------------------------------------------------------*/ + +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. +---------------------------------------------------------------------*/ + +playbackstatus MV_GetNextWAVBlock +( + 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_ServiceRecord + + Starts recording of the waiting buffer. +---------------------------------------------------------------------*/ + +static void MV_ServiceRecord +( + void +) + +{ + if (MV_RecordFunc) + { + MV_RecordFunc(MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize, + MixBufferSize); + } + + // Toggle which buffer we'll mix next + MV_MixPage++; + if (MV_MixPage >= NumberOfBuffers) + { + MV_MixPage = 0; + } +} + + +/*--------------------------------------------------------------------- + Function: MV_GetVoice + + Locates the voice with the specified handle. +---------------------------------------------------------------------*/ + +VoiceNode *MV_GetVoice +( + int32_t handle +) + +{ + VoiceNode *voice; + int32_t flags; + + flags = DisableInterrupts(); + + for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next) + { + if (handle == voice->handle) + { + break; + } + } + + RestoreInterrupts(flags); + + if (voice == &VoiceList) + { + MV_SetErrorCode(MV_VoiceNotFound); + voice = 0; + } + + return(voice); +} + + +/*--------------------------------------------------------------------- + Function: MV_VoicePlaying + + Checks if the voice associated with the specified handle is + playing. +---------------------------------------------------------------------*/ + +int32_t MV_VoicePlaying +( + int32_t handle +) + +{ + VoiceNode *voice; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(FALSE); + } + + voice = MV_GetVoice(handle); + + if (voice == NULL) + { + return(FALSE); + } + + return(TRUE); +} + + +/*--------------------------------------------------------------------- + Function: MV_KillAllVoices + + Stops output of all currently active voices. +---------------------------------------------------------------------*/ + +int32_t MV_KillAllVoices +( + void +) + +{ + VoiceNode * voice, * next; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + // Remove all the voices from the list + for (voice = VoiceList.next; voice != &VoiceList; voice = next) + { + next = voice->next; + if (voice->priority < MV_MUSIC_PRIORITY) + { + MV_Kill(voice->handle); + } + } + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_Kill + + Stops output of the voice associated with the specified handle. +---------------------------------------------------------------------*/ + +int32_t MV_Kill +( + int32_t handle +) + +{ + VoiceNode *voice; + int32_t flags; + uint32_t callbackval; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + flags = DisableInterrupts(); + + voice = MV_GetVoice(handle); + if (voice == NULL) + { + RestoreInterrupts(flags); + MV_SetErrorCode(MV_VoiceNotFound); + return(MV_Error); + } + + callbackval = voice->callbackval; + + MV_StopVoice(voice); + + RestoreInterrupts(flags); + + if (MV_CallBackFunc) + { + MV_CallBackFunc(callbackval); + } + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_VoicesPlaying + + Determines the number of currently active voices. +---------------------------------------------------------------------*/ + +int32_t MV_VoicesPlaying +( + void +) + +{ + VoiceNode *voice; + int32_t NumVoices = 0; + int32_t flags; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(0); + } + + flags = DisableInterrupts(); + + for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next) + { + NumVoices++; + } + + RestoreInterrupts(flags); + + return(NumVoices); +} + + +/*--------------------------------------------------------------------- + Function: MV_AllocVoice + + Retrieve an inactive or lower priority voice for output. +---------------------------------------------------------------------*/ + +VoiceNode *MV_AllocVoice +( + int32_t priority +) + +{ + VoiceNode *voice; + VoiceNode *node; + int32_t flags; + +//return( NULL ); + if (MV_Recording) + { + return(NULL); + } + + flags = DisableInterrupts(); + + // Check if we have any free voices + if (LL_Empty(&VoicePool, next, prev)) + { + // check if we have a higher priority than a voice that is playing. + voice = VoiceList.next; + for (node = voice->next; node != &VoiceList; node = node->next) + { + if (node->priority < voice->priority) + { + voice = node; + } + } + + if (priority >= voice->priority) + { + MV_Kill(voice->handle); + } + } + + // Check if any voices are in the voice pool + if (LL_Empty(&VoicePool, next, prev)) + { + // No free voices + RestoreInterrupts(flags); + return(NULL); + } + + voice = VoicePool.next; + LL_Remove(voice, next, prev); + RestoreInterrupts(flags); + + // Find a free voice handle + do + { + MV_VoiceHandle++; + if (MV_VoiceHandle < MV_MinVoiceHandle) + { + MV_VoiceHandle = MV_MinVoiceHandle; + } + } + while (MV_VoicePlaying(MV_VoiceHandle)); + + voice->handle = MV_VoiceHandle; + + return(voice); +} + + +/*--------------------------------------------------------------------- + Function: MV_VoiceAvailable + + Checks if a voice can be play at the specified priority. +---------------------------------------------------------------------*/ + +int32_t MV_VoiceAvailable +( + int32_t priority +) + +{ + VoiceNode *voice; + VoiceNode *node; + int32_t flags; + + // Check if we have any free voices + if (!LL_Empty(&VoicePool, next, prev)) + { + return(TRUE); + } + + flags = DisableInterrupts(); + + // check if we have a higher priority than a voice that is playing. + voice = VoiceList.next; + for (node = VoiceList.next; node != &VoiceList; node = node->next) + { + if (node->priority < voice->priority) + { + voice = node; + } + } + + RestoreInterrupts(flags); + + if ((voice != &VoiceList) && (priority >= voice->priority)) + { + return(TRUE); + } + + return(FALSE); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetVoicePitch + + Sets the pitch for the specified voice. +---------------------------------------------------------------------*/ + +void MV_SetVoicePitch +( + VoiceNode *voice, + uint32_t rate, + int32_t pitchoffset +) + +{ + voice->SamplingRate = rate; + voice->PitchScale = PITCH_GetScale(pitchoffset); + voice->RateScale = (rate * voice->PitchScale) / MV_MixRate; + + // Multiply by MixBufferSize - 1 + voice->FixedPointBufferSize = (voice->RateScale * MixBufferSize) - + voice->RateScale; +} + + +/*--------------------------------------------------------------------- + Function: MV_SetPitch + + Sets the pitch for the voice associated with the specified handle. +---------------------------------------------------------------------*/ + +int32_t MV_SetPitch +( + int32_t handle, + int32_t pitchoffset +) + +{ + VoiceNode *voice; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + voice = MV_GetVoice(handle); + if (voice == NULL) + { + MV_SetErrorCode(MV_VoiceNotFound); + return(MV_Error); + } + + MV_SetVoicePitch(voice, voice->SamplingRate, pitchoffset); + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetFrequency + + Sets the frequency for the voice associated with the specified handle. +---------------------------------------------------------------------*/ + +int32_t MV_SetFrequency +( + int32_t handle, + int32_t frequency +) + +{ + VoiceNode *voice; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + voice = MV_GetVoice(handle); + if (voice == NULL) + { + MV_SetErrorCode(MV_VoiceNotFound); + return(MV_Error); + } + + MV_SetVoicePitch(voice, frequency, 0); + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_GetVolumeTable + + Returns a pointer to the volume table associated with the specified + volume. +---------------------------------------------------------------------*/ + +static int16_t *MV_GetVolumeTable +( + int32_t vol +) + +{ + int32_t volume; + int16_t *table; + + volume = MIX_VOLUME(vol); + + table = (int16_t *) &MV_VolumeTable[ volume ]; + + return(table); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetVoiceMixMode + + Selects which method should be used to mix the voice. + + 8Bit 16Bit 8Bit 16Bit | 8Bit 16Bit 8Bit 16Bit | + Mono Mono Ster Ster | Mono Mono Ster Ster | Mixer + Out Out Out Out | In In In In | +--------------------------+---------------------------+------------- + X | X | Mix8BitMono16 + X | X | Mix8BitMono + X | X | Mix8BitStereo16 + X | X | Mix8BitStereo + X | X | Mix16BitMono16 + X | X | Mix16BitMono + X | X | Mix16BitStereo16 + X | X | Mix16BitStereo +--------------------------+---------------------------+------------- + X | X | Mix16BitStereo16Stereo + X | X | Mix16BitStereo8Stereo + X | X | Mix8BitStereo16Stereo + X | X | Mix8BitStereo8Stereo + X | X | Mix16BitMono16Stereo + X | X | Mix16BitMono8Stereo + X | X | Mix8BitMono16Stereo + X | X | Mix8BitMono8Stereo + +---------------------------------------------------------------------*/ + +void MV_SetVoiceMixMode +( + VoiceNode *voice +) + +{ + //int32_t flags; + int32_t test; + + //flags = DisableInterrupts(); + + test = T_DEFAULT; + if (MV_Bits == 8) + { + test |= T_8BITS; + } + + if (MV_Channels == 1) + { + test |= T_MONO; + } + else + { + if (IS_QUIET(voice->RightVolume)) + { + test |= T_RIGHTQUIET; + } + else if (IS_QUIET(voice->LeftVolume)) + { + test |= T_LEFTQUIET; + } + } + + if (voice->bits == 16) + { + test |= T_16BITSOURCE; + } + + if (voice->channels == 2) + { + test |= T_STEREOSOURCE; + test &= ~(T_RIGHTQUIET | T_LEFTQUIET); + } + + switch (test) + { + case T_8BITS | T_MONO | T_16BITSOURCE : + voice->mix = MV_Mix8BitMono16; + break; + + case T_8BITS | T_MONO : + voice->mix = MV_Mix8BitMono; + break; + + case T_8BITS | T_16BITSOURCE | T_LEFTQUIET : + MV_LeftVolume = MV_RightVolume; + voice->mix = MV_Mix8BitMono16; + break; + + case T_8BITS | T_LEFTQUIET : + MV_LeftVolume = MV_RightVolume; + voice->mix = MV_Mix8BitMono; + break; + + case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET : + voice->mix = MV_Mix8BitMono16; + break; + + case T_8BITS | T_RIGHTQUIET : + voice->mix = MV_Mix8BitMono; + break; + + case T_8BITS | T_16BITSOURCE : + voice->mix = MV_Mix8BitStereo16; + break; + + case T_8BITS : + voice->mix = MV_Mix8BitStereo; + break; + + case T_MONO | T_16BITSOURCE : + voice->mix = MV_Mix16BitMono16; + break; + + case T_MONO : + voice->mix = MV_Mix16BitMono; + break; + + case T_16BITSOURCE | T_LEFTQUIET : + MV_LeftVolume = MV_RightVolume; + voice->mix = MV_Mix16BitMono16; + break; + + case T_LEFTQUIET : + MV_LeftVolume = MV_RightVolume; + voice->mix = MV_Mix16BitMono; + break; + + case T_16BITSOURCE | T_RIGHTQUIET : + voice->mix = MV_Mix16BitMono16; + break; + + case T_RIGHTQUIET : + voice->mix = MV_Mix16BitMono; + break; + + case T_16BITSOURCE : + voice->mix = MV_Mix16BitStereo16; + break; + + case T_SIXTEENBIT_STEREO : + voice->mix = MV_Mix16BitStereo; + break; + + case T_16BITSOURCE | T_STEREOSOURCE: + voice->mix = MV_Mix16BitStereo16Stereo; + break; + + case T_16BITSOURCE | T_STEREOSOURCE | T_8BITS: + voice->mix = MV_Mix8BitStereo16Stereo; + break; + + case T_16BITSOURCE | T_STEREOSOURCE | T_MONO: + voice->mix = MV_Mix16BitMono16Stereo; + break; + + case T_16BITSOURCE | T_STEREOSOURCE | T_8BITS | T_MONO: + voice->mix = MV_Mix8BitMono16Stereo; + break; + + case T_STEREOSOURCE: + voice->mix = MV_Mix16BitStereo8Stereo; + break; + + case T_STEREOSOURCE | T_8BITS: + voice->mix = MV_Mix8BitStereo8Stereo; + break; + + case T_STEREOSOURCE | T_MONO: + voice->mix = MV_Mix16BitMono8Stereo; + break; + + case T_STEREOSOURCE | T_8BITS | T_MONO: + voice->mix = MV_Mix8BitMono8Stereo; + break; + + default : + voice->mix = 0; + } + + //RestoreInterrupts( flags ); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetVoiceVolume + + Sets the stereo and mono volume level of the voice associated + with the specified handle. +---------------------------------------------------------------------*/ + +void MV_SetVoiceVolume +( + VoiceNode *voice, + int32_t vol, + int32_t left, + int32_t right +) + +{ + if (MV_Channels == 1) + { + left = vol; + right = vol; + } + + if (MV_SwapLeftRight) + { + // SBPro uses reversed panning + voice->LeftVolume = MV_GetVolumeTable(right); + voice->RightVolume = MV_GetVolumeTable(left); + } + else + { + voice->LeftVolume = MV_GetVolumeTable(left); + voice->RightVolume = MV_GetVolumeTable(right); + } + + MV_SetVoiceMixMode(voice); +} + +/*--------------------------------------------------------------------- +Function: MV_PauseVoice + +Pauses the voice associated with the specified handle +without stoping the sound. +---------------------------------------------------------------------*/ + +int32_t MV_PauseVoice +( + int32_t handle, + int32_t pause +) + +{ + VoiceNode *voice; + int32_t flags; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + flags = DisableInterrupts(); + + voice = MV_GetVoice(handle); + if (voice == NULL) + { + RestoreInterrupts(flags); + MV_SetErrorCode(MV_VoiceNotFound); + return(MV_Warning); + } + + voice->Paused = pause; + + RestoreInterrupts(flags); + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_EndLooping + + Stops the voice associated with the specified handle from looping + without stoping the sound. +---------------------------------------------------------------------*/ + +int32_t MV_EndLooping +( + int32_t handle +) + +{ + VoiceNode *voice; + int32_t flags; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + flags = DisableInterrupts(); + + voice = MV_GetVoice(handle); + if (voice == NULL) + { + RestoreInterrupts(flags); + MV_SetErrorCode(MV_VoiceNotFound); + return(MV_Warning); + } + + voice->LoopCount = 0; + voice->LoopStart = NULL; + voice->LoopEnd = NULL; + + RestoreInterrupts(flags); + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetPan + + Sets the stereo and mono volume level of the voice associated + with the specified handle. +---------------------------------------------------------------------*/ + +int32_t MV_SetPan +( + int32_t handle, + int32_t vol, + int32_t left, + int32_t right +) + +{ + VoiceNode *voice; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + voice = MV_GetVoice(handle); + if (voice == NULL) + { + MV_SetErrorCode(MV_VoiceNotFound); + return(MV_Warning); + } + + MV_SetVoiceVolume(voice, vol, left, right); + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_Pan3D + + Set the angle and distance from the listener of the voice associated + with the specified handle. +---------------------------------------------------------------------*/ + +int32_t MV_Pan3D +( + int32_t handle, + int32_t angle, + int32_t distance +) + +{ + int32_t left; + int32_t right; + int32_t mid; + int32_t volume; + int32_t status; + + if (distance < 0) + { + distance = -distance; + angle += MV_NumPanPositions / 2; + } + + volume = MIX_VOLUME(distance); + + // Ensure angle is within 0 - 31 + angle &= MV_MaxPanPosition; + + left = MV_PanTable[ angle ][ volume ].left; + right = MV_PanTable[ angle ][ volume ].right; + mid = max(0, 255 - distance); + + status = MV_SetPan(handle, mid, left, right); + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetReverb + + Sets the level of reverb to add to mix. +---------------------------------------------------------------------*/ + +void MV_SetReverb +( + int32_t reverb +) + +{ + MV_ReverbLevel = MIX_VOLUME(reverb); + MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ]; +} + + +/*--------------------------------------------------------------------- + Function: MV_SetFastReverb + + Sets the level of reverb to add to mix. +---------------------------------------------------------------------*/ + +void MV_SetFastReverb +( + int32_t reverb +) + +{ + MV_ReverbLevel = max(0, min(16, reverb)); + MV_ReverbTable = NULL; +} + + +/*--------------------------------------------------------------------- + Function: MV_GetMaxReverbDelay + + Returns the maximum delay time for reverb. +---------------------------------------------------------------------*/ + +int32_t MV_GetMaxReverbDelay +( + void +) + +{ + int32_t maxdelay; + + maxdelay = MixBufferSize * MV_NumberOfBuffers; + + return maxdelay; +} + + +/*--------------------------------------------------------------------- + Function: MV_GetReverbDelay + + Returns the current delay time for reverb. +---------------------------------------------------------------------*/ + +int32_t MV_GetReverbDelay +( + void +) + +{ + return MV_ReverbDelay / MV_SampleSize; +} + + +/*--------------------------------------------------------------------- + Function: MV_SetReverbDelay + + Sets the delay level of reverb to add to mix. +---------------------------------------------------------------------*/ + +void MV_SetReverbDelay +( + int32_t delay +) + +{ + int32_t maxdelay; + + maxdelay = MV_GetMaxReverbDelay(); + MV_ReverbDelay = max(MixBufferSize, min(delay, maxdelay)); + MV_ReverbDelay *= MV_SampleSize; +} + + +/*--------------------------------------------------------------------- + Function: MV_SetMixMode + + Prepares Multivoc to play stereo of mono digitized sounds. +---------------------------------------------------------------------*/ + +int32_t MV_SetMixMode +( + int32_t numchannels, + int32_t samplebits +) + +{ + int32_t mode; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + mode = 0; + if (numchannels == 2) + { + mode |= STEREO; + } + if (samplebits == 16) + { + mode |= SIXTEEN_BIT; + } + + MV_MixMode = mode; + + MV_Channels = 1; + if (MV_MixMode & STEREO) + { + MV_Channels = 2; + } + + MV_Bits = 8; + if (MV_MixMode & SIXTEEN_BIT) + { + MV_Bits = 16; + } + + MV_BuffShift = 7 + MV_Channels; + MV_SampleSize = sizeof(MONO8) * MV_Channels; + + if (MV_Bits == 8) + { + MV_Silence = SILENCE_8BIT; + } + else + { + MV_Silence = SILENCE_16BIT; + MV_BuffShift += 1; + MV_SampleSize *= 2; + } + + MV_BufferSize = MixBufferSize * MV_SampleSize; + MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize; + MV_BufferLength = TotalBufferSize; + + MV_RightChannelOffset = MV_SampleSize / 2; + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_StartPlayback + + Starts the sound playback engine. +---------------------------------------------------------------------*/ + +int32_t MV_StartPlayback +( + void +) + +{ + int32_t status; + int32_t buffer; + + // Initialize the buffers + ClearBuffer_DW(MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2); + for (buffer = 0; buffer < MV_NumberOfBuffers; buffer++) + { + MV_BufferEmpty[ buffer ] = TRUE; + } + + // Set the mix buffer variables + MV_MixPage = 1; + + MV_MixFunction = MV_Mix; + +//JIM +// MV_MixRate = MV_RequestedMixRate; +// return( MV_Ok ); + + // Start playback + status = SoundDriver_BeginPlayback(MV_MixBuffer[0], MV_BufferSize, + MV_NumberOfBuffers, MV_ServiceVoc); + if (status != MV_Ok) + { + MV_SetErrorCode(MV_DriverError); + return MV_Error; + } + + MV_MixRate = MV_RequestedMixRate; + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_StopPlayback + + Stops the sound playback engine. +---------------------------------------------------------------------*/ + +void MV_StopPlayback +( + void +) + +{ + VoiceNode *voice; + VoiceNode *next; + int32_t flags; + + // Stop sound playback + SoundDriver_StopPlayback(); + + // Make sure all callbacks are done. + flags = DisableInterrupts(); + + for (voice = VoiceList.next; voice != &VoiceList; voice = next) + { + next = voice->next; + + MV_StopVoice(voice); + + if (MV_CallBackFunc) + { + MV_CallBackFunc(voice->callbackval); + } + } + + RestoreInterrupts(flags); +} + + +/*--------------------------------------------------------------------- + Function: MV_StartRecording + + Starts the sound recording engine. +---------------------------------------------------------------------*/ + +int32_t MV_StartRecording +( + int32_t MixRate, + void (*function)(char *ptr, int32_t length) +) + +{ + MV_SetErrorCode(MV_UnsupportedCard); + return(MV_Error); +} + + +/*--------------------------------------------------------------------- + Function: MV_StopRecord + + Stops the sound record engine. +---------------------------------------------------------------------*/ + +void MV_StopRecord +( + void +) + +{ +} + + +/*--------------------------------------------------------------------- + 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->BlockLength = 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); +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayRaw + + Begin playback of sound data with the given sound levels and + priority. +---------------------------------------------------------------------*/ + +int32_t MV_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 status; + + status = MV_PlayLoopedRaw(ptr, length, NULL, NULL, rate, pitchoffset, + vol, left, right, priority, callbackval); + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayLoopedRaw + + Begin playback of sound data with the given sound levels and + priority. +---------------------------------------------------------------------*/ + +int32_t MV_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 +) + +{ + VoiceNode *voice; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + // Request a voice from the voice pool + voice = MV_AllocVoice(priority); + if (voice == NULL) + { + MV_SetErrorCode(MV_NoVoices); + return(MV_Error); + } + + voice->wavetype = Raw; + voice->bits = 8; + voice->channels = 1; + voice->GetSound = MV_GetNextRawBlock; + voice->Playing = TRUE; + voice->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 = (voice->LoopEnd - voice->LoopStart) + 1; + + MV_SetVoicePitch(voice, rate, pitchoffset); + MV_SetVoiceVolume(voice, vol, left, right); + MV_PlayVoice(voice); + + return(voice->handle); +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayWAV + + Begin playback of sound data with the given sound levels and + priority. +---------------------------------------------------------------------*/ + +int32_t MV_PlayWAV +( + 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 status; + + status = MV_PlayLoopedWAV(ptr, length, -1, -1, pitchoffset, vol, left, right, + priority, callbackval); + + return(status); +} + + +/*--------------------------------------------------------------------- + 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 pitchoffset, + int32_t angle, + int32_t distance, + int32_t priority, + uint32_t callbackval +) + +{ + int32_t left; + int32_t right; + int32_t mid; + int32_t volume; + int32_t status; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + if (distance < 0) + { + distance = -distance; + angle += MV_NumPanPositions / 2; + } + + volume = MIX_VOLUME(distance); + + // Ensure angle is within 0 - 31 + angle &= MV_MaxPanPosition; + + left = MV_PanTable[ angle ][ volume ].left; + right = MV_PanTable[ angle ][ volume ].right; + mid = max(0, 255 - distance); + + status = MV_PlayWAV(ptr, length, pitchoffset, mid, left, right, priority, + callbackval); + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayLoopedWAV + + Begin playback of sound data with the given sound levels and + priority. +---------------------------------------------------------------------*/ + +int32_t MV_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 +) + +{ + riff_header riff; + format_header format; + data_header data; + VoiceNode *voice; + int32_t length; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + memcpy(&riff, ptr, sizeof(riff_header)); + riff.file_size = LITTLE32(riff.file_size); + riff.format_size = LITTLE32(riff.format_size); + + if ((memcmp(riff.RIFF, "RIFF", 4) != 0) || + (memcmp(riff.WAVE, "WAVE", 4) != 0) || + (memcmp(riff.fmt, "fmt ", 4) != 0)) + { + MV_SetErrorCode(MV_InvalidWAVFile); + return(MV_Error); + } + + memcpy(&format, ptr + sizeof(riff_header), sizeof(format_header)); + format.wFormatTag = LITTLE16(format.wFormatTag); + format.nChannels = LITTLE16(format.nChannels); + format.nSamplesPerSec = LITTLE32(format.nSamplesPerSec); + format.nAvgBytesPerSec = LITTLE32(format.nAvgBytesPerSec); + format.nBlockAlign = LITTLE16(format.nBlockAlign); + format.nBitsPerSample = LITTLE16(format.nBitsPerSample); + + memcpy(&data, ptr + sizeof(riff_header) + riff.format_size, sizeof(data_header)); + data.size = LITTLE32(data.size); + + // Check if it's PCM data. + if (format.wFormatTag != 1) + { + MV_SetErrorCode(MV_InvalidWAVFile); + return(MV_Error); + } + + if (format.nChannels != 1 && format.nChannels != 2) + { + MV_SetErrorCode(MV_InvalidWAVFile); + return(MV_Error); + } + + if ((format.nBitsPerSample != 8) && + (format.nBitsPerSample != 16)) + { + MV_SetErrorCode(MV_InvalidWAVFile); + return(MV_Error); + } + + if (memcmp(data.DATA, "data", 4) != 0) + { + MV_SetErrorCode(MV_InvalidWAVFile); + 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 = WAV; + voice->bits = format.nBitsPerSample; + voice->channels = format.nChannels; + voice->GetSound = MV_GetNextWAVBlock; + + length = data.size; + if (voice->bits == 16) + { + data.size &= ~1; + length /= 2; + } + if (voice->channels == 2) + { + data.size &= ~1; + length /= 2; + } + + voice->Playing = TRUE; + voice->DemandFeed = NULL; + voice->LoopStart = NULL; + voice->LoopCount = 0; + voice->position = 0; + voice->length = 0; + voice->BlockLength = length; + voice->NextBlock = (char *)((intptr_t) ptr + sizeof(riff_header) + riff.format_size + sizeof(data_header)); + voice->next = NULL; + voice->prev = NULL; + voice->priority = priority; + voice->callbackval = callbackval; + voice->LoopStart = loopstart >= 0 ? voice->NextBlock : NULL; + voice->LoopEnd = NULL; + voice->LoopSize = length; + + MV_SetVoicePitch(voice, format.nSamplesPerSec, pitchoffset); + MV_SetVoiceVolume(voice, vol, left, right); + MV_PlayVoice(voice); + + return(voice->handle); +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayVOC3D + + Begin playback of sound data at specified angle and distance + from listener. +---------------------------------------------------------------------*/ + +int32_t MV_PlayVOC3D +( + char *ptr, + uint32_t ptrlength, + int32_t pitchoffset, + int32_t angle, + int32_t distance, + int32_t priority, + uint32_t callbackval +) + +{ + int32_t left; + int32_t right; + int32_t mid; + int32_t volume; + int32_t status; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + if (distance < 0) + { + distance = -distance; + angle += MV_NumPanPositions / 2; + } + + volume = MIX_VOLUME(distance); + + // Ensure angle is within 0 - 31 + angle &= MV_MaxPanPosition; + + left = MV_PanTable[ angle ][ volume ].left; + right = MV_PanTable[ angle ][ volume ].right; + mid = max(0, 255 - distance); + + status = MV_PlayVOC(ptr, ptrlength, pitchoffset, mid, left, right, priority, + callbackval); + + return(status); +} + + +/*--------------------------------------------------------------------- + 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 pitchoffset, + int32_t vol, + int32_t left, + int32_t right, + int32_t priority, + uint32_t callbackval +) + +{ + int32_t status; + + status = MV_PlayLoopedVOC(ptr, ptrlength, -1, -1, pitchoffset, vol, left, right, + priority, callbackval); + + return(status); +} + + +/*--------------------------------------------------------------------- + Function: MV_PlayLoopedVOC + + Begin playback of sound data with the given sound levels and + priority. +---------------------------------------------------------------------*/ + +int32_t MV_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 +) + +{ + VoiceNode *voice; + int32_t status; + + if (!MV_Installed) + { + MV_SetErrorCode(MV_NotInstalled); + return(MV_Error); + } + + // Make sure it's a valid VOC file. + status = memcmp(ptr, "Creative Voice File", 19); + if (status != 0) + { + MV_SetErrorCode(MV_InvalidVOCFile); + 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 = VOC; + voice->bits = 8; + voice->channels = 1; + voice->GetSound = MV_GetNextVOCBlock; + voice->NextBlock = ptr + LITTLE16(*(uint16_t *)(ptr + 0x14)); + voice->DemandFeed = NULL; + voice->LoopStart = NULL; + voice->LoopCount = 0; + voice->BlockLength = 0; + voice->PitchScale = PITCH_GetScale(pitchoffset); + voice->length = 0; + voice->next = NULL; + voice->prev = NULL; + voice->priority = priority; + voice->callbackval = callbackval; + voice->LoopStart = loopstart >= 0 ? voice->NextBlock : 0; + voice->LoopEnd = 0; + voice->LoopSize = loopend - loopstart + 1; + + if (loopstart < 0) + { + voice->LoopStart = NULL; + voice->LoopEnd = NULL; + } + + MV_SetVoiceVolume(voice, vol, left, right); + MV_PlayVoice(voice); + + return(voice->handle); +} + + +/*--------------------------------------------------------------------- + Function: MV_CreateVolumeTable + + Create the table used to convert sound data to a specific volume + level. +---------------------------------------------------------------------*/ + +void MV_CreateVolumeTable +( + int32_t index, + int32_t volume, + int32_t MaxVolume +) + +{ + int32_t val; + int32_t level; + int32_t i; + + level = (volume * MaxVolume) / MV_MaxTotalVolume; + if (MV_Bits == 16) + { + for (i = 0; i < 65536; i += 256) + { + val = i - 0x8000; + val *= level; + val /= MV_MaxVolume; + MV_VolumeTable[ index ][ i / 256 ] = val; + } + } + else + { + for (i = 0; i < 256; i++) + { + val = i - 0x80; + val *= level; + val /= MV_MaxVolume; + MV_VolumeTable[ volume ][ i ] = val; + } + } +} + + +/*--------------------------------------------------------------------- + Function: MV_CalcVolume + + Create the table used to convert sound data to a specific volume + level. +---------------------------------------------------------------------*/ + +void MV_CalcVolume +( + int32_t MaxVolume +) + +{ + int32_t volume; + + for (volume = 0; volume < 128; volume++) + { + MV_HarshClipTable[ volume ] = 0; + MV_HarshClipTable[ volume + 384 ] = 255; + } + for (volume = 0; volume < 256; volume++) + { + MV_HarshClipTable[ volume + 128 ] = volume; + } + + // For each volume level, create a translation table with the + // appropriate volume calculated. + for (volume = 0; volume <= MV_MaxVolume; volume++) + { + MV_CreateVolumeTable(volume, volume, MaxVolume); + } +} + + +/*--------------------------------------------------------------------- + Function: MV_CalcPanTable + + Create the table used to determine the stereo volume level of + a sound located at a specific angle and distance from the listener. +---------------------------------------------------------------------*/ + +void MV_CalcPanTable +( + void +) + +{ + int32_t level; + int32_t angle; + int32_t distance; + int32_t HalfAngle; + int32_t ramp; + + HalfAngle = (MV_NumPanPositions / 2); + + for (distance = 0; distance <= MV_MaxVolume; distance++) + { + level = (255 * (MV_MaxVolume - distance)) / MV_MaxVolume; + for (angle = 0; angle <= HalfAngle / 2; angle++) + { + ramp = level - ((level * angle) / + (MV_NumPanPositions / 4)); + + MV_PanTable[ angle ][ distance ].left = ramp; + MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp; + MV_PanTable[ HalfAngle + angle ][ distance ].left = level; + MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level; + + MV_PanTable[ angle ][ distance ].right = level; + MV_PanTable[ HalfAngle - angle ][ distance ].right = level; + MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp; + MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp; + } + } +} + + +/*--------------------------------------------------------------------- + Function: MV_SetVolume + + Sets the volume of digitized sound playback. +---------------------------------------------------------------------*/ + +void MV_SetVolume +( + int32_t volume +) + +{ + volume = max(0, volume); + volume = min(volume, MV_MaxTotalVolume); + + MV_TotalVolume = volume; + + // Calculate volume table + MV_CalcVolume(volume); +} + + +/*--------------------------------------------------------------------- + Function: MV_GetVolume + + Returns the volume of digitized sound playback. +---------------------------------------------------------------------*/ + +int32_t MV_GetVolume +( + void +) + +{ + return(MV_TotalVolume); +} + + +/*--------------------------------------------------------------------- + Function: MV_SetCallBack + + Set the function to call when a voice stops. +---------------------------------------------------------------------*/ + +void MV_SetCallBack +( + void (*function)(uint32_t) +) + +{ + MV_CallBackFunc = function; +} + + +/*--------------------------------------------------------------------- + Function: MV_SetReverseStereo + + Set the orientation of the left and right channels. +---------------------------------------------------------------------*/ + +void MV_SetReverseStereo +( + int32_t setting +) + +{ + MV_SwapLeftRight = setting; +} + + +/*--------------------------------------------------------------------- + Function: MV_GetReverseStereo + + Returns the orientation of the left and right channels. +---------------------------------------------------------------------*/ + +int32_t MV_GetReverseStereo +( + void +) + +{ + return(MV_SwapLeftRight); +} + + +/*--------------------------------------------------------------------- + Function: MV_Init + + Perform the initialization of variables and memory used by + Multivoc. +---------------------------------------------------------------------*/ + +int32_t MV_Init +( + int32_t soundcard, + int32_t MixRate, + int32_t Voices, + int32_t numchannels, + int32_t samplebits, + void * initdata +) + +{ + char *ptr; + int32_t status; + int32_t buffer; + int32_t index; + + if (MV_Installed) + { + MV_Shutdown(); + } + + MV_SetErrorCode(MV_Ok); + + MV_TotalMemory = Voices * sizeof(VoiceNode) + sizeof(HARSH_CLIP_TABLE_8) + TotalBufferSize; + ptr = (char *) malloc(MV_TotalMemory); + if (!ptr) + { + MV_SetErrorCode(MV_NoMem); + return(MV_Error); + } + + MV_Voices = (VoiceNode *)ptr; + ptr += Voices * sizeof(VoiceNode); + + MV_HarshClipTable = ptr; + ptr += sizeof(HARSH_CLIP_TABLE_8); + + // Set number of voices before calculating volume table + MV_MaxVoices = Voices; + + LL_Reset((VoiceNode*) &VoiceList, next, prev); + LL_Reset((VoiceNode*) &VoicePool, next, prev); + + for (index = 0; index < Voices; index++) + { + LL_Add((VoiceNode*) &VoicePool, &MV_Voices[ index ], next, prev); + } + + MV_SetReverseStereo(FALSE); + + ASS_SoundDriver = soundcard; + + // Initialize the sound card + status = SoundDriver_Init(MixRate, numchannels, samplebits, initdata); + if (status != MV_Ok) + { + MV_SetErrorCode(MV_DriverError); + } + + if (MV_ErrorCode != MV_Ok) + { + status = MV_ErrorCode; + + free(MV_Voices); + MV_Voices = NULL; + MV_HarshClipTable = NULL; + MV_TotalMemory = 0; + + MV_SetErrorCode(status); + return(MV_Error); + } + + MV_Installed = TRUE; + MV_CallBackFunc = NULL; + MV_RecordFunc = NULL; + MV_Recording = FALSE; + MV_ReverbLevel = 0; + MV_ReverbTable = NULL; + + // Set the sampling rate + MV_RequestedMixRate = MixRate; + + // Set Mixer to play stereo digitized sound + MV_SetMixMode(numchannels, samplebits); + MV_ReverbDelay = MV_BufferSize * 3; + + // Make sure we don't cross a physical page + MV_MixBuffer[ MV_NumberOfBuffers ] = ptr; + for (buffer = 0; buffer < MV_NumberOfBuffers; buffer++) + { + MV_MixBuffer[ buffer ] = ptr; + ptr += MV_BufferSize; + } + + // Calculate pan table + MV_CalcPanTable(); + + MV_SetVolume(MV_MaxTotalVolume); + + // Start the playback engine + status = MV_StartPlayback(); + if (status != MV_Ok) + { + // Preserve error code while we shutdown. + status = MV_ErrorCode; + MV_Shutdown(); + MV_SetErrorCode(status); + return(MV_Error); + } + + return(MV_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MV_Shutdown + + Restore any resources allocated by Multivoc back to the system. +---------------------------------------------------------------------*/ + +int32_t MV_Shutdown +( + void +) + +{ + int32_t buffer; + + if (!MV_Installed) + { + return(MV_Ok); + } + + MV_KillAllVoices(); + + MV_Installed = FALSE; + + // Stop the sound recording engine + if (MV_Recording) + { + MV_StopRecord(); + } + + // Stop the sound playback engine + MV_StopPlayback(); + + // Shutdown the sound card + SoundDriver_Shutdown(); + + // Free any voices we allocated + free(MV_Voices); + MV_Voices = NULL; + MV_TotalMemory = 0; + + LL_Reset((VoiceNode*) &VoiceList, next, prev); + LL_Reset((VoiceNode*) &VoicePool, next, prev); + + MV_MaxVoices = 1; + + // Release the descriptor from our mix buffer + for (buffer = 0; buffer < NumberOfBuffers; buffer++) + { + MV_MixBuffer[ buffer ] = NULL; + } + + return(MV_Ok); +} + +// vim:ts=3:expandtab: diff --git a/polymer/eduke32/source/jaudiolib/src/multivoc.h b/polymer/eduke32/source/jaudiolib/src/multivoc.h new file mode 100644 index 000000000..9c42ecd1d --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/multivoc.h @@ -0,0 +1,119 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + file: MULTIVOC.H + + author: James R. Dose + date: December 20, 1993 + + Public header for MULTIVOC.C + + (c) Copyright 1993 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#ifndef __MULTIVOC_H +#define __MULTIVOC_H + +#define MV_MinVoiceHandle 1 + +extern int32_t MV_ErrorCode; + +enum MV_Errors + { + MV_Warning = -2, + MV_Error = -1, + MV_Ok = 0, + MV_UnsupportedCard, + MV_NotInstalled, + MV_DriverError, + MV_NoVoices, + MV_NoMem, + MV_VoiceNotFound, + MV_InvalidVOCFile, + MV_InvalidWAVFile, + MV_InvalidVorbisFile, + MV_InvalidMixMode, + MV_NullRecordFunction + }; + +const char *MV_ErrorString( int32_t ErrorNumber ); +int32_t MV_VoicePlaying( int32_t handle ); +int32_t MV_KillAllVoices( void ); +int32_t MV_Kill( int32_t handle ); +int32_t MV_VoicesPlaying( void ); +int32_t MV_VoiceAvailable( int32_t priority ); +int32_t MV_SetPitch( int32_t handle, int32_t pitchoffset ); +int32_t MV_SetFrequency( int32_t handle, int32_t frequency ); +int32_t MV_PauseVoice( int32_t handle, int32_t pause ); +int32_t MV_EndLooping( int32_t handle ); +int32_t MV_SetPan( int32_t handle, int32_t vol, int32_t left, int32_t right ); +int32_t MV_Pan3D( int32_t handle, int32_t angle, int32_t distance ); +void MV_SetReverb( int32_t reverb ); +void MV_SetFastReverb( int32_t reverb ); +int32_t MV_GetMaxReverbDelay( void ); +int32_t MV_GetReverbDelay( void ); +void MV_SetReverbDelay( int32_t delay ); +int32_t MV_SetMixMode( int32_t numchannels, int32_t samplebits ); +int32_t MV_StartPlayback( void ); +void MV_StopPlayback( void ); +int32_t MV_StartRecording( int32_t MixRate, void ( *function )( char *ptr, int32_t length ) ); +void MV_StopRecord( 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, + unsigned rate, int32_t pitchoffset, int32_t vol, int32_t left, + int32_t right, int32_t priority, uint32_t callbackval ); +int32_t MV_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 ); +int32_t MV_PlayWAV( 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 MV_PlayWAV3D( char *ptr, uint32_t length, int32_t pitchoffset, int32_t angle, int32_t distance, + int32_t priority, uint32_t callbackval ); +int32_t MV_PlayLoopedWAV( 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 MV_PlayVOC3D( char *ptr, uint32_t length, int32_t pitchoffset, int32_t angle, int32_t distance, + int32_t priority, uint32_t callbackval ); +int32_t MV_PlayVOC( 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 MV_PlayLoopedVOC( 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 MV_PlayVorbis3D( char *ptr, uint32_t length, int32_t pitchoffset, int32_t angle, int32_t distance, + int32_t priority, uint32_t callbackval ); +int32_t MV_PlayVorbis( 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 MV_PlayLoopedVorbis( 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 ); +void MV_CreateVolumeTable( int32_t index, int32_t volume, int32_t MaxVolume ); +void MV_SetVolume( int32_t volume ); +int32_t MV_GetVolume( void ); +void MV_SetCallBack( void ( *function )( uint32_t ) ); +void MV_SetReverseStereo( int32_t setting ); +int32_t MV_GetReverseStereo( void ); +int32_t MV_Init( int32_t soundcard, int32_t MixRate, int32_t Voices, int32_t numchannels, + int32_t samplebits, void * initdata ); +int32_t MV_Shutdown( void ); + +#endif diff --git a/polymer/eduke32/source/jaudiolib/src/pitch.c b/polymer/eduke32/source/jaudiolib/src/pitch.c new file mode 100644 index 000000000..824f0cd04 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/pitch.c @@ -0,0 +1,187 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + module: PITCH.C + + author: James R. Dose + date: June 14, 1993 + + Routines for pitch scaling. + + (c) Copyright 1993 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#include +//#include +#include "pitch.h" + +#define MAXDETUNE 25 + +static uint32_t PitchTable[ 12 ][ MAXDETUNE ] = + { + { 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c, + 0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907, + 0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8, + 0x10e98 }, + { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5, + 0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9, + 0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06, + 0x11eaf }, + { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409, + 0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b, + 0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08, + 0x12fbc }, + { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566, + 0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c, + 0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d, + 0x141cb }, + { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc, + 0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea, + 0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424, + 0x154ee }, + { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a, + 0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5, + 0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e, + 0x16934 }, + { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1, + 0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce, + 0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc, + 0x17eae }, + { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2, + 0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17, + 0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480, + 0x1956f }, + { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00, + 0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4, + 0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d, + 0x1ad8b }, + { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f, + 0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8, + 0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609, + 0x1c716 }, + { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93, + 0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839, + 0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109, + 0x1e225 }, + { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24, + 0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e, + 0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3, + 0x1fed1 } + }; + + +//static int32_t PITCH_Installed = FALSE; + + +/*--------------------------------------------------------------------- + Function: PITCH_Init + + Initializes pitch table. +---------------------------------------------------------------------*/ +/* +void PITCH_Init + ( + void + ) + + { + int32_t note; + int32_t detune; + + if ( !PITCH_Installed ) + { + for( note = 0; note < 12; note++ ) + { + for( detune = 0; detune < MAXDETUNE; detune++ ) + { + PitchTable[ note ][ detune ] = 0x10000 * + pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) ); + } + } + + PITCH_Installed = TRUE; + } + } +*/ + + +/*--------------------------------------------------------------------- + Function: PITCH_GetScale + + Returns a fixed-point value to scale number the specified amount. +---------------------------------------------------------------------*/ + +uint32_t PITCH_GetScale + ( + int32_t pitchoffset + ) + + { + uint32_t scale; + int32_t octaveshift; + int32_t noteshift; + int32_t note; + int32_t detune; + +// if ( !PITCH_Installed ) +// { +// PITCH_Init(); +// } + + if ( pitchoffset == 0 ) + { + return( PitchTable[ 0 ][ 0 ] ); + } + + noteshift = pitchoffset % 1200; + if ( noteshift < 0 ) + { + noteshift += 1200; + } + + note = noteshift / 100; + detune = ( noteshift % 100 ) / ( 100 / MAXDETUNE ); + octaveshift = ( pitchoffset - noteshift ) / 1200; + + if ( detune < 0 ) + { + detune += ( 100 / MAXDETUNE ); + note--; + if ( note < 0 ) + { + note += 12; + octaveshift--; + } + } + + scale = PitchTable[ note ][ detune ]; + + if ( octaveshift < 0 ) + { + scale >>= -octaveshift; + } + else + { + scale <<= octaveshift; + } + + return( scale ); + } + diff --git a/polymer/eduke32/source/jaudiolib/src/pitch.h b/polymer/eduke32/source/jaudiolib/src/pitch.h new file mode 100644 index 000000000..8bead2435 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/pitch.h @@ -0,0 +1,47 @@ +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/********************************************************************** + module: PITCH.H + + author: James R. Dose + date: June 14, 1994 + + Public header for PITCH.C + + (c) Copyright 1994 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#ifndef __PITCH_H +#define __PITCH_H + +#include "inttypes.h" + +enum PITCH_ERRORS + { + PITCH_Warning = -2, + PITCH_Error = -1, + PITCH_Ok = 0, + }; + +//void PITCH_Init( void ); +uint32_t PITCH_GetScale( int32_t pitchoffset ); +void PITCH_UnlockMemory( void ); +int32_t PITCH_LockMemory( void ); +#endif diff --git a/polymer/eduke32/source/jaudiolib/src/vorbis.c b/polymer/eduke32/source/jaudiolib/src/vorbis.c new file mode 100644 index 000000000..1688e0e42 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/src/vorbis.c @@ -0,0 +1,424 @@ +/* + Copyright (C) 2009 Jonathon Fowler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +/** + * OggVorbis source support for MultiVoc + */ + +#ifdef __APPLE__ +# include +#else +# include "vorbis/vorbisfile.h" +#endif + +#include +#include +#include +#include +#include +#include "pitch.h" +#include "multivoc.h" +#include "_multivc.h" + +#define min(x,y) ((x) < (y) ? (x) : (y)) +#define max(x,y) ((x) > (y) ? (x) : (y)) + + +typedef struct { + void * ptr; + size_t length; + size_t pos; + + OggVorbis_File vf; + + char block[0x8000]; + int32_t blockused; + int32_t lastbitstream; +} vorbis_data; + +static size_t read_vorbis(void * ptr, size_t size, size_t nmemb, void * datasource) +{ + vorbis_data * vorb = (vorbis_data *) datasource; + size_t nread = 0; + size_t bytes; + + errno = 0; + + if (vorb->length == vorb->pos) { + return 0; + } + + for (; nmemb > 0; nmemb--, nread++) { + bytes = vorb->length - vorb->pos; + if (size < bytes) { + bytes = size; + } + + memcpy(ptr, vorb->ptr + vorb->pos, bytes); + vorb->pos += bytes; + ptr += bytes; + + if (vorb->length == vorb->pos) { + nread++; + break; + } + } + + return nread; +} + +static int32_t seek_vorbis(void * datasource, ogg_int64_t offset, int32_t whence) +{ + vorbis_data * vorb = (vorbis_data *) datasource; + + switch (whence) { + case SEEK_SET: vorb->pos = 0; break; + case SEEK_CUR: break; + case SEEK_END: vorb->pos = vorb->length; break; + } + + vorb->pos += offset; + if (vorb->pos < 0) { + vorb->pos = 0; + } else if (vorb->pos > vorb->length) { + vorb->pos = vorb->length; + } + + return vorb->pos; +} + +static int32_t close_vorbis(void * datasource) +{ + return 0; +} + +static int32_t tell_vorbis(void * datasource) +{ + vorbis_data * vorb = (vorbis_data *) datasource; + + return vorb->pos; +} + +static ov_callbacks vorbis_callbacks = { + read_vorbis, + seek_vorbis, + close_vorbis, + tell_vorbis +}; + + +/*--------------------------------------------------------------------- +Function: MV_GetNextVorbisBlock + +Controls playback of OggVorbis data +---------------------------------------------------------------------*/ + +playbackstatus MV_GetNextVorbisBlock +( + VoiceNode *voice + ) + +{ + vorbis_data * vd = (vorbis_data *) voice->extra; + int32_t bytes, bytesread; + int32_t bitstream, err; + + voice->Playing = TRUE; + + 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 ); + } + + bytesread = 0; + do { + bytes = ov_read(&vd->vf, vd->block + bytesread, sizeof(vd->block) - bytesread, 0, 2, 1, &bitstream); + //fprintf(stderr, "ov_read = %d\n", bytes); + if (bytes == OV_HOLE) continue; + if (bytes == 0) { + if (voice->LoopStart) { + err = ov_pcm_seek_page(&vd->vf, 0); + if (err != 0) { + fprintf(stderr, "MV_GetNextVorbisBlock ov_pcm_seek_page_lap: err %d\n", err); + } else { + continue; + } + } else { + break; + } + } else if (bytes < 0) { + fprintf(stderr, "MV_GetNextVorbisBlock ov_read: err %d\n", bytes); + voice->Playing = FALSE; + return NoMoreData; + } + + bytesread += bytes; + } while (bytesread < sizeof(vd->block)); + + if (bytesread == 0) { + voice->Playing = FALSE; + return NoMoreData; + } + + if (bitstream != vd->lastbitstream) { + vorbis_info * vi = 0; + + vi = ov_info(&vd->vf, -1); + if (!vi) { + voice->Playing = FALSE; + return NoMoreData; + } + + if (vi->channels != 1 && vi->channels != 2) { + voice->Playing = FALSE; + return NoMoreData; + } + + voice->channels = vi->channels; + voice->SamplingRate = vi->rate; + voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; + MV_SetVoiceMixMode( voice ); + } + vd->lastbitstream = bitstream; + + vd->blockused = bytesread; + bytesread /= 2 * voice->channels; + + voice->position = 0; + voice->sound = vd->block; + voice->BlockLength = bytesread; + voice->length = min( voice->BlockLength, 0x8000 ); + voice->BlockLength -= voice->length; + voice->length <<= 16; + + return( KeepPlaying ); +} + + +/*--------------------------------------------------------------------- +Function: MV_PlayVorbis3D + +Begin playback of sound data at specified angle and distance +from listener. +---------------------------------------------------------------------*/ + +int32_t MV_PlayVorbis3D +( + char *ptr, + uint32_t ptrlength, + int32_t pitchoffset, + int32_t angle, + int32_t distance, + int32_t priority, + uint32_t callbackval + ) + +{ + int32_t left; + int32_t right; + int32_t mid; + int32_t volume; + int32_t status; + + if ( !MV_Installed ) + { + MV_SetErrorCode( MV_NotInstalled ); + return( MV_Error ); + } + + if ( distance < 0 ) + { + distance = -distance; + angle += MV_NumPanPositions / 2; + } + + volume = MIX_VOLUME( distance ); + + // Ensure angle is within 0 - 31 + angle &= MV_MaxPanPosition; + + left = MV_PanTable[ angle ][ volume ].left; + right = MV_PanTable[ angle ][ volume ].right; + mid = max( 0, 255 - distance ); + + status = MV_PlayVorbis( ptr, ptrlength, pitchoffset, mid, left, right, priority, + callbackval ); + + return( status ); +} + + +/*--------------------------------------------------------------------- +Function: MV_PlayVorbis + +Begin playback of sound data with the given sound levels and +priority. +---------------------------------------------------------------------*/ + +int32_t MV_PlayVorbis +( + 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 status; + + status = MV_PlayLoopedVorbis( ptr, ptrlength, -1, -1, pitchoffset, vol, left, right, + priority, callbackval ); + + return( status ); +} + + +/*--------------------------------------------------------------------- +Function: MV_PlayLoopedVorbis + +Begin playback of sound data with the given sound levels and +priority. +---------------------------------------------------------------------*/ + +int32_t MV_PlayLoopedVorbis +( + 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; + + if ( !MV_Installed ) + { + MV_SetErrorCode( MV_NotInstalled ); + return( MV_Error ); + } + + vd = (vorbis_data *) malloc( sizeof(vorbis_data) ); + if (!vd) { + MV_SetErrorCode( MV_InvalidVorbisFile ); + return MV_Error; + } + + memset(vd, 0, sizeof(vorbis_data)); + vd->ptr = ptr; + vd->pos = 0; + vd->length = ptrlength; + vd->blockused = 0; + vd->lastbitstream = -1; + + status = ov_open_callbacks((void *) vd, &vd->vf, 0, 0, vorbis_callbacks); + if (status < 0) { + fprintf(stderr, "MV_PlayLoopedVorbis: err %d\n", status); + MV_SetErrorCode( MV_InvalidVorbisFile ); + return MV_Error; + } + + vi = ov_info(&vd->vf, 0); + if (!vi) { + ov_clear(&vd->vf); + free(vd); + MV_SetErrorCode( MV_InvalidVorbisFile ); + return MV_Error; + } + + if (vi->channels != 1 && vi->channels != 2) { + ov_clear(&vd->vf); + free(vd); + MV_SetErrorCode( MV_InvalidVorbisFile ); + return MV_Error; + } + + // Request a voice from the voice pool + voice = MV_AllocVoice( priority ); + if ( voice == NULL ) + { + ov_clear(&vd->vf); + free(vd); + MV_SetErrorCode( MV_NoVoices ); + return( MV_Error ); + } + + voice->wavetype = Vorbis; + voice->bits = 16; + voice->channels = vi->channels; + voice->extra = (void *) vd; + voice->GetSound = MV_GetNextVorbisBlock; + voice->NextBlock = vd->block; + voice->DemandFeed = NULL; + voice->LoopCount = 0; + voice->BlockLength = 0; + voice->PitchScale = PITCH_GetScale( pitchoffset ); + voice->length = 0; + voice->next = NULL; + voice->prev = NULL; + voice->priority = priority; + voice->callbackval = callbackval; + voice->LoopStart = (char *) (loopstart >= 0 ? TRUE : FALSE); + voice->LoopEnd = 0; + voice->LoopSize = 0; + + voice->SamplingRate = vi->rate; + voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; + MV_SetVoiceMixMode( voice ); + + MV_SetVoiceVolume( voice, vol, left, right ); + MV_PlayVoice( voice ); + + return( voice->handle ); +} + + +void MV_ReleaseVorbisVoice( VoiceNode * voice ) +{ + vorbis_data * vd = (vorbis_data *) voice->extra; + + if (voice->wavetype != Vorbis) { + return; + } + + ov_clear(&vd->vf); + free(vd); + + voice->extra = 0; +} + diff --git a/polymer/eduke32/source/jaudiolib/third-party/README.txt b/polymer/eduke32/source/jaudiolib/third-party/README.txt new file mode 100644 index 000000000..3dbfa6736 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/README.txt @@ -0,0 +1,13 @@ +OS X frameworks compiled from the sources contained in the Max audio ripper +application by Stephen Booth. + + http://svn.sbooth.org/max/trunk/Frameworks/ogg/ + http://svn.sbooth.org/max/trunk/Frameworks/vorbis/ + http://sbooth.org/Max/ + + +MinGW binaries compiled from vanilla Xiph.org libogg-1.1.4 and libvorbis-1.2.3 +on MinGW GCC 3.4.5. + + http://xiph.org/downloads/ + diff --git a/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/config_types.h b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/config_types.h new file mode 100644 index 000000000..a320fc854 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/config_types.h @@ -0,0 +1,11 @@ +#ifndef __CONFIG_TYPES_H__ +#define __CONFIG_TYPES_H__ + +/* these are filled in by configure */ +typedef short ogg_int16_t; +typedef unsigned short ogg_uint16_t; +typedef int ogg_int32_t; +typedef unsigned int ogg_uint32_t; +typedef long long ogg_int64_t; + +#endif diff --git a/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/ogg.h b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/ogg.h new file mode 100644 index 000000000..ae0cfd534 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/ogg.h @@ -0,0 +1,208 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel libogg include + last mod: $Id: ogg.h 16051 2009-05-27 05:00:06Z xiphmont $ + + ********************************************************************/ +#ifndef _OGG_H +#define _OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef struct { + void *iov_base; + size_t iov_len; +} ogg_iovec_t; + +typedef struct { + long endbyte; + int endbit; + + unsigned char *buffer; + unsigned char *ptr; + long storage; +} oggpack_buffer; + +/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ + +typedef struct { + unsigned char *header; + long header_len; + unsigned char *body; + long body_len; +} ogg_page; + +/* ogg_stream_state contains the current encode/decode state of a logical + Ogg bitstream **********************************************************/ + +typedef struct { + unsigned char *body_data; /* bytes from packet bodies */ + long body_storage; /* storage elements allocated */ + long body_fill; /* elements stored; fill mark */ + long body_returned; /* elements of fill returned */ + + + int *lacing_vals; /* The values that will go to the segment table */ + ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact + this way, but it is simple coupled to the + lacing fifo */ + long lacing_storage; + long lacing_fill; + long lacing_packet; + long lacing_returned; + + unsigned char header[282]; /* working space for header encode */ + int header_fill; + + int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ + ogg_int64_t granulepos; + +} ogg_stream_state; + +/* ogg_packet is used to encapsulate the data and metadata belonging + to a single raw Ogg/Vorbis packet *************************************/ + +typedef struct { + unsigned char *packet; + long bytes; + long b_o_s; + long e_o_s; + + ogg_int64_t granulepos; + + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ +} ogg_packet; + +typedef struct { + unsigned char *data; + int storage; + int fill; + int returned; + + int unsynced; + int headerbytes; + int bodybytes; +} ogg_sync_state; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void oggpack_writeinit(oggpack_buffer *b); +extern int oggpack_writecheck(oggpack_buffer *b); +extern void oggpack_writetrunc(oggpack_buffer *b,long bits); +extern void oggpack_writealign(oggpack_buffer *b); +extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpack_reset(oggpack_buffer *b); +extern void oggpack_writeclear(oggpack_buffer *b); +extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern long oggpack_look1(oggpack_buffer *b); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern void oggpack_adv1(oggpack_buffer *b); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_read1(oggpack_buffer *b); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); + +extern void oggpackB_writeinit(oggpack_buffer *b); +extern int oggpackB_writecheck(oggpack_buffer *b); +extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); +extern void oggpackB_writealign(oggpack_buffer *b); +extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpackB_reset(oggpack_buffer *b); +extern void oggpackB_writeclear(oggpack_buffer *b); +extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpackB_look(oggpack_buffer *b,int bits); +extern long oggpackB_look1(oggpack_buffer *b); +extern void oggpackB_adv(oggpack_buffer *b,int bits); +extern void oggpackB_adv1(oggpack_buffer *b); +extern long oggpackB_read(oggpack_buffer *b,int bits); +extern long oggpackB_read1(oggpack_buffer *b); +extern long oggpackB_bytes(oggpack_buffer *b); +extern long oggpackB_bits(oggpack_buffer *b); +extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ + +extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); +extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, + int count, long e_o_s, ogg_int64_t granulepos); +extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern int ogg_sync_init(ogg_sync_state *oy); +extern int ogg_sync_clear(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); +extern int ogg_sync_destroy(ogg_sync_state *oy); +extern int ogg_sync_check(ogg_sync_state *oy); + +extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern int ogg_stream_init(ogg_stream_state *os,int serialno); +extern int ogg_stream_clear(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_check(ogg_stream_state *os); +extern int ogg_stream_eos(ogg_stream_state *os); + +extern void ogg_page_checksum_set(ogg_page *og); + +extern int ogg_page_version(const ogg_page *og); +extern int ogg_page_continued(const ogg_page *og); +extern int ogg_page_bos(const ogg_page *og); +extern int ogg_page_eos(const ogg_page *og); +extern ogg_int64_t ogg_page_granulepos(const ogg_page *og); +extern int ogg_page_serialno(const ogg_page *og); +extern long ogg_page_pageno(const ogg_page *og); +extern int ogg_page_packets(const ogg_page *og); + +extern void ogg_packet_clear(ogg_packet *op); + + +#ifdef __cplusplus +} +#endif + +#endif /* _OGG_H */ diff --git a/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/os_types.h b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/os_types.h new file mode 100644 index 000000000..a42f8007e --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/ogg/os_types.h @@ -0,0 +1,139 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 14997 2008-06-04 03:27:18Z ivo $ + + ********************************************************************/ +#ifndef _OS_TYPES_H +#define _OS_TYPES_H + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _ogg_malloc malloc +#define _ogg_calloc calloc +#define _ogg_realloc realloc +#define _ogg_free free + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + typedef uint64_t ogg_uint64_t; +# elif defined(__MINGW32__) +# include + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + typedef unsigned long long ogg_uint64_t; +# elif defined(__MWERKS__) + typedef long long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; +# else + /* MSVC/Borland */ + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 ogg_int16_t; + typedef UInt16 ogg_uint16_t; + typedef SInt32 ogg_int32_t; + typedef UInt32 ogg_uint32_t; + typedef SInt64 ogg_int64_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t ogg_int16_t; + typedef u_int16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef u_int32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined(__HAIKU__) + + /* Haiku */ +# include + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t ogg_int16_t; + typedef u_int16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef u_int32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short ogg_int16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned ogg_uint32_t; + typedef short ogg_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#else + +# include +# include + +#endif + +#endif /* _OS_TYPES_H */ diff --git a/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/codec.h b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/codec.h new file mode 100644 index 000000000..259798c61 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/codec.h @@ -0,0 +1,243 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec.h 16037 2009-05-26 21:10:58Z xiphmont $ + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + void *codec_setup; +} vorbis_info; + +/* vorbis_dsp_state buffers the current vorbis audio + analysis/synthesis state. The DSP state belongs to a specific + logical bitstream ****************************************************/ +typedef struct vorbis_dsp_state{ + int analysisp; + vorbis_info *vi; + + float **pcm; + float **pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + int preextrapolate; + int eofflag; + + long lW; + long W; + long nW; + long centerW; + + ogg_int64_t granulepos; + ogg_int64_t sequence; + + ogg_int64_t glue_bits; + ogg_int64_t time_bits; + ogg_int64_t floor_bits; + ogg_int64_t res_bits; + + void *backend_state; +} vorbis_dsp_state; + +typedef struct vorbis_block{ + /* necessary stream state for linking to the framing abstraction */ + float **pcm; /* this is a pointer into local storage */ + oggpack_buffer opb; + + long lW; + long W; + long nW; + int pcmend; + int mode; + + int eofflag; + ogg_int64_t granulepos; + ogg_int64_t sequence; + vorbis_dsp_state *vd; /* For read-only access of configuration */ + + /* local storage to avoid remallocing; it's up to the mapping to + structure it */ + void *localstore; + long localtop; + long localalloc; + long totaluse; + struct alloc_chain *reap; + + /* bitmetrics for the frame */ + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + void *internal; + +} vorbis_block; + +/* vorbis_block is a single block of data to be processed as part of +the analysis/synthesis stream; it belongs to a specific logical +bitstream, but is independant from other vorbis_blocks belonging to +that logical bitstream. *************************************************/ + +struct alloc_chain{ + void *ptr; + struct alloc_chain *next; +}; + +/* vorbis_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). vorbis_info and substructures are in backends.h. +*********************************************************************/ + +/* the comments are not part of vorbis_info so that vorbis_info can be + static storage */ +typedef struct vorbis_comment{ + /* unlimited user comment fields. libvorbis writes 'libvorbis' + whatever vendor is set to in encode */ + char **user_comments; + int *comment_lengths; + int comments; + char *vendor; + +} vorbis_comment; + + +/* libvorbis encodes in two abstraction layers; first we perform DSP + and produce a packet (see docs/analysis.txt). The packet is then + coded into a framed OggSquish bitstream by the second layer (see + docs/framing.txt). Decode is the reverse process; we sync/frame + the bitstream and extract individual packets, then decode the + packet back into PCM audio. + + The extra framing/packetizing is used in streaming formats, such as + files. Over the net (such as with UDP), the framing and + packetization aren't necessary as they're provided by the transport + and the streaming layer is not used */ + +/* Vorbis PRIMITIVES: general ***************************************/ + +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, const char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + const char *tag, const char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, const char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); + +extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); +extern int vorbis_block_clear(vorbis_block *vb); +extern void vorbis_dsp_clear(vorbis_dsp_state *v); +extern double vorbis_granule_time(vorbis_dsp_state *v, + ogg_int64_t granulepos); + +extern const char *vorbis_version_string(void); + +/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ + +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code); +extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); + +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, + ogg_packet *op); + +/* Vorbis PRIMITIVES: synthesis layer *******************************/ +extern int vorbis_synthesis_idheader(ogg_packet *op); +extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, + ogg_packet *op); + +extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_synthesis_restart(vorbis_dsp_state *v); +extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); + +extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); +extern int vorbis_synthesis_halfrate_p(vorbis_info *v); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/vorbisfile.h b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/vorbisfile.h new file mode 100644 index 000000000..ef2a36d3e --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/mingw32/include/vorbis/vorbisfile.h @@ -0,0 +1,206 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.h 16243 2009-07-10 02:49:31Z xiphmont $ + + ********************************************************************/ + +#ifndef _OV_FILE_H_ +#define _OV_FILE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include +#include "codec.h" + +/* The function prototypes for the callbacks are basically the same as for + * the stdio functions fread, fseek, fclose, ftell. + * The one difference is that the FILE * arguments have been replaced with + * a void * - this is to be used as a pointer to whatever internal data these + * functions might need. In the stdio case, it's just a FILE * cast to a void * + * + * If you use other functions, check the docs for these functions and return + * the right values. For seek_func(), you *MUST* return -1 if the stream is + * unseekable + */ +typedef struct { + size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); + long (*tell_func) (void *datasource); +} ov_callbacks; + +#ifndef OV_EXCLUDE_STATIC_CALLBACKS + +/* a few sets of convenient callbacks, especially for use under + * Windows where ov_open_callbacks() should always be used instead of + * ov_open() to avoid problems with incompatable crt.o version linking + * issues. */ + +static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){ + if(f==NULL)return(-1); + +#ifdef __MINGW32__ + return fseeko64(f,off,whence); +#elif defined (_WIN32) + return _fseeki64(f,off,whence); +#else + return fseek(f,off,whence); +#endif +} + +/* These structs below (OV_CALLBACKS_DEFAULT etc) are defined here as + * static data. That means that every file which includes this header + * will get its own copy of these structs whether it uses them or + * not unless it #defines OV_EXCLUDE_STATIC_CALLBACKS. + * These static symbols are essential on platforms such as Windows on + * which several different versions of stdio support may be linked to + * by different DLLs, and we need to be certain we know which one + * we're using (the same one as the main application). + */ + +static ov_callbacks OV_CALLBACKS_DEFAULT = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) NULL, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) fclose, + (long (*)(void *)) NULL +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) NULL, + (long (*)(void *)) NULL +}; + +#endif + +#define NOTOPEN 0 +#define PARTOPEN 1 +#define OPENED 2 +#define STREAMSET 3 +#define INITSET 4 + +typedef struct OggVorbis_File { + void *datasource; /* Pointer to a FILE *, etc. */ + int seekable; + ogg_int64_t offset; + ogg_int64_t end; + ogg_sync_state oy; + + /* If the FILE handle isn't seekable (eg, a pipe), only the current + stream appears */ + int links; + ogg_int64_t *offsets; + ogg_int64_t *dataoffsets; + long *serialnos; + ogg_int64_t *pcmlengths; /* overloaded to maintain binary + compatability; x2 size, stores both + beginning and end values */ + vorbis_info *vi; + vorbis_comment *vc; + + /* Decoding working state local storage */ + ogg_int64_t pcm_offset; + int ready_state; + long current_serialno; + int current_link; + + double bittrack; + double samptrack; + + ogg_stream_state os; /* take physical pages, weld into a logical + stream of packets */ + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + ov_callbacks callbacks; + +} OggVorbis_File; + + +extern int ov_clear(OggVorbis_File *vf); +extern int ov_fopen(char *path,OggVorbis_File *vf); +extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); +extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); + +extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); +extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_test_open(OggVorbis_File *vf); + +extern long ov_bitrate(OggVorbis_File *vf,int i); +extern long ov_bitrate_instant(OggVorbis_File *vf); +extern long ov_streams(OggVorbis_File *vf); +extern long ov_seekable(OggVorbis_File *vf); +extern long ov_serialnumber(OggVorbis_File *vf,int i); + +extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); +extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); +extern double ov_time_total(OggVorbis_File *vf,int i); + +extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page(OggVorbis_File *vf,double pos); + +extern int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek_lap(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page_lap(OggVorbis_File *vf,double pos); + +extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); +extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); +extern double ov_time_tell(OggVorbis_File *vf); + +extern vorbis_info *ov_info(OggVorbis_File *vf,int link); +extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); + +extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, + int *bitstream); +extern long ov_read_filter(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream, + void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param); +extern long ov_read(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream); +extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2); + +extern int ov_halfrate(OggVorbis_File *vf,int flag); +extern int ov_halfrate_p(OggVorbis_File *vf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Headers b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Headers new file mode 120000 index 000000000..a177d2a6b --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Resources b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/ogg.h b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/ogg.h new file mode 100644 index 000000000..9082679d9 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/ogg.h @@ -0,0 +1,202 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel libogg include + last mod: $Id: ogg.h 7188 2004-07-20 07:26:04Z xiphmont $ + + ********************************************************************/ +#ifndef _OGG_H +#define _OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct { + long endbyte; + int endbit; + + unsigned char *buffer; + unsigned char *ptr; + long storage; +} oggpack_buffer; + +/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ + +typedef struct { + unsigned char *header; + long header_len; + unsigned char *body; + long body_len; +} ogg_page; + +/* ogg_stream_state contains the current encode/decode state of a logical + Ogg bitstream **********************************************************/ + +typedef struct { + unsigned char *body_data; /* bytes from packet bodies */ + long body_storage; /* storage elements allocated */ + long body_fill; /* elements stored; fill mark */ + long body_returned; /* elements of fill returned */ + + + int *lacing_vals; /* The values that will go to the segment table */ + ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact + this way, but it is simple coupled to the + lacing fifo */ + long lacing_storage; + long lacing_fill; + long lacing_packet; + long lacing_returned; + + unsigned char header[282]; /* working space for header encode */ + int header_fill; + + int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ + ogg_int64_t granulepos; + +} ogg_stream_state; + +/* ogg_packet is used to encapsulate the data and metadata belonging + to a single raw Ogg/Vorbis packet *************************************/ + +typedef struct { + unsigned char *packet; + long bytes; + long b_o_s; + long e_o_s; + + ogg_int64_t granulepos; + + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ +} ogg_packet; + +typedef struct { + unsigned char *data; + int storage; + int fill; + int returned; + + int unsynced; + int headerbytes; + int bodybytes; +} ogg_sync_state; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void oggpack_writeinit(oggpack_buffer *b); +extern void oggpack_writetrunc(oggpack_buffer *b,long bits); +extern void oggpack_writealign(oggpack_buffer *b); +extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpack_reset(oggpack_buffer *b); +extern void oggpack_writeclear(oggpack_buffer *b); +extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern long oggpack_look1(oggpack_buffer *b); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern void oggpack_adv1(oggpack_buffer *b); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_read1(oggpack_buffer *b); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); + +extern void oggpackB_writeinit(oggpack_buffer *b); +extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); +extern void oggpackB_writealign(oggpack_buffer *b); +extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpackB_reset(oggpack_buffer *b); +extern void oggpackB_writeclear(oggpack_buffer *b); +extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpackB_look(oggpack_buffer *b,int bits); +extern long oggpackB_look1(oggpack_buffer *b); +extern void oggpackB_adv(oggpack_buffer *b,int bits); +extern void oggpackB_adv1(oggpack_buffer *b); +extern long oggpackB_read(oggpack_buffer *b,int bits); +extern long oggpackB_read1(oggpack_buffer *b); +extern long oggpackB_bytes(oggpack_buffer *b); +extern long oggpackB_bits(oggpack_buffer *b); +extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ + +extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); +extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern int ogg_sync_init(ogg_sync_state *oy); +extern int ogg_sync_clear(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); +extern int ogg_sync_destroy(ogg_sync_state *oy); + +extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern int ogg_stream_init(ogg_stream_state *os,int serialno); +extern int ogg_stream_clear(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_eos(ogg_stream_state *os); + +extern void ogg_page_checksum_set(ogg_page *og); + +extern int ogg_page_version(ogg_page *og); +extern int ogg_page_continued(ogg_page *og); +extern int ogg_page_bos(ogg_page *og); +extern int ogg_page_eos(ogg_page *og); +extern ogg_int64_t ogg_page_granulepos(ogg_page *og); +extern int ogg_page_serialno(ogg_page *og); +extern long ogg_page_pageno(ogg_page *og); +extern int ogg_page_packets(ogg_page *og); + +extern void ogg_packet_clear(ogg_packet *op); + + +#ifdef __cplusplus +} +#endif + +#endif /* _OGG_H */ + + + + + + diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/os_types.h b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/os_types.h new file mode 100644 index 000000000..32dcb8bff --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Headers/os_types.h @@ -0,0 +1,127 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ + + ********************************************************************/ +#ifndef _OS_TYPES_H +#define _OS_TYPES_H + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _ogg_malloc malloc +#define _ogg_calloc calloc +#define _ogg_realloc realloc +#define _ogg_free free + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int64_t ogg_int64_t; + typedef _G_int32_t ogg_int32_t; + typedef _G_uint32_t ogg_uint32_t; + typedef _G_int16_t ogg_int16_t; + typedef _G_uint16_t ogg_uint16_t; +# elif defined(__MINGW32__) + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + typedef unsigned long long ogg_uint64_t; +# elif defined(__MWERKS__) + typedef long long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; +# else + /* MSVC/Borland */ + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 ogg_int16_t; + typedef UInt16 ogg_uint16_t; + typedef SInt32 ogg_int32_t; + typedef UInt32 ogg_uint32_t; + typedef SInt64 ogg_int64_t; + +#elif defined(__MACOSX__) /* MacOS X Framework build */ + +# include + typedef int16_t ogg_int16_t; + typedef u_int16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef u_int32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t ogg_int16_t; + typedef u_int16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef u_int32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short ogg_int16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned ogg_uint32_t; + typedef short ogg_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#else + +# include +# include + +#endif + +#endif /* _OS_TYPES_H */ diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/English.lproj/InfoPlist.strings b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..7080cf949924e8817cb2121399f078b287079883 GIT binary patch literal 204 zcmW-ZOAf&R6h+Utt7r@xK@3d9$bMd*s%ZBv=Kme5Fyy^_xDn;J8+CjLwb{$gz->i_@% literal 0 HcmV?d00001 diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/Info.plist b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..4b6c1a8d5 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ogg + CFBundleIdentifier + com.yourcompany.yourcocoaframework + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ogg + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/ogg b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/A/ogg new file mode 100755 index 0000000000000000000000000000000000000000..9e4a0555ee6d103601b65cca98f52fe64a0b2c4c GIT binary patch literal 48348 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 literal 0 HcmV?d00001 diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/Current b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/Current new file mode 120000 index 000000000..8c7e5a667 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/ogg b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/ogg new file mode 120000 index 000000000..aa84ee717 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/ogg.framework/ogg @@ -0,0 +1 @@ +Versions/Current/ogg \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Headers b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Headers new file mode 120000 index 000000000..a177d2a6b --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Resources b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/codec.h b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/codec.h new file mode 100644 index 000000000..03f29bf36 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/codec.h @@ -0,0 +1,240 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec.h 7485 2004-08-05 14:54:23Z thomasvs $ + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + void *codec_setup; +} vorbis_info; + +/* vorbis_dsp_state buffers the current vorbis audio + analysis/synthesis state. The DSP state belongs to a specific + logical bitstream ****************************************************/ +typedef struct vorbis_dsp_state{ + int analysisp; + vorbis_info *vi; + + float **pcm; + float **pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + int preextrapolate; + int eofflag; + + long lW; + long W; + long nW; + long centerW; + + ogg_int64_t granulepos; + ogg_int64_t sequence; + + ogg_int64_t glue_bits; + ogg_int64_t time_bits; + ogg_int64_t floor_bits; + ogg_int64_t res_bits; + + void *backend_state; +} vorbis_dsp_state; + +typedef struct vorbis_block{ + /* necessary stream state for linking to the framing abstraction */ + float **pcm; /* this is a pointer into local storage */ + oggpack_buffer opb; + + long lW; + long W; + long nW; + int pcmend; + int mode; + + int eofflag; + ogg_int64_t granulepos; + ogg_int64_t sequence; + vorbis_dsp_state *vd; /* For read-only access of configuration */ + + /* local storage to avoid remallocing; it's up to the mapping to + structure it */ + void *localstore; + long localtop; + long localalloc; + long totaluse; + struct alloc_chain *reap; + + /* bitmetrics for the frame */ + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + void *internal; + +} vorbis_block; + +/* vorbis_block is a single block of data to be processed as part of +the analysis/synthesis stream; it belongs to a specific logical +bitstream, but is independant from other vorbis_blocks belonging to +that logical bitstream. *************************************************/ + +struct alloc_chain{ + void *ptr; + struct alloc_chain *next; +}; + +/* vorbis_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). vorbis_info and substructures are in backends.h. +*********************************************************************/ + +/* the comments are not part of vorbis_info so that vorbis_info can be + static storage */ +typedef struct vorbis_comment{ + /* unlimited user comment fields. libvorbis writes 'libvorbis' + whatever vendor is set to in encode */ + char **user_comments; + int *comment_lengths; + int comments; + char *vendor; + +} vorbis_comment; + + +/* libvorbis encodes in two abstraction layers; first we perform DSP + and produce a packet (see docs/analysis.txt). The packet is then + coded into a framed OggSquish bitstream by the second layer (see + docs/framing.txt). Decode is the reverse process; we sync/frame + the bitstream and extract individual packets, then decode the + packet back into PCM audio. + + The extra framing/packetizing is used in streaming formats, such as + files. Over the net (such as with UDP), the framing and + packetization aren't necessary as they're provided by the transport + and the streaming layer is not used */ + +/* Vorbis PRIMITIVES: general ***************************************/ + +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + char *tag, char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); + +extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); +extern int vorbis_block_clear(vorbis_block *vb); +extern void vorbis_dsp_clear(vorbis_dsp_state *v); +extern double vorbis_granule_time(vorbis_dsp_state *v, + ogg_int64_t granulepos); + +/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ + +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code); +extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); + +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, + ogg_packet *op); + +/* Vorbis PRIMITIVES: synthesis layer *******************************/ +extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, + ogg_packet *op); + +extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_synthesis_restart(vorbis_dsp_state *v); +extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); + +extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); +extern int vorbis_synthesis_halfrate_p(vorbis_info *v); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisenc.h b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisenc.h new file mode 100644 index 000000000..a60081ac9 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisenc.h @@ -0,0 +1,112 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ******************************************************************** + + function: vorbis encode-engine setup + last mod: $Id: vorbisenc.h 7485 2004-08-05 14:54:23Z thomasvs $ + + ********************************************************************/ + +#ifndef _OV_ENC_H_ +#define _OV_ENC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "codec.h" + +extern int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +extern int vorbis_encode_setup_managed(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +extern int vorbis_encode_setup_vbr(vorbis_info *vi, + long channels, + long rate, + + float quality /* quality level from 0. (lo) to 1. (hi) */ + ); + +extern int vorbis_encode_init_vbr(vorbis_info *vi, + long channels, + long rate, + + float base_quality /* quality level from 0. (lo) to 1. (hi) */ + ); + +extern int vorbis_encode_setup_init(vorbis_info *vi); + +extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg); + + /* deprecated rate management supported only for compatability */ +#define OV_ECTL_RATEMANAGE_GET 0x10 +#define OV_ECTL_RATEMANAGE_SET 0x11 +#define OV_ECTL_RATEMANAGE_AVG 0x12 +#define OV_ECTL_RATEMANAGE_HARD 0x13 + +struct ovectl_ratemanage_arg { + int management_active; + + long bitrate_hard_min; + long bitrate_hard_max; + double bitrate_hard_window; + + long bitrate_av_lo; + long bitrate_av_hi; + double bitrate_av_window; + double bitrate_av_window_center; +}; + + + /* new rate setup */ +#define OV_ECTL_RATEMANAGE2_GET 0x14 +#define OV_ECTL_RATEMANAGE2_SET 0x15 + +struct ovectl_ratemanage2_arg { + int management_active; + + long bitrate_limit_min_kbps; + long bitrate_limit_max_kbps; + long bitrate_limit_reservoir_bits; + double bitrate_limit_reservoir_bias; + + long bitrate_average_kbps; + double bitrate_average_damping; +}; + + + +#define OV_ECTL_LOWPASS_GET 0x20 +#define OV_ECTL_LOWPASS_SET 0x21 + +#define OV_ECTL_IBLOCK_GET 0x30 +#define OV_ECTL_IBLOCK_SET 0x31 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + + diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisfile.h b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisfile.h new file mode 100644 index 000000000..259fa89b6 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Headers/vorbisfile.h @@ -0,0 +1,143 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.h 7485 2004-08-05 14:54:23Z thomasvs $ + + ********************************************************************/ + +#ifndef _OV_FILE_H_ +#define _OV_FILE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include +#include "codec.h" + +/* The function prototypes for the callbacks are basically the same as for + * the stdio functions fread, fseek, fclose, ftell. + * The one difference is that the FILE * arguments have been replaced with + * a void * - this is to be used as a pointer to whatever internal data these + * functions might need. In the stdio case, it's just a FILE * cast to a void * + * + * If you use other functions, check the docs for these functions and return + * the right values. For seek_func(), you *MUST* return -1 if the stream is + * unseekable + */ +typedef struct { + size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); + long (*tell_func) (void *datasource); +} ov_callbacks; + +#define NOTOPEN 0 +#define PARTOPEN 1 +#define OPENED 2 +#define STREAMSET 3 +#define INITSET 4 + +typedef struct OggVorbis_File { + void *datasource; /* Pointer to a FILE *, etc. */ + int seekable; + ogg_int64_t offset; + ogg_int64_t end; + ogg_sync_state oy; + + /* If the FILE handle isn't seekable (eg, a pipe), only the current + stream appears */ + int links; + ogg_int64_t *offsets; + ogg_int64_t *dataoffsets; + long *serialnos; + ogg_int64_t *pcmlengths; /* overloaded to maintain binary + compatability; x2 size, stores both + beginning and end values */ + vorbis_info *vi; + vorbis_comment *vc; + + /* Decoding working state local storage */ + ogg_int64_t pcm_offset; + int ready_state; + long current_serialno; + int current_link; + + double bittrack; + double samptrack; + + ogg_stream_state os; /* take physical pages, weld into a logical + stream of packets */ + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + ov_callbacks callbacks; + +} OggVorbis_File; + +extern int ov_clear(OggVorbis_File *vf); +extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); +extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); + +extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); +extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_test_open(OggVorbis_File *vf); + +extern long ov_bitrate(OggVorbis_File *vf,int i); +extern long ov_bitrate_instant(OggVorbis_File *vf); +extern long ov_streams(OggVorbis_File *vf); +extern long ov_seekable(OggVorbis_File *vf); +extern long ov_serialnumber(OggVorbis_File *vf,int i); + +extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); +extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); +extern double ov_time_total(OggVorbis_File *vf,int i); + +extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page(OggVorbis_File *vf,double pos); + +extern int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek_lap(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page_lap(OggVorbis_File *vf,double pos); + +extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); +extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); +extern double ov_time_tell(OggVorbis_File *vf); + +extern vorbis_info *ov_info(OggVorbis_File *vf,int link); +extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); + +extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, + int *bitstream); +extern long ov_read(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream); +extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2); + +extern int ov_halfrate(OggVorbis_File *vf,int flag); +extern int ov_halfrate_p(OggVorbis_File *vf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + + diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/English.lproj/InfoPlist.strings b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..7080cf949924e8817cb2121399f078b287079883 GIT binary patch literal 204 zcmW-ZOAf&R6h+Utt7r@xK@3d9$bMd*s%ZBv=Kme5Fyy^_xDn;J8+CjLwb{$gz->i_@% literal 0 HcmV?d00001 diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/Info.plist b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..e73b193b3 --- /dev/null +++ b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + vorbis + CFBundleIdentifier + com.yourcompany.yourcocoaframework + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + vorbis + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/vorbis b/polymer/eduke32/source/jaudiolib/third-party/vorbis.framework/Versions/A/vorbis new file mode 100755 index 0000000000000000000000000000000000000000..64b37e759a1d882b8646b0c1c81b4773a22c0b50 GIT binary patch literal 2639520 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 z zpK?-`ugw82DftrEw`p_X$e&tnd7?{hDD8=7Crr(cki(myZ_cCi&L!eIN8U*R6zW3d+T zjYU6;wFC~-pIm&aH{Y7unM1<2zZ!vcWuC^t5&1UI^~3PKdDL?`xo-sbXU={&dWEIg zc|or2eM9f-y)3khuV=6J8YavYt->qcxAU!YJ)i^0=PMTSyRP8(HT;ej{GQHlPL4&7~1z1<_Gy8NAQm{ncGdb^M_)U{fNEGwCWUIkpDI!jh-*^^(a$C7E*E>ix6 zcRkpvad9>>^1SnEPCNsAV0x z$D7abf8~Gb9oBbMxbw4~f_q*Gzymm#C=<>?@V$7`Dr$m>uEqU9lu?ViG)w2-I$fDkdcYTC60=_@uT%{nM>Lju@fy(s^jIc6 zg8P-(HI~-)3&)Jj+R=hJGUay9CjX%Ai9MUh(-m!2>N%|!a9j?K$AjYva4g&40MAzH z9^b_UYwCz(spe?qDfE-iSA}+Z{P~E-ZYr4PI{vTBx>4D%tCT~5EUn(wZI)rS~= znXNAYTs1%D@NLa8mkW*a=c#Ar(@tHo&66>16MP?9Oqh!MTPFjr=UJn~800%~$$e%n zwvWEG)g8Xfs{vF-ALL_9KAYSdM*cFJ@4M^Z1>6-z&kAwO3>o;)NB)%j5S~ zMc=;MOW@azG0z%jhHCQ6h#>z$?m_I~AhFMd$lK+}jm7b>Q(qNMrvAD`aTnPHPVoFR zHew`ur z!9Kxj3i$bWMb0<*XVz{-eQ5IRA7mr@Yb`Gt1J1qkweXWTMZ_?RIP+s(U?uqVeN?CB zmY-LiuAN2jD_|~~Rt+@SB?a^w0;h@tH)_4GUIR1HcP5X6j)s}V>c4M8mCY;rob={l zCXuWyuk2f7<_kVGhIsU7d^+s;P|irr407xqH;cWT)!YI8pRcz1*2XsXEsq_}?*|!J zM6Qyzx2zx1uym_$7u;yvqO;bEi8%!A{6kK05k8S9beB7>y=CwUdoDb7P{hMGwMD$O zSHhZ}qc(V-dd27lP2Sn6)>o(ebs@sfgdx=_4AzO6HB_BorPYPr|G zW4HD&cu;L@)dukJF>s7_eLNH;HFoIl8=h<_N@&beyNgs$gFQb{{a*ncg!vs|4^W)n z(O4W^7n*gu&7A5vW=S=+1ZSz~e6*zSHK`xDhYg!Bm%b5mq$l0{jJ0=tpB6cYFY8^| zp$T*O2=DvSZ)=^Y{t|upGA%HtdOJ3v{7I~Lp6#+SY;~ZHXHu;-tP}E6oYV}vAJ@~r z0#**x=eE9>m%|#1Z!!0p`JT`B0&JMYr{;RubZbw^-eygCK9Rir^7bPZ#_a2~_gw4$`aQU9={frQ)AP^6e;v;rsrU>rV9y?LKExh5 z1)nnT{^9n>u!g)nlI(K8iD=By;lyiB(c8q&0qdepXiW3g{c7Nate9ngTbitx?vH7d z{J6-N=BlV_1XGuk`+2zYPOCSsU)|4oko}R5WrW2`&h({hV=tEW=lFX~6vwEbYw330 zdR$XH)2_!jewk_Z8v1PUcy}6c19wnI4#IoQ((BBewu{KKsHO%4^4^(wzSW!Ei-KF+ zJ5TqQGp~d_`(+`vG5&ID3xv9^qZSKwTlhvdeEV}&=aepw-YI*Ub>0aK@MBI`oqfRC zp*6tGTsj3EeMDfTas||u#sy#TeQJ!cU;5)a7x*+p4r);{`+el~zy2nz_Y2>P_0Zm@ zXzwF|m1=`=;J1|ADT-3#rjmIiCei++6rWyV==hHkru^S@uakS+pP6irUct3zsKcOZ zGm}L+{4*) z@=VM=bKk?%QT{;$UD3E}jq=@w(|*Ez&dj`;F0vXo|&aG!E{ETEU0<=)&*Oh2KNho!}Bu*5On5M7Ax zkXLz~iC;a7Iz|t|gX#b3M#dr;*@N7qKRxTTt)C$NoWR9u=VJZ$`L+Hg{!iiBtQT+L znWxmI^U<)i^MO;R+VgCtPk)B-)*-v&!i)TqPWnRTx%qm<3wX9f`7AsW%}lz`=C)*_ zA7gI?dou88=i^OkPwytor(g7No!jL1ZR-oE9elBhKP3I@lacdbe7U`SDBSBrh8xu^PJ<2?~>KN57{3#K5k&S^f}SnC9N7`_J_z2#@PyP zTfuGSo+z=g3&LF))*<>Q{Ih$-bJ&Kj+5eN4o?LIeBMPddOUZ92*wAk|{KK_t3Ht54 zNbBuav$!7ST9NdBa+_ph?h&jl9}?d|AGJE)Ag__V_y_5p)_${k+ji`-Q#Q#aY`Qcy zozpeSxY%^<@b94>&d6)RHz3>A>P&i%_G!;vFTAEcZQIzj`8^nVmi&Qmto|QsS{MCe z4YjRGq~D0XGhexmT=U$1)%a6R3j4|XSG491q5CS1lveEq;FVOH?DKfqA*SUJ50!4? zojXp=CC+W=^x~h<`rLm{b}wKZp#NAnTK#iKKi7)U|9rh?$l-|(2(LqSW*_J$PBNrd zu+BahCEhaRY4;lR%4>*|G_h{5v&3(Ob9|=DlAHmG{BEd<%9m*Ui*>4ZD%q~_=5^25 zu-vii!-vD!wl~7r?mhWfOgU#lDi#w(w^&xSD3|Nv8(H6rp0RA!z0oUdy&A4DhFE4? zZ6tHkwUO4hsns;p6t~u6FI{3n$&_bDQR~#SVJEb)7TRiAkD2{pXU@yvOecE8EyE)% z!`B<9xgp~Guj!GNCmvT$f4ZyHIKawfF6}M<{zKMfaB=24o#D*amxqwK|0760a3YGO7J>zz0}%x{<9?M}(`eNG4G%kL=-JO4C1>@05hm^0&= zeU5=Iq|S@LpEqQ#j&cU!1(D0oetmb#+kw5=@2*#0r55h1HUW22a{0%IBmEXxgUq!) zogs=t_J6yT`cUAbMAs#=ou71uoej&w+=pdab?A#1d-@{J?-496xo2Y?|L?H4 zBTnkva#6bF<_FU)|3F;r6fQb1y&C%ajOImj$(vVkc2xuY1W!Qg#PgSle}wtJBw{@PoJ&otuO`%X1abuvXfeoXd0 z;qhdWHcLNj{8PIIR`Fbk_uN27X5FH6=Ebks_K;l(+S*X4cZmkNs?d3_!LQNd$uQRN zNuK+)C&z+O=9dD-%d#%`C9bHkkt_0hT@zpKyheM5KhY;%*?GH}(+O{2d?m5lWv9#? zUVQ=ifA?e8Y$py!+>d7m}pSjeDd}@U)8(v*=gTseeT`K$|-@q5-aXUK0IUP!#d>kacE}&w6pkh zTZH{zRm`9LMzhAkJG|J2A+}MRSqg16L0hcpuG@j({U*tJh{zt2y#QPqfJf5RhyOFz z!!v4zM=}@Jrv>lq(mjUz4bWD*=rViHesBwIYYn20ARGSE>WSJPvN6}pVC?AcQNfY^F5z$^b}yTe;dMDlw%@9AxRQ)uvG;JD|t|CvMP^a>Jax1vEf_wB` zl7EiA60{YlKe_c%=MM4Rk2O2!|2F5qK?Ynmojia%4-9P1epfs&pqv|1y*XH?@h8lf zQ5viKBlWo_u2)V#c7M)vS=_8I(+{Djt0?D2Ho21Z8tx=t2dCyTBldow>y z(Oq?le&{QIEpHQJ>xO)rxRN!Rw~5P=qKQ@5sTSVRr^J^uhEDoNp0#>379gj`izP_j zCCn)3W1uIG>->6}w3!%pBkL*6dTL}nrR{p!((>@*b}eS-Yz}9up9G*_OOk0K)=FcAq{80v!Ai$>MZa0Za@4c7Za~y z9rsAb{6Or4`XOh=>cyLKy`j#67y~}zBV+UWpzaIy>;bxw_*zR zwh%QME?$;fBVKOy=30;GdpEJWO3q=-&AvmnCic+{==`)PpQY+vQv>}N>p}H#O0tik z11^69UF8?QB{or>TXWpj3}KyzIUg}+{W9I0@hm%u^_DOnA7C7b*-hn@ic1WvIbJTG zup2ClPh4D47@x?;CQghGk-PKPtASUuYHACYf}6(n9Iz^khoZY{uJVUA>zOm}59;xM zF^u1N@q;k_Mc^-k@#r!C@4)!YuD=Y%A5+}?&%k)p?mrIWkyU>gjDIup&%(G#aZm7& z!l@SY{6dNqxJ_QH%HrXVKhuDZB3Xc|{(P({Z+pp3DvYyf-6~&Y=jhR;@FV%6^0@_e z|4yDyOIGhX7=<3qGEd$gepBn#s}sr^vNGb(C}KO6T0_;(vmRcx>p^u8>heDJ53C12 zzoS0)^EZjrGzec=mvxVfVBME-Etz%u| ziU|Lwh^JV8G%y;2k1ioRaGe+_yc@sz%x-?y@{B8=^?4C{|I~ATX&*C_#==#7%={yL z%uKrYFi!PhpR;!OC~{Vn!<4s~Rp&^#a<5*F--sGGp55H(&rN)A%Ylr)0{jbCL5W!AZoEEx85i zLu0J&v2w!3*`@1Qo~F4=-#a5;H+xrw`7u6>{2I|S%)7*%mHgu6=_>WvYsWC3y*lQ~ z|3hw3UB!gVyow32A;`Bl`>}8M>#*Xiaq5||Rsz{R>kBB)Y~Z|{d-yDha6WF)ZAZ>t zz`1!vmmQ_%U*_?_GX@S&+tSwM&wevyNDP=F*s5rfa!n=!8eqzxr&Q$2a}@ zeU=yWS>_C-zsGe>66YTNU+kR?fK^qw{`bs~qWMo$x}i~xib{q!=>P-san1|_3`m7a zMpx89(I8PqMZ+9rL_{P~G%7?YQY7@EQjr%Gn1Mi1$uLPtsYWBSn-!TA-MsRDerNVW zi|v^&Km}#jn?&;;q*K)V6Hwp2&^fliIi@^XyWm=U6?9>HWN=+F!#m zc?dtF7k`$0g}%41IFdhqFP_MESzptoDD&M_nfG=0e2KohDy~gl8_dl-(`4%I%qw|* zR^5%O?Xpx z)?TIG4*eDH#~%89{k=km_%k>gCw0+p!|HFxSnHZDi{@VUv zJg9u;HeSOlDw>e9scB!FnR(rio~-v78}v7TWlv1}oW4&Mn^UYot) z_fGvRRT91NN8W4G{iK@D|5Qi+`y`*=zPd~QiN#0j^PTt&rG`Nzn+rB*jSIPtAM2`g}6yXjT^iL!(Xqp$U%xT@z=`?#PRC(4t*Xmz*uw z!v5v=7O|=JD@RYfx@!Nzt3TeUCpLw)?O@jd#Cg&-;+3##L>%XlCr*y-np`K@*sk>c zg~WOB`(@jO{jhB*f1j!E4$0-7p%~XFZX@{Zb=`v&VMC@aUWkhNDu3AX*p2_LhsHPUGy80vdHUU5*}RZ{Yo0VMQxnwmLTtp=I@>u`b_R936LyXX>>Sskod@cBcBtDX zJ0sbdlg-Y|`(S$gbjllNeDK<<^_=i6)y_9m%lbEuN$2u!;MJY4KI-$GZ_#t0ersa5 z;(rkPTYsk()n5LKXNXUHZ}Mk%vcG0b{JTU--%p;Zj}9)K6dg>AuA6)Lxa*c*UUTh* zmrp3F`1xym_dDOe%I_G(|2DBv|6Z|~f2-iPaGL&o;+aOCwN~)ERC@m}^IS1EKjQU} z&rWR9xmlC>eTHx6j?mw9a{lRgOMg$;A#-NwH!3(AbGyZ3`n{dp{LJ%Ko$9&i9Mrw% zsk7qy?56lWyFqh0)^!ce!0n%>h`NYhU02(522QHx9;5e+)F-ZOIXACq$ef!8P5!0c z$6ED6{ceWpEWPa-#b2*!zjX}fX>ou3ox)^32hzmnv#c6Bpx(yfx%iYf?zx=%qW=9dUHj!{3ivF%c%$IeerZKP z=DnIX&iH<&ulN0%-lsU@yPwnFe`n5JJx5IXxZa#sN&Wj?he==2UY@(HG4nfe$LhVoOkMIB(+BiirQc1feSZ6AcWbI;1E|w$8)_5XC)V+MDb!-l#`u1!TFi+*2PoUO z*W!~;y}1^1=4bA^SI0G17uVdkRC9_e_0vz^r^)_3W!s$J_Pb8!Yn@`LvFr5RGQ}U^ z{lZ+du^n2|5p5H0k{(5*^FP&|RzQcHo-Y=cl zT%B-k`Lm2Ak1NlQyf|C$JL=z(a~HgM?B(?uo1cB`7j+t&mN^r@yKSA{li+=VcGTX6 zp!Sv~o(FXfuKR43+9U4ObuHCigKKa0*nU6GR(p5-rK$EFh->e(@;BAq94$S14?{Y(`u&SvtlU=fix;*{d@g5O-E&87oA#W3+vvGb+h#v^?Y4Q( z>9;kWTe)rVb1!UL`n*01^Zb$9);_QADt}&|GkN~nZH>?CyWgK*+4MJlyx%~bJSKgQ zN#Enr_qg;uE`5(n-{aEvxb!_PeUD4u6VmsD^gSVcPe|Vr()Wb)ao^?rb?&>=HaeBo z9j@(lJ|=fT>4nk3$X@@IFTQ^DjZNRN+{}1mE90wM8DH4S_>5M@Yg!o}-pY7UE8|^T z8IM{XAG^7g@wKgtFKT6cW-H?pS{WbF%6LgDqgLGCr@B@hPp0k7;FmXe;9d zt&DeWd3^NNR>n8AGTzY2`21GJr?oOZu9fj&t&A78GTx=-@$+79WxTPK@zt%2FKlIe zMl0hrt&9(EWxS}B@vg0mM;<@toY7Z~8-31sqsEOp=c4hWFCTaQIb$y#J7Mgoabv%H z{-u|lbHVsakr;b!{M2>KW#=3-y5~jFm(;&t)Yx(7kItVkK7V}8`4{Jp9yMW9{^-ju zs>#1Ve2pJ-LB4QcbjA2f&mDW2-V^#vasH_B!!JK0|J+{rXP#70(EF1GCl#KR-~HTC zmr2j~i}Oc}tr^qvGnanhxXbdj&#C%yS&uVI zMqN}hZtR51N1tDIR{ohSjrQ!>^Q;3g|Clf2SADrhzKG_EbIf^7|6{D?yo-j$^fYLy zDs@YvX!`h*Pfm-Lo&L+x2KqUFxISMrbwuwM8|l}l^=&vf-y zhfOrim&fZ$pVQDp4>w{gu$ZE51y$F!*@I~G6kk9j}( z<5yS2wDhk3oAkn!qrYDK=-lrfbZf=Y>B@5oE_v~hvs2G>{_+ch?$hg&rghS>g4Bbz z-8N6{bXgN4^{b_){^9zME=@fXumAMPnX7(6X8Kk2C*OU1!DmkzmFA5#U8zm$xPFqZ zPG|ZJl^GH>=)HHYbW9t%HTCP)RF~h_=affNro+zt)X)BM_v@)`+rF7Ek<{NliUA)> z&2L&SwXFN!R^2@E1`Mu%Z-g`b#o=eD?ce{Y=&AqyQ2Kv9@ZHKujnPW+DKw-`g zzEXH#eo5hBM;u+)_3rAzW1szA;V17urLeSkSmEFsY6{PocXZ+CTbCAIcF|`Gul>%n z!s+jSz3^)tzE(K**0F^P>Q5^C{?}85%RlzD!pFvLE_|l$-onk7^e+7C;03*MW=!jK zz&{##9s1|}dUd_(ieASqXz2CHtNQdR&3mrb;Gt*tI%8CEuhE}*u-9eByx!~DE2sCm z@i$X@-TI5#UUNrZ-)q55r}g^&sFQmwd-<4NkM-Qt>zVQ=du{Gn-s`WqpX;4-!Ogu7 z_~~bQANu3J_3rwq*}adw{N>)C9CT9el64b$4?g7V-e(+je(%u-J=y!xUoGu@?djj_ zedEJjd*6EBrM>6&zQ6Z^v##y^{S$iiUbgtr-fRE5x%V@9IlX`Lhw9$1KK#)>Iq5t4 z9I)UIeGZ-dmp)xT_E?`|2Yj^8Cl4#_Q}XqX_NjVie4o$$=8it+J@$`2mwxlcKG&Xb zf1ev~UD4;(>n8M>+wrA73wo^Rv-qEb`YgNh%06qCzR~CBs|WS@&B9yzyn5NzqMRcd ziVnEuYek1%^v|LXzq()1v7OH?D){voMI~o#EULQw)}qhOf3@hm8%{2|blAm3*Y5vx z(T!icu;|tilZ$SD{`jK1UO%8{@tQG3%PNYC)?V}RqMu(sujn`D|Dx#C9xwNeUi*FD z1I`%O_t5?y==T|0eLs7_>3z?uysq!12aM@k_hL@p z8!Ni?z4e4|^}YSxtNPyc#Cd%e-*Q{uW$*ugeb@HCpzqHIy}$2ojy|dHUw-??e$h`q z((izt@9TGHmx6vD{>I(?j``sS`xSiYzxx&cxwc=`u?P11>~W9wJ1^&@ewVD8*spF` zalac6|9!t(b06t<`=sal-8JWlev8lA*ze(||J-kF#~=3ldB}VR!($IFK4$Wi;)4GFS6saG3&n%}FsgX??>|+1Zv9!sms~Zsxb7R1 zil_bMq2gPf{b%v*rwuB;>x<>Zi;q99_~E%P7C-vrp~V{>|4{LZ-_9@o%ZOej(RB+- zI{xx|C5NnH$t8swO6qEUS~Bgi zZp1A43(&8Z(l@7WhT{?W+Ev4u7yS}vMPe+y3opOBXwC_$T zy=C&W(mDUAD!uD~5vBL9dbRZ7o?A;F{d`{OhEH8o`r_duOSe4!R9RGXW?9FteyQw` zi%u>(qH$(fx4#@$cH-SV%Zd-Xp=?m`<7LBpeyVKL);?u5-NDaz4KXv++kEBNZ=wGRt>VI+Wrmi_YKlSBl6H-^a)+u$_ zxHYNqub!J4H|4)mV~_r3>ij34PMtfoEOpM{MX8Zp{*oH;*B4TseeSf>Y3mM8ede(b zq=r7Ve`@e=Hf8iye*CIb`I%c&WwU>jD*p9NslEjxQ@y9Zo;vx@LsFkS>&R5k4Wm*$ zhW|G8@n6kI9d}8u)G-Iur;hsm0T~;PoI0-Ti49B2>TX|GcGM~Ran_bzTXaV0(Vb?N z{N$0&CD;D^J0(XydtmXC4bzJ!U$&sQ+qbXi_tRyc?04OvD~R77kX`2I;Gdt zKFfQ3{G5XefBx|J!l}=HxbXNBdJj@O2I-!{nLY4F9sW8{{ekKaRDXc_1Joa&{s8qW z)vr{)QvFKx`>Wqy{r>86?pLUvxlgHIp?grD=iZi9pLK)ZFghNX5%zxGRg{j57uU;9bF)UAV$NzGjU~P% zZQg;I7+}YwSNf+WegELpq)%Uzx@NU-Shv*G{T8Kai@T?;>bxR#<)hz9O+0;T>WYW< zPfhsW_opuFJScU^0Uc8pZ~QjT1F0__@V(R*F5H+Jeb47pqt?t$oxS3HsWWFCks48T zdTRLdpG=+lsnXP^zLT38{M4bT0h{wumN>i;txYo$MrrV zb<`JbOMPV0Q>iYK8d8UiIX?A)zR#sP{_XZu-rUl%*Uvhx>@WZMKV>hSe0kY(FV~g* z^s2{s4k=q&d3@QT+6`s%=KQv7*1S)aO}pu9WfOn8uB>|GVP%8XtSURP(;a31k-o0< ze}8aU>DuMJOTTgV`%0_+RZ#NSfs2)nXqo78^_PpkT;t0nw?gtOG;f9GuaKS<(zil- zS4jT~t+PVwtg89x{HvFr_42n~ ze%H(Ydc~n$@u*i^>J^`Q#i?HLs#o0V6~B7Lv0m}4S6u5A-+INlUh%G1+<6A8S03t> zk9y^$Uiqn4p6ZpadgZNN`KwnR>y^)X<+WbNiMGtn1qWP~! z(cOBkxoargvZ3pK0`-+@Y-(+%TjKuK9cj8lQ{S|r@U;tLR%T%P{Kj~mX{;~Zv5BA7 zXFs^oM>f&qf8V6X_QW(P-&}vY9?y^cvHfX%4>gzVNEg&)`k`N^>^E)2kk=Pf4f$j7 z{2{+uxpv4?$9EXA`hrD6mVR;Gkb6JAamXFBHx8M-XycHZ&wORb)VULf)IKq6$VF$5 z8FKcEHA7CVS~{fiy1F4n*DoA$LjUeVj#@l>NS7ZM3^}-F%aHvRcOU%vmb$@zyf!`f z*Lmr|Pko_o@alQ#!As{Y9(?b}d4um*TQ_+2FBT8J`TEAeQ&&fWul`{5;EU#W8hp;t z>j$4YHGgpB^8CR?53e75!WEqcAJterxXYGKgAcwv8ob}L4ORcwZ(h|OA8D-mb!A=E zQ}Y|ERzDY2Eq$i3>fW2{s_xjDuDWf%x~iKO=T}YrLtWL?=QLDZ^!tXYbIwm!o%-Xt zs>;7NR297%Rh@8mRCRQxbk*S>iK-4>ldjrtTYAv{T^|kl(?NBEemzy+;QM0Tpf!ip z4SMkZ9XsgWRhJFAv-=T)ZaevcK{r2_9(2QDM-009o+AcbeBzuz=PY<>&}lg*4;oM~ zXHehnpBi++^DhlLIvouzpw;LHve47{P=PX=E7+64nIzI@KWb6&n+;Av$)893mJ z7Yyus_D=@({J>8J9$ga+Jp76m26j69=7IZv`sM*|9RBQpKh3^sK;r=;2mI`;IRn<* zaLIrNuY7jEeci7baOVxL47ly9BL~dvxpcq{=Uy=2n$&>0oBKs4mhp$ssRJ$ zUp1ibtiKQFS zCzf1%S805G_q^EuS#`L5me^1vO@s;$b%T}gO|3O}Q;G>76``xuQePYGHbhnw4 z(??wYeEN_sIq8n2m!!5mcWP=&>Fuc(zMhwQ`l)WIM>ZFy9$NW{)ct4vJT-se%G8{> z6H~XGaCB^f-2=-meBu0M*N@t;>>G~{T6WLqA1`aT;_79; zsJv&{-;V6O{J;}`y8Oe7tCycxK5qGdBW_rJ)}_6dPn_I+`B(aXWBKjBK4AHM1y3wr zb;k1L8^;~Be9QD>SG@1s7gikh&0nrK>i2_Ioc#GKS5&_AofV&({{0mf7N4|Y((g}N zF}>lg6<_~*d^%;0B>yKzjSzZe9finKKLp2fi1(=W4T){Sd?`#9``(;GLNe`lXsE1b3nkA5uR=7xhCN zuD$^uS>~gYbyypFuo1iQ1^@7wI1n4+MGT26u_pfHgglWu@=1=PmAYT85_gqmu9Egu zU4?E!51~-dL+h$aVW==%7%7Yv#t9RIT4Ayj=@_iJRW16=##>F;b+2z7|)0Tc#I)~ zEb~IW*nlmz$7^9Hw$Br02vtJ9;<;rCt#kiKv*o`4{_TRW!^92J+rq0tI}Gdy%?@J6ND)- z@Xx-@RvX|S{^KA0xdJ}E-Trmfnk}J=#`A^lLXki$@Nc9rQ6P_Fgz6ahO+CQJXYzZK zz}^D*IZv1`EEJqe_Q(dIarfqP$P@e>~b zxt=EAFL?#Cg?YjqG42rsiv;^E+jgafSJuhymLQu}%8r$?W2M$yxn5`#wrbscp+x8! zgMN3RhX5a6M+?J*kuhpS#|RUJT49EO|M)#qz;E)b^)fkLAbOv$L|7(}XW6jorMBgH zWh7hM0@=Q@K#+YIe-&5GwpATP3vr=4R@O?aD^&o7S*J>qId+h#n;1Yo$;XQ)(a`W0>erVYGmc69oK*)(K&L z!`$NMLg604XUbBw8w7lPMrdqbUNdKfV%aR6r!lR$QtM>y5%`LKodkR=5(*Y?-Gde1(tF?`+Jy00rc$?ld=pmEum zL5*mgFi*hWEn1_q&{62nL^(sZ=emp9Snh@Utq$h`2vdRO@7X$Nw3^ zOkuWw-wOnM4(oWm`kUVDZ)X3XuQk+4hBc=MtO=ba5NoeZ8yn^d*fC#NC{S-pgk=J; z&tk`0adx6}`+AM? zP$b(@2BH$-}r(-%&l)U3RKI6YJU2Q_LVc&YgqtZdXds5q@`5EcvbVk{MXS=b_M6_Asz45ck(?i2Z<9fU|c z%QHvF_*y91EpB%arH|hrEesbb<2G@i4TcKCgfT+3Fgm6+q7#IPg6m+G+H-{k!eW8@ z$Xa1T^L~f>JM)~%a|CmU+XDh|MBh9C-Lqp#n_6RxdRr7w<}4AYy=U6Cc4)`0w%_Cj zwqPUnQX|w2F`F7=nke;SKDFhT!l$Md3it}eSK|AF7{qzCKhZFANu|gfYUfxJ{onV5Z3&_U=TbP}Sb^Aoxq z$lyEj$N_YquP|=ov)6!*hyfo|3!{Z`!W3bKFjJT%;Ir#|iQ43QbIbm2uUp0CO?z{Z zc=H6}>6p@I9q1jxd||P`UV2h!CB9zo?V_3cC3dYA*aO%~jPPNufM4uY?19Dy$(`llt zGfQwRh{Ga*yzfHJTlEb)u!me#3SET`LcVa25D8u4K74qc1^n(N6bi(He)qUfdzera zV1(L$bw&#l1^k~P*#FsTVVRQUnAiE6oLFs7sxSSK0N!6PV!A0$Tz;T-Xp?#VHfsRvo*O8nS>x8KSxd-+ipBD+PZ+u@SJT8#; zSK62NW}jW=N*6U}->|npI7sLcqoXM3B;*U-1Z0K^_)RQIVmd;!N+1SM16jt1!5D!! z;=e&0CJWO9@;_f7=euz4$lUYSNyjQ-X{>L7C_YnbtikyS&wC6x)?6(R>z@h4`^EOf zySe(>UHr^Bw^nvx>k?s+z<$9uYG`^)Y0nny=R&oSrLORm*ic*OdQx~s*!0f&`X=9~ z19CJ^AaD2<)()3$5&zjn1|2F^Wz=z^-cSbJWzYoBDUWoOcX{6V`7XD1@OiR z69i=Nc}k3_aet;LF+vx98;jL`Kv*KUzSpTu95x7>c0K1i__jkhqoy%{g#@EUQ_BQ#zR`P{UqlGa-wJ=m*uYeIT7@H!D6KaIoxIbN# z7?5xKJx^`w9I(b>VX3fMV4uCX`(yB?XBXm+P1uKTB?A6H3xqD*-gk7y2P|d6q~~_ zc$PtqIq*zN)b0_3_`rt}1ALt(;3xZHi9j8#6F9eaQ%*C_j?@TeLxaE`!e7po`7!Ph z{eeKN*9sei-4yG$^6W%+##U-$wXjscmw5tp#5pokm@UA=??nQ>a*p8ZZjANr^fhDG zdf7+bRtfmFSilE-sS~CMwLyEj+P4bimbwD?OU{W8`hK;0_Ry~Sn$X?H)om!F~-@ z8~?DKarlhmE3~V?oGwCVAz$z~^YC}FK#h}MVrqXMSNmtebHa;nfzO;1YX$O2oQbz{ zN{xl*$>!a^{;uw~mgZ;nBJsmFe4$Qf3&eS*K&%%E)G;!|fmm-6UfT10&76CyWh=Gf z+|5v%TAClJutT!`&P*|@`LTO zv%x+OSG!7pH!N<`hd)xN6Q&E~oOsO_<_hSiPu|xFjc=W=Z}N|I7YO(_Q>Ya3g&r}; zBl*Nn;w+ghP``{51AHbP%tgnhJI1$+ja zoA`{s%v~f<#|^?d;W^>uch=`jjZtgZg?-pct~g7E2_?cv0pG?5@P-P7LZwh83>QWS z6NHwwAI1)fKP%cn z?Jh!Rp+H~`z9U;JOcUk`^9Aa8ned2!ujF|1+mqwW8M;>M;VW_HTp^#>m9&lhhHWps zJ+|$RvouqyoE7*rQ*iFu;sfj{OjM1Xh8otgE$R~Nm z&((r!?ZrJapWL%EuM4nup@1)A1oqx=fxR>=2ENt_Qv`ClKp-aM7U1^^0lyy?$ngeY zqwuSD#{W!hV$&jFmVi%HLKmTjP#M$iqFrMYiQ+TqfdmveKez_^_j&3q++&;G8M}6upWFQ-?f@Sb3BGTwR+~MwLDlLgL^SpsLsVu9QuLp^hDJR|HSe(vBOXXi+vQkWu46K)db#vlgxOZ}2t z&X2VMXU87u?+*TPJ`5AO3FBhmD}GlCwE}g^nXyFh9(7I|_pE)I@r@i%f1G!PLcY*J zz}E=^{*4f-Vo<}xV5%@nxI=>Ee#6%#0yW54vKQnO z8#B)^+}D-~FTLp4S9X1H~{?gv*<96S; z_stVHSLy`vNS||)vAr~p8UNPHex6^bN%mTez&^xJ&J=Qqubd|f1@;(zlV9!Kw${lz zA;;&{Gr7TD{HPSFgaToVKt91#fpcVH0Q%GRaR0QgGVhm=7i`BreCr|<#eI0Ry9%9S znlIX2=&@(}=bFjfFQ~U!0(qns0kyb9;2!sguzv6G$9|b^_iu`Pm?7LDu;-xU7T?*U z5AEgtvDaz^eB_?(eB$c@LHTq{_9mLi-y+%19>hN=7$Xc5s$$R{v3L2HIYT$fZt8G& z?1%jsseXx2C~&64*sF5)itJu1@Z8cv=qz-P+xXih<{cyo)ZbhD%hV;lads>eW(n-I z1ojqxl6GeGZ<_o|AUSVu>2LRMk$jpf%n)h>?YEU%1m$#Z@g&&-Z{UVTP6TQ^3zXEq4) zgt{naOGlwwl+$Zrl#{RiQEGpzMrep~3T8$*C#ik%>)FRom>1>r=qkC+5m$14h6(=@ z^D@72_SnJCr_TD}v-M)}`z&eofx4=O%y(|*iM~(Z%8T;uEf6|w)78ZKSXzCJfJKXi zTA?b+`>&#=8KQar)j7)h-sTLNCQ0^tlD%uau((O?uK8+%*)gVxP87xn(sx^fFfYpc z`lcwab5)f4@-(3~GdFkSqA2&LU=jh z->L5J@Mb=FY>I`fP@DYjCum1xzQq%Cy$brlYkv$?>F)2U7?O_ zYqW*u_1hxboD65s3p%%76U}M-WkXbbi&{-*l1`}emS%dn=jjP5zH-m26TebD|6a#V zpT(3xyw0> zZ=A!NyV%I(a~N6RbIY-G-)Dg1hCZL|mhl|RBF?NXF1PB zFFbUIb8SO%UUEIpMc%M|j+NI;&hxFXR+>r0K$F0x&kkU4s|M=V)GfrbUFPynKs@~S9W@b-n=Z-0$6XkwkQHD0P z^&I$xWoqv7xwHDG1<~sJhefMzu8CHklOL`ASatN{`gF8PPy7`^f3+*ctJGMfWGW?F zsX4l+t=)0%IPPtwKGUeNw$8B}bCWggv3<1t@!S`)w>D-zL*EL@xpQTdJC4_rIgP_3 zzy9Rjtn+5vw3v3w&?a8B_&onO@9ZVc0iHY9TRdNIp&LCu9}aBmYfH^Rm*=7r{pe%A zqn|aohzWe;0c!!|Log4tMP_GYTUyilOxq)y%?ImA()P$E=Z1Y^OW$WCdc*OsosI)0>V$!UDJE~>slt?l>6@$vof;&mA=|H&QSG0MGolUnVr(^UiY z?0tluyES{|lqmDQ2=8~4t6eT$g~lo*qpLl2O5IY^u50SRK6`K5)=El@kv_}@5_BUyt_4)ayt+LERXKVU8Nd~k<);7d-dMP={ za-LqYQGC_rB@;5Vsl8bJDQenJ{2=Gl);o2cVt=-}a=n@&gPp*2>M_@YX?tYD+Os}W z>oaYStaXIcdXhAhaXTsFKI3jDsrR<&o*+vuPK|OW3>D33)L9yzr_`_Nb3!_%T{D#b zu#+ z8}3Wn;&Jpa-jYm9dOSCrj}5?UwM7Q|4bQg@@&G&zwG3;}wv5*dsmDyiF}FQt8s~dr z59!X5?}@Cb418%xhBmeJ?@wP^t)_Ki=i8C*aDRs}qHSB8L+ru!FoyQoGUUtgHMLAQ z&$><7C!j4d)(iD~ufaYo+*19UD;&d8}V6^dx`#i@fGoN8Vk1XZ}yV% zd}aK+aOM0=zlpb2eDY6Bv*tPZ?{<=-uEu@Z>{nQfAV^I5@jh9Uyd2+6p zLmad5tS^jnl1D6?TZ25Jm-)=|njz2YL(zpVUe7$wH{Wue3%@y@`RJt$$h%_}^3Z3U zp69;TfNwiOp7ldrf7y5~#fo@YceYr0EL=CqW6k7TWZ(h&gIu@=>4&=95B-JbczKPa z&FF{c`Lw+bJo8N*XV&((*RZXOwZseOhOzfND6cuJ1Bx8H=GF-9Lq1%?dXS+FP3nga z53t9>__L<_VNSBelywcq$9<@6$u`$<5A$I;`)xn1(>{fLc*M)Ki$0Hg4eNt%pP-?B zw{0`BA&-8jCn;w;;AfMwJe0U&GjjkuDEx4)$83xH%njv2-EN0#z(WT-bTHTRt7OqpKb9xsO4xQOCQSn0M-l7K)2WNIP%PgpKT3z=tG7!a$(#^W&5rYG-+VoD#o2yl%6` zo37j`dSCRq*VOT|AJ2q58*=fS*rAQjkIb;)+JAdd6y>C4G-B+mu*Sf$6V{R3_Pz7 zkI#NWZL@8GXMONI-#ps~-}=mBP4j582G{P)c^CuR3@=+g!uVkq25 zTfgTqPOO*@;KNI#4*MRRe;D@n77T9L%V6J(#GhBoAVS?AN9$q1U=>7jsyH zi!~U>7cTm|_o{zixM{d(PNO*0aGRb3_1~MSntC^N%h1foO=-brb=Pf`#Y*T;k)8-7K?{+8;pK;G|JCyOfP)|~xKA>ihgMx5fk3&P5a4pMQ zA97w7nw)F7{Zb~~T1CPBK%7pfW`ongpC!EW=K8sqC zv0c1=8m+%MnjqTNi`=4{bAt8QpHOz9ZDb4?`$D}TW1CE|6}TRm50Evm)w)A{$R+hU zp6EBM+kMutcEbfM>c?L-04C`BBr~fX;0COk~BS z@9r4Y*U8T<`de7himI5-YohSLyZmZ;e>ivTh$#2bZcUg|sK3AFb-h^nYlmS z@bC76v;N(_fB3)K_v)GH?#%-CYdyz)Z)B8vhx&6?ZO$W7 zl5P4%D3guHc!*FYoQpk-!LvOf&-0+o+39sGYyD8`@|dY*(3wpy^N>l7CH2wAZe+cl z=RhrQ%KDbGE!imYA*|EugmWzCoSTL+=2@08bV8H%AcH((ZhM~fKtmbEtqXnOT-t`^ ztPg%tS8}fPnQv+xrnb%f&@XtN2W8B9EpHji*)I4=-5xVV#_L($dgvz+>I>V*h4ZX4 zohOyo7a*~%h)f^_nOH*^5Gorefk^!J2#5vG`?CL zRexQrrhBCBjCW=p97LP$vW(>3sppeByQ{^$beEn9e%!GxTJ<~qebI8^Yr<)IE_hv# z_Hv+hg?JSjtB_2EWczE5F79`}m->AY?(6u*eI5Vt4ga~X^Blm%a{ztjgh(X zglltNwv?Z6KKA-v%^dVF9_AyI58JHk`S4jc9B-)|&JAsC%evUu*4QL%uz&5bHK}7? zzwLQ`D`Mr`?{3Oo)xWiTuR%2Dg~Jv{qXb>-S^f8WOJb^5)$x`4J$=vB_vWd`{@&p= z$B#c!7xfo(vA4O&LsR)b#nf zL$1Vc&u6Nr6X3JYZJ)!$7M{;I$J*zt`_ODW{JT5Ky{ADmr%~UzUETCb9G&v(o*6L> z?tk~lzk9li&pidO?|hzP$D8~WkF}{o_R&F^zok`$uax$cid5!xaDLSEonm@#rChvn zjg?D=zp>TDeEW=T=wcn##Rv3K@7Th1kU$?<;5Z-;d{!U_cs&fz$y%T}S$yU`%4_Cu z4r?UmAd7zF0k5~2lTFsPSk|USef(l(d;OJP&G{puW%n$T1gV&Uc0p|Hr=2 z4d>H#pEbBb*(Od??dm>oAF^5g#_Qf!GJ?7H&h~^T_uh5FLiJs1)KZK4uAw^G9e>l8 zZ9gUV6?@J5hds(T6!;#Rl<{~dgAViUr>XaDsM}+vEy>spY6-b)dMsl-=uPq%bIn7u z$%NyyyfbSuXK77wbpW{W_F%EgQ!Mr5(8s^hwV1c{nq3-Qo`u~8t{;_U5uGW+p@@n`p}77C`%hY_ZX<> za1UV2YlL&H-@N1+^w9?m^;@^8@0~l7bJh-h4Q;o5P_NZeKJXDabdV3{B-F#0*RW3> zhYyc^?)e_Gt}u?+LLbUpWG(MCu*WQK zT*EfN3)e`-#cLtsHZq|ce8ip8htQMd`SC%$W2`Ip!L=FM)P6<%jcWSYkLN(1<+*t6+@AL%tb?-_ zgwJB+5oF`JRvE`10MB#GOP=|})N^TDE*mc#cMg+0V!A79V6SyHw+4Ldv#sQgb(zN) zeCIdhIrqpQ4|ToKb`8K|ez=BfCA1A5a@ly;;C0Z89DT0?k9Ej5>x65CIrJRH!*$?$ z4ch2OXUL-u!uz)U4t0gTc|GP?7HS#$VIFZKw5_7tTk9KGZhjM<_$Ah>PtD z{Y}b+bD0N_LAULNdOg~_caU7e@}WLtkqdeBdGEq&Fwgqnc};l8Ip<-X!~EOF)^Z-k z%5!XUm~+Ok!?CyD=HZKFm>>Fv?eIKqAK`~Nhi`qzTAsP#x|R#qAb!Aekny@<&XIwS zKI@?mLVd&;9{M~^+~G41n*d|z4A-!HsLygq9{g|(`w`l2TbvJcc#Y7H=6r*1TbYMG zK0_3)0U!TDKWvL_MhA1@n}-hbY!l#t`A~*&0FRtQLmBfuW_fhN^IYVpY5GurjOERD-!jRyJdQrvtdUKR*Ro#A*e2@_ z?TYiXrcpYxP((?~A~m9f4gv19o-(o*kWi*6oYHz6k7#z`h9Vi@?4Jyj2n4^99B`{XD^E zA9m&9Ga~QgMf|XV&jszOFYlxu`_|sM2sr0;ntr6f=Y05_&_Llmb5+#n-_y6~`;-1x z-(6a#w*GxR{@l&J^JUknVBh(&Yw_FLXUFGDW*b$=8P1k`VTSOYxmq}1eE)x^&Y4}k z?_D_m}v>2X!gDpfLe1739;Y^tzz~@uA?}31fFl7xCr!CF>Qh@4vU9Hg~wvgbux?m z9Vz&1;XN3}$uEB^^&z3B@UDBFY2kdqcP{pq_t>uN^^CH1{Ab_!^6$Ur+jqXSqj2^R z(eQlX4B`CXd?A-Szi_5-=7eVr_X=K1@%Q08^BgDenrg2-cUm}KI8)xq%g;|cYlHK< zv-5X#UU(+&sxP~0%f9(&O9L)zXd z!S>MpHqX!U`lz+nJ4xNG#mDdMCg-`&d%n(rdE04guaDw!?wfqK1NX#z*V`L``2LnD zgR``>o>y{s|Ap5DJj*pSB{xS3<-%miXhLoewW&9rXZXGeKg;w{`!m9LLBDDc zZIZm+$H`f*Iny=eH1YPRD|~)Qr}v#NPR_pb#gW)YcQOL;`I5Os=q%w($$eRrGk;{$ zS@S-f51F&0LeyuACUoF?eK?0Y3*7|X3;wilvB0_VE6pzvmP%)h&Xsw3D^Iff&DYo- zb+vH5;2&4`48WP%-urk)$xi%-{CK^cU2~_NU9dIF`O;n&TC(Y^8t&zBuOUzc}t_b6}L zgedQt`BC144N>0tYM;?L%KJ=pl-GB5ly~&{D6eykXl;~tR8^FBq{cqlDD;T(KD<>B z|A@LMuglOV??aOP59#PUPeEeOi{E*}UKy}mGnz9+_owae^CkP7H;kKd#%GiFIF#Ca zw}YBFNp(al-tH^B&yg?g8^oP9`7w1a;E@mK&J-U1-iHso?t$_w1JB=2$oKFu2Ib!b zKOo@yq1s2R)1C|YY{33(eES47;=S6XPQ3TpMVvwqvoLm!5&3n_y${JPAcs(LY>;30 z27Gu)KI7)^O*G!CM=X*3Z}%1ED48q9T;t@6J`|oQ`J9r$ zUzSPsnHM6C*-^FPxAn4*Q0jnvM%)1PgFpBH>=$-0W*@ybv6D8s!ucLYm*apg)^oi( zrr~LcKZ=hx8uEf+$-%__+29F zy$U6NrrwibPMz;0@4eWM_v-Qa??4@pBO|QyuU|pK5T5VT>{G@ zd-W4t)o#xf+SlH;{fPJKCuX;2;dfY;T;Xq$!ox39`{-OjoiFFf)Oq6UL?%he6a0`m zkK{DWr_W;Z8Ot_qxuhP;n_7>l`OQ)ET6a>WIet>Er9L&2uV=P(qHVo=FAVeJJefLQ zAth(@Lz>Jdc}ar2hKTFDXPx+a%VnSOjTk_Ql_~zw&qmoB=2KtDwM5a+xG8JXXDukY zpaykBo0^33nghyf3dUNZ%<(w$s5K~jD6el!ku#8U8;V>u8p`Z!oAu*5FKEyEzr?vE z5Z|^Stnsi-KIk_`<2wK37|FEtYR(?kVXUnbn~+aZY6pIjQZMkKtU=v`lzO1wUP_%{ z1M^yjGHnZ_L)Pi!Q*u|6qpasuitkUMP~?VCau@x zd%+4@_CJ~PaK7V39<2{Q=%d#@c}_^}KmJ)hj2CtQ z*RsFxX*W0DzFD3=_Pd|dpVWgKYnUI#1N#}bOmjZ(PCoH! zk3OG~o=4xlv`5c7CCfRh_f-3`2ikfuhqKb>hWC&60pp#dlh28^^+KO(i5j4Ws0;Qp zKqu?520#`N?*pT}PwV~JPwV~KA$q@da6yze@O7ao%B$4prutV$dF4H#y!7HIFSR7f zE3FecM0q9ny+QNQEnYur^}TixcjD>zCvzI+mb@TKUWk22ov$RHImi)P=-vjOKS@f> z=zZLh64AH&A}8d_l$>~P!1LaKk{3Yyvr+QHSd!webH*6^%oN}CK5i+W`)<#LZP?lz zwGT-e%Ex=Pv^}qX+GFFMEK6L-A(Y%e$y3-TNA43h`liI5K6Sx7D1CIYFQLveXD%{O zczZMAy_$Mie!Sfmxd7zAl(s=mk{~be$On{M!!vcx$PY45#!Sg2GSGOhrZ=nIo(ua} z+Z5aBC#n4~MaGEtYI(JId&`9%&XcKQkfiwOT$ws&P<(&urs!pzmMF0&mZrp?J~~|c zP~bX+x<;uR>N2cT#&~ZEo+)kDY}kfJpU+9T?f13(IjY@F<2oPMp3ndIS)F($&!Vv3 zQk^rG_?jY1oU>7K2H!NU^FamTwe@115UttP-to{E`xMf)`WDt7Hc)G(tU(`2-R&&J z7U~p=o{*XkCEm?Z=3%QTa`dTpY=koAy%AE{u6w9qJ~jVAfxpQDVcR@Y#@YgECau@x zqea_#QRm!yi8KCD+kiecJEz3SHhbSN%Vpj4_{f7#sNL0h}X@L6Pem_bpFfG1LF^hP3D3zlpQ!9$mDF6L!+a7uwVY zYXEF_8=ox?kJ=CW_zK8}=h!d$jtB9j&s^3-hQ8;zZyn9ia2;fbmE)Cd4)tQ28K>=> z(a+|8sK>Fx56?%3`>oBlzqZ@4bG-2%9qxx~(@y&4*qRTee%w#acRgFb*JoX1$qTkQ zKgs#_)$`GZ4$p`0946<|cmADU$HVJ+zWdp9>w?)}Nfuyl_t=YhB1Pzoqq)`r6xP|LgtCPp=bg>%|=QJ?AC)_nGUxz_{MW{Y<`S zTQ77`=j5MwQb%F#eNK5T)+hGJ{l6&h)J8#{#XU70nV1>JgI|J3#EP|TcAm-_mD-f8T=wqDLRx#JwN-}KoF&ad-NzQ`YS z56riG*k_!*WF7RKZ}_Yij=OIjeXoNK+N^CpZO$#9T~ME0)Ej+d0lpv)1?WOH^q29_ ze&*R0_}GB`)&~vcsbgf!3+Kb9AKFhJJ3NQ^;d=BLhX*|0c?tdJe8yiWHUj$SK%V)u z9Ru_dBi8nsjMF!g_FD&XjCnkq?=~^;xb->q@M%Ls|FF${=Gb<4^h0^~xu*eg={9~5 z2lKried|CcePjV^L+u;(g?;4liFGXFImkKY@K^&G&u1=R3^)$R*iNW(#~SFfUgYR| zZO0D2eQt>&$GY~{G0?w*oSz@%ou_|)JXe1oQavTgJ7;~Acb4v9XNf$3vxbaOTvhJyG<%cKNL3%%lx9I7etxm$cajP-0EpkTWQ`aBZ7VI}?&%*B#S#t4qg4n+s5bxEI?fLx6?kXATnf1fEX3x^6uE{5D_Llb= zlyedu_efLrCwPbMc&6l(c60Z_@V-f&>6=mq^!+U5KF?an z@C;_kn4ihQ@sQ6rx=d*!OMhp<{I-Ca$&d1?iD_FeYLJ+_Ub9h;hm`!#Pg3#)FG-ur zX$A3fG^Ix2w?wfatnaW-P1A>>vo%WnBi9mT zE$Y2B%38=lseg2udXGTiQRB3!QSSwKetp6F54#i8Oj@r|UJ-5Uvn2pX?yR8>d;zyD#!Vj-cd-+=Y}}&^IL~&LtEdLP~DvL(yr<)b+?)YX(oarYi@rG|oZqSvDqKlk`l$@c{xr920=wRHGG5UZr zIc)Q63gGiPfiY;Z&of;%esl8XGtYCGzq>)r4@D+PUDr^?l9W1w zZ^}5JpQP}Tpw5%^={>>gJcHMM@adb<_Upp1ZQkyr)J$5hQHF}P^>VI=54N~Zoay7c zV`o1@N`3k4f={2bj@n=!GnY2{!kAcx=OaUmnakcoCwagg+8$?~^X9V#8v$di#~kv? zdfDuUZ(HJ+T~;SvTQBBdkJrRL+SZ8;Zrjh0`fR}u_{4xV{@Vw)!+CDA9`W@0%x6va zX*0h$8xp`u z{UyE5zM?_su616MOq{37yQ{q?U17bt?(HL#JmDkM`+)Xa4Ps2p^!ckRMvCsvi`?NG zpcYMO<0}+jX+yCk^c}knkX_`pJ(t%sbq#s_xJJG-v^`4S23hPQ7T)*nLy3ziadWJo z)CiRQOdD!&zR~u%VG19xm$QMr9U`ugiFM-d&I_Ny+GxpVVqo8i6F$c^a%Fp-e>5!< zW7Y~0+9AFAf8Lcf2)FTa9g_pjKkOy;zQ;g`zt2r%La;t_@XPa^U;5~Be#3cgGdCP( zZaAOyLwh_gq`n`RXPe!3t+*f3Z1#utpbIqTzv~`9(Cc_Q9_R|=6RsV~BNz5PAKzP= z@8<-^06UZZC)W)7jy3DRcdXH2Io1H~hcxMLQXlqMXE@Jo&oJlP=a_XsU0ckh55*T~xW4<|%hYaYqt}PWe8)4)9c}a=i;Q)!E~;&E1`s^8>}d5TVcZ9g2^p zag9uVS-kdK;kwz{(yRaHU6*c$QsPS-{oV_GV(q@;?tYTu7ki)A#EiMmnMfaf;dpXB zxn=!OK3t!sg;`0DHpt;tyl?JJf|f>#~jbhP?e@p4-TyJJgZvw^o0SAG$(+yuRb-aqM?(z+>FL z(kFId{dvCiVQVN)-($=VeRV(72hXvi%~_O=@@|+Q+SUtw*yX$sbL_S+j5C&uCF=p? zh?{GTx$GP7CFXgYwsS_@XovG@GvDVS^E}^sk$e*;$11cR+e3ZmvOl(g_%av1{#I`K zYrR3Rri#(IpoxO;A_$=r8M0W@2-rNqw)@3Rk`hVV6y0=3I zevwZ=4(OXl-?@fIo?Y{tC*<05se@$S^DV<1=h^fBKYQ;3WZ7NacivX_>k*($WFumM z0gXU_Y-BuC#Fk8yqGvQ>hq4j|EV2Tz&;sEMMz{pg8hJ~>vsfXMvdRpFOaxXrN|lU7 zqTmUU3%L+c&uGA+EW=={wx~j(S}AI+C35YoOLi$lHhVtzzE97Y-~8Ttw|iRBNZea< z=A7U8o%22CcYc5FeXrl^29x~*p;PYmR2LI$2;aPCk?|4NHg@R9)qKg#cIJ7!RS!3p?2o;3PEL+V8^=x?TR6I0Gy9B{$EHu# z<=Wy)ZRy89+uP2*^lNJlyY}FDO(H|ggL6flcy@qOC+dp~ zQ7`(e*)⪚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