|
|
/*==========================================================================
* * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved. * * File: sndutils.cpp * Content: * This module contains the implementation of sound related utility * functions. Functions in this module manipulate WAVEFORMATEX * structures and provide full duplex initialization / testing * facilities. * * This module also contains the routines used to measure peak * of an audio buffer and for voice activation. * * History: * Date By Reason * ==== == ====== * 07/16/99 rodtoll Created * 07/30/99 rodtoll Updated util functions to take GUIDs and allow for * users to pre-create capture/playback devices and * pass them into InitXXXXDuplex * 08/25/99 rodtoll General Cleanup/Modifications to support new * compression sub-system. * 08/30/99 rodtoll Added new playback format param to sound init * 09/03/99 rodtoll Fixed return codes on InitFullDuplex * 09/20/99 rodtoll Now checks for invalid GUIDs for playback/record * 10/05/99 rodtoll Added DPF_MODNAMEs * 10/29/99 rodtoll Bug #113726 - Fixed memory leak when full duplex * fails caused by architecture update. * 11/12/99 rodtoll Updated full duplex test to use new abstracted recording * and playback systems. * rodtoll Updated to allow passing of sounddeviceconfig flags in dwflags * parameter to init is effected by the flags specified by user * rodtoll Sound buffers (rec and playback) are now set to silence before * recording/playback is started. * 11/22/99 rodtoll Removed unnessessary set of recording buffer to silence. * 12/01/99 rodtoll Bug #115783 - Will always adjust volume of default device * Updated for new parameters added by above bug. * 12/08/99 rodtoll Bug #121054 - Support for capture focus and removed flags * from buffer, allow dsound to manage buffer location. * 01/21/2000 pnewson Fixed error cleanup code in InitHalfDuplex * 01/27/2000 rodtoll Updated tests to accept buffer descriptions and play flags/priority * 02/10/2000 rodtoll Removed more capture focus * 02/23/2000 rodtoll Fix to allow to run on dsound7. * 05/19/2000 rodtoll Bug #35395 - Unable to run two copies of DPVHELP on same system without * DirectX 8 installed. * 06/21/2000 rodtoll Bug #35767 - Must implement ability to use effects processing on voice buffers * Updated sound initialization routines to handle buffers being passed in. * 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard * 10/04/2000 rodtoll Bug #43510 - DPVOICE: Apps receive a DVMSGID_SESSIONLOST w/DVERR_LOCKEDBUFFER * 01/04/2001 rodtoll WinBug #94200 - Remove stray comments * 01/26/2001 rodtoll WINBUG #293197 - DPVOICE: [STRESS} Stress applications cannot tell difference between out of memory and internal errors. * Remap DSERR_OUTOFMEMORY to DVERR_OUTOFMEMORY instead of DVERR_SOUNDINITFAILURE. * Remap DSERR_ALLOCATED to DVERR_PLAYBACKSYSTEMERROR instead of DVERR_SOUNDINITFAILURE. * 04/12/2001 kareemc WINBUG #360971 - Wizard Memory Leaks * ***************************************************************************/
#include "dxvutilspch.h"
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
#define DSERRBREAK_NAME "DSASSERT"
DNCRITICAL_SECTION g_csDSDebug;
CHAR g_szLastDirectSoundAPI[100] = ""; HRESULT g_hrLastDirectSoundResult = DS_OK; BOOL g_fDSErrorBreak = FALSE;
void DSERTRACK_Update( const char *szAPICall, HRESULT hrResult ) { DNEnterCriticalSection( &g_csDSDebug ); if( SUCCEEDED( g_hrLastDirectSoundResult ) ) { g_hrLastDirectSoundResult = hrResult; strcpy( g_szLastDirectSoundAPI , szAPICall ); } DNLeaveCriticalSection( &g_csDSDebug ); }
void DSERRTRACK_Reset() { DNEnterCriticalSection( &g_csDSDebug ); g_hrLastDirectSoundResult = DS_OK; g_szLastDirectSoundAPI[0] = 0; DNLeaveCriticalSection( &g_csDSDebug ); }
BOOL DSERRTRACK_Init() { if (!DNInitializeCriticalSection( &g_csDSDebug )) { return FALSE; }
// Load the setting for the directsound assert
g_fDSErrorBreak = GetProfileIntA( "DirectPlay8", DSERRBREAK_NAME, FALSE );
return TRUE; }
void DSERRTRACK_UnInit() { DNDeleteCriticalSection( &g_csDSDebug ); }
#undef DPF_MODNAME
#define DPF_MODNAME "DV_SetupBufferDesc"
void DV_SetupBufferDesc( LPDSBUFFERDESC lpdsBufferDesc, LPDSBUFFERDESC lpdsBufferSource, LPWAVEFORMATEX lpwfxFormat, DWORD dwBufferSize ) { // Confirm specified buffer description is valid
if( lpdsBufferSource != NULL ) { if( lpdsBufferSource->dwSize == sizeof( DSBUFFERDESC1 ) ) { memcpy( lpdsBufferDesc, lpdsBufferSource, sizeof( DSBUFFERDESC1 ) ); } else { memcpy( lpdsBufferDesc, lpdsBufferSource, sizeof( DSBUFFERDESC ) ); }
// We require the following flags, at a minimum so they should always be set
lpdsBufferDesc->dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2; } // User did not specify a buffer description, let's use our own!
else { lpdsBufferDesc->dwSize = sizeof( DSBUFFERDESC ); lpdsBufferDesc->dwFlags = DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; lpdsBufferDesc->dwBufferBytes = 0; lpdsBufferDesc->dwReserved = 0; lpdsBufferDesc->lpwfxFormat = NULL; lpdsBufferDesc->guid3DAlgorithm = DS3DALG_DEFAULT; }
lpdsBufferDesc->lpwfxFormat = lpwfxFormat; lpdsBufferDesc->dwBufferBytes = dwBufferSize;
}
#undef DPF_MODNAME
#define DPF_MODNAME "SetRecordBufferToSilence"
HRESULT SetPlaybackBufferToSilence( CAudioPlaybackBuffer *pRecBuffer, const WAVEFORMATEX* lpwfxFormat ) { HRESULT hr; LPVOID pBufferPtr1, pBufferPtr2; DWORD dwBufferSize1, dwBufferSize2;
hr = pRecBuffer->Lock( 0, 0, &pBufferPtr1, &dwBufferSize1, &pBufferPtr2, &dwBufferSize2, DSBLOCK_ENTIREBUFFER );
DSERTRACK_Update( "Lock", hr );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Lock() failed during silence write hr=0x%x", hr ); return hr; }
memset( pBufferPtr1, (lpwfxFormat->wBitsPerSample==8) ? 0x80 : 0x00, dwBufferSize1 );
hr = pRecBuffer->UnLock( pBufferPtr1, dwBufferSize1, pBufferPtr2, dwBufferSize2 );
DSERTRACK_Update( "UnLock", hr );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unlock() failed uffer unlock failed hr=0x%x", hr ); return hr; }
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "InitHalfDuplex"
// InitHalfDuplex
//
// This function initializes the playback system for the
// specified compression type and the specified playback
// format. This function is used to initialize
// the AudioPlaybackDevice and AudioPlaybackBuffer.
//
// It also starts the audio buffer which is used for voice
// output playing. (In looping mode).
//
// Parameters:
// HWND hwnd -
// Window handle for the window where the output will
// be associated
// ARDID playbackDeviceID -
// The deviceID for the device which will be used for
// playback
// CAudioPlaybackDevice ** -
// A pointer to a pointer which will contain a pointer
// to a newly created CAudioPlaybackDevice which will
// represent the playback device on success.
// CAudioPlaybackBuffer ** -
// A pointer to a pointer which will contain a pointer
// to a newly created CAudioPlaybacKbuffer which will
// be used for voice audio output on success.
// CompressionType ct -
// The type of compression which will be in use. Used
// to determine buffer sizes etc.
// WAVEFORMATEX *primaryFormat -
// Pointer to a WAVEFORMATEX structure describing the
// format of the voice output. (This will also be used
// to set the primary format of the output device if
// normal is set to false).
// bool normal -
// Specifies if normal mode should be used or not.
// (Only used when using the DirectSound playback
// system. Set to true for normal cooperative mode,
// false for priority mode).
//
// Returns:
// bool -
// Returns true if playback was initializes succesfully,
// false if initialization fails.
//
HRESULT InitHalfDuplex( HWND hwnd, const GUID &guidPlayback, CAudioPlaybackDevice **audioPlaybackDevice, LPDSBUFFERDESC lpdsBufferDesc, CAudioPlaybackBuffer **audioPlaybackBuffer, const GUID &guidCT, WAVEFORMATEX *primaryFormat, WAVEFORMATEX *lpwfxPlayFormat, DWORD dwPlayPriority, DWORD dwPlayFlags, DWORD dwFlags ) { DWORD frameSize; HRESULT hr; DWORD dwBufferSize; BOOL fPriorityMode; DSBUFFERDESC dsBufferDesc; BOOL fPlaybackDeviceAllocated = FALSE; BOOL fPlaybackBufferAllocated = FALSE;
fPriorityMode = !( dwFlags & DVSOUNDCONFIG_NORMALMODE );
// *audioPlaybackBuffer = NULL;
DPFX(DPFPREP, DVF_INFOLEVEL, "HALFDUPLEX INIT: Begin ==========" );
LPDVFULLCOMPRESSIONINFO lpdvfInfo;
hr = DVCDB_GetCompressionInfo( guidCT, &lpdvfInfo );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Error loading compression type: hr = 0x%x", hr ); goto INIT_EXIT_ERROR2; }
if( (*audioPlaybackDevice) == NULL ) { #ifdef __WAVESUBSYSTEM
if( !(dwFlags & DVSOUNDCONFIG_FORCEWAVEOUT) ) { #endif
// Create the object to represent the device using the playback subsystem's
// CreateDevice function
(*audioPlaybackDevice) = new CDirectSoundPlaybackDevice(); fPlaybackDeviceAllocated = TRUE; if( *audioPlaybackDevice == NULL ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Out of memory" ); hr = DVERR_OUTOFMEMORY; goto INIT_EXIT_ERROR2; }
hr = (*audioPlaybackDevice)->Initialize( guidPlayback, hwnd, primaryFormat, fPriorityMode );
#ifndef __WAVESUBSYSTEM
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize playback. hr=0x%x", hr ); goto INIT_EXIT_ERROR2; } #endif
#ifdef __WAVESUBSYSTEM
}
if( dwFlags & DVSOUNDCONFIG_FORCEWAVEOUT || ((dwFlags & DVSOUNDCONFIG_ALLOWWAVEOUT) && FAILED( hr )) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Could not initialize directsound, defaulting to waveout hr=0x%x", hr ); delete (*audioPlaybackDevice);
(*audioPlaybackDevice) = new CWaveOutPlaybackDevice( ); fPlaybackDeviceAllocated = TRUE; if( (*audioPlaybackDevice) == NULL ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Out of memory" ); hr = DVERR_OUTOFMEMORY; goto INIT_EXIT_ERROR2; }
hr = (*audioPlaybackDevice)->Initialize( guidPlayback, hwnd, primaryFormat, fPriorityMode );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Could not initalize waveOut. Init failed hr=0x%x", hr ); goto INIT_EXIT_ERROR2; } } else if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize playback. hr=0x%x", hr ); goto INIT_EXIT_ERROR2; } #endif
// At this point we should have a valid device, waveOut or DirectSound
}
DPFX(DPFPREP, DVF_INFOLEVEL, "> Play init" );
// Create a buffer if the user didn't specify one
if( !(*audioPlaybackBuffer) ) { frameSize = DVCDB_CalcUnCompressedFrameSize( lpdvfInfo, lpwfxPlayFormat ); dwBufferSize = lpdvfInfo->dwFramesPerBuffer * frameSize;
DV_SetupBufferDesc( &dsBufferDesc, lpdsBufferDesc, lpwfxPlayFormat, dwBufferSize );
// Create the audio buffer which will be used for output
hr = (*audioPlaybackDevice)->CreateBuffer( &dsBufferDesc, frameSize, audioPlaybackBuffer); fPlaybackBufferAllocated = TRUE;
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to create sound buffer. hr=0x%x", hr ); goto INIT_EXIT_ERROR2; } }
DPFX(DPFPREP, DVF_INFOLEVEL, "> Play init 2" );
hr = SetPlaybackBufferToSilence( *audioPlaybackBuffer, lpwfxPlayFormat );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Unable to set playback to silence" ); goto INIT_EXIT_ERROR2; }
DPFX(DPFPREP, DVF_INFOLEVEL, "> Play init 3" );
// Start the audio playback buffer playing
hr = (*audioPlaybackBuffer)->Play( dwPlayPriority, dwPlayFlags );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "> Can't play" ); goto INIT_EXIT_ERROR2; }
Diagnostics_Write( DVF_INFOLEVEL, "Half Duplex Init Result = DV_OK " );
return DV_OK;
// Handle errors
INIT_EXIT_ERROR2:
if( fPlaybackBufferAllocated && *audioPlaybackBuffer != NULL ) { delete *audioPlaybackBuffer; *audioPlaybackBuffer = NULL; }
if( fPlaybackDeviceAllocated && *audioPlaybackDevice != NULL ) { delete *audioPlaybackDevice; *audioPlaybackDevice = NULL; }
Diagnostics_Write( DVF_ERRORLEVEL, "Half Duplex Init Result = 0x%x", hr );
return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "InitializeRecordBuffer"
HRESULT InitializeRecordBuffer( HWND hwnd, const DVFULLCOMPRESSIONINFO* lpdvfInfo, CAudioRecordDevice *parecDevice, CAudioRecordBuffer **pparecBuffer, DWORD dwFlags ) { WAVEFORMATEX *lpwfxRecordFormat; DSCBUFFERDESC1 dscdesc; DWORD dwFrameSize; HRESULT hr; for( DWORD dwIndex = 0; dwIndex < GetNumRecordFormats(); dwIndex++ ) { lpwfxRecordFormat = GetRecordFormat( dwIndex ); dwFrameSize = DVCDB_CalcUnCompressedFrameSize( lpdvfInfo, lpwfxRecordFormat );
memset( &dscdesc, 0x00, sizeof( DSCBUFFERDESC1 ) ); dscdesc.dwSize = sizeof( DSCBUFFERDESC1 ); dscdesc.dwFlags = 0; dscdesc.lpwfxFormat = lpwfxRecordFormat; dscdesc.dwBufferBytes = dwFrameSize*lpdvfInfo->dwFramesPerBuffer;
if( !(dwFlags & DVSOUNDCONFIG_NOFOCUS) ) { dscdesc.dwFlags |= DSCBCAPS_FOCUSAWARE;
if( dwFlags & DVSOUNDCONFIG_STRICTFOCUS ) { dscdesc.dwFlags |= DSCBCAPS_STRICTFOCUS; } }
hr = parecDevice->CreateBuffer( (DSCBUFFERDESC *) &dscdesc, hwnd, dwFrameSize, pparecBuffer );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_WARNINGLEVEL, "Could not initialize %d hz, %d bits, %s (hr=0x%x)", lpwfxRecordFormat->nSamplesPerSec, lpwfxRecordFormat->wBitsPerSample, (lpwfxRecordFormat->nChannels==1) ? _T("Mono") : _T("Stereo"), hr ); continue; } else { Diagnostics_Write( DVF_INFOLEVEL, "Recording Initialized. Format=" ); Diagnositcs_WriteWAVEFORMATEX( DVF_INFOLEVEL, lpwfxRecordFormat ); }
hr = (*pparecBuffer)->Record(TRUE);
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_WARNINGLEVEL, "Could not start rec at %d hz, %d bits, %s (hr=0x%x)", lpwfxRecordFormat->nSamplesPerSec, lpwfxRecordFormat->wBitsPerSample, (lpwfxRecordFormat->nChannels==1) ? _T("Mono") : _T("Stereo"), hr ); delete (*pparecBuffer); (*pparecBuffer) = NULL; continue; } else { Diagnostics_Write( DVF_INFOLEVEL, "Recording Started. Format=" ); Diagnositcs_WriteWAVEFORMATEX( DVF_INFOLEVEL, lpwfxRecordFormat ); // Reset the directsound erros as we expect errors in this part and if we suceed we handled
// them.
return DV_OK; } }
return DVERR_RECORDSYSTEMERROR; }
#undef DPF_MODNAME
#define DPF_MODNAME "InitFullDuplex"
// InitFullDuplex
//
// The tricky part.
//
// This function is responsible for initializing the system into full duplex
// mode using the specified parameters. This function will create and
// initialize the playback and record devices as well as start the
// playback device playing and the recording device recording. (On success).
// This is neccessary because the order of Play and Record and device
// creation is important.
//
// Parameters:
// HWND hwnd -
// Window handle for the window where the output will
// be associated
// ARDID playbackDeviceID -
// The deviceID for the device which will be used for
// playback
// CAudioPlaybackDevice ** -
// A pointer to a pointer which will contain a pointer
// to a newly created CAudioPlaybackDevice which will
// represent the playback device on success.
// CAudioPlaybackBuffer ** -
// A pointer to a pointer which will contain a pointer
// to a newly created CAudioPlaybacKbuffer which will
// be used for voice audio output on success.
// ARDID recordDeviceID -
// The ARDID for the device which will be used for recording.
// CAudioRecordSubSystem *recordSubSystem -
// This parameter is a pointer to the object representing
// the subsystem which will be used for recording.
// CAudioRecordDevice ** -
// A pointer to a pointer which will contain a newly
// create CAudioRecordDevice for voice recording on
// success.
// CompressionType ct -
// The type of compression which will be in use. Used
// to determine buffer sizes etc.
// WAVEFORMATEX *primaryFormat -
// Pointer to a WAVEFORMATEX structure describing the
// format of the voice output. (This will also be used
// to set the primary format of the output device if
// normal is set to false).
// bool aso -
// This parameter controls the ASO option. The ASO
// option controls the "Startup Order". Enabling
// this option allows full duplex to be initialized
// on some troublesome cards.
// bool normal -
// Specifies if normal mode should be used or not.
// (Only used when using the DirectSound playback
// system. Set to true for normal cooperative mode,
// false for priority mode).
//
// Returns:
// bool - true on successful full duplex initialization,
// false on failure.
//
HRESULT InitFullDuplex( HWND hwnd, const GUID &guidPlayback, CAudioPlaybackDevice **audioPlaybackDevice, LPDSBUFFERDESC lpdsBufferDesc, CAudioPlaybackBuffer **audioPlaybackBuffer, const GUID &guidRecord, CAudioRecordDevice **audioRecordDevice, CAudioRecordBuffer **audioRecordBuffer, const GUID &guidCT, WAVEFORMATEX *primaryFormat, WAVEFORMATEX *lpwfxPlayFormat, BOOL aso, DWORD dwPlayPriority, DWORD dwPlayFlags, DWORD dwFlags ) { DWORD frameSize; DWORD dwBufferSize; HRESULT hr; DSBUFFERDESC dsbdesc; BOOL fPriorityMode; BOOL fPlaybackDeviceAllocated = FALSE; BOOL fPlaybackBufferAllocated = FALSE; BOOL fRecordDeviceAllocated = FALSE;
fPriorityMode = !(dwFlags & DVSOUNDCONFIG_NORMALMODE);
// *audioPlaybackBuffer = NULL;
*audioRecordBuffer = NULL;
DPFX(DPFPREP, DVF_INFOLEVEL, "FULLDUPLEX INIT: Begin ==========" );
LPDVFULLCOMPRESSIONINFO lpdvfInfo;
hr = DVCDB_GetCompressionInfo( guidCT, &lpdvfInfo );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Error loading compression type: hr = 0x%x", hr ); goto INIT_EXIT_ERROR; }
if( (*audioPlaybackDevice) == NULL ) { #ifdef __WAVESUBSYSTEM
if( !(dwFlags & DVSOUNDCONFIG_FORCEWAVEOUT) ) { #endif
// Create the object to represent the device using the playback subsystem's
// CreateDevice function
(*audioPlaybackDevice) = new CDirectSoundPlaybackDevice(); fPlaybackDeviceAllocated = TRUE; if( *audioPlaybackDevice == NULL ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Out of memory" ); hr = DVERR_OUTOFMEMORY; goto INIT_EXIT_ERROR; }
hr = (*audioPlaybackDevice)->Initialize( guidPlayback, hwnd, primaryFormat, fPriorityMode );
#ifndef __WAVESUBSYSTEM
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize playback. hr=0x%x", hr ); goto INIT_EXIT_ERROR; } #endif
#ifdef __WAVESUBSYSTEM
}
if( dwFlags & DVSOUNDCONFIG_FORCEWAVEOUT || ((dwFlags & DVSOUNDCONFIG_ALLOWWAVEOUT) && FAILED( hr )) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Could not initialize directsound, defaulting to waveout hr=0x%x", hr ); delete (*audioPlaybackDevice);
(*audioPlaybackDevice) = new CWaveOutPlaybackDevice(); fPlaybackDeviceAllocated = TRUE;
if( (*audioPlaybackDevice) == NULL ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Out of memory" ); hr = DVERR_OUTOFMEMORY; goto INIT_EXIT_ERROR; }
hr = (*audioPlaybackDevice)->Initialize( guidPlayback, hwnd, primaryFormat, fPriorityMode );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Could not initalize waveOut. Init failed hr=0x%x", hr ); goto INIT_EXIT_ERROR; } } else if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize playback. hr=0x%x", hr ); goto INIT_EXIT_ERROR; } #endif
}
DPFX(DPFPREP, DVF_INFOLEVEL, "> Play init" );
frameSize = DVCDB_CalcUnCompressedFrameSize( lpdvfInfo, lpwfxPlayFormat );
DPFX(DPFPREP, DVF_INFOLEVEL, "> Play init" );
dwBufferSize = lpdvfInfo->dwFramesPerBuffer * frameSize;
if( !(*audioPlaybackBuffer) ) { DV_SetupBufferDesc( &dsbdesc, lpdsBufferDesc, lpwfxPlayFormat, dwBufferSize );
// Create the audio buffer which will be used for output
hr = (*audioPlaybackDevice)->CreateBuffer( &dsbdesc, frameSize, audioPlaybackBuffer); fPlaybackBufferAllocated = TRUE; if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to create sound buffer. hr=0x%x", hr ); goto INIT_EXIT_ERROR; } }
DPFX(DPFPREP, DVF_INFOLEVEL, "> Play init 2" );
DPFX(DPFPREP, DVF_INFOLEVEL, "> Initing Recording" );
// We're creating the device..
if( (*audioRecordDevice) == NULL ) { #ifdef __WAVESUBSYSTEM
if( !(dwFlags & DVSOUNDCONFIG_FORCEWAVEIN) ) { #endif
(*audioRecordDevice) = new CDirectSoundCaptureRecordDevice(); fRecordDeviceAllocated = TRUE; if( *audioRecordDevice == NULL ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Out of memory" ); hr = DVERR_OUTOFMEMORY; goto INIT_EXIT_ERROR; }
hr = (*audioRecordDevice)->Initialize( guidRecord );
// DSC Init passed, try getting a buffer
if( SUCCEEDED( hr ) ) { hr = InitializeRecordBuffer( hwnd, lpdvfInfo, *audioRecordDevice, audioRecordBuffer, dwFlags ); if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize dsc buffer hr=0x%x", hr ); #ifndef __WAVESUBSYSTEM
Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize record. hr=0x%x", hr ); goto INIT_EXIT_ERROR; #endif
} else { // Need to reset because we expect errors during initialization.
DSERRTRACK_Reset(); } } #ifndef __WAVESUBSYSTEM
else { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize record. hr=0x%x", hr ); goto INIT_EXIT_ERROR; } #endif
#ifdef __WAVESUBSYSTEM
}
// DSC Init failed, try and get a waveIn device
if( dwFlags & DVSOUNDCONFIG_FORCEWAVEIN || ((dwFlags & DVSOUNDCONFIG_ALLOWWAVEIN) && FAILED( hr ))) { Diagnostics_Write( DVF_ERRORLEVEL, "Could not initialize directsoundcapture, defaulting to wavein hr=0x%x", hr ); delete (*audioRecordDevice);
(*audioRecordDevice) = new CWaveInRecordDevice(); fRecordDeviceAllocated = TRUE; if( (*audioRecordDevice) == NULL ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Out of memory" ); hr = DVERR_OUTOFMEMORY; goto INIT_EXIT_ERROR; }
hr = (*audioRecordDevice)->Initialize( guidPlayback );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Could not initalize waveIn. Init failed hr=0x%x", hr ); goto INIT_EXIT_ERROR; }
hr = InitializeRecordBuffer( hwnd, lpdvfInfo, *audioRecordDevice, audioRecordBuffer, dwFlags );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize waveIn buffer hr=0x%x", hr ); goto INIT_EXIT_ERROR; } } else if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize record. hr=0x%x", hr ); goto INIT_EXIT_ERROR; } #endif
} // Use specified device, just try and create the buffer
else { hr = InitializeRecordBuffer( hwnd, lpdvfInfo, *audioRecordDevice, audioRecordBuffer, dwFlags );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "Unable to initialize dsc buffer hr=0x%x", hr ); goto INIT_EXIT_ERROR; } }
DPFX(DPFPREP, DVF_INFOLEVEL, "> Rec Init 2" );
hr = SetPlaybackBufferToSilence( *audioPlaybackBuffer, lpwfxPlayFormat );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Unable to set playback to silence" ); goto INIT_EXIT_ERROR; } DPFX(DPFPREP, DVF_INFOLEVEL, "> Rec Init 3" );
// Depending on the ASO parameter start the playback buffer
// playing and the recording buffer recording.
if( aso ) { DPFX(DPFPREP, DVF_INFOLEVEL, "> ASO " );
hr = (*audioPlaybackBuffer)->Play( dwPlayPriority, dwPlayFlags );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Can't play" ); goto INIT_EXIT_ERROR; }
hr = (*audioRecordBuffer)->Record(TRUE);
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Can't start recording" ); goto INIT_EXIT_ERROR; } } else { DPFX(DPFPREP, DVF_INFOLEVEL, "> !ASO " );
/* hr = (*audioRecordBuffer)->Record(TRUE);
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Can't start recording" ); goto INIT_EXIT_ERROR; } */
hr = (*audioPlaybackBuffer)->Play( dwPlayPriority, dwPlayFlags );
if( FAILED( hr ) ) { Diagnostics_Write( DVF_ERRORLEVEL, "> Can't play" ); goto INIT_EXIT_ERROR; } } DPFX(DPFPREP, DVF_INFOLEVEL, "FULL DUPLEX INIT: End ==========" );
Diagnostics_Write( DVF_INFOLEVEL, "Full Duplex Init Result = DV_OK" );
return DV_OK;
INIT_EXIT_ERROR:
if( *audioRecordBuffer != NULL ) { delete *audioRecordBuffer; *audioRecordBuffer = NULL; }
// Only delete on error if we allocated
if( fRecordDeviceAllocated && *audioRecordDevice != NULL ) { delete *audioRecordDevice; *audioRecordDevice = NULL; }
// Only delete on error if we allocated
if( fPlaybackBufferAllocated && *audioPlaybackBuffer != NULL ) { delete *audioPlaybackBuffer; *audioPlaybackBuffer = NULL; }
// Only delete on error if we allocated
if( fPlaybackDeviceAllocated && *audioPlaybackDevice != NULL ) { delete *audioPlaybackDevice; *audioPlaybackDevice = NULL; }
Diagnostics_Write( DVF_ERRORLEVEL, "Full Duplex Init Result = 0x%x", hr );
return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "FindPeak8Bit"
// FindPeak8Bit
//
// This function determines what the peak for a buffer
// of 8 bit audio is. Peak is defined as the loudest
// sample in a set of audio data rated on a scale of
// between 0 and 100.
//
// Parameters:
// BYTE *data -
// Pointer to the buffer containing the audio data
// to find the peak of.
// DWORD frameSize -
// The size in bytes of the audio data we are
// checking.
//
// Returns:
// BYTE -
// The peak of the audio buffer, a value between 0 and 100.
//
BYTE FindPeak8Bit( const BYTE *data, DWORD frameSize ) { BYTE peak = 0; int tmpData;
for( int index = 0; index < frameSize; index++ ) { tmpData = data[index];
tmpData -= 0x80;
if( tmpData < 0 ) tmpData *= -1;
if( tmpData > peak ) { peak = (unsigned char) tmpData; } }
tmpData = peak * 100 / 0x7F;
return (BYTE) tmpData; }
#undef DPF_MODNAME
#define DPF_MODNAME "FindPeak16Bit"
// FindPeak16Bit
//
// This function determines what the peak for a buffer
// of 16 bit audio is. Peak is defined as the loudest
// sample in a set of audio data rated on a scale of
// between 0 and 100.
//
// Parameters:
// BYTE *data -
// Pointer to the buffer containing the audio data
// to find the peak of.
// DWORD frameSize -
// The size in bytes of the audio data we are
// checking.
//
// Returns:
// BYTE -
// The peak of the audio buffer, a value between 0 and 100.
//
BYTE FindPeak16Bit( const short *data, DWORD frameSize ) { int peak, tmpData;
frameSize /= 2; peak = 0; for( int index = 0; index < frameSize; index++ ) { tmpData = data[index];
if( tmpData < 0 ) { tmpData *= -1; }
if( tmpData > peak ) { peak = tmpData; } }
tmpData = (peak * 100) / 0x7FFF;
return (BYTE) tmpData; }
#undef DPF_MODNAME
#define DPF_MODNAME "FindPeak"
// FindPeak
//
// This function determines what the peak for a buffer
// of 8 or 16 bit audio is. Peak is defined as the loudest
// sample in a set of audio data rated on a scale of
// between 0 and 100.
//
// Parameters:
// BYTE *data -
// Pointer to the buffer containing the audio data
// to find the peak of.
// DWORD frameSize -
// The size in bytes of the audio data we are
// checking.
// BOOL eightBit -
// Determins if the buffer is 8 bit or not. Set to
// TRUE for 8 bit data, FALSE for 16 bit data.
//
// Returns:
// BYTE -
// The peak of the audio buffer, a value between 0 and 100.
//
BYTE FindPeak( BYTE *data, DWORD frameSize, BOOL eightBit ) { if( eightBit ) { return FindPeak8Bit( data, frameSize ); } else { return FindPeak16Bit( (signed short *) data, frameSize ); } }
|