//========= Copyright 1996-2009, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// // This module implements the voice record and compression functions //#include "audio_pch.h" //#include "voice.h" #include "tier0/platform.h" #include "ivoicerecord.h" #include "tier0/dbg.h" #include "tier0/threadtools.h" #include #include #define RECORDING_BUFFER_SECONDS 3 #define SAMPLE_COUNT 2048 // ------------------------------------------------------------------------------ // VoiceRecord_SDL // ------------------------------------------------------------------------------ struct AudioBuf { int Read(char *out, int len) { int nAvalible = (size + (writePtr - readPtr)) % size; if( nAvalible == 0 ) return 0; if( len > nAvalible ) len = nAvalible; int diff = (data + size) - readPtr; if( len > diff ) { memcpy(out, readPtr, diff ); memcpy(out+diff, data, len-diff ); } else memcpy(out, readPtr, len); readPtr += len; if( readPtr >= data + size ) readPtr -= size; return len; } void Write(char *in, int len) { int diff = (data + size) - writePtr; if( len > diff ) { memcpy(writePtr, in, diff ); memcpy(data, in+diff, len-diff ); } else memcpy(writePtr, in, len); writePtr += len; if (writePtr >= (data + size)) writePtr -= size; } int size; char *data; char *readPtr; char *writePtr; }; class VoiceRecord_SDL : public IVoiceRecord { protected: virtual ~VoiceRecord_SDL(); public: VoiceRecord_SDL(); virtual void Release(); virtual bool RecordStart(); virtual void RecordStop(); // Initialize. The format of the data we expect from the provider is // 8-bit signed mono at the specified sample rate. virtual bool Init(int sampleRate); virtual void Idle() {}; // Stub void RenderBuffer( char *pszBuf, int size ); // Get the most recent N samples. virtual int GetRecordedData(short *pOut, int nSamplesWanted ); SDL_AudioSpec m_ReceivedRecordingSpec; int m_BytesPerSample; // Да кому нужна эта ваша инкапсуляция? int m_nSampleRate; private: bool InitalizeInterfaces(); // Initialize the openal capture buffers and other interfaces void ReleaseInterfaces(); // Release openal buffers and other interfaces void ClearInterfaces(); // Clear members. private: SDL_AudioDeviceID m_Device; AudioBuf m_AudioBuffer; }; void audioRecordingCallback( void *userdata, uint8 *stream, int len ) { VoiceRecord_SDL *voice = (VoiceRecord_SDL*)userdata; voice->RenderBuffer( (char*)stream, len ); } VoiceRecord_SDL::VoiceRecord_SDL() : m_nSampleRate( 0 ) ,m_Device( 0 ) { m_AudioBuffer.data = NULL; m_AudioBuffer.readPtr = NULL; m_AudioBuffer.writePtr = NULL; ClearInterfaces(); } VoiceRecord_SDL::~VoiceRecord_SDL() { ReleaseInterfaces(); ClearInterfaces(); } void VoiceRecord_SDL::Release() { ReleaseInterfaces(); ClearInterfaces(); delete this; } bool VoiceRecord_SDL::RecordStart() { if ( !m_Device ) InitalizeInterfaces(); if ( !m_Device ) return false; SDL_PauseAudioDevice( m_Device, SDL_FALSE ); return true; } void VoiceRecord_SDL::RecordStop() { // Stop capturing. if ( m_Device ) SDL_PauseAudioDevice( m_Device, SDL_TRUE ); // Release the capture buffer interface and any other resources that are no // longer needed ReleaseInterfaces(); } bool VoiceRecord_SDL::InitalizeInterfaces() { //Default audio spec SDL_AudioSpec desiredRecordingSpec; SDL_zero(desiredRecordingSpec); desiredRecordingSpec.freq = m_nSampleRate; desiredRecordingSpec.format = AUDIO_S16; desiredRecordingSpec.channels = 1; desiredRecordingSpec.samples = SAMPLE_COUNT; desiredRecordingSpec.callback = audioRecordingCallback; desiredRecordingSpec.userdata = (void*)this; //Open recording device m_Device = SDL_OpenAudioDevice( NULL, SDL_TRUE, &desiredRecordingSpec, &m_ReceivedRecordingSpec, 0 ); if( m_Device != 0 ) { //Calculate per sample bytes m_BytesPerSample = m_ReceivedRecordingSpec.channels * ( SDL_AUDIO_BITSIZE( m_ReceivedRecordingSpec.format ) / 8 ); //Calculate bytes per second int bytesPerSecond = m_ReceivedRecordingSpec.freq * m_BytesPerSample; //Allocate and initialize byte buffer m_AudioBuffer.size = RECORDING_BUFFER_SECONDS * bytesPerSecond; if( !m_AudioBuffer.data ) m_AudioBuffer.data = (char *)malloc( m_AudioBuffer.size ); m_AudioBuffer.readPtr = m_AudioBuffer.data; m_AudioBuffer.writePtr = m_AudioBuffer.data + SAMPLE_COUNT*m_BytesPerSample*2; memset( m_AudioBuffer.data, 0, m_AudioBuffer.size ); return true; } else return false; } bool VoiceRecord_SDL::Init(int sampleRate) { m_nSampleRate = sampleRate; ReleaseInterfaces(); return true; } void VoiceRecord_SDL::ReleaseInterfaces() { if( m_Device != 0 ) SDL_CloseAudioDevice( m_Device ); m_Device = 0; } void VoiceRecord_SDL::ClearInterfaces() { if( m_AudioBuffer.data ) { free( m_AudioBuffer.data ); m_AudioBuffer.data = NULL; m_AudioBuffer.readPtr = NULL; m_AudioBuffer.writePtr = NULL; } m_Device = 0; } void VoiceRecord_SDL::RenderBuffer( char *pszBuf, int size ) { m_AudioBuffer.Write( pszBuf, size ); } int VoiceRecord_SDL::GetRecordedData(short *pOut, int nSamples ) { if ( !m_AudioBuffer.data || nSamples == 0 ) return 0; int cbSamples = nSamples * m_BytesPerSample; return m_AudioBuffer.Read( (char*)pOut, cbSamples )/m_BytesPerSample; } IVoiceRecord* CreateVoiceRecord_SDL(int sampleRate) { VoiceRecord_SDL *pRecord = new VoiceRecord_SDL; if ( pRecord && pRecord->Init(sampleRate) ) return pRecord; else if( pRecord ) pRecord->Release(); return NULL; }