diff options
Diffstat (limited to 'engine/audio/public')
| -rw-r--r-- | engine/audio/public/ivoicecodec.h | 61 | ||||
| -rw-r--r-- | engine/audio/public/ivoicerecord.h | 40 | ||||
| -rw-r--r-- | engine/audio/public/snd_audio_source.h | 526 | ||||
| -rw-r--r-- | engine/audio/public/snd_device.h | 127 | ||||
| -rw-r--r-- | engine/audio/public/snd_io.h | 16 | ||||
| -rw-r--r-- | engine/audio/public/sound.h | 150 | ||||
| -rw-r--r-- | engine/audio/public/soundservice.h | 135 | ||||
| -rw-r--r-- | engine/audio/public/voice.h | 138 | ||||
| -rw-r--r-- | engine/audio/public/vox.h | 46 |
9 files changed, 1239 insertions, 0 deletions
diff --git a/engine/audio/public/ivoicecodec.h b/engine/audio/public/ivoicecodec.h new file mode 100644 index 0000000..f7c43b3 --- /dev/null +++ b/engine/audio/public/ivoicecodec.h @@ -0,0 +1,61 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Define the IVoiceCodec interface. +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IVOICECODEC_H +#define IVOICECODEC_H +#pragma once + + +#include "interface.h" + + +#define BYTES_PER_SAMPLE 2 + + +// This interface is for voice codecs to implement. + +// Codecs are guaranteed to be called with the exact output from Compress into Decompress (ie: +// data won't be stuck together and sent to Decompress). + +// Decompress is not guaranteed to be called in any specific order relative to Compress, but +// Codecs maintain state between calls, so it is best to call Compress with consecutive voice data +// and decompress likewise. If you call it out of order, it will sound wierd. + +// In the same vein, calling Decompress twice with the same data is a bad idea since the state will be +// expecting the next block of data, not the same block. + +class IVoiceCodec +{ +protected: + virtual ~IVoiceCodec() {} + +public: + // Initialize the object. The uncompressed format is always 8-bit signed mono. + virtual bool Init( int quality )=0; + + // Use this to delete the object. + virtual void Release()=0; + + + // Compress the voice data. + // pUncompressed - 16-bit signed mono voice data. + // maxCompressedBytes - The length of the pCompressed buffer. Don't exceed this. + // bFinal - Set to true on the last call to Compress (the user stopped talking). + // Some codecs like big block sizes and will hang onto data you give them in Compress calls. + // When you call with bFinal, the codec will give you compressed data no matter what. + // Return the number of bytes you filled into pCompressed. + virtual int Compress(const char *pUncompressed, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal)=0; + + // Decompress voice data. pUncompressed is 16-bit signed mono. + virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes)=0; + + // Some codecs maintain state between Compress and Decompress calls. This should clear that state. + virtual bool ResetState()=0; +}; + + +#endif // IVOICECODEC_H diff --git a/engine/audio/public/ivoicerecord.h b/engine/audio/public/ivoicerecord.h new file mode 100644 index 0000000..9f830ff --- /dev/null +++ b/engine/audio/public/ivoicerecord.h @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IVOICERECORD_H +#define IVOICERECORD_H +#pragma once + + +// This is the voice recording interface. It provides 16-bit signed mono data from +// a mic at some sample rate. +abstract_class IVoiceRecord +{ +protected: + + virtual ~IVoiceRecord() {} + + +public: + + // Use this to delete the object. + virtual void Release()=0; + + // Start/stop capturing. + virtual bool RecordStart() = 0; + virtual void RecordStop() = 0; + + // Idle processing. + virtual void Idle()=0; + + // Get the most recent N samples. If nSamplesWanted is less than the number of + // available samples, it discards the first samples and gives you the last ones. + virtual int GetRecordedData(short *pOut, int nSamplesWanted)=0; +}; + + +#endif // IVOICERECORD_H diff --git a/engine/audio/public/snd_audio_source.h b/engine/audio/public/snd_audio_source.h new file mode 100644 index 0000000..b8ac6b9 --- /dev/null +++ b/engine/audio/public/snd_audio_source.h @@ -0,0 +1,526 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SND_AUDIO_SOURCE_H +#define SND_AUDIO_SOURCE_H +#pragma once + +#if !defined( _X360 ) +#define MP3_SUPPORT 1 +#endif + +#define AUDIOSOURCE_COPYBUF_SIZE 4096 + +struct channel_t; +class CSentence; +class CSfxTable; + +class CAudioSource; +class IAudioDevice; +class CUtlBuffer; + +#include "tier0/vprof.h" + +//----------------------------------------------------------------------------- +// Purpose: This is an instance of an audio source. +// Mixers are attached to channels and reference an audio source. +// Mixers are specific to the sample format and source format. +// Mixers are never re-used, so they can track instance data like +// sample position, fractional sample, stream cache, faders, etc. +//----------------------------------------------------------------------------- +abstract_class CAudioMixer +{ +public: + virtual ~CAudioMixer( void ) {} + + // return number of samples mixed + virtual int MixDataToDevice( IAudioDevice *pDevice, channel_t *pChannel, int sampleCount, int outputRate, int outputOffset ) = 0; + virtual int SkipSamples( channel_t *pChannel, int sampleCount, int outputRate, int outputOffset ) = 0; + virtual bool ShouldContinueMixing( void ) = 0; + + virtual CAudioSource *GetSource( void ) = 0; + + // get the current position (next sample to be mixed) + virtual int GetSamplePosition( void ) = 0; + + // Allow the mixer to modulate pitch and volume. + // returns a floating point modulator + virtual float ModifyPitch( float pitch ) = 0; + virtual float GetVolumeScale( void ) = 0; + + // NOTE: Playback is optimized for linear streaming. These calls will usually cost performance + // It is currently optimal to call them before any playback starts, but some audio sources may not + // guarantee this. Also, some mixers may choose to ignore these calls for internal reasons (none do currently). + + // Move the current position to newPosition + // BUGBUG: THIS CALL DOES NOT SUPPORT MOVING BACKWARD, ONLY FORWARD!!! + virtual void SetSampleStart( int newPosition ) = 0; + + // End playback at newEndPosition + virtual void SetSampleEnd( int newEndPosition ) = 0; + + // How many samples to skip before commencing actual data reading ( to allow sub-frametime sound + // offsets and avoid synchronizing sounds to various 100 msec clock intervals throughout the + // engine and game code) + virtual void SetStartupDelaySamples( int delaySamples ) = 0; + virtual int GetMixSampleSize() = 0; + + // Certain async loaded sounds lazilly load into memory in the background, use this to determine + // if the sound is ready for mixing + virtual bool IsReadyToMix() = 0; + + // NOTE: The "saved" position can be different than the "sample" position + // NOTE: Allows mixer to save file offsets, loop info, etc + virtual int GetPositionForSave() = 0; + virtual void SetPositionFromSaved( int savedPosition ) = 0; +}; + +inline int CalcSampleSize( int bitsPerSample, int _channels ) +{ + return (bitsPerSample >> 3) * _channels; +} + +#include "UtlCachedFileData.h" + +class CSentence; +class CSfxTable; +class CAudioSourceCachedInfo : public IBaseCacheInfo +{ +public: + CAudioSourceCachedInfo(); + CAudioSourceCachedInfo( const CAudioSourceCachedInfo& src ); + + virtual ~CAudioSourceCachedInfo(); + + CAudioSourceCachedInfo& operator =( const CAudioSourceCachedInfo& src ); + + void Clear(); + void RemoveData(); + + virtual void Save( CUtlBuffer& buf ); + virtual void Restore( CUtlBuffer& buf ); + virtual void Rebuild( char const *filename ); + + // A hack, but will work okay + static int s_CurrentType; + static CSfxTable *s_pSfx; + static bool s_bIsPrecacheSound; + + inline int Type() const + { + return info.m_Type; + } + void SetType( int type ) + { + info.m_Type = type; + } + + inline int Bits() const + { + return info.m_bits; + } + void SetBits( int bits ) + { + info.m_bits = bits; + } + + inline int Channels() const + { + return info.m_channels; + } + void SetChannels( int _channels ) + { + info.m_channels = _channels; + } + + inline int SampleSize() const + { + return info.m_sampleSize; + } + void SetSampleSize( int size ) + { + info.m_sampleSize = size; + } + + inline int Format() const + { + return info.m_format; + } + void SetFormat( int format ) + { + info.m_format = format; + } + + inline int SampleRate() const + { + return info.m_rate; + } + void SetSampleRate( int rate ) + { + info.m_rate = rate; + } + + inline int CachedDataSize() const + { + return (int)m_usCachedDataSize; + } + + void SetCachedDataSize( int size ) + { + m_usCachedDataSize = (unsigned short)size; + } + + inline const byte *CachedData() const + { + return m_pCachedData; + } + + void SetCachedData( const byte *data ) + { + m_pCachedData = ( byte * )data; + flags.m_bCachedData = ( data != NULL ) ? true : false; + } + + inline int HeaderSize() const + { + return (int)m_usHeaderSize; + } + + void SetHeaderSize( int size ) + { + m_usHeaderSize = (unsigned short)size; + } + + inline const byte *HeaderData() const + { + return m_pHeader; + } + + void SetHeaderData( const byte *data ) + { + m_pHeader = ( byte * )data; + flags.m_bHeader = ( data != NULL ) ? true : false; + } + + inline int LoopStart() const + { + return m_loopStart; + } + void SetLoopStart( int start ) + { + m_loopStart = start; + } + + inline int SampleCount() const + { + return m_sampleCount; + } + + void SetSampleCount( int count ) + { + m_sampleCount = count; + } + inline int DataStart() const + { + return m_dataStart; + } + void SetDataStart( int start ) + { + m_dataStart = start; + } + inline int DataSize() const + { + return m_dataSize; + } + void SetDataSize( int size ) + { + m_dataSize = size; + } + inline CSentence *Sentence() const + { + return m_pSentence; + } + void SetSentence( CSentence *sentence ) + { + m_pSentence = sentence; + flags.m_bSentence = ( sentence != NULL ) ? true : false; + } + +private: + + union + { + unsigned int infolong; + struct + { + unsigned int m_Type : 2; // 0 1 2 or 3 + unsigned int m_bits : 5; // 0 to 31 + unsigned int m_channels : 2; // 1 or 2 + unsigned int m_sampleSize : 3; // 1 2 or 4 + unsigned int m_format : 2; // 1 == PCM, 2 == ADPCM + unsigned int m_rate : 17; // 0 to 64 K + } info; + }; + + union + { + byte flagsbyte; + struct + { + bool m_bSentence : 1; + bool m_bCachedData : 1; + bool m_bHeader : 1; + } flags; + }; + + int m_loopStart; + int m_sampleCount; + int m_dataStart; // offset of wave data chunk + int m_dataSize; // size of wave data chunk + + unsigned short m_usCachedDataSize; + unsigned short m_usHeaderSize; + + CSentence *m_pSentence; + byte *m_pCachedData; + byte *m_pHeader; +}; + +class IAudioSourceCache +{ +public: + virtual bool Init( unsigned int memSize ) = 0; + virtual void Shutdown() = 0; + virtual void LevelInit( char const *mapname ) = 0; + virtual void LevelShutdown() = 0; + + // This invalidates the cached size/date info for sounds so it'll regenerate that next time it's accessed. + // Used when you connect to a pure server. + virtual void ForceRecheckDiskInfo() = 0; + + virtual CAudioSourceCachedInfo *GetInfo( int audiosourcetype, bool soundisprecached, CSfxTable *sfx ) = 0; + virtual void RebuildCacheEntry( int audiosourcetype, bool soundisprecached, CSfxTable *sfx ) = 0; +}; + +extern IAudioSourceCache *audiosourcecache; + +FORWARD_DECLARE_HANDLE( memhandle_t ); + +typedef int StreamHandle_t; +enum +{ + INVALID_STREAM_HANDLE = (StreamHandle_t)~0 +}; + +typedef int BufferHandle_t; +enum +{ + INVALID_BUFFER_HANDLE = (BufferHandle_t)~0 +}; + +typedef unsigned int streamFlags_t; +enum +{ + STREAMED_FROMDVD = 0x00000001, // stream buffers are compliant to dvd sectors + STREAMED_SINGLEPLAY = 0x00000002, // non recurring data, buffers don't need to persist and can be recycled + STREAMED_QUEUEDLOAD = 0x00000004, // hint the streamer to load using the queued loader system +}; + +abstract_class IAsyncWavDataCache +{ +public: + virtual bool Init( unsigned int memSize ) = 0; + virtual void Shutdown() = 0; + + // implementation that treats file as monolithic + virtual memhandle_t AsyncLoadCache( char const *filename, int datasize, int startpos, bool bIsPrefetch = false ) = 0; + virtual void PrefetchCache( char const *filename, int datasize, int startpos ) = 0; + virtual bool CopyDataIntoMemory( char const *filename, int datasize, int startpos, void *buffer, int bufsize, int copystartpos, int bytestocopy, bool *pbPostProcessed ) = 0; + virtual bool CopyDataIntoMemory( memhandle_t& handle, char const *filename, int datasize, int startpos, void *buffer, int bufsize, int copystartpos, int bytestocopy, bool *pbPostProcessed ) = 0; + virtual bool IsDataLoadCompleted( memhandle_t handle, bool *pIsValid ) = 0; + virtual void RestartDataLoad( memhandle_t *pHandle, const char *pFilename, int dataSize, int startpos ) = 0; + virtual bool GetDataPointer( memhandle_t& handle, char const *filename, int datasize, int startpos, void **pData, int copystartpos, bool *pbPostProcessed ) = 0; + virtual void SetPostProcessed( memhandle_t handle, bool proc ) = 0; + virtual void Unload( memhandle_t handle ) = 0; + + // alternate multi-buffer streaming implementation + virtual StreamHandle_t OpenStreamedLoad( char const *pFileName, int dataSize, int dataStart, int startPos, int loopPos, int bufferSize, int numBuffers, streamFlags_t flags ) = 0; + virtual void CloseStreamedLoad( StreamHandle_t hStream ) = 0; + virtual int CopyStreamedDataIntoMemory( StreamHandle_t hStream, void *pBuffer, int buffSize, int copyStartPos, int bytesToCopy ) = 0; + virtual bool IsStreamedDataReady( StreamHandle_t hStream ) = 0; + virtual void MarkBufferDiscarded( BufferHandle_t hBuffer ) = 0; + virtual void *GetStreamedDataPointer( StreamHandle_t hStream, bool bSync ) = 0; + virtual bool IsDataLoadInProgress( memhandle_t handle ) = 0; + virtual void Flush() = 0; + virtual void OnMixBegin() = 0; + virtual void OnMixEnd() = 0; +}; + +extern IAsyncWavDataCache *wavedatacache; + +struct CAudioSourceCachedInfoHandle_t +{ + CAudioSourceCachedInfoHandle_t() : + info( NULL ), + m_FlushCount( 0 ) + { + } + + CAudioSourceCachedInfo *info; + unsigned int m_FlushCount; + + inline CAudioSourceCachedInfo *Get( int audiosourcetype, bool soundisprecached, CSfxTable *sfx, int *pcacheddatasize ) + { + VPROF("CAudioSourceCachedInfoHandle_t::Get"); + + if ( m_FlushCount != s_nCurrentFlushCount ) + { + // Reacquire + info = audiosourcecache->GetInfo( audiosourcetype, soundisprecached, sfx ); + + if ( pcacheddatasize ) + { + *pcacheddatasize = info ? info->CachedDataSize() : 0; + } + + // Tag as current + m_FlushCount = s_nCurrentFlushCount; + } + return info; + } + + inline bool IsValid() + { + return !!( m_FlushCount == s_nCurrentFlushCount ); + } + + inline CAudioSourceCachedInfo *FastGet() + { + VPROF("CAudioSourceCachedInfoHandle_t::FastGet"); + + if ( m_FlushCount != s_nCurrentFlushCount ) + { + return NULL; + } + return info; + } + + static void InvalidateCache(); + static unsigned int s_nCurrentFlushCount; +}; + + +//----------------------------------------------------------------------------- +// Purpose: A source is an abstraction for a stream, cached file, or procedural +// source of audio. +//----------------------------------------------------------------------------- +abstract_class CAudioSource +{ +public: + enum + { + AUDIO_SOURCE_UNK = 0, + AUDIO_SOURCE_WAV, + AUDIO_SOURCE_MP3, + AUDIO_SOURCE_VOICE, + + AUDIO_SOURCE_MAXTYPE, + }; + + enum + { + AUDIO_NOT_LOADED = 0, + AUDIO_IS_LOADED = 1, + AUDIO_LOADING = 2, + }; + + virtual ~CAudioSource( void ) {} + + // Create an instance (mixer) of this audio source + virtual CAudioMixer *CreateMixer( int initialStreamPosition = 0 ) = 0; + + // Serialization for caching + virtual int GetType( void ) = 0; + virtual void GetCacheData( CAudioSourceCachedInfo *info ) = 0; + + // Provide samples for the mixer. You can point pData at your own data, or if you prefer to copy the data, + // you can copy it into copyBuf and set pData to copyBuf. + virtual int GetOutputData( void **pData, int samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] ) = 0; + + virtual int SampleRate( void ) = 0; + + // Returns true if the source is a voice source. + // This affects the voice_overdrive behavior (all sounds get quieter when + // someone is speaking). + virtual bool IsVoiceSource() = 0; + + // Sample size is in bytes. It will not be accurate for compressed audio. This is a best estimate. + // The compressed audio mixers understand this, but in general do not assume that SampleSize() * SampleCount() = filesize + // or even that SampleSize() is 100% accurate due to compression. + virtual int SampleSize( void ) = 0; + + // Total number of samples in this source. NOTE: Some sources are infinite (mic input), they should return + // a count equal to one second of audio at their current rate. + virtual int SampleCount( void ) = 0; + + virtual int Format( void ) = 0; + virtual int DataSize( void ) = 0; + + virtual bool IsLooped( void ) = 0; + virtual bool IsStereoWav( void ) = 0; + virtual bool IsStreaming( void ) = 0; + virtual int GetCacheStatus( void ) = 0; + int IsCached( void ) { return GetCacheStatus() == AUDIO_IS_LOADED ? true : false; } + virtual void CacheLoad( void ) = 0; + virtual void CacheUnload( void ) = 0; + virtual CSentence *GetSentence( void ) = 0; + + // these are used to find good splice/loop points. + // If not implementing these, simply return sample + virtual int ZeroCrossingBefore( int sample ) = 0; + virtual int ZeroCrossingAfter( int sample ) = 0; + + // mixer's references + virtual void ReferenceAdd( CAudioMixer *pMixer ) = 0; + virtual void ReferenceRemove( CAudioMixer *pMixer ) = 0; + + // check reference count, return true if nothing is referencing this + virtual bool CanDelete( void ) = 0; + + virtual void Prefetch() = 0; + + virtual bool IsAsyncLoad() = 0; + + // Make sure our data is rebuilt into the per-level cache + virtual void CheckAudioSourceCache() = 0; + + virtual char const *GetFileName() = 0; + + virtual void SetPlayOnce( bool ) = 0; + virtual bool IsPlayOnce() = 0; + + // Used to identify a word that is part of a sentence mixing operation + virtual void SetSentenceWord( bool bIsWord ) = 0; + virtual bool IsSentenceWord() = 0; + + virtual int SampleToStreamPosition( int samplePosition ) = 0; + virtual int StreamToSamplePosition( int streamPosition ) = 0; +}; + +// Fast method for determining duration of .wav/.mp3, exposed to server as well +extern float AudioSource_GetSoundDuration( char const *pName ); + +// uses wave file cached in memory already +extern float AudioSource_GetSoundDuration( CSfxTable *pSfx ); + +#endif // SND_AUDIO_SOURCE_H diff --git a/engine/audio/public/snd_device.h b/engine/audio/public/snd_device.h new file mode 100644 index 0000000..9c844b6 --- /dev/null +++ b/engine/audio/public/snd_device.h @@ -0,0 +1,127 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This abstracts the various hardware dependent implementations of sound +// At the time of this writing there are Windows WAVEOUT, Direct Sound, +// and Null implementations. +// +//=====================================================================================// + +#ifndef SND_DEVICE_H +#define SND_DEVICE_H +#pragma once + +#include "snd_fixedint.h" +#include "snd_mix_buf.h" + +// sound engine rate defines +#define SOUND_DMA_SPEED 44100 // hardware playback rate + +#define SOUND_11k 11025 // 11khz sample rate +#define SOUND_22k 22050 // 22khz sample rate +#define SOUND_44k 44100 // 44khz sample rate +#define SOUND_ALL_RATES 1 // mix all sample rates + +#define SOUND_MIX_WET 0 // mix only samples that don't have channel set to 'dry' or 'speaker' (default) +#define SOUND_MIX_DRY 1 // mix only samples with channel set to 'dry' (ie: music) +#define SOUND_MIX_SPEAKER 2 // mix only samples with channel set to 'speaker' +#define SOUND_MIX_SPECIAL_DSP 3 // mix only samples with channel set to 'special dsp' + +#define SOUND_BUSS_ROOM (1<<0) // mix samples using channel dspmix value (based on distance from player) +#define SOUND_BUSS_FACING (1<<1) // mix samples using channel dspface value (source facing) +#define SOUND_BUSS_FACINGAWAY (1<<2) // mix samples using 1-dspface +#define SOUND_BUSS_SPEAKER (1<<3) // mix ch->bspeaker samples in mono to speaker buffer +#define SOUND_BUSS_DRY (1<<4) // mix ch->bdry samples into dry buffer +#define SOUND_BUSS_SPECIAL_DSP (1<<5) // mix ch->bspecialdsp samples into special dsp buffer + +class Vector; +struct channel_t; + +// UNDONE: Create a simulated audio device to replace the old -simsound functionality? + +// General interface to an audio device +abstract_class IAudioDevice +{ +public: + // Add a virtual destructor to silence the clang warning. + // This is harmless but not important since the only derived class + // doesn't have a destructor. + virtual ~IAudioDevice() {} + + // Detect the sound hardware and create a compatible device + // NOTE: This should NEVER fail. There is a function called Audio_GetNullDevice + // which will create a "null" device that makes no sound. If we can't create a real + // sound device, this will return a device of that type. All of the interface + // functions can be called on the null device, but it will not, of course, make sound. + static IAudioDevice *AutoDetectInit( bool waveOnly ); + + // This is needed by some of the routines to avoid doing work when you've got a null device + virtual bool IsActive( void ) = 0; + // This initializes the sound hardware. true on success, false on failure + virtual bool Init( void ) = 0; + // This releases all sound hardware + virtual void Shutdown( void ) = 0; + // stop outputting sound, but be ready to resume on UnPause + virtual void Pause( void ) = 0; + // return to normal operation after a Pause() + virtual void UnPause( void ) = 0; + // The volume of the "dry" mix (no effects). + // This should return 0 on all implementations that don't need a separate dry mix + virtual float MixDryVolume( void ) = 0; + // Should we mix sounds to a 3D (quadraphonic) sound buffer (front/rear both stereo) + virtual bool Should3DMix( void ) = 0; + + // This is called when the application stops all sounds + // NOTE: Stopping each channel and clearing the sound buffer are done separately + virtual void StopAllSounds( void ) = 0; + + // Called before painting channels, must calculated the endtime and return it (once per frame) + virtual int PaintBegin( float, int soundtime, int paintedtime ) = 0; + // Called when all channels are painted (once per frame) + virtual void PaintEnd( void ) = 0; + + // Called to set the volumes on a channel with the given gain & dot parameters + virtual void SpatializeChannel( int volume[6], int master_vol, const Vector& sourceDir, float gain, float mono ) = 0; + + // The device should apply DSP up to endtime in the current paint buffer + // this is called during painting + virtual void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount ) = 0; + + // replaces SNDDMA_GetDMAPos, gets the output sample position for tracking + virtual int GetOutputPosition( void ) = 0; + + // Fill the output buffer with silence (e.g. during pause) + virtual void ClearBuffer( void ) = 0; + + // Called each frame with the listener's coordinate system + virtual void UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up ) = 0; + + // Called each time a new paint buffer is mixed (may be multiple times per frame) + virtual void MixBegin( int sampleCount ) = 0; + virtual void MixUpsample( int sampleCount, int filtertype ) = 0; + + // sink sound data + virtual void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) = 0; + virtual void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) = 0; + virtual void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) = 0; + virtual void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) = 0; + + // Reset a channel + virtual void ChannelReset( int entnum, int channelIndex, float distanceMod ) = 0; + virtual void TransferSamples( int end ) = 0; + + // device parameters + virtual const char *DeviceName( void ) = 0; + virtual int DeviceChannels( void ) = 0; // 1 = mono, 2 = stereo + virtual int DeviceSampleBits( void ) = 0; // bits per sample (8 or 16) + virtual int DeviceSampleBytes( void ) = 0; // above / 8 + virtual int DeviceDmaSpeed( void ) = 0; // Actual DMA speed + virtual int DeviceSampleCount( void ) = 0; // Total samples in buffer + + virtual bool IsSurround( void ) = 0; // surround enabled, could be quad or 5.1 + virtual bool IsSurroundCenter( void ) = 0; // surround enabled as 5.1 + virtual bool IsHeadphone( void ) = 0; +}; + +extern IAudioDevice *Audio_GetNullDevice( void ); + +#endif // SND_DEVICE_H diff --git a/engine/audio/public/snd_io.h b/engine/audio/public/snd_io.h new file mode 100644 index 0000000..dd74798 --- /dev/null +++ b/engine/audio/public/snd_io.h @@ -0,0 +1,16 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SND_IO_H +#define SND_IO_H +#pragma once + +class IFileReadBinary; + +extern IFileReadBinary *g_pSndIO; + +#endif // SND_IO_H diff --git a/engine/audio/public/sound.h b/engine/audio/public/sound.h new file mode 100644 index 0000000..64b4f9d --- /dev/null +++ b/engine/audio/public/sound.h @@ -0,0 +1,150 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: client sound i/o functions +// +//===========================================================================// +#ifndef SOUND_H +#define SOUND_H +#ifdef _WIN32 +#pragma once +#endif + +#include "basetypes.h" +#include "datamap.h" +#include "mathlib/vector.h" +#include "mathlib/mathlib.h" +#include "tier1/strtools.h" +#include "soundflags.h" +#include "utlvector.h" +#include "engine/SndInfo.h" + +#define MAX_SFX 2048 + +#define AUDIOSOURCE_CACHE_ROOTDIR "maps/soundcache" + +class CSfxTable; +enum soundlevel_t; +struct SoundInfo_t; +struct AudioState_t; +class IFileList; + +void S_Init (void); +void S_Shutdown (void); +bool S_IsInitted(); + +void S_StopAllSounds(bool clear); +void S_Update( const AudioState_t *pAudioState ); +void S_ExtraUpdate (void); +void S_ClearBuffer (void); +void S_BlockSound (void); +void S_UnblockSound (void); +float S_GetMasterVolume( void ); +void S_SoundFade( float percent, float holdtime, float intime, float outtime ); +void S_OnLoadScreen(bool value); +void S_EnableThreadedMixing( bool bEnable ); +void S_EnableMusic( bool bEnable ); + +struct StartSoundParams_t +{ + StartSoundParams_t() : + staticsound( false ), + userdata( 0 ), + soundsource( 0 ), + entchannel( CHAN_AUTO ), + pSfx( 0 ), + bUpdatePositions( true ), + fvol( 1.0f ), + soundlevel( SNDLVL_NORM ), + flags( SND_NOFLAGS ), + pitch( PITCH_NORM ), + specialdsp( 0 ), + fromserver( false ), + delay( 0.0f ), + speakerentity( -1 ), + suppressrecording( false ), + initialStreamPosition( 0 ) + { + origin.Init(); + direction.Init(); + } + + bool staticsound; + int userdata; + int soundsource; + int entchannel; + CSfxTable *pSfx; + Vector origin; + Vector direction; + bool bUpdatePositions; + float fvol; + soundlevel_t soundlevel; + int flags; + int pitch; + int specialdsp; + bool fromserver; + float delay; + int speakerentity; + bool suppressrecording; + int initialStreamPosition; +}; + +int S_StartSound( StartSoundParams_t& params ); +void S_StopSound ( int entnum, int entchannel ); +enum clocksync_index_t +{ + CLOCK_SYNC_CLIENT = 0, + CLOCK_SYNC_SERVER, + NUM_CLOCK_SYNCS +}; + +extern float S_ComputeDelayForSoundtime( float soundtime, clocksync_index_t syncIndex ); + +void S_StopSoundByGuid( int guid ); +float S_SoundDurationByGuid( int guid ); +int S_GetGuidForLastSoundEmitted(); +bool S_IsSoundStillPlaying( int guid ); +void S_GetActiveSounds( CUtlVector< SndInfo_t >& sndlist ); +void S_SetVolumeByGuid( int guid, float fvol ); +float S_GetElapsedTimeByGuid( int guid ); +bool S_IsLoopingSoundByGuid( int guid ); +void S_ReloadSound( const char *pSample ); +float S_GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList ); + +CSfxTable *S_DummySfx( const char *name ); +CSfxTable *S_PrecacheSound (const char *sample ); +void S_PrefetchSound( char const *name, bool bPlayOnce ); +void S_MarkUISound( CSfxTable *pSfx ); +void S_ReloadFilesInList( IFileList *pFilesToReload ); + +vec_t S_GetNominalClipDist(); + +extern bool TestSoundChar(const char *pch, char c); +extern char *PSkipSoundChars(const char *pch); + +#include "soundchars.h" + +// for recording movies +void SND_MovieStart( void ); +void SND_MovieEnd( void ); + +//------------------------------------- + +int S_GetCurrentStaticSounds( SoundInfo_t *pResult, int nSizeResult, int entchannel ); + +//----------------------------------------------------------------------------- + +float S_GetGainFromSoundLevel( soundlevel_t soundlevel, vec_t dist ); + +struct musicsave_t +{ + DECLARE_SIMPLE_DATADESC(); + + char songname[ 128 ]; + int sampleposition; + short master_volume; +}; + +void S_GetCurrentlyPlayingMusic( CUtlVector< musicsave_t >& list ); +void S_RestartSong( const musicsave_t *song ); + +#endif // SOUND_H diff --git a/engine/audio/public/soundservice.h b/engine/audio/public/soundservice.h new file mode 100644 index 0000000..b1fb4df --- /dev/null +++ b/engine/audio/public/soundservice.h @@ -0,0 +1,135 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Applicaton-level hooks for clients of the audio subsystem +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SOUNDSERVICE_H +#define SOUNDSERVICE_H + +#if defined( _WIN32 ) +#pragma once +#endif + +class Vector; +class QAngle; +class CAudioSource; +typedef int SoundSource; +struct SpatializationInfo_t; +typedef void *FileNameHandle_t; +struct StartSoundParams_t; + +#include "utlrbtree.h" + +//----------------------------------------------------------------------------- +// Purpose: Services required by the audio system to function, this facade +// defines the bridge between the audio code and higher level +// systems. +// +// Note that some of these currently suggest that certain +// functionality would like to exist at a deeper layer so +// systems like audio can take advantage of them +// diectly (toml 05-02-02) +//----------------------------------------------------------------------------- + +abstract_class ISoundServices +{ +public: + //--------------------------------- + // Allocate a block of memory that will be automatically + // cleaned up on level change + //--------------------------------- + virtual void *LevelAlloc( int nBytes, const char *pszTag ) = 0; + + //--------------------------------- + // Notification that someone called S_ExtraUpdate() + //--------------------------------- + virtual void OnExtraUpdate() = 0; + + //--------------------------------- + // Return false if the entity doesn't exist or is out of the PVS, in which case the sound shouldn't be heard. + //--------------------------------- + virtual bool GetSoundSpatialization( int entIndex, SpatializationInfo_t& info ) = 0; + + //--------------------------------- + // This is the client's clock, which follows the servers and thus isn't 100% smooth all the time (it is in single player) + //--------------------------------- + virtual float GetClientTime() = 0; + + //--------------------------------- + // This is the engine's filtered timer, it's pretty smooth all the time + //--------------------------------- + virtual float GetHostTime() = 0; + + //--------------------------------- + //--------------------------------- + virtual int GetViewEntity() = 0; + + //--------------------------------- + //--------------------------------- + virtual float GetHostFrametime() = 0; + virtual void SetSoundFrametime( float realDt, float hostDt ) = 0; + + //--------------------------------- + //--------------------------------- + virtual int GetServerCount() = 0; + + //--------------------------------- + //--------------------------------- + virtual bool IsPlayer( SoundSource source ) = 0; + + //--------------------------------- + //--------------------------------- + virtual void OnChangeVoiceStatus( int entity, bool status) = 0; + + // Is the player fully connected (don't do DSP processing if not) + virtual bool IsConnected() = 0; + + // Calls into client .dll with list of close caption tokens to construct a caption out of + virtual void EmitSentenceCloseCaption( char const *tokenstream ) = 0; + // Calls into client .dll with list of close caption tokens to construct a caption out of + virtual void EmitCloseCaption( char const *captionname, float duration ) = 0; + + virtual char const *GetGameDir() = 0; + + // If the game is paused, certain audio will pause, too (anything with phoneme/sentence data for now) + virtual bool IsGamePaused() = 0; + + // If the game is not active, certain audio will pause + virtual bool IsGameActive() = 0; + + // restarts the sound system externally + virtual void RestartSoundSystem() = 0; + + virtual void GetAllSoundFilesReferencedInReslists( CUtlRBTree< FileNameHandle_t, int >& list ) = 0; + virtual void GetAllManifestFiles( CUtlRBTree< FileNameHandle_t, int >& list ) = 0; + virtual void GetAllSoundFilesInManifest( CUtlRBTree< FileNameHandle_t, int >& list, char const *manifestfile ) = 0; + + virtual void CacheBuildingStart() = 0; + virtual void CacheBuildingUpdateProgress( float percent, char const *cachefile ) = 0; + virtual void CacheBuildingFinish() = 0; + + // For building sound cache manifests + virtual int GetPrecachedSoundCount() = 0; + virtual char const *GetPrecachedSound( int index ) = 0; + + virtual void OnSoundStarted( int guid, StartSoundParams_t& params, char const *soundname ) = 0; + virtual void OnSoundStopped( int guid, int soundsource, int channel, char const *soundname ) = 0; + + virtual bool GetToolSpatialization( int iUserData, int guid, SpatializationInfo_t& info ) = 0; + +#if defined( _XBOX ) + virtual bool ShouldSuppressNonUISounds() = 0; +#endif + + virtual char const *GetUILanguage() = 0; +}; + +//------------------------------------- + +extern ISoundServices *g_pSoundServices; + +//============================================================================= + +#endif // SOUNDSERVICE_H diff --git a/engine/audio/public/voice.h b/engine/audio/public/voice.h new file mode 100644 index 0000000..2bfea81 --- /dev/null +++ b/engine/audio/public/voice.h @@ -0,0 +1,138 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VOICE_H +#define VOICE_H +#pragma once + + +#include "ivoicetweak.h" + + +/*! @defgroup Voice Voice +Defines the engine's interface to the voice code. +@{ +*/ + +// Voice_Init will pick a sample rate, it must be within RATE_MAX +#define VOICE_OUTPUT_SAMPLE_RATE_LOW 11025 // Sample rate that we feed to the mixer. +#define VOICE_OUTPUT_SAMPLE_RATE_HIGH 22050 // Sample rate that we feed to the mixer. +#define VOICE_OUTPUT_SAMPLE_RATE_MAX 22050 // Sample rate that we feed to the mixer. + + +//! Returned on error from certain voice functions. +#define VOICE_CHANNEL_ERROR -1 +#define VOICE_CHANNEL_IN_TWEAK_MODE -2 // Returned by AssignChannel if currently in tweak mode (not an error). + + +//! Initialize the voice code. +bool Voice_Init( const char *pCodec, int nSampleRate ); + +//! Inits voice with defaults if it is not initialized normally, e.g. for local mixer use. +void Voice_ForceInit(); + +//! Get the default sample rate to use for this codec +inline int Voice_GetDefaultSampleRate( const char *pCodec ) // Inline for DEDICATED builds +{ + // Use legacy lower rate for speex + if ( Q_stricmp( pCodec, "vaudio_speex" ) == 0 ) + { + return VOICE_OUTPUT_SAMPLE_RATE_LOW; + } + else if ( Q_stricmp( pCodec, "steam" ) == 0 ) + { + return 0; // For the steam codec, 0 passed to voice_init means "use optimal steam voice rate" + } + + // Use high sample rate by default for other codecs. + return VOICE_OUTPUT_SAMPLE_RATE_HIGH; +} + +//! Shutdown the voice code. +void Voice_Deinit(); + +//! Returns true if the client has voice enabled +bool Voice_Enabled( void ); + +//! The codec voice was initialized with. Empty string if voice is not initialized. +const char *Voice_ConfiguredCodec(); + +//! The sample rate voice was initialized with. -1 if voice is not initialized. +int Voice_ConfiguredSampleRate(); + +//! Returns true if the user can hear themself speak. +bool Voice_GetLoopback(); + + +//! This is called periodically by the engine when the server acks the local player talking. +//! This tells the client DLL that the local player is talking and fades after about 200ms. +void Voice_LocalPlayerTalkingAck(); + + +//! Call every frame to update the voice stuff. +void Voice_Idle(float frametime); + + +//! Returns true if mic input is currently being recorded. +bool Voice_IsRecording(); + +//! Begin recording input from the mic. +bool Voice_RecordStart( + //! Filename to store incoming mic data, or NULL if none. + const char *pUncompressedFile, + + //! Filename to store the output of compression and decompressiong with the codec, or NULL if none. + const char *pDecompressedFile, + + //! If this is non-null, the voice manager will use this file for input instead of the mic. + const char *pMicInputFile + ); + +// User wants to stop recording +void Voice_UserDesiresStop(); + +//! Stop recording from the mic. +bool Voice_RecordStop(); + + +//! Get the most recent N bytes of compressed data. If nCount is less than the number of +//! available bytes, it discards the first bytes and gives you the last ones. +//! Set bFinal to true on the last call to this (it will flush out any stored voice data). +int Voice_GetCompressedData(char *pchData, int nCount, bool bFinal); + + + +//! Pass incoming data from the server into here. +//! The data should have been compressed and gotten through a Voice_GetCompressedData call. +int Voice_AddIncomingData( + //! Channel index. + int nChannel, + //! Compressed data to add to the channel. + const char *pchData, + //! Number of bytes in pchData. + int nCount, + //! Sequence number. If a packet is missed, it adds padding so the time isn't squashed. + int iSequenceNumber + ); + +//! Call this to reserve a voice channel for the specified entity to talk into. +//! \return A channel index for use with Voice_AddIncomingData or VOICE_CHANNEL_ERROR on error. +int Voice_AssignChannel(int nEntity, bool bProximity ); + +//! Call this to get the channel index that the specified entity is talking into. +//! \return A channel index for use with Voice_AddIncomingData or VOICE_CHANNEL_ERROR if the entity isn't talking. +int Voice_GetChannel(int nEntity); + +#if !defined( NO_VOICE ) +extern IVoiceTweak g_VoiceTweakAPI; +extern bool g_bUsingSteamVoice; +#endif + +/*! @} */ + + +#endif // VOICE_H diff --git a/engine/audio/public/vox.h b/engine/audio/public/vox.h new file mode 100644 index 0000000..6b50008 --- /dev/null +++ b/engine/audio/public/vox.h @@ -0,0 +1,46 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VOX_H +#define VOX_H +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +struct sfxcache_t; +struct channel_t; + +class CUtlSymbol; + +extern void VOX_Init( void ); +extern void VOX_Shutdown( void ); +extern void VOX_ReadSentenceFile( const char *psentenceFileName ); +extern int VOX_SentenceCount( void ); +extern void VOX_LoadSound( channel_t *pchan, const char *psz ); +// UNDONE: Improve the interface of this call, it returns sentence data AND the sentence index +extern char *VOX_LookupString( const char *pSentenceName, int *psentencenum, bool *pbEmitCaption = NULL, CUtlSymbol *pCaptionSymbol = NULL, float * pflDuration = NULL ); +extern void VOX_PrecacheSentenceGroup( class IEngineSound *pSoundSystem, const char *pGroupName, const char *pPathOverride = NULL ); +extern const char *VOX_SentenceNameFromIndex( int sentencenum ); +extern float VOX_SentenceLength( int sentence_num ); +extern const char *VOX_GroupNameFromIndex( int groupIndex ); +extern int VOX_GroupIndexFromName( const char *pGroupName ); +extern int VOX_GroupPick( int isentenceg, char *szfound, int strLen ); +extern int VOX_GroupPickSequential( int isentenceg, char *szfound, int szfoundLen, int ipick, int freset ); + +#ifdef __cplusplus +} +#endif + +#endif // VOX_H |