Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Import Unreal Tournament 432 public source code.

  • Loading branch information...
commit 2f3027c95c1a3ab49f3890fa4bdc62ad48238a8a 0 parents
Stéphan Kochen authored
Showing with 36,511 additions and 0 deletions.
  1. +45 −0 Audio/Inc/Audio.h
  2. +56 −0 Audio/Inc/AudioCore.h
  3. +71 −0 Audio/Inc/AudioLibrary.h
  4. +22 −0 Audio/Inc/AudioMixer.h
  5. +24 −0 Audio/Inc/AudioNative.h
  6. +156 −0 Audio/Inc/AudioSubsystem.h
  7. +134 −0 Audio/Inc/AudioTypes.h
  8. +64 −0 Audio/Inc/FormatWAV.h
  9. +20 −0 Audio/Src/Audio.cpp
  10. +351 −0 Audio/Src/AudioCoreLinux.cpp
  11. +371 −0 Audio/Src/AudioLibrary.cpp
  12. +427 −0 Audio/Src/AudioMixer.cpp
  13. +18 −0 Audio/Src/AudioPrivate.h
  14. +674 −0 Audio/Src/AudioSubsystem.cpp
  15. +96 −0 Audio/Src/FormatWAV.cpp
  16. +54 −0 Audio/Src/makefile
  17. +416 −0 Core/Inc/Core.h
  18. +439 −0 Core/Inc/FCodec.h
  19. +397 −0 Core/Inc/FConfigCacheIni.h
  20. +137 −0 Core/Inc/FFeedbackContextAnsi.h
  21. +134 −0 Core/Inc/FFeedbackContextWindows.h
  22. +360 −0 Core/Inc/FFileManagerAnsi.h
  23. +291 −0 Core/Inc/FFileManagerArc.h
  24. +151 −0 Core/Inc/FFileManagerGeneric.h
  25. +422 −0 Core/Inc/FFileManagerLinux.h
  26. +312 −0 Core/Inc/FFileManagerPSX2.h
  27. +692 −0 Core/Inc/FFileManagerPSX2CD.h
  28. +394 −0 Core/Inc/FFileManagerWindows.h
  29. +86 −0 Core/Inc/FMallocAnsi.h
  30. +174 −0 Core/Inc/FMallocDebug.h
  31. +422 −0 Core/Inc/FMallocWindows.h
  32. +91 −0 Core/Inc/FOutputDeviceAnsiError.h
  33. +112 −0 Core/Inc/FOutputDeviceFile.h
  34. +21 −0 Core/Inc/FOutputDeviceNull.h
  35. +23 −0 Core/Inc/FOutputDeviceStdout.h
  36. +84 −0 Core/Inc/FOutputDeviceWindowsError.h
  37. +224 −0 Core/Inc/FRiffChunk.h
  38. +45 −0 Core/Inc/UExporter.h
  39. +58 −0 Core/Inc/UFactory.h
  40. +239 −0 Core/Inc/UnArc.h
  41. +90 −0 Core/Inc/UnBits.h
  42. +77 −0 Core/Inc/UnBuild.h
  43. +78 −0 Core/Inc/UnCId.h
  44. +194 −0 Core/Inc/UnCache.h
  45. +538 −0 Core/Inc/UnClass.h
  46. +161 −0 Core/Inc/UnCorObj.h
  47. +46 −0 Core/Inc/UnCoreNative.h
  48. +153 −0 Core/Inc/UnCoreNet.h
  49. +523 −0 Core/Inc/UnFile.h
  50. +338 −0 Core/Inc/UnGnuG.h
  51. +338 −0 Core/Inc/UnLinker.h
  52. +2,596 −0 Core/Inc/UnMath.h
  53. +205 −0 Core/Inc/UnMem.h
  54. +45 −0 Core/Inc/UnMsg.h
  55. +164 −0 Core/Inc/UnName.h
  56. +364 −0 Core/Inc/UnNames.h
  57. +1,101 −0 Core/Inc/UnObjBas.h
  58. +44 −0 Core/Inc/UnObjVer.h
  59. +198 −0 Core/Inc/UnScript.h
  60. +252 −0 Core/Inc/UnStack.h
  61. +1,763 −0 Core/Inc/UnTemplate.h
  62. +582 −0 Core/Inc/UnType.h
  63. +31 −0 Core/Inc/UnUnix.h
  64. +349 −0 Core/Inc/UnVcWin32.h
  65. +274 −0 Core/Inc/UnVcWn32SSE.h
  66. +774 −0 Core/Inc/afxres.h
  67. BIN  Core/Lib/Core.lib
  68. +18 −0 D3DDrv/Src/D3DDrv.cpp
  69. +112 −0 D3DDrv/Src/D3DDrv.dsp
  70. +25 −0 D3DDrv/Src/D3DDrv.h
  71. +3,194 −0 D3DDrv/Src/Direct3D7.cpp
  72. +2,531 −0 D3DDrv/Src/und3d.cpp
  73. +139 −0 Engine/Inc/AActor.h
  74. +14 −0 Engine/Inc/AAmmo.h
  75. +64 −0 Engine/Inc/ABrush.h
  76. +11 −0 Engine/Inc/ACamera.h
  77. +14 −0 Engine/Inc/ACarcass.h
  78. +13 −0 Engine/Inc/AGameReplicationInfo.h
  79. +18 −0 Engine/Inc/AInventory.h
  80. +14 −0 Engine/Inc/ALevelInfo.h
  81. +26 −0 Engine/Inc/AMover.h
  82. +105 −0 Engine/Inc/APawn.h
  83. +14 −0 Engine/Inc/APickup.h
  84. +24 −0 Engine/Inc/APlayerPawn.h
  85. +14 −0 Engine/Inc/APlayerReplicationInfo.h
  86. +14 −0 Engine/Inc/AWeapon.h
  87. +17 −0 Engine/Inc/AZoneInfo.h
  88. +48 −0 Engine/Inc/ENCVAG.H
  89. +68 −0 Engine/Inc/Engine.h
  90. +3,322 −0 Engine/Inc/EngineClasses.h
  91. +37 −0 Engine/Inc/Palette.h
  92. +81 −0 Engine/Inc/S3tc.h
  93. +27 −0 Engine/Inc/ULevelSummary.h
  94. +186 −0 Engine/Inc/UnActor.h
  95. +52 −0 Engine/Inc/UnAnim.h
  96. +265 −0 Engine/Inc/UnAudio.h
  97. +64 −0 Engine/Inc/UnBunch.h
  98. +404 −0 Engine/Inc/UnCamera.h
  99. +189 −0 Engine/Inc/UnChan.h
  100. +178 −0 Engine/Inc/UnCon.h
  101. +201 −0 Engine/Inc/UnConn.h
  102. +179 −0 Engine/Inc/UnDDraw.h
  103. +46 −0 Engine/Inc/UnDemoPenLev.h
  104. +85 −0 Engine/Inc/UnDemoRec.h
  105. +64 −0 Engine/Inc/UnDownload.h
  106. +32 −0 Engine/Inc/UnDynBsp.h
  107. +91 −0 Engine/Inc/UnEngine.h
  108. +15 −0 Engine/Inc/UnEngineGnuG.h
  109. +122 −0 Engine/Inc/UnEngineNative.h
  110. +970 −0 Engine/Inc/UnEngineWin.h
  111. +64 −0 Engine/Inc/UnGame.h
  112. +93 −0 Engine/Inc/UnIn.h
  113. +336 −0 Engine/Inc/UnLevel.h
  114. +344 −0 Engine/Inc/UnMesh.h
  115. +233 −0 Engine/Inc/UnModel.h
  116. +83 −0 Engine/Inc/UnNet.h
  117. +86 −0 Engine/Inc/UnNetDrv.h
  118. +490 −0 Engine/Inc/UnObj.h
  119. +73 −0 Engine/Inc/UnPenLev.h
  120. +48 −0 Engine/Inc/UnPlayer.h
  121. +111 −0 Engine/Inc/UnPrim.h
  122. +61 −0 Engine/Inc/UnReach.h
  123. +105 −0 Engine/Inc/UnRenDev.h
  124. +522 −0 Engine/Inc/UnRender.h
  125. +22 −0 Engine/Inc/UnRenderIterator.h
  126. +27 −0 Engine/Inc/UnRenderIteratorSupport.h
  127. +49 −0 Engine/Inc/UnScrTex.h
  128. +449 −0 Engine/Inc/UnSkeletalMesh.h
  129. +479 −0 Engine/Inc/UnTex.h
  130. +65 −0 Engine/Inc/UnURL.h
  131. BIN  Engine/Lib/Engine.lib
  132. +79 −0 Help/ReadMeSrc.htm
Sorry, we could not display the entire diff because it was too big.
45 Audio/Inc/Audio.h
@@ -0,0 +1,45 @@
+/*=============================================================================
+ Audio.h: Unreal audio public header file.
+ Copyright 1997-1999 Epic Games, Inc. All Rights Reserved.
+=============================================================================*/
+
+#ifndef _INC_AUDIO
+#define _INC_AUDIO
+
+/*----------------------------------------------------------------------------
+ API.
+----------------------------------------------------------------------------*/
+
+#ifndef AUDIO_API
+ #define AUDIO_API DLL_IMPORT
+#endif
+
+/*-----------------------------------------------------------------------------
+ Dependencies.
+-----------------------------------------------------------------------------*/
+
+#include "Engine.h"
+#include "UnRender.h"
+
+/*-----------------------------------------------------------------------------
+ Global variables.
+-----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ Audio compiler specific includes.
+-----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ Audio public includes.
+-----------------------------------------------------------------------------*/
+
+#include "AudioLibrary.h"
+#include "AudioMixer.h"
+#include "AudioCore.h"
+#include "AudioSubsystem.h"
+#include "FormatWAV.h"
+
+/*-----------------------------------------------------------------------------
+ The End.
+-----------------------------------------------------------------------------*/
+#endif
56 Audio/Inc/AudioCore.h
@@ -0,0 +1,56 @@
+/*=============================================================================
+ AudioCore.h: Core audio function declarations.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Audio state control.
+------------------------------------------------------------------------------------*/
+
+void* GetAudioBuffer();
+INT OpenAudio( DWORD Rate, INT OutputMode, INT Latency );
+void CloseAudio();
+INT ReopenAudioDevice( DWORD Rate, INT OutputMode, INT Latency );
+
+/*------------------------------------------------------------------------------------
+ Audio flow control.
+------------------------------------------------------------------------------------*/
+
+void PlayAudio();
+
+/*------------------------------------------------------------------------------------
+ Read helpers.
+------------------------------------------------------------------------------------*/
+
+void* ReadMem( void* DestData, INT NumChunks, INT ChunkSize, MemChunk* SrcData );
+void* SeekMem( MemChunk* SrcData, INT Position, INT SeekMode );
+BYTE Read8_Mem( void* Data );
+_WORD Read16_Mem( void* Data );
+DWORD Read32_Mem( void* Data );
+QWORD Read64_Mem( void* Data );
+
+/*------------------------------------------------------------------------------------
+ Thread control.
+------------------------------------------------------------------------------------*/
+
+UBOOL CreateAudioThread( AudioThread* NewThread, void* (*ThreadRoutine)(void*) );
+UBOOL DestroyAudioThread( AudioThread* OldThread );
+UBOOL ExitAudioThread( AudioThread* Thread );
+UBOOL CreateAudioMutex( AudioMutex* Mutex );
+UBOOL DestroyAudioMutex( AudioMutex* Mutex );
+UBOOL AudioLock( AudioMutex* Mutex );
+UBOOL AudioUnlock( AudioMutex* Mutex );
+
+/*------------------------------------------------------------------------------------
+ Timing.
+------------------------------------------------------------------------------------*/
+
+void AudioSleep( INT ms );
+INT AudioWait();
+
+/*------------------------------------------------------------------------------------
+ End.
+------------------------------------------------------------------------------------*/
71 Audio/Inc/AudioLibrary.h
@@ -0,0 +1,71 @@
+/*=============================================================================
+ AudioLibrary.h: Unreal general audio management functions.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+#include "AudioTypes.h"
+
+/*------------------------------------------------------------------------------------
+ Globals
+------------------------------------------------------------------------------------*/
+
+// Raw Buffer
+extern void* AudioBuffer;
+extern void* MixBuffer;
+extern INT BufferSize;
+extern INT AudioFormat;
+extern INT AudioRate;
+
+// State
+extern INT AudioInitialized;
+extern INT AudioPaused;
+
+// Audio
+extern INT MusicVoices;
+extern INT SampleVoices;
+extern Voice Voices[AUDIO_TOTALVOICES];
+
+// Volume
+extern INT SampleVolume;
+
+// Threads
+extern AudioThread MixingThread;
+extern AudioMutex Mutex;
+
+/*------------------------------------------------------------------------------------
+ Interface
+------------------------------------------------------------------------------------*/
+
+// Library control.
+UBOOL AudioInit( DWORD Rate, INT OutputMode, INT Latency );
+UBOOL AudioReinit( DWORD Rate, INT OutputMode, INT Latency );
+UBOOL AudioShutdown();
+UBOOL AllocateVoices( INT Channels );
+
+// Master control.
+UBOOL AudioStartOutput( DWORD Rate, INT OutputMode, INT Latency );
+UBOOL AudioStopOutput();
+
+// Sample control.
+Sample* LoadSample( MemChunk* LoadChunk, const TCHAR* SampleName );
+UBOOL UnloadSample( Sample* UnloadSample );
+Voice* StartSample( INT Voice, Sample* Sample, INT Freq, INT Volume, INT Panning );
+UBOOL StopSample( Voice* StopVoice );
+UBOOL SampleFinished( Voice* Sample );
+void UpdateSample( Voice* InVoice, INT Freq, INT Volume, INT Panning );
+
+// Voice control.
+Voice* AcquireVoice();
+void GetVoiceStats( VoiceStats* InStats, Voice* InVoice );
+
+// Volume control.
+UBOOL SetSampleVolume( FLOAT Volume );
+UBOOL SetMusicVolume( FLOAT Volume );
+UBOOL SetCDAudioVolume( FLOAT Volume );
+
+// CD Audio control.
+UBOOL StartCDAudio( INT Track );
+UBOOL StopCDAudio();
22 Audio/Inc/AudioMixer.h
@@ -0,0 +1,22 @@
+/*=============================================================================
+ AudioMixer.h: Unreal sound mixer.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Mixing functions.
+------------------------------------------------------------------------------------*/
+
+void* DoSound(void* Arguments);
+void MixVoice8to16(INT VoiceIndex);
+void MixVoice16to16(INT VoiceIndex);
+
+void ConvertVoice8( Voice* InVoice );
+void ConvertVoice16( Voice* InVoice );
+
+/*------------------------------------------------------------------------------------
+ End.
+------------------------------------------------------------------------------------*/
24 Audio/Inc/AudioNative.h
@@ -0,0 +1,24 @@
+/*=============================================================================
+ AudioNative.h: Native function lookup table for static libraries.
+ Copyright 2000 Epic Games, Inc. All Rights Reserved.
+
+ Revision history:
+ * Created by Brandon Reinhart
+=============================================================================*/
+
+#ifndef AUDIONATIVE_H
+#define AUDIONATIVE_H
+
+#if __STATIC_LINK
+
+#include "AudioTypes.h"
+#include "AudioSubsystem.h"
+
+/* No native execs. */
+
+#define AUTO_INITIALIZE_REGISTRANTS_AUDIO \
+ UGenericAudioSubsystem::StaticClass();
+
+#endif
+
+#endif
156 Audio/Inc/AudioSubsystem.h
@@ -0,0 +1,156 @@
+/*=============================================================================
+ AudioSubsystem.h: Unreal audio interface object.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Helpers
+------------------------------------------------------------------------------------*/
+
+// Constants.
+#define MAX_EFFECTS_CHANNELS 32
+#define MUSIC_CHANNELS 32
+#define EFFECT_FACTOR 1.0
+
+// Utility Macros.
+#define safecall(f) \
+{ \
+ guard(f); \
+ INT Error=f; \
+ if( Error==0 ) \
+ debugf( NAME_Warning, TEXT("%s failed: %i"), TEXT(#f), Error ); \
+ unguard; \
+}
+#define silentcall(f) \
+{ \
+ guard(f); \
+ f; \
+ unguard; \
+}
+
+/*------------------------------------------------------------------------------------
+ UGenericAudioSubsystem.
+------------------------------------------------------------------------------------*/
+
+//
+// Information about a playing sound.
+//
+class FPlayingSound
+{
+public:
+ Voice* Channel;
+ AActor* Actor;
+ INT Id;
+ UBOOL Is3D;
+ USound* Sound;
+ FVector Location;
+ FLOAT Volume;
+ FLOAT Radius;
+ FLOAT Pitch;
+ FLOAT Priority;
+ FPlayingSound()
+ : Channel (NULL)
+ , Actor (NULL)
+ , Id (0)
+ , Is3D (0)
+ , Sound (0)
+ , Priority(0)
+ , Volume (0)
+ , Radius (0)
+ , Pitch (0)
+ {}
+ FPlayingSound( AActor* InActor, INT InId, USound* InSound, FVector InLocation, FLOAT InVolume, FLOAT InRadius, FLOAT InPitch, FLOAT InPriority )
+ : Channel (NULL)
+ , Actor (InActor)
+ , Id (InId)
+ , Is3D (0)
+ , Sound (InSound)
+ , Location(InLocation)
+ , Volume (InVolume)
+ , Radius (InRadius)
+ , Pitch (InPitch)
+ , Priority(InPriority)
+ {}
+};
+
+//
+// The Generic implementation of UAudioSubsystem.
+//
+class DLL_EXPORT_CLASS UGenericAudioSubsystem : public UAudioSubsystem
+{
+ DECLARE_CLASS(UGenericAudioSubsystem,UAudioSubsystem,CLASS_Config,Audio)
+
+ // Configuration.
+ BITFIELD UseFilter;
+ BITFIELD UseSurround;
+ BITFIELD UseStereo;
+ BITFIELD UseCDMusic;
+ BITFIELD UseDigitalMusic;
+ BITFIELD ReverseStereo;
+ BITFIELD Initialized;
+ FLOAT AmbientFactor;
+ FLOAT DopplerSpeed;
+ INT Latency;
+ INT Channels;
+ BYTE OutputRate;
+ BYTE MusicVolume;
+ BYTE SoundVolume;
+ UBOOL AudioStats;
+ UBOOL DetailStats;
+ DWORD OutputMode;
+
+ // Variables.
+ UViewport* Viewport;
+ FPlayingSound PlayingSounds[MAX_EFFECTS_CHANNELS];
+ FTime LastTime;
+ UMusic* CurrentMusic;
+ BYTE CurrentCDTrack;
+ INT FreeSlot;
+ FLOAT MusicFade;
+
+ // Constructor.
+ UGenericAudioSubsystem();
+ void StaticConstructor();
+
+ // UObject interface.
+ void Destroy();
+ void PostEditChange();
+ void ShutdownAfterError();
+
+ // UAudioSubsystem interface.
+ UBOOL Init();
+ void SetViewport( UViewport* Viewport );
+ UBOOL Exec( const TCHAR* Cmd, FOutputDevice& Ar=*GLog );
+ void Update( FPointRegion Region, FCoords& Coords );
+ void UnregisterSound( USound* Sound );
+ void UnregisterMusic( UMusic* Music );
+ UBOOL PlaySound( AActor* Actor, INT Id, USound* Sound, FVector Location, FLOAT Volume, FLOAT Radius, FLOAT Pitch );
+ void NoteDestroy( AActor* Actor );
+ void RegisterSound( USound* Sound );
+ void RegisterMusic( UMusic* Music ) {};
+ UBOOL GetLowQualitySetting() {return 0;}
+ UViewport* GetViewport();
+ void RenderAudioGeometry( FSceneNode* Frame );
+ void PostRender( FSceneNode* Frame );
+
+ // Internal functions.
+ void SetVolumes();
+ void StopSound( INT Index );
+// FPlayingSound* FindActiveSound( INT Id, INT& Index );
+
+ // Inlines.
+ Sample* GetSound( USound* Sound )
+ {
+ check(Sound);
+ if( !Sound->Handle )
+ RegisterSound( Sound );
+ return (Sample*)Sound->Handle;
+ }
+ FLOAT SoundPriority( UViewport* Viewport, FVector Location, FLOAT Volume, FLOAT Radius )
+ {
+ return Volume * (1.0 - (Location - (Viewport->Actor->ViewTarget?Viewport->Actor->ViewTarget:Viewport->Actor)->Location).Size()/Radius);
+ }
+};
134 Audio/Inc/AudioTypes.h
@@ -0,0 +1,134 @@
+/*=============================================================================
+ AudioTypes.h: Unreal general audio types.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+
+/*------------------------------------------------------------------------------------
+ Helpers
+------------------------------------------------------------------------------------*/
+
+#define CheckAudioLib(f) if( !AudioInitialized ) return f;
+
+#define ALock AudioLock(&Mutex);
+#define AUnlock AudioUnlock(&Mutex);
+
+/*------------------------------------------------------------------------------------
+ Constants
+------------------------------------------------------------------------------------*/
+
+#define AUDIO_TOTALCHANNELS 32
+#define AUDIO_TOTALVOICES 256
+
+#define AUDIO_MINPAN 0
+#define AUDIO_MIDPAN 16384
+#define AUDIO_MAXPAN 32767
+#define AUDIO_SURPAN 32768
+
+#define AUDIO_MINVOLUME 0
+#define AUDIO_MAXVOLUME 256
+
+#define AUDIO_DISABLED 0
+#define AUDIO_ENABLED 1
+
+#define AUDIO_MINSAMPLE8 -128
+#define AUDIO_MAXSAMPLE8 127
+
+#define AUDIO_MINSAMPLE16 -32768
+#define AUDIO_MAXSAMPLE16 32767
+
+/*------------------------------------------------------------------------------------
+ Flags
+------------------------------------------------------------------------------------*/
+
+#define AUDIO_MONO 0
+#define AUDIO_STEREO 1
+
+#define AUDIO_8BIT 0
+#define AUDIO_16BIT 2
+
+#define AUDIO_SHOLD 0
+#define AUDIO_COSINE 4
+
+#define AUDIO_2DAUDIO 0
+#define AUDIO_3DAUDIO 8
+
+#define SAMPLE_8BIT 1
+#define SAMPLE_16BIT 2
+#define SAMPLE_BIDILOOP 4
+#define SAMPLE_LOOPED 8
+#define SAMPLE_MONO 16
+#define SAMPLE_STEREO 32
+
+#define MEM_SEEK_CUR 0
+#define MEM_SEEK_ABS 1
+
+#define VOICE_AUTO 0
+#define VOICE_DISABLED 0
+#define VOICE_ENABLED 1
+#define VOICE_ACTIVE 2
+#define VOICE_FINISHED 4
+
+/*------------------------------------------------------------------------------------
+ Structs
+------------------------------------------------------------------------------------*/
+
+struct AudioVector
+{
+ FLOAT X, Y, Z, W;
+};
+
+struct MemChunk
+{
+ BYTE* Data;
+ DWORD DataLength;
+ DWORD Position;
+};
+
+struct Sample
+{
+ DWORD Size; // Size of the rest of structure.
+ _WORD Panning; // Panning position.
+ _WORD Volume; // Volume level.
+ _WORD Type; // Loop or sample type.
+ DWORD Length; // Length in samples.
+ DWORD LoopStart; // Start of loop in samples.
+ DWORD LoopEnd; // End of loop in samples.
+ DWORD SamplesPerSec; // Samples per second.
+ void* Data; // Data.
+};
+
+struct Voice
+{
+ INT State;
+ Sample* pSample;
+ INT PlayPosition;
+ FTime StartTime;
+ FTime LastTime;
+ Voice* StereoVoice;
+ INT Panning;
+ INT BasePanning;
+ INT Volume;
+};
+
+struct VoiceStats
+{
+ FString CompletionString;
+ FLOAT Completion;
+};
+
+struct AudioThread
+{
+ void* Thread;
+ INT Valid;
+ INT Exited;
+};
+
+struct AudioMutex
+{
+ void* Mutex;
+};
+
64 Audio/Inc/FormatWAV.h
@@ -0,0 +1,64 @@
+/*=============================================================================
+ FormatWAV.h: WAV file format.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+typedef struct
+{
+ BYTE ID[4];
+ DWORD Size;
+ BYTE Type[4];
+} WAVFileHeader;
+
+typedef struct
+{
+ _WORD Format;
+ _WORD Channels;
+ DWORD SamplesPerSec;
+ DWORD BytesPerSec;
+ _WORD BlockAlign;
+ _WORD BitsPerSample;
+} WAVFormatHeader;
+
+typedef struct
+{
+ _WORD Size;
+ _WORD SamplesPerBlock;
+} WAVFormatExHeader;
+
+typedef struct
+{
+ DWORD Manufacturer;
+ DWORD Product;
+ DWORD SamplePeriod;
+ DWORD Note;
+ DWORD FineTune;
+ DWORD SMPTEFormat;
+ DWORD SMPTEOffset;
+ DWORD Loops;
+ DWORD SamplerData;
+ struct
+ {
+ DWORD Identifier;
+ DWORD Type;
+ DWORD Start;
+ DWORD End;
+ DWORD Fraction;
+ DWORD Count;
+ } Loop[1];
+} WAVSampleHeader;
+
+typedef struct
+{
+ BYTE ID[4];
+ DWORD Size;
+} WAVChunkHeader;
+
+/*------------------------------------------------------------------------------------
+ WAVE management.
+------------------------------------------------------------------------------------*/
+
+Sample* LoadWAV( Sample* lSample, MemChunk* Chunk );
20 Audio/Src/Audio.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Audio.cpp: Unreal audio package.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+=============================================================================*/
+
+#include "AudioPrivate.h"
+
+/*-----------------------------------------------------------------------------
+ Globals.
+-----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ Package implementation.
+-----------------------------------------------------------------------------*/
+
+IMPLEMENT_PACKAGE(Audio);
+
+/*-----------------------------------------------------------------------------
+ The end.
+-----------------------------------------------------------------------------*/
351 Audio/Src/AudioCoreLinux.cpp
@@ -0,0 +1,351 @@
+/*=============================================================================
+ AudioCoreLinux.h: Core audio implementation for Linux.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Audio includes.
+------------------------------------------------------------------------------------*/
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#define __USE_UNIX98 1
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <linux/soundcard.h>
+#include "AudioPrivate.h"
+
+/*------------------------------------------------------------------------------------
+ AudioCore Globals.
+------------------------------------------------------------------------------------*/
+
+// Audio Device
+INT AudioDevice = -1;
+
+#define FRAGMENT_SIZE 0x0002000C
+
+/*------------------------------------------------------------------------------------
+ AudioCore Implementation.
+------------------------------------------------------------------------------------*/
+
+// Audio state control.
+void* GetAudioBuffer()
+{
+ return AudioBuffer;
+}
+
+INT OpenAudio( DWORD Rate, INT OutputMode, INT Latency )
+{
+ // Open the audio device.
+ AudioDevice = open("/dev/dsp", O_WRONLY | O_NONBLOCK, 0);
+
+ if (AudioDevice == -1)
+ {
+ debugf( NAME_Init, TEXT("Failed to open audio device.") );
+ return 0;
+ }
+
+ // Set the buffer size.
+ INT Fragment = FRAGMENT_SIZE;
+ if (ioctl(AudioDevice, SNDCTL_DSP_SETFRAGMENT, &Fragment) == -1)
+ {
+ debugf( NAME_Init, TEXT("Failed to set fragment format.") );
+ close(AudioDevice);
+ AudioDevice = -1;
+ return 0;
+ }
+
+ // Set the output format.
+ INT Format;
+ if (OutputMode & AUDIO_16BIT)
+ {
+ Format = AFMT_S16_LE;
+ AudioFormat |= AUDIO_16BIT;
+ } else {
+ Format = AFMT_U8;
+ AudioFormat &= ~AUDIO_16BIT;
+ }
+ if (ioctl(AudioDevice, SNDCTL_DSP_SETFMT, &Format) == -1)
+ {
+ debugf( NAME_Init, TEXT("Failed to set audio format.") );
+ close(AudioDevice);
+ AudioDevice = -1;
+ return 0;
+ }
+
+ // Set stereo.
+ INT Stereo;
+ if (OutputMode & AUDIO_STEREO)
+ {
+ Stereo = 1;
+ AudioFormat |= AUDIO_STEREO;
+ } else {
+ Stereo = 0;
+ AudioFormat &= ~AUDIO_STEREO;
+ }
+ if (ioctl(AudioDevice, SNDCTL_DSP_STEREO, &Stereo) == -1)
+ {
+ debugf( NAME_Init, TEXT("Failed to enable stereo audio.") );
+ close(AudioDevice);
+ AudioDevice = -1;
+ return 0;
+ }
+
+ // Get buffer size.
+ if (ioctl(AudioDevice, SNDCTL_DSP_GETBLKSIZE, &BufferSize) == -1)
+ {
+ debugf( NAME_Init, TEXT("Failed to get audio buffer size.") );
+ close(AudioDevice);
+ AudioDevice = -1;
+ return 0;
+ }
+
+ // Set the rate.
+ if (ioctl(AudioDevice, SNDCTL_DSP_SPEED, &Rate) == -1)
+ {
+ debugf( NAME_Init, TEXT("Failed to set playback rate to %iHz"), Rate );
+ close(AudioDevice);
+ AudioDevice = -1;
+ return 0;
+ }
+ AudioRate = Rate;
+
+ // Initialize AudioBuffer.
+ debugf( NAME_Init, TEXT("Allocating an audio buffer of %i bytes."), BufferSize );
+ AudioBuffer = (BYTE*) appMalloc( BufferSize, TEXT("Audio Buffer") );
+
+ return 1;
+}
+
+INT ReopenAudioDevice( DWORD Rate, INT OutputMode, INT Latency )
+{
+ ALock;
+ debugf( NAME_Init, TEXT("Reopening audio device.") );
+ CloseAudio();
+ INT Result = OpenAudio( Rate, OutputMode, Latency );
+ AUnlock;
+
+ return Result;
+}
+
+void CloseAudio()
+{
+ ALock;
+ if (AudioBuffer != NULL)
+ {
+ appFree(AudioBuffer);
+ AudioBuffer = NULL;
+ }
+ if (AudioDevice > -1)
+ {
+ close(AudioDevice);
+ AudioDevice = -1;
+ }
+ AUnlock;
+}
+
+// Audio flow control.
+void PlayAudio()
+{
+ if (AudioDevice == -1)
+ return;
+
+ ssize_t WriteResult;
+ WriteResult = write( AudioDevice, AudioBuffer, BufferSize );
+
+ if (WriteResult == -1)
+ {
+ switch (errno)
+ {
+ case 0: // No error condition, try again?
+ case EAGAIN: // No room, write again.
+ case EINTR: // Write blocked, try again.
+ PlayAudio();
+ break;
+ default:
+ // Handle legit error.
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------------
+ Read helpers.
+------------------------------------------------------------------------------------*/
+
+void* ReadMem( void* DestData, INT NumChunks, INT ChunkSize, MemChunk* SrcData )
+{
+ void* Result = memcpy( DestData, SrcData->Data + SrcData->Position, ChunkSize*NumChunks );
+ SrcData->Position += ChunkSize*NumChunks;
+
+ return Result;
+}
+
+void* SeekMem( MemChunk* SrcData, INT Position, INT SeekMode )
+{
+ switch (SeekMode)
+ {
+ case MEM_SEEK_CUR:
+ SrcData->Position += Position;
+ break;
+ case MEM_SEEK_ABS:
+ SrcData->Position = Position;
+ break;
+ }
+ return SrcData->Data;
+}
+
+BYTE Read8_Mem( void* Data )
+{
+ BYTE Result;
+
+ memcpy( Data, &Result, (sizeof Result) );
+
+ return Result;
+}
+
+_WORD Read16_Mem( void* Data )
+{
+ _WORD Result;
+
+ memcpy( Data, &Result, (sizeof Result) );
+
+ return Result;
+}
+
+DWORD Read32_Mem( void* Data )
+{
+ DWORD Result;
+
+ memcpy( Data, &Result, (sizeof Result) );
+
+ return Result;
+}
+
+QWORD Read64_Mem( void* Data )
+{
+ QWORD Result;
+
+ memcpy( Data, &Result, (sizeof Result) );
+
+ return Result;
+}
+
+/*------------------------------------------------------------------------------------
+ Thread control.
+------------------------------------------------------------------------------------*/
+
+UBOOL CreateAudioThread(AudioThread* NewThread, void* (*ThreadRoutine)(void*) )
+{
+ // Allocate a new thread.
+ pthread_t* NewPosixThread;
+ NewPosixThread = (pthread_t*) appMalloc(sizeof(pthread_t), TEXT("POSIX Thread"));
+
+ // Initialize parameters.
+ pthread_attr_t NewThreadAttributes;
+ pthread_attr_init(&NewThreadAttributes);
+ pthread_attr_setdetachstate(&NewThreadAttributes, PTHREAD_CREATE_JOINABLE);
+
+ // Try to create the thread.
+ NewThread->Valid = 1;
+ INT Error = pthread_create(NewPosixThread, &NewThreadAttributes, ThreadRoutine, NULL);
+ if (Error != 0)
+ {
+ // Some error occured.
+ NewThread->Valid = 0;
+ appErrorf( TEXT("Failed to create a valid mixing thread.") );
+ return 0;
+ }
+ NewThread->Thread = NewPosixThread;
+ NewThread->Exited = 0;
+ debugf( NAME_Init, TEXT("Created a new audio thread.") );
+
+ return 1;
+}
+
+UBOOL DestroyAudioThread(AudioThread* OldThread)
+{
+ ALock;
+ OldThread->Valid = 0;
+ AUnlock;
+ pthread_t* Thread = (pthread_t*) OldThread->Thread;
+ pthread_join(*Thread, NULL);
+ appFree(OldThread->Thread);
+ return 1;
+}
+
+UBOOL ExitAudioThread(AudioThread* Thread)
+{
+ Thread->Exited = 1;
+ pthread_exit(NULL);
+ return 1;
+}
+
+UBOOL CreateAudioMutex(AudioMutex* Mutex)
+{
+ pthread_mutex_t* NewMutex;
+ NewMutex = (pthread_mutex_t*) appMalloc(sizeof(pthread_mutex_t), TEXT("POSIX Mutex"));
+
+ pthread_mutexattr_t MutexAttr;
+ pthread_mutexattr_init(&MutexAttr);
+ pthread_mutexattr_settype(&MutexAttr, PTHREAD_MUTEX_RECURSIVE_NP);
+
+ pthread_mutex_init(NewMutex, &MutexAttr);
+ Mutex->Mutex = NewMutex;
+ return 1;
+}
+
+UBOOL DestroyAudioMutex(AudioMutex* Mutex)
+{
+ pthread_mutex_destroy((pthread_mutex_t*) Mutex->Mutex);
+ appFree(Mutex->Mutex);
+ return 1;
+}
+
+UBOOL AudioLock(AudioMutex* Mutex)
+{
+ pthread_mutex_lock((pthread_mutex_t*) Mutex->Mutex);
+ return 1;
+}
+
+UBOOL AudioUnlock(AudioMutex* Mutex)
+{
+ pthread_mutex_unlock((pthread_mutex_t*) Mutex->Mutex);
+ return 1;
+}
+
+/*------------------------------------------------------------------------------------
+ Timing
+------------------------------------------------------------------------------------*/
+
+// Sleeps for ms milliseconds.
+void AudioSleep(INT ms)
+{
+ struct timeval tv;
+
+ tv.tv_sec = ms/1000;
+ tv.tv_usec = (ms%1000)*1000;
+ select(0, NULL, NULL, NULL, &tv);
+}
+
+// Blocks until audio device is open.
+INT AudioWait()
+{
+ if (AudioDevice && AudioInitialized)
+ {
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(AudioDevice, &fdset);
+ select(AudioDevice+1, NULL, &fdset, NULL, NULL);
+ return 1;
+ } else
+ return 0;
+}
371 Audio/Src/AudioLibrary.cpp
@@ -0,0 +1,371 @@
+/*=============================================================================
+ AudioLibrary.cpp: Unreal audio interface object.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Audio includes.
+------------------------------------------------------------------------------------*/
+
+#include "AudioPrivate.h"
+
+/*------------------------------------------------------------------------------------
+ Globals
+------------------------------------------------------------------------------------*/
+
+// Raw Buffer
+void* AudioBuffer=NULL;
+void* MixBuffer=NULL;
+INT BufferSize=0;
+INT AudioFormat;
+INT AudioRate;
+
+// State
+INT AudioInitialized=0;
+INT AudioPaused=0;
+
+// Audio
+INT MusicVoices;
+INT SampleVoices;
+Voice Voices[AUDIO_TOTALVOICES];
+
+// Volume
+INT SampleVolume;
+
+// Threads
+AudioThread MixingThread;
+AudioMutex Mutex;
+
+/*------------------------------------------------------------------------------------
+ Library control.
+------------------------------------------------------------------------------------*/
+
+// Start the audio system.
+UBOOL AudioInit( DWORD Rate, INT OutputMode, INT Latency )
+{
+ if (AudioInitialized)
+ appErrorf( TEXT("Soundsystem already initialized!") );
+
+ // Open the audio subsystem.
+ if (OpenAudio( Rate, OutputMode, Latency ) == 0)
+ return 0;
+
+ // Initialize defaults.
+ SampleVoices = 0;
+ MusicVoices = 0;
+ for (INT i=0; i<AUDIO_TOTALVOICES; i++)
+ Voices[i].State = VOICE_DISABLED;
+
+ // Create the thread sync mutex.
+ CreateAudioMutex(&Mutex);
+
+ // Create the mixing thread.
+ AudioPaused = 1;
+ CreateAudioThread(&MixingThread, DoSound);
+
+ AudioInitialized = 1;
+ return 1;
+}
+
+// Restart the audio system.
+UBOOL AudioReinit( DWORD Rate, INT OutputMode, INT Latency )
+{
+ AudioInitialized = 0;
+ INT Result = ReopenAudioDevice( Rate, OutputMode, Latency );
+ AudioInitialized = 1;
+
+ return Result;
+}
+
+// Stop the audio system.
+UBOOL AudioShutdown()
+{
+ AudioInitialized = 0;
+ DestroyAudioThread(&MixingThread);
+ CloseAudio();
+ DestroyAudioMutex(&Mutex);
+ return 1;
+}
+
+// Allocate memory.
+UBOOL AllocateVoices( INT RequestedChannels )
+{
+ CheckAudioLib(0);
+
+ ALock;
+ if (RequestedChannels + MusicVoices <= AUDIO_TOTALVOICES)
+ {
+ SampleVoices = RequestedChannels;
+ for (INT i=0; i<RequestedChannels; i++)
+ Voices[i].State |= VOICE_ENABLED;
+ AUnlock;
+ return 1;
+ }
+ AUnlock;
+ return 0;
+}
+
+/*------------------------------------------------------------------------------------
+ Master control.
+------------------------------------------------------------------------------------*/
+
+// Start [Unpause] all playing audio.
+UBOOL AudioStartOutput( DWORD Rate, INT OutputMode, INT Latency )
+{
+ CheckAudioLib(0);
+
+ ALock;
+ AudioReinit( Rate, OutputMode, Latency );
+ AudioPaused = 0;
+ AUnlock;
+ return 1;
+}
+
+// Stop [Pause] all playing audio.
+UBOOL AudioStopOutput()
+{
+ ALock;
+ AudioPaused = 1;
+ for (INT i=0; i++; i<AUDIO_TOTALVOICES)
+ {
+ if (Voices[i].State & VOICE_ACTIVE)
+ {
+ Voices[i].PlayPosition = 0;
+ Voices[i].State &= ~VOICE_ACTIVE;
+ }
+ }
+ AUnlock;
+ return 1;
+}
+
+/*------------------------------------------------------------------------------------
+ Sample control.
+------------------------------------------------------------------------------------*/
+
+// Load a sound image from memory.
+Sample* LoadSample( MemChunk* LoadChunk, const TCHAR* SampleName )
+{
+ CheckAudioLib(NULL);
+
+ if (LoadChunk == NULL)
+ return NULL;
+
+ Sample* lSample = (Sample*) appMalloc( sizeof(Sample), SampleName );
+ if (lSample == NULL)
+ return NULL;
+
+ appMemset( lSample, 0, sizeof(Sample) );
+ BYTE Type[4];
+ LoadChunk->Position = 8;
+ ReadMem(Type, 1, 4, LoadChunk);
+ SeekMem(LoadChunk, 0, MEM_SEEK_ABS);
+ if (!appMemcmp( Type, "WAVE", 4 ))
+ return LoadWAV(lSample, LoadChunk);
+
+ return NULL;
+}
+
+// Unload a sound image from memory.
+UBOOL UnloadSample( Sample* UnloadSample )
+{
+ CheckAudioLib(0);
+
+ ALock;
+ if (UnloadSample)
+ {
+ // Set length to zero stopping the sound.
+ UnloadSample->Length = 0;
+
+ if (UnloadSample->Data)
+ {
+ appFree(UnloadSample->Data);
+ UnloadSample->Data = NULL;
+ }
+ appFree(UnloadSample);
+ }
+ AUnlock;
+
+ return 1;
+}
+
+// Add sample to set of playing sounds.
+Voice* StartSample( INT VoiceNum, Sample* Sample, INT Freq, INT Volume, INT Panning )
+{
+ CheckAudioLib(NULL);
+
+ if (SampleVoices == 0)
+ return NULL;
+ if (Sample == NULL)
+ return NULL;
+
+ ALock;
+ INT Layers;
+ if (Sample->Type & SAMPLE_STEREO)
+ {
+ Layers = 2;
+ VoiceNum = VOICE_AUTO;
+ } else
+ Layers = 1;
+ Voice* CurrentVoice = NULL;
+ Voice* StereoVoice = NULL;
+ for (INT i=0; i<Layers; i++)
+ {
+ if (VoiceNum == VOICE_AUTO)
+ CurrentVoice = AcquireVoice();
+ else
+ CurrentVoice = &Voices[VoiceNum-1];
+ if (CurrentVoice)
+ {
+ CurrentVoice->State &= ~VOICE_ACTIVE;
+ if (Sample->Data)
+ {
+ CurrentVoice->State |= VOICE_ACTIVE;
+ CurrentVoice->State &= ~VOICE_FINISHED;
+ CurrentVoice->pSample = Sample;
+ if (Layers > 1)
+ CurrentVoice->Panning = (i&1) ? AUDIO_MINPAN : AUDIO_MAXPAN;
+ else
+ CurrentVoice->Panning = Panning;
+ CurrentVoice->BasePanning = Panning;
+ CurrentVoice->StartTime = CurrentVoice->LastTime = appSeconds();
+ CurrentVoice->StereoVoice = StereoVoice;
+ CurrentVoice->PlayPosition = 0;
+ CurrentVoice->Volume = Volume;
+ StereoVoice = CurrentVoice;
+ }
+ }
+ }
+ AUnlock;
+
+ return CurrentVoice;
+}
+
+// Stop a playing sample.
+UBOOL StopSample( Voice* StopVoice )
+{
+ ALock;
+ if (StopVoice)
+ {
+ StopVoice->State &= ~VOICE_ACTIVE;
+ if (StopVoice->StereoVoice)
+ StopVoice->StereoVoice->State &= ~VOICE_ACTIVE;
+ }
+ AUnlock;
+ return 1;
+}
+
+// Check status of a sample.
+UBOOL SampleFinished( Voice* Sample )
+{
+ return Sample->State & VOICE_FINISHED;
+}
+
+// Change a sample.
+void UpdateSample( Voice* InVoice, INT Freq, INT Volume, INT Panning )
+{
+ ALock;
+ InVoice->Volume = Volume;
+ InVoice->Panning = InVoice->Panning + ((Panning - InVoice->Panning)/2);
+ InVoice->BasePanning = InVoice->Panning;
+ AUnlock;
+}
+
+/*------------------------------------------------------------------------------------
+ Voice control.
+------------------------------------------------------------------------------------*/
+
+// Acquire an active voice.
+Voice* AcquireVoice()
+{
+ ALock;
+ Voice* OpenVoice = NULL;
+ INT FoundVoice = 0, OldestVoice = -1;
+ FTime LastTime = 0xfffffffe;
+ for (INT i=0; i<SampleVoices && !FoundVoice; i++)
+ {
+ if (Voices[i].State & VOICE_ENABLED)
+ {
+ if ((~Voices[i].State) & VOICE_ACTIVE)
+ {
+ OpenVoice = &Voices[i];
+ FoundVoice = 1;
+ }
+ else if (Voices[i].StartTime < LastTime)
+ {
+ LastTime = Voices[i].StartTime;
+ OldestVoice = i;
+ }
+ }
+ }
+ if (OldestVoice > -1)
+ OpenVoice = &Voices[OldestVoice];
+ AUnlock;
+
+ return OpenVoice;
+}
+
+// Get some info on a voice.
+void GetVoiceStats( VoiceStats* InStats, Voice* InVoice )
+{
+ ALock;
+
+ // % complete.
+ if (InVoice->PlayPosition == 0)
+ InStats->Completion = 0;
+ else if (InVoice->pSample != NULL)
+ {
+ FLOAT SoundSamples = InVoice->pSample->Length;
+ FLOAT Position = InVoice->PlayPosition;
+ InStats->Completion = Position / SoundSamples;
+ }
+
+ // Completion string.
+ FString CompletionString;
+ INT NumStars = (INT) (InStats->Completion * 10);
+ for (INT i=0; i<NumStars; i++)
+ CompletionString = CompletionString + FString::Printf( TEXT("*") );
+ for (i=NumStars; i<10; i++)
+ CompletionString = CompletionString + FString::Printf( TEXT("-") );
+ InStats->CompletionString = CompletionString;
+
+ AUnlock;
+}
+
+/*------------------------------------------------------------------------------------
+ Volume control.
+------------------------------------------------------------------------------------*/
+
+UBOOL SetSampleVolume( FLOAT Volume )
+{
+ ALock;
+ SampleVolume = (INT) Volume;
+ AUnlock;
+ return 1;
+}
+
+UBOOL SetMusicVolume( FLOAT Volume )
+{
+ return 1;
+}
+
+UBOOL SetCDAudioVolume( FLOAT Volume )
+{
+ return 1;
+}
+
+/*------------------------------------------------------------------------------------
+ CD Audio control.
+------------------------------------------------------------------------------------*/
+
+UBOOL StartCDAudio( INT Track )
+{
+ return 1;
+}
+
+UBOOL StopCDAudio()
+{
+ return 1;
+}
427 Audio/Src/AudioMixer.cpp
@@ -0,0 +1,427 @@
+/*=============================================================================
+ AudioMixer.cpp: Unreal sound mixer.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Audio includes.
+------------------------------------------------------------------------------------*/
+
+#include "AudioPrivate.h"
+
+/*------------------------------------------------------------------------------------
+ Mixing functions.
+------------------------------------------------------------------------------------*/
+
+#define SOUND_MIXING 0
+#define SOUND_PLAYING 1
+
+#define ADJUST_VOLUME(s, v) (s = (s*v)/AUDIO_MAXVOLUME)
+
+void* DoSound(void* Arguments)
+{
+ // Allocate the mixing buffer.
+ ALock;
+ MixBuffer = appMalloc(BufferSize, TEXT("Mixing Buffer"));
+ AUnlock;
+
+ INT Task = SOUND_MIXING, i;
+ while (MixingThread.Valid)
+ {
+ switch (Task)
+ {
+ case SOUND_MIXING:
+ ALock;
+ // Empty the mixing buffer.
+ appMemset(MixBuffer, 0, BufferSize);
+ for (i=0; i<AUDIO_TOTALVOICES; i++)
+ {
+ // Get an enabled and active voice.
+ if ((Voices[i].State&VOICE_ENABLED) && (Voices[i].State&VOICE_ACTIVE) && !AudioPaused)
+ {
+ // Mix a buffer's worth of sound.
+ INT Format = Voices[i].pSample->Type & SAMPLE_16BIT
+ ? SAMPLE_16BIT : SAMPLE_8BIT;
+ switch (Format)
+ {
+ case SAMPLE_8BIT:
+ if (AudioFormat & AUDIO_16BIT)
+ MixVoice8to16( i );
+ break;
+ case SAMPLE_16BIT:
+ if (AudioFormat & AUDIO_16BIT)
+ MixVoice16to16( i );
+ break;
+ }
+ }
+ }
+ AUnlock;
+ Task = SOUND_PLAYING;
+ break;
+ case SOUND_PLAYING:
+ // Block until the audio device is writable.
+ if (!AudioPaused)
+ {
+ if (AudioWait() == 0)
+ break;
+ } else break;
+
+ ALock;
+ // Silence the audio buffer.
+ appMemset(AudioBuffer, 0, BufferSize);
+
+ // Ready the most recently mixed audio.
+ appMemcpy(AudioBuffer, MixBuffer, BufferSize);
+
+ // Play it.
+ if (!AudioPaused)
+ {
+ PlayAudio();
+ }
+ AUnlock;
+
+ Task = SOUND_MIXING;
+ break;
+ }
+ }
+
+ // Free the mixing buffer.
+ ALock;
+ if (MixBuffer != NULL)
+ appFree(MixBuffer);
+ AUnlock;
+
+ ExitAudioThread(&MixingThread);
+}
+
+// Mixes an 8 bit unsigned voice into 16 bit signed output.
+void MixVoice8to16(INT VoiceIndex)
+{
+ Voice* CurrentVoice = &Voices[VoiceIndex];
+
+ if (CurrentVoice->State & VOICE_FINISHED)
+ return;
+
+ if (CurrentVoice->pSample->SamplesPerSec != AudioRate)
+ ConvertVoice8( CurrentVoice );
+
+ // How many samples are in this sound?
+ INT SoundSamples = CurrentVoice->pSample->Length;
+
+ // What is our sample size.
+ INT SampleSize;
+ if (AudioFormat & AUDIO_STEREO)
+ SampleSize = 4;
+ else
+ SampleSize = 2;
+
+ // Mix a buffer's worth of samples.
+ INT SamplesToMix = BufferSize / SampleSize;
+
+ // Get our start position...
+ BYTE* Src8 = (BYTE*) CurrentVoice->pSample->Data;
+
+ // ...fast forward to where we left off...
+ Src8 += CurrentVoice->PlayPosition;
+
+ // ...and get the initial target.
+ SBYTE* Dst8 = (SBYTE*) MixBuffer;
+
+ // Scale playing volume by the volume set by the player.
+ INT VolumeAdjust = ((CurrentVoice->Volume*2) * SampleVolume) / AUDIO_MAXVOLUME;
+
+ // Calculate panning offset.
+ FLOAT PanningOffset = CurrentVoice->Panning - AUDIO_MIDPAN;
+ FLOAT PanningFactor = PanningOffset / AUDIO_MIDPAN;
+ UBOOL PanSample = AudioFormat & AUDIO_STEREO;
+
+ // For each target sample, mix two input samples.
+ INT MixedSample, SourceSample;
+ for (INT i=0; i<SamplesToMix; i++)
+ {
+ // Perform this operation for each speaker.
+ for (INT j=0; j<SampleSize; j += 2)
+ {
+ // Ignore low byte.
+ Dst8++;
+
+ // Scale the source by the volume.
+ SourceSample = *Src8 - 128;
+ SourceSample = (SourceSample * VolumeAdjust) / AUDIO_MAXVOLUME;
+
+ // Pan the source.
+ if (PanSample)
+ {
+ // Even the sound.
+ SourceSample /= (SampleSize/2);
+ // Pan according to our factor.
+ if (j == 0)
+ SourceSample -= (INT) (SourceSample * PanningFactor);
+ else
+ SourceSample += (INT) (SourceSample * PanningFactor);
+ }
+
+ // Mix the result.
+ MixedSample = SourceSample + *Dst8;
+
+ // Bound the result.
+ if (MixedSample > AUDIO_MAXSAMPLE8) {
+ *Dst8 = AUDIO_MAXSAMPLE8;
+ } else if (MixedSample < AUDIO_MINSAMPLE8) {
+ *Dst8 = AUDIO_MINSAMPLE8;
+ } else {
+ *Dst8 = MixedSample;
+ }
+
+ // Destination is 16 bit, so increment another byte.
+ Dst8++;
+ }
+ // Source is 8 bit, so increment 1 byte.
+ Src8++;
+
+ // Keep track of how much we've mixed.
+ CurrentVoice->PlayPosition++;
+ if (CurrentVoice->PlayPosition >= SoundSamples)
+ {
+ // We've run out of source.
+ // Finish if this isn't a looping sound.
+ CurrentVoice->PlayPosition = 0;
+ if (CurrentVoice->pSample->Type & SAMPLE_LOOPED)
+ {
+ Src8 = (BYTE*) CurrentVoice->pSample->Data;
+ } else {
+ i = SamplesToMix;
+ CurrentVoice->State |= VOICE_FINISHED;
+ CurrentVoice->State &= ~VOICE_ACTIVE;
+ }
+ }
+ }
+}
+
+// Mix a 16 bit signed sample into 16 bit signed output.
+void MixVoice16to16(INT VoiceIndex)
+{
+ Voice* CurrentVoice = &Voices[VoiceIndex];
+
+ if (CurrentVoice->State & VOICE_FINISHED)
+ return;
+
+ if (CurrentVoice->pSample->SamplesPerSec != AudioRate)
+ ConvertVoice16( CurrentVoice );
+
+ // How many samples are in this sound?
+ INT SoundSamples = CurrentVoice->pSample->Length;
+
+ // What is our sample size.
+ INT SampleSize;
+ if (AudioFormat & AUDIO_STEREO)
+ SampleSize = 4;
+ else
+ SampleSize = 2;
+
+ // Mix a buffer's worth of samples.
+ INT SamplesToMix = BufferSize/SampleSize;
+
+ // Get our start position...
+ SWORD* Src16 = (SWORD*) CurrentVoice->pSample->Data;
+
+ // ...fast forward to where we left off...
+ Src16 += CurrentVoice->PlayPosition;
+
+ // ...and get the initial target.
+ SWORD* Dst16 = (SWORD*) MixBuffer;
+
+ // Determine volume.
+ INT VolumeAdjust = ((CurrentVoice->Volume*2) * SampleVolume) / AUDIO_MAXVOLUME;
+
+ // Calculate panning offset.
+ FLOAT PanningOffset = CurrentVoice->Panning - AUDIO_MIDPAN;
+ FLOAT PanningFactor = PanningOffset / AUDIO_MIDPAN;
+ UBOOL PanSample = AudioFormat & AUDIO_STEREO;
+
+ // For each target sample, mix two input samples.
+ INT MixedSample, SourceSample;
+ for (INT i=0; i<SamplesToMix; i++)
+ {
+ // Perform this operation for each speaker.
+ for (INT j=0; j<SampleSize; j+= 2)
+ {
+ // Adjust the volume.
+ SourceSample = *Src16;
+ SourceSample = (SourceSample * VolumeAdjust) / AUDIO_MAXVOLUME;
+
+ // Pan the source.
+ if (PanSample)
+ {
+ // Even the sound.
+ SourceSample /= (SampleSize/2);
+ // Pan according to our factor.
+ if (j == 0)
+ SourceSample -= (INT) (SourceSample * PanningFactor);
+ else
+ SourceSample += (INT) (SourceSample * PanningFactor);
+ }
+
+ // Mix the result.
+ MixedSample = SourceSample + *Dst16;
+
+ // Apply limits.
+ if (MixedSample > AUDIO_MAXSAMPLE16) {
+ *Dst16 = AUDIO_MAXSAMPLE16;
+ } else if (MixedSample < AUDIO_MINSAMPLE16) {
+ *Dst16 = AUDIO_MINSAMPLE16;
+ } else {
+ *Dst16 = MixedSample;
+ }
+
+ // Destination is 16 bit, so increment by an SWORD.
+ Dst16++;
+ }
+
+ // Source is 16 bit, so increment by an SWORD.
+ Src16++;
+
+ // Keep track of how much we've mixed.
+ CurrentVoice->PlayPosition++;
+ if (CurrentVoice->PlayPosition >= SoundSamples)
+ {
+ // We've run out of source.
+ // Finish if this isn't a looping sound.
+ CurrentVoice->PlayPosition = 0;
+ if (CurrentVoice->pSample->Type & SAMPLE_LOOPED)
+ {
+ Src16 = (SWORD*) CurrentVoice->pSample->Data;
+ } else {
+ i = SamplesToMix;
+ CurrentVoice->State |= VOICE_FINISHED;
+ CurrentVoice->State &= ~VOICE_ACTIVE;
+ }
+ }
+ }
+}
+
+// Convert an 8 bit unsigned voice to the current rate.
+// Maintains unsignedness.
+void ConvertVoice8( Voice* InVoice )
+{
+ // How fast is this sample?
+ INT VoiceRate = InVoice->pSample->SamplesPerSec;
+ if ((VoiceRate != 11025) && (VoiceRate != 22050) && (VoiceRate != 44100))
+ appErrorf( TEXT("Unsupported playback rate: %i"), VoiceRate );
+ if (VoiceRate > AudioRate)
+ {
+ // This voice is slower than our current rate.
+ INT RateFactor = VoiceRate / AudioRate;
+ INT NewSize;
+ if (InVoice->pSample->Length % 2 == 1)
+ NewSize = (InVoice->pSample->Length+1) / RateFactor;
+ else
+ NewSize = InVoice->pSample->Length / RateFactor;
+ BYTE* Source = (BYTE*) InVoice->pSample->Data;
+ BYTE* NewData = (BYTE*) appMalloc(NewSize, TEXT("Sample Data"));
+ check(NewData);
+ BYTE* Dest = NewData;
+
+ appMemset( Dest, 0x80, NewSize );
+ for (INT i=0; i<InVoice->pSample->Length; i += RateFactor)
+ {
+ *Dest = Source[i];
+ Dest++;
+ }
+
+ InVoice->PlayPosition = 0;
+ InVoice->pSample->SamplesPerSec = AudioRate;
+ InVoice->pSample->Length = NewSize;
+ void* OldData = InVoice->pSample->Data;
+ InVoice->pSample->Data = NewData;
+ appFree( OldData );
+ } else {
+ // This voice is faster than our current rate.
+ INT RateFactor = AudioRate / VoiceRate;
+ INT NewSize = InVoice->pSample->Length * RateFactor;
+
+ BYTE* Source = (BYTE*) InVoice->pSample->Data;
+ BYTE* NewData = (BYTE*) appMalloc(NewSize, TEXT("Sample Data"));
+ check(NewData);
+ BYTE* Dest = NewData;
+
+ appMemset( Dest, 0x80, NewSize );
+ for (INT i=0; i<NewSize; i++)
+ {
+ Dest[i] = *Source;
+ if (i%RateFactor == 1)
+ Source++;
+ }
+
+ InVoice->PlayPosition = 0;
+ InVoice->pSample->SamplesPerSec = AudioRate;
+ InVoice->pSample->Length = NewSize;
+ void* OldData = InVoice->pSample->Data;
+ InVoice->pSample->Data = (void*) NewData;
+ appFree( OldData );
+ }
+}
+
+// Convert an 16 bit signed voice to the current rate.
+// Maintains signedness.
+void ConvertVoice16( Voice* InVoice )
+{
+ // How fast is this sample?
+ INT VoiceRate = InVoice->pSample->SamplesPerSec;
+ if ((VoiceRate != 11025) && (VoiceRate != 22050) && (VoiceRate != 44100))
+ appErrorf( TEXT("Unsupported playback rate: %i"), VoiceRate );
+ if (VoiceRate > AudioRate)
+ {
+ // This voice is faster than our current rate.
+ INT RateFactor = VoiceRate / AudioRate;
+ INT NewSize;
+ if (InVoice->pSample->Length % 2 == 1)
+ NewSize = (InVoice->pSample->Length+1) / RateFactor;
+ else
+ NewSize = InVoice->pSample->Length / RateFactor;
+
+ SWORD* Source = (SWORD*) InVoice->pSample->Data;
+ SWORD* NewData = (SWORD*) appMalloc(NewSize*2, TEXT("Sample Data"));
+ SWORD* Dest = NewData;
+
+ appMemset(Dest, 0, NewSize*2);
+ for (INT i=0; i<InVoice->pSample->Length; i += RateFactor)
+ {
+ *Dest = Source[i];
+ Dest++;
+ }
+
+ InVoice->PlayPosition = 0;
+ InVoice->pSample->SamplesPerSec = AudioRate;
+ InVoice->pSample->Length = NewSize;
+ void* OldData = InVoice->pSample->Data;
+ InVoice->pSample->Data = (void*) NewData;
+ appFree( OldData );
+ } else {
+ // This voice is slower than our current rate.
+ INT RateFactor = AudioRate / VoiceRate;
+ INT NewSize = InVoice->pSample->Length * RateFactor;
+
+ SWORD* Source = (SWORD*) InVoice->pSample->Data;
+ SWORD* NewData = (SWORD*) appMalloc(NewSize*2, TEXT("Sample Data"));
+ SWORD* Dest = NewData;
+
+ appMemset( Dest, 0, NewSize*2 );
+ for (INT i=0; i<NewSize; i++)
+ {
+ Dest[i] = *Source;
+ if (i%RateFactor == 1)
+ Source++;
+ }
+
+ InVoice->PlayPosition = 0;
+ InVoice->pSample->SamplesPerSec = AudioRate;
+ InVoice->pSample->Length = NewSize;
+ void* OldData = InVoice->pSample->Data;
+ InVoice->pSample->Data = (void*) NewData;
+ appFree( OldData );
+ }
+}
18 Audio/Src/AudioPrivate.h
@@ -0,0 +1,18 @@
+/*=============================================================================
+ AudioPrivate.h: Unreal audio private header file.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+=============================================================================*/
+
+/*----------------------------------------------------------------------------
+ Audio public includes.
+----------------------------------------------------------------------------*/
+
+#include "Audio.h"
+
+/*-----------------------------------------------------------------------------
+ Audio private includes.
+-----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ The End.
+-----------------------------------------------------------------------------*/
674 Audio/Src/AudioSubsystem.cpp
@@ -0,0 +1,674 @@
+/*=============================================================================
+ AudioSubsystem.cpp: Unreal audio interface object.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+ Based on the UGalaxyAudioSubsystem interface.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Audio includes.
+------------------------------------------------------------------------------------*/
+
+#include "AudioPrivate.h"
+
+/*------------------------------------------------------------------------------------
+ UGenericAudioSubsystem.
+------------------------------------------------------------------------------------*/
+
+IMPLEMENT_CLASS(UGenericAudioSubsystem);
+
+UGenericAudioSubsystem::UGenericAudioSubsystem()
+{
+ guard(UGenericAudioSubsystem::UGenericAudioSubsystem);
+
+ MusicFade = 1.0;
+ CurrentCDTrack = 255;
+ LastTime = appSeconds();
+
+ unguard;
+}
+
+void UGenericAudioSubsystem::StaticConstructor()
+{
+ guard(UGenericAudioSubsystem::StaticConstructor);
+
+ UEnum* OutputRates = new( GetClass(), TEXT("OutputRates") )UEnum( NULL );
+ new( OutputRates->Names )FName( TEXT("8000Hz" ) );
+ new( OutputRates->Names )FName( TEXT("11025Hz") );
+ new( OutputRates->Names )FName( TEXT("16000Hz") );
+ new( OutputRates->Names )FName( TEXT("22050Hz") );
+ new( OutputRates->Names )FName( TEXT("32000Hz") );
+ new( OutputRates->Names )FName( TEXT("44100Hz") );
+ new( OutputRates->Names )FName( TEXT("48000Hz") );
+ new(GetClass(),TEXT("UseFilter"), RF_Public)UBoolProperty (CPP_PROPERTY(UseFilter ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("UseSurround"), RF_Public)UBoolProperty (CPP_PROPERTY(UseSurround ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("UseStereo"), RF_Public)UBoolProperty (CPP_PROPERTY(UseStereo ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("UseCDMusic"), RF_Public)UBoolProperty (CPP_PROPERTY(UseCDMusic ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("UseDigitalMusic"), RF_Public)UBoolProperty (CPP_PROPERTY(UseDigitalMusic), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("ReverseStereo"), RF_Public)UBoolProperty (CPP_PROPERTY(ReverseStereo ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("Latency"), RF_Public)UIntProperty (CPP_PROPERTY(Latency ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("OutputRate"), RF_Public)UByteProperty (CPP_PROPERTY(OutputRate ), TEXT("Audio"), CPF_Config, OutputRates );
+ new(GetClass(),TEXT("Channels"), RF_Public)UIntProperty (CPP_PROPERTY(Channels), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("MusicVolume"), RF_Public)UByteProperty (CPP_PROPERTY(MusicVolume ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("SoundVolume"), RF_Public)UByteProperty (CPP_PROPERTY(SoundVolume ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("AmbientFactor"), RF_Public)UFloatProperty (CPP_PROPERTY(AmbientFactor ), TEXT("Audio"), CPF_Config );
+ new(GetClass(),TEXT("DopplerSpeed"), RF_Public)UFloatProperty (CPP_PROPERTY(DopplerSpeed ), TEXT("Audio"), CPF_Config );
+
+ unguard;
+}
+
+/*------------------------------------------------------------------------------------
+ UObject Interface.
+------------------------------------------------------------------------------------*/
+
+void UGenericAudioSubsystem::PostEditChange()
+{
+ guard(UGenericAudioSubsystem::PostEditChange);
+
+ // Validate configurable variables.
+ OutputRate = Clamp(OutputRate,(BYTE)0,(BYTE)6);
+ Latency = Clamp(Latency,10,250);
+ Channels = Clamp(Channels,0,MAX_EFFECTS_CHANNELS);
+ DopplerSpeed = Clamp(DopplerSpeed,1.f,100000.f);
+ AmbientFactor = Clamp(AmbientFactor,0.f,10.f);
+ SetVolumes();
+
+ unguard;
+}
+
+void UGenericAudioSubsystem::Destroy()
+{
+ guard(UGenericAudioSubsystem::Destroy);
+ if( Initialized )
+ {
+ // Unhook.
+ USound::Audio = NULL;
+ UMusic::Audio = NULL;
+
+ // Shut down viewport.
+ SetViewport( NULL );
+
+ // Stop CD.
+ if( UseCDMusic && CurrentCDTrack != 255 )
+ StopCDAudio();
+
+ // Shutdown soundsystem.
+ safecall(AudioShutdown());
+
+ debugf( NAME_Exit, TEXT("Generic audio subsystem shut down.") );
+ }
+ Super::Destroy();
+ unguard;
+}
+
+void UGenericAudioSubsystem::ShutdownAfterError()
+{
+ guard(UGenericAudioSubsystem::ShutdownAfterError);
+
+ // Unhook.
+ USound::Audio = NULL;
+ UMusic::Audio = NULL;
+
+ // Safely shut down.
+ debugf( NAME_Exit, TEXT("UGenericAudioSubsystem::ShutdownAfterError") );
+ safecall(AudioStopOutput());
+ if( Viewport )
+ safecall(AudioShutdown());
+ Super::ShutdownAfterError();
+ unguard;
+}
+
+/*------------------------------------------------------------------------------------
+ UAudioSubsystem Interface.
+------------------------------------------------------------------------------------*/
+
+UBOOL UGenericAudioSubsystem::Init()
+{
+ guard(UGenericAudioSubsystem::Init);
+
+ // Initialize Unreal Audio library.
+ guard(InitAudio);
+ OutputMode = AUDIO_16BIT;
+ if( UseFilter )
+ OutputMode |= AUDIO_COSINE;
+ if( UseStereo )
+ OutputMode |= AUDIO_STEREO;
+ OutputMode |= AUDIO_2DAUDIO;
+ INT Rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000};
+ INT Rate = Rates[OutputRate];
+ if (AudioInit( Rate, OutputMode, Latency ) == 0)
+ return false;
+ unguard;
+
+ // Allocate voices.
+ guard(AllocateVoices);
+ verify(AllocateVoices(Channels));
+ unguard;
+
+ // Initialized!
+ USound::Audio = this;
+ UMusic::Audio = this;
+ Initialized = 1;
+
+ debugf( NAME_Init, TEXT("Generic audio subsystem initialized.") );
+ return 1;
+ unguard;
+}
+
+void UGenericAudioSubsystem::SetViewport( UViewport* InViewport )
+{
+ guard(UGenericAudioSubsystem::SetViewport);
+
+ // Stop playing sounds.
+ for( INT i=0; i<Channels; i++ )
+ StopSound( i );
+
+ // Remember the viewport.
+ if( Viewport != InViewport )
+ {
+ if( Viewport )
+ {
+ // Unregister everything.
+ for( TObjectIterator<UMusic> MusicIt; MusicIt; ++MusicIt )
+ if( MusicIt->Handle )
+ UnregisterMusic( *MusicIt );
+
+ // Shut down.
+ safecall(AudioStopOutput());
+ }
+ Viewport = InViewport;
+ if( Viewport )
+ {
+ // Determine startup parameters.
+ if( Viewport->Actor->Song && Viewport->Actor->Transition==MTRAN_None )
+ Viewport->Actor->Transition = MTRAN_Instant;
+
+ // Start sound output.
+ guard(AudioStartOutput);
+ /*
+ if (OutputRate == 0)
+ OutputRate = 1;
+ else if (OutputRate == 2)
+ OutputRate = 3;
+ else if ((OutputRate == 4) || (OutputRate = 6))
+ OutputRate = 5;
+ */
+ INT Rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000};
+ INT Rate = Rates[OutputRate];
+ INT Result = AudioStartOutput( Rate, OutputMode, Latency );
+ if (Result == 0)
+ {
+ // Initialization failed.
+ debugf( NAME_Init, TEXT("Failed to initialize audio subsystem.") );
+ Viewport = NULL;
+ return;
+ }
+ unguard;
+ SetVolumes();
+ }
+ }
+ unguard;
+}
+
+UViewport* UGenericAudioSubsystem::GetViewport()
+{
+ guard(UGenericAudioSubsystem::GetViewport);
+ return Viewport;
+ unguard;
+}
+
+void UGenericAudioSubsystem::RegisterSound( USound* Sound )
+{
+ guard(UGenericAudioSubsystem::RegisterSound);
+ checkSlow(Sound);
+ if( !Sound->Handle )
+ {
+ // Set the handle to avoid reentrance.
+ Sound->Handle = (void*)-1;
+
+ // Load the data.
+ Sound->Data.Load();
+ debugf( NAME_DevSound, TEXT("Register sound: %s (%i)"), Sound->GetPathName(), Sound->Data.Num() );
+ check(Sound->Data.Num()>0);
+
+ // Register the sound.
+ guard(LoadSample);
+ MemChunk SoundChunk;
+ SoundChunk.Data = &Sound->Data(0);
+ SoundChunk.DataLength = Sound->Data.Num();
+ SoundChunk.Position = 0;
+ Sound->Handle = LoadSample( &SoundChunk, Sound->GetFullName() );
+ if( !Sound->Handle )
+ appErrorf( TEXT("Invalid sound format in %s"), Sound->GetFullName() );
+ unguardf(( TEXT("(%i)"), Sound->Data.Num() ));
+
+ // Unload the data.
+ Sound->Data.Unload();
+ }
+ unguard;
+}
+
+void UGenericAudioSubsystem::UnregisterSound( USound* Sound )
+{
+ guard(UGenericAudioSubsystem::UnregisterSound);
+ check(Sound);
+ if( Sound->Handle )
+ {
+ debugf( NAME_DevSound, TEXT("Unregister sound: %s"), Sound->GetFullName() );
+
+ // Stop this sound.
+ for( INT i=0; i<Channels; i++ )
+ if ( PlayingSounds[i].Sound == Sound )
+ StopSound( i );
+
+ // Unload this sound.
+ safecall( UnloadSample( (Sample*) Sound->Handle ) );
+ }
+ unguard;
+}
+
+void UGenericAudioSubsystem::UnregisterMusic( UMusic* Music )
+{
+ guard(UGenericAudioSubsystem::UnregisterMusic);
+
+ unguard;
+}
+
+UBOOL UGenericAudioSubsystem::Exec( const TCHAR* Cmd, FOutputDevice& Ar )
+{
+ guard(UGenericAudioSubsystem::Exec);
+ const TCHAR* Str = Cmd;
+ if( ParseCommand(&Str,TEXT("ASTAT")) )
+ {
+ if( ParseCommand(&Str,TEXT("Audio")) )
+ {
+ AudioStats ^= 1;
+ return 1;
+ }
+ if( ParseCommand(&Str,TEXT("Detail")) )
+ {
+ DetailStats ^= 1;
+ return 1;
+ }
+ }
+ return 0;
+
+ unguard;
+}
+
+UBOOL UGenericAudioSubsystem::PlaySound
+(
+ AActor* Actor,
+ INT Id,
+ USound* Sound,
+ FVector Location,
+ FLOAT Volume,
+ FLOAT Radius,
+ FLOAT Pitch
+)
+{
+ guard(UGenericAudioSubsystem::PlaySound);
+ check(Radius);
+ if( !Viewport || !Sound )
+ return 0;
+
+ // Allocate a new slot if requested.
+ if( (Id&14)==2*SLOT_None )
+ Id = 16 * --FreeSlot;
+
+ // Compute priority.
+ FLOAT Priority = SoundPriority( Viewport, Location, Volume, Radius );
+
+ // If already playing, stop it.
+ INT Index = -1;
+ FLOAT BestPriority = Priority;
+ for( INT i=0; i<Channels; i++ )
+ {
+ FPlayingSound& Playing = PlayingSounds[i];
+ if( (Playing.Id&~1)==(Id&~1) )
+ {
+ // Skip if not interruptable.
+ if( Id&1 )
+ return 0;
+
+ // Stop the sound.
+ Index = i;
+ break;
+ }
+ else if( Playing.Priority<=BestPriority )
+ {
+ Index = i;
+ BestPriority = Playing.Priority;
+ }
+ }
+
+ // If no sound, or its priority is overruled, stop it.
+ if( Index==-1 )
+ return 0;
+
+ // Put the sound on the play-list.
+ StopSound( Index );
+ if( Sound!=(USound*)-1 )
+ PlayingSounds[Index] = FPlayingSound( Actor, Id, Sound, Location, Volume, Radius, Pitch, Priority );
+ return 1;
+
+ unguard;
+}
+
+void UGenericAudioSubsystem::NoteDestroy( AActor* Actor )
+{
+ guard(UGenericAudioSubsystem::NoteDestroy);
+ check(Actor);
+ check(Actor->IsValid());
+
+ // Stop referencing actor.
+ for( INT i=0; i<Channels; i++ )
+ {
+ if( PlayingSounds[i].Actor==Actor )
+ {
+ if( (PlayingSounds[i].Id&14)==SLOT_Ambient*2 )
+ {
+ // Stop ambient sound when actor dies.
+ StopSound( i );
+ }
+ else
+ {
+ // Unbind regular sounds from actors.
+ PlayingSounds[i].Actor = NULL;
+ }
+ }
+ }
+
+ unguard;
+}
+
+void UGenericAudioSubsystem::RenderAudioGeometry( FSceneNode* Frame )
+{
+ guard(UGenericAudioSubsystem::RenderAudioGeometry);
+
+ unguard;
+}
+
+void UGenericAudioSubsystem::Update( FPointRegion Region, FCoords& Coords )
+{
+ guard(UGenericAudioSubsystem::Update);
+ if( !Viewport )
+ return;
+
+ // Lock to sync sound.
+ ALock;
+
+ // Time passes...
+ FTime DeltaTime = appSeconds() - LastTime;
+ LastTime += DeltaTime;
+ DeltaTime = Clamp( DeltaTime, 0.0, 1.0 );
+
+ AActor *ViewActor = Viewport->Actor->ViewTarget?Viewport->Actor->ViewTarget:Viewport->Actor;
+
+ // See if any new ambient sounds need to be started.
+ UBOOL Realtime = Viewport->IsRealtime() && Viewport->Actor->Level->Pauser==TEXT("");
+ if( Realtime )
+ {
+ guard(StartAmbience);
+ for( INT i=0; i<Viewport->Actor->GetLevel()->Actors.Num(); i++ )
+ {
+ AActor* Actor = Viewport->Actor->GetLevel()->Actors(i);
+ if
+ ( Actor
+ && Actor->AmbientSound
+ && FDistSquared(ViewActor->Location,Actor->Location)<=Square(Actor->WorldSoundRadius()) )
+ {
+ INT Id = Actor->GetIndex()*16+SLOT_Ambient*2;
+ for( INT j=0; j<Channels; j++ )
+ if( PlayingSounds[j].Id==Id )
+ break;
+ if( j==Channels )
+ PlaySound( Actor, Id, Actor->AmbientSound, Actor->Location, AmbientFactor*Actor->SoundVolume/255.0, Actor->WorldSoundRadius(), Actor->SoundPitch/64.0 );
+ }
+ }
+ unguard;
+ }
+
+ // Update all playing ambient sounds.
+ guard(UpdateAmbience);
+ for( INT i=0; i<Channels; i++ )
+ {
+ FPlayingSound& Playing = PlayingSounds[i];
+ if( (Playing.Id&14)==SLOT_Ambient*2 )
+ {
+ check(Playing.Actor);
+ if
+ ( FDistSquared(ViewActor->Location,Playing.Actor->Location)>Square(Playing.Actor->WorldSoundRadius())
+ || Playing.Actor->AmbientSound!=Playing.Sound
+ || !Realtime )
+ {
+ // Ambient sound went out of range.
+ StopSound( i );
+ }
+ else
+ {
+ // Update basic sound properties.
+ FLOAT Brightness = 2.0 * (AmbientFactor*Playing.Actor->SoundVolume/255.0);
+ if( Playing.Actor->LightType!=LT_None )
+ {
+ FPlane Color;
+ Brightness *= Playing.Actor->LightBrightness/255.0;
+// Viewport->GetOuterUClient()->Engine->Render->GlobalLighting( (Viewport->Actor->ShowFlags & SHOW_PlayerCtrl)!=0, Playing.Actor, Brightness, Color );
+ }
+ Playing.Volume = Brightness;
+ Playing.Radius = Playing.Actor->WorldSoundRadius();
+ Playing.Pitch = Playing.Actor->SoundPitch/64.0;
+ }
+ }
+ }
+ unguard;
+
+ // Update all active sounds.
+ guard(UpdateSounds);
+ for( INT Index=0; Index<Channels; Index++ )
+ {
+ FPlayingSound& Playing = PlayingSounds[Index];
+ if( Playing.Actor )
+ check(Playing.Actor->IsValid());
+ if( PlayingSounds[Index].Id==0 )
+ {
+ // Sound is not playing.
+ continue;
+ }
+ else if( Playing.Channel && SampleFinished(Playing.Channel) )
+ {
+ // Sound is finished.
+ StopSound( Index );
+ }
+ else
+ {
+ // Update positioning from actor, if available.
+ if( Playing.Actor )
+ Playing.Location = Playing.Actor->Location;void UpdateSample( Voice* InVoice, INT Freq, INT Volume, INT Panning );
+
+ // Update the priority.
+ Playing.Priority = SoundPriority( Viewport, Playing.Location, Playing.Volume, Playing.Radius );
+
+ // Compute the spatialization.
+ FVector Location = Playing.Location.TransformPointBy( Coords );
+ FLOAT PanAngle = appAtan2(Location.X, Abs(Location.Z));
+
+ // Despatialize sounds when you get real close to them.
+ FLOAT CenterDist = 0.1*Playing.Radius;
+ FLOAT Size = Location.Size();
+ if( Location.SizeSquared() < Square(CenterDist) )
+ PanAngle *= Size / CenterDist;
+
+ // Compute panning and volume.
+ INT SoundPan = Clamp( (INT)(AUDIO_MAXPAN/2 + PanAngle*AUDIO_MAXPAN*7/8/PI), 0, AUDIO_MAXPAN );
+ FLOAT Attenuation = Clamp(1.0-Size/Playing.Radius,0.0,1.0);
+ INT SoundVolume = Clamp( (INT)(AUDIO_MAXVOLUME * Playing.Volume * Attenuation * EFFECT_FACTOR), 0, AUDIO_MAXVOLUME );
+ if( ReverseStereo )
+ SoundPan = AUDIO_MAXPAN - SoundPan;
+ if( Location.Z<0.0 && UseSurround )
+ SoundPan = AUDIO_MIDPAN | AUDIO_SURPAN;
+
+ // Compute doppler shifting (doesn't account for player's velocity).
+ FLOAT Doppler=1.0;
+ if( Playing.Actor )
+ {
+ FLOAT V = (Playing.Actor->Velocity/*-ViewActor->Velocity*/) | (Playing.Actor->Location - ViewActor->Location).SafeNormal();
+ Doppler = Clamp( 1.0 - V/DopplerSpeed, 0.5, 2.0 );
+ }
+
+ // Update the sound.
+ Sample* Sample = GetSound(Playing.Sound);
+ FVector Z(0,0,0);
+ FVector L(Location.X/400.0,Location.Y/400.0,Location.Z/400.0);
+
+ if( Playing.Channel )
+ {
+ // Update an existing sound.
+ guard(UpdateSample);
+ UpdateSample
+ (
+ Playing.Channel,
+ (INT) (Sample->SamplesPerSec * Playing.Pitch * Doppler),
+ SoundVolume,
+ SoundPan
+ );
+ Playing.Channel->BasePanning = SoundPan;
+ unguard;
+ }
+ else
+ {
+ // Start this new sound.
+ guard(StartSample);
+ if( !Playing.Channel )
+ Playing.Channel = StartSample
+ ( Index+1, Sample,
+ (INT) (Sample->SamplesPerSec * Playing.Pitch * Doppler),
+ SoundVolume, SoundPan );
+ check(Playing.Channel);
+ unguard;
+ }
+ }
+ }
+ unguard;
+
+ // Unlock.
+ AUnlock;
+ unguard;
+}
+
+void UGenericAudioSubsystem::PostRender( FSceneNode* Frame )
+{
+ guard(UGenericAudioSubsystem::PostRender);
+ Frame->Viewport->Canvas->Color = FColor(255,255,255);
+ if( AudioStats )
+ {
+ Frame->Viewport->Canvas->CurX=0;
+ Frame->Viewport->Canvas->CurY=16;
+ Frame->Viewport->Canvas->WrappedPrintf
+ (
+ Frame->Viewport->Canvas->SmallFont,
+ 0, TEXT("GenericAudioSubsystem Statistics")
+ );
+ for (INT i=0; i<Channels; i++)
+ {
+ if (PlayingSounds[i].Channel)
+ {
+ INT Factor;
+ if (DetailStats)
+ Factor = 16;
+ else
+ Factor = 8;
+
+ // Current Sound.
+ Frame->Viewport->Canvas->CurX=10;
+ Frame->Viewport->Canvas->CurY=24 + Factor*i;
+ Frame->Viewport->Canvas->WrappedPrintf
+ ( Frame->Viewport->Canvas->SmallFont, 0, TEXT("Channel %2i: %s"),
+ i, PlayingSounds[i].Sound->GetFullName() );
+
+ if (DetailStats)
+ {
+ // Play meter.
+ VoiceStats CurrentStats;
+ GetVoiceStats( &CurrentStats, PlayingSounds[i].Channel );
+ Frame->Viewport->Canvas->CurX=10;
+ Frame->Viewport->Canvas->CurY=32 + Factor*i;
+ Frame->Viewport->Canvas->WrappedPrintf
+ ( Frame->Viewport->Canvas->SmallFont, 0, TEXT(" [%s] %05.1f\% Vol: %05.2f"),
+ *CurrentStats.CompletionString, CurrentStats.Completion*100, PlayingSounds[i].Volume );
+ }
+ } else {
+ INT Factor;
+ if (DetailStats)
+ Factor = 16;
+ else
+ Factor = 8;
+
+ Frame->Viewport->Canvas->CurX=10;
+ Frame->Viewport->Canvas->CurY=24 + Factor*i;
+ if (i >= 10)
+ Frame->Viewport->Canvas->WrappedPrintf
+ ( Frame->Viewport->Canvas->SmallFont, 0, TEXT("Channel %i: None"),
+ i );
+ else
+ Frame->Viewport->Canvas->WrappedPrintf
+ ( Frame->Viewport->Canvas->SmallFont, 0, TEXT("Channel %i: None"),
+ i );
+
+ if (DetailStats)
+ {
+ // Play meter.
+ Frame->Viewport->Canvas->CurX=10;
+ Frame->Viewport->Canvas->CurY=32 + Factor*i;
+ Frame->Viewport->Canvas->WrappedPrintf
+ ( Frame->Viewport->Canvas->SmallFont, 0, TEXT(" [----------]") );
+ }
+ }
+ }
+ }
+ unguard;
+}
+
+/*------------------------------------------------------------------------------------
+ Internals.
+------------------------------------------------------------------------------------*/
+
+void UGenericAudioSubsystem::SetVolumes()
+{
+ guard(UGenericAudioSubsystem::SetVolumes);
+
+ // Normalize the volumes.
+ FLOAT NormSoundVolume = SoundVolume/255.0;
+ FLOAT NormMusicVolume = Clamp(MusicVolume/255.0,0.0,1.0);
+
+ // Set music and effects volumes.
+ verify( SetSampleVolume( 127*NormSoundVolume ) );
+ if( UseDigitalMusic )
+ verify( SetMusicVolume( 127*NormMusicVolume*Max(MusicFade,0.f) ) );
+ if( UseCDMusic )
+ SetCDAudioVolume( 127*NormMusicVolume*Max(MusicFade,0.f) );
+
+ unguard;
+}
+
+void UGenericAudioSubsystem::StopSound( INT Index )
+{
+ guard(UGenericAudioSubsystem::StopSound);
+ FPlayingSound& Playing = PlayingSounds[Index];
+
+ if( Playing.Channel )
+ {
+ guard(StopSample);
+ StopSample( Playing.Channel );
+ unguard;
+ }
+ PlayingSounds[Index] = FPlayingSound();
+
+ unguard;
+}
+
+/*-----------------------------------------------------------------------------
+ The End.
+-----------------------------------------------------------------------------*/
96 Audio/Src/FormatWAV.cpp
@@ -0,0 +1,96 @@
+/*=============================================================================
+ FormatWAV.cpp: Unreal audio wav reading code.
+ Copyright 1999 Epic Games, Inc. All Rights Reserved.
+
+Revision history:
+ * Created by Brandon Reinhart.
+=============================================================================*/
+
+/*------------------------------------------------------------------------------------
+ Audio includes.
+------------------------------------------------------------------------------------*/
+
+#include "AudioPrivate.h"
+
+/*------------------------------------------------------------------------------------
+ WAVE management.
+------------------------------------------------------------------------------------*/
+
+Sample* LoadWAV( Sample* lSample, MemChunk* Chunk )
+{
+ WAVFileHeader FileHeader;
+ ReadMem(&FileHeader, 1, sizeof(WAVFileHeader), Chunk);
+ FileHeader.Size = ((FileHeader.Size+1)&~1);
+ FileHeader.Size -= 4;
+
+ WAVChunkHeader ChunkHeader;
+ WAVFormatHeader FormatHeader;
+ WAVFormatExHeader FormatExHeader;
+ WAVSampleHeader SampleHeader;
+ while (FileHeader.Size != 0)
+ {
+ if (ReadMem(&ChunkHeader, 1, sizeof(WAVChunkHeader), Chunk))
+ {
+ if (!appMemcmp(ChunkHeader.ID, "fmt ", 4))
+ {
+ ReadMem(&FormatHeader, 1, sizeof(WAVFormatHeader), Chunk);
+ if (FormatHeader.Format != 0x0001)
+ {
+ ReadMem(&FormatExHeader, 1, sizeof(WAVFormatExHeader), Chunk);
+ SeekMem(Chunk, ChunkHeader.Size - sizeof(WAVFormatHeader) - sizeof(WAVFormatExHeader), MEM_SEEK_CUR);
+ } else
+ SeekMem(Chunk, ChunkHeader.Size - sizeof(WAVFormatHeader), MEM_SEEK_CUR);
+ }
+ else if (!appMemcmp(ChunkHeader.ID, "data", 4))
+ {
+ if (FormatHeader.Format == 0x0001)
+ {
+ lSample->Size = sizeof(lSample);
+ lSample->Panning = AUDIO_MIDPAN;
+ lSample->Volume = AUDIO_MAXVOLUME;
+ if (FormatHeader.Channels == 2)
+ lSample->Type = SAMPLE_STEREO;
+ else
+ lSample->Type = SAMPLE_MONO;
+ if (FormatHeader.BitsPerSample == 16)
+ lSample->Type |= SAMPLE_16BIT;
+ else
+ lSample->Type |= SAMPLE_8BIT;
+ lSample->Length = (ChunkHeader.Size / FormatHeader.BlockAlign);
+ lSample->LoopStart = 0;
+ lSample->LoopEnd = 0;
+ lSample->SamplesPerSec = FormatHeader.SamplesPerSec;
+ if ((lSample->SamplesPerSec != 11025) && (lSample->SamplesPerSec != 22050) && (lSample->SamplesPerSec != 44100))
+ appErrorf( TEXT("Unsupported rate: %i"), lSample->SamplesPerSec );
+ if (lSample->Data = appMalloc(ChunkHeader.Size, TEXT("Sample data.")))
+ ReadMem(lSample->Data, FormatHeader.BlockAlign, lSample->Length, Chunk);
+ } else {
+ appErrorf( TEXT("Unsupported WAVE format!") );
+ SeekMem(Chunk, ChunkHeader.Size, MEM_SEEK_CUR);
+ }
+ }
+ else if (!appMemcmp(ChunkHeader.ID, "smpl", 4))
+ {
+ ReadMem(&SampleHeader, 1, sizeof(WAVSampleHeader), Chunk);
+ SeekMem(Chunk, ChunkHeader.Size - sizeof(WAVSampleHeader), MEM_SEEK_CUR);
+ if (SampleHeader.Loops != 0)
+ {
+ if (SampleHeader.Loop[0].Type & 1)
+ lSample->Type |= SAMPLE_BIDILOOP | SAMPLE_LOOPED;
+ else
+ lSample->Type |= SAMPLE_LOOPED;
+ lSample->LoopStart = SampleHeader.Loop[0].Start;
+ lSample->LoopEnd = SampleHeader.Loop[0].End;
+ }
+ }
+ else
+ // Move past this chunk.
+ SeekMem(Chunk, ChunkHeader.Size, MEM_SEEK_CUR);
+
+ SeekMem(Chunk, ChunkHeader.Size & 1, MEM_SEEK_CUR);
+ FileHeader.Size -= (((ChunkHeader.Size+1)&~1)+8);
+ }
+ }
+ return lSample;
+}
+
54 Audio/Src/makefile
@@ -0,0 +1,54 @@
+#=============================================================================
+# Unreal Audio makefile for Linux.
+#
+# Revision history:
+# * Created by Brandon Reinhart
+#=============================================================================
+
+# Unreal directory. (Required by makefile-header.)
+UNREAL_DIR = ../..
+
+# Include global definitions.
+include $(UNREAL_DIR)/makefile-header
+
+#-----------------------------------------------------------------------------
+# Directories.
+#-----------------------------------------------------------------------------
+
+SRC_DIRS = $(AUDIO_SRC)