Beispiel #1
0
CXAudio2::IntCacheIterator CXAudio2::_PreCacheResource(int ID)
{
	// File already in cache
	IntCacheIterator i = resourceCache.find(ID);

	if (i != resourceCache.end())
		return i;

	// Load WAV (PCM, ADPCM, xWMA).  OGG not supported via resources.

	// Wave file reading class; from the SDK samples
	CWaveFile wav;

	hr = wav.Open(MAKEINTRESOURCE(ID), 0, WAVEFILE_READ, true);

	if (FAILED(hr)) throw CXAudio2Error(hr, "Failed to load file from disk.  Check the filename exists and that the file is of a supported format.");

	DWORD size = wav.GetSize();
	BYTE* pBuffer = new BYTE[size];

	// Read WAV data
	hr = wav.Read(pBuffer, size, &size);

	if (FAILED(hr)) {
		delete[] pBuffer;
		throw CXAudio2Error(hr, "Failed to read WAV data.  Check the WAV file encoding is supported.");
	}

	// Make a cache entry of the WAV data now
	// Avoid invocation of CacheEntry copy constructor which copies pBuffer's memory
	//fileCache[filename] = CacheEntry(pwfx, pBuffer, size);
	resourceCache[ID] = CacheEntry(this);
	i = resourceCache.find(ID);
	CacheEntry& ce = i->second;

	// xWMA
	if (wav.m_bIsXWMA) {

		ce.SetWma((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size, wav.m_nPacketCount, wav.m_aDecodedPacketCumulativeBytes);	
	}
	// PCM or ADPCM
	else {
		// Cache entry now has reference count 1 and responsibility for deleting pBuffer
		ce.Set((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size);
	}
	ce.refCount = 0;	// Just precached, nothing referencing yet
	totalCacheSize += size;

	return i;
}
void GameAudio::registerMusic(MusicTypes muType, LPWSTR wavFilePath)
{
	CWaveFile wav;	/// wav file will be destroyed at the end of this function

					//// All the file references are rooted at the directory "Apps/Rebelle/data"
	bool wavOpenSuccess = SUCCEEDED(wav.Open(wavFilePath, 0, WAVEFILE_READ));

	WAVEFORMATEX *format = wav.GetFormat();
	unsigned long wavSize = wav.GetSize();
	unsigned char *wavData = new unsigned char[wavSize];

	bool wavReadSuccess = SUCCEEDED(wav.Read(wavData, wavSize, &wavSize));

	IXAudio2SourceVoice* srcVoice;	/// this will be stored in the map of this class

	bool csvSuccess = SUCCEEDED(xAudio2Engine->CreateSourceVoice(&srcVoice, format,
		0, XAUDIO2_DEFAULT_FREQ_RATIO, 0, 0, 0));

	XAUDIO2_BUFFER *bufferPrototype = new XAUDIO2_BUFFER();
	bufferPrototype->pAudioData = wavData;
	bufferPrototype->Flags = XAUDIO2_END_OF_STREAM;
	bufferPrototype->AudioBytes = wavSize;

	//// register sound buffer prototype
	musicBufferPrototypeMap[muType] = bufferPrototype;

	//// mark this sourceVoice as registered
	musicRegistrationMap[muType] = true;

	//// store the source voice
	musicMap[muType] = srcVoice;
}
Beispiel #3
0
//计算WAV文件播放时间,这个时间由数据大小和格式共同决定
DWORD GetSoundLength(LPSTR strFileName){
	CWaveFile* pWav;
	DWORD dwLen = 0;
	DWORD dwSize;
	WAVEFORMATEX* pwfx;
	
	pWav = new CWaveFile();
	if (SUCCEEDED(pWav->Open(strFileName, NULL, WAVEFILE_READ)))){
		pwfx = pWav->GetFormat();
		dwSize = pWav->GetSize();
		dwLen = (DWORD)(1000 * dwSize / pwfx->nAvgBytesPerSec);
		pWav->Close();
	}
	if (pWav)
		delete pWav;
	return dwLen;
}
//-----------------------------------------------------------------------------
// Name: ValidateWaveFile()
// Desc: Open the wave file with the helper 
//       class CWaveFile to make sure it is valid
//-----------------------------------------------------------------------------
HRESULT ValidateWaveFile( HWND hDlg, TCHAR* strFileName )
{
    HRESULT hr;
    CWaveFile waveFile;

    if( -1 == GetFileAttributes(strFileName) )
        return E_FAIL;
    
    // Load the wave file
    if( FAILED( hr = waveFile.Open( strFileName, NULL, WAVEFILE_READ ) ) )
    {        
        waveFile.Close();
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Bad wave file.") );
        return DXTRACE_ERR( TEXT("Open"), hr );
    }
    else // The load call succeeded
    {
        WAVEFORMATEX* pwfx = waveFile.GetFormat();
        if( pwfx->wFormatTag != WAVE_FORMAT_PCM )
        {
            // Sound must be PCM when using DSBCAPS_CTRLFX            
            SAFE_RELEASE( g_pIGargle );
            SAFE_DELETE( g_pSound );
            SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be PCM for effects control.") );
            SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );
            return S_FALSE;
        }
  
        // Update the UI controls to show the sound as the file is loaded
        waveFile.Close();

        EnablePlayUI( hDlg, TRUE );
        SetDlgItemText( hDlg, IDC_FILENAME, strFileName );
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded.") );
        strcpy( g_strWaveFileName, strFileName );

        // Get the samples per sec from the wave file
        DWORD dwSamplesPerSec = waveFile.m_pwfx->nSamplesPerSec;
        return S_OK;
    }
}
/*
=================
- Play sound.
=================
*/
void cXAudio::playSound(LPWSTR theFilename, bool pLoop )					// Play sound
{
	HRESULT hResult;
	CWaveFile wavFile;

	wavFile.Open( theFilename, NULL, WAVEFILE_READ );
    // Get format of wave file
    WAVEFORMATEX* pwfx = wavFile.GetFormat();

    // Calculate how many bytes and samples are in the wave
    DWORD cbWaveSize = wavFile.GetSize();

    // Read the sample data into memory
    BYTE* pbWaveData = new BYTE[ cbWaveSize ];

    wavFile.Read( pbWaveData, cbWaveSize, &cbWaveSize );

    // Submit the wave sample data using an XAUDIO2_BUFFER structure
    XAUDIO2_BUFFER buffer = {0};
    buffer.pAudioData = pbWaveData;
    buffer.Flags = XAUDIO2_END_OF_STREAM;  // tell the source voice not to expect any data after this buffer
    buffer.AudioBytes = cbWaveSize;
	if (pLoop)
	{
		buffer.LoopLength = 0;
		buffer.LoopCount = XAUDIO2_LOOP_INFINITE;
	}

    // Create the source voice
    if( FAILED( hResult = mXAudio2->CreateSourceVoice( &mSourceVoice, pwfx ) ) )
    {
        OutputDebugString("Error creating source voice\n");
        delete pbWaveData;
    }
	else
	{
		mSourceVoice->SubmitSourceBuffer(&buffer);
		mSourceVoice->Start(0, XAUDIO2_COMMIT_NOW );
	}
}
Beispiel #6
0
/* Loads a sound with the specified id and path
 */
void XAudioSoundSystem::OnLoadSound(uint32 soundID, const char* szSoundPath)
{
	if(mSounds[soundID] != NULL)
		return;

	HRESULT hr = S_OK;

	char szFullPath[1024];
	sprintf_s(szFullPath, 1024, "Data/Win32/%s", szSoundPath);
		
    size_t convertedChars = 0;
    wchar_t wpath[1024];
	mbstowcs_s(&convertedChars, wpath, strlen(szFullPath) + 1, szFullPath, _TRUNCATE);

    //
    // Read in the wave file
    //
    CWaveFile wav;
    if( FAILED( hr = wav.Open( wpath, NULL, WAVEFILE_READ ) ) )
    {
        wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, wpath );
        return;
    }

    // Get format of wave file
    WAVEFORMATEX* pwfx = wav.GetFormat();

    // Calculate how many bytes and samples are in the wave
    DWORD cbWaveSize = wav.GetSize();

    // Read the sample data into memory
    BYTE* pbWaveData = new BYTE[ cbWaveSize ];

    if( FAILED( hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) )
    {
        wprintf( L"Failed to read WAV data: %#X\n", hr );
        SAFE_DELETE_ARRAY( pbWaveData );
        return;
    }

    //
    // Play the wave using a XAudio2SourceVoice
    //

    // Create the source voice
    IXAudio2SourceVoice* pSourceVoice;
    if( FAILED( hr = mXAudio2->CreateSourceVoice( &pSourceVoice, pwfx ) ) )
    {
        wprintf( L"Error %#X creating source voice\n", hr );
        SAFE_DELETE_ARRAY( pbWaveData );
        return;
    }

    // Submit the wave sample data using an XAUDIO2_BUFFER structure
    XAUDIO2_BUFFER buffer = {0};
    buffer.pAudioData = pbWaveData;
    buffer.Flags = XAUDIO2_END_OF_STREAM;  // tell the source voice not to expect any data after this buffer
    buffer.AudioBytes = cbWaveSize;

    if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
    {
        wprintf( L"Error %#X submitting source buffer\n", hr );
        pSourceVoice->DestroyVoice();
        SAFE_DELETE_ARRAY( pbWaveData );
        return;
    }

	Sound* pSound = new Sound();
	pSound->mVoice = pSourceVoice;
	pSound->mAudioBuffer = buffer;
	pSound->mData = pbWaveData;
	pSound->mStarted = false;

	mSounds[soundID] = pSound;
}	
Beispiel #7
0
CXAudio2::StringCacheIterator CXAudio2::_PreCacheFile(std::string filename)
{
	// File already in cache
	StringCacheIterator i = fileCache.find(filename);

	if (i != fileCache.end())
		return i;

	// Check for OGG file
	std::string ext = filename;
	ext.erase(0, ext.length() - 4);

	// Load OGG file
	if (_stricmp(ext.c_str(), ".ogg") == 0 || _stricmp(ext.c_str(), ".oga") == 0) {
#ifdef XAUDIO2_OGGVORBIS
		FILE* f = fopen(filename.c_str(), "rb");

		if (f == NULL)
			throw CXAudio2Error(E_FAIL, std::string("Error loading file '") + filename + "'.  Check the file exists and is valid.");

		OggVorbis_File oggFile;
		ov_open(f, &oggFile, NULL, 0);	// Takes control of f; no need to call fclose()
		vorbis_info* pInfo = ov_info(&oggFile, -1);

		int endian = 0;             // 0 for Little-Endian, 1 for Big-Endian
		int bytesRead = 0;
		int bitStream;

		// Read the file data
		vector<char> oggData;
		char readbuffer[XAUDIO2_OGGVORBIS_BUFFERSIZE];

		do {
			// Read up to a buffer's worth of decoded sound data
			bytesRead = ov_read(&oggFile, readbuffer, XAUDIO2_OGGVORBIS_BUFFERSIZE, endian, 2, 1, &bitStream);

			// Append to end of buffer
		   oggData.insert(oggData.end(), readbuffer, readbuffer + bytesRead);
		}
		while (bytesRead > 0);

		// Fill out a WAVEFORMATEX for the decompressed OGG
		WAVEFORMATEX wfx;
		memset(&wfx, 0, sizeof(WAVEFORMATEX));
		wfx.cbSize = sizeof(WAVEFORMATEX);
		wfx.nChannels = pInfo->channels;
		wfx.nSamplesPerSec = pInfo->rate;
		wfx.wBitsPerSample = 16;		// OGG is always 16 bit
		wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nChannels * 2;
		wfx.nBlockAlign = 2 * wfx.nChannels;
		wfx.wFormatTag = WAVE_FORMAT_PCM;

		ov_clear(&oggFile);

		// Copy the vector which is local scope and will deallocate: the cache takes responsibility for deleting
		BYTE* pBuffer = new BYTE[oggData.size()];
		memcpy(pBuffer, &(oggData.front()), oggData.size());

		// Make a cache entry of the WAV data now
		// Avoid invocation of CacheEntry copy constructor which copies pBuffer's memory
		//fileCache[filename] = CacheEntry(pwfx, pBuffer, size);
		fileCache[filename] = CacheEntry(this);
		i = fileCache.find(filename);
		CacheEntry& ce = i->second;
		ce.Set((GENERICWAVEFILE*)&wfx, pBuffer, oggData.size());
		ce.refCount = 0;	// Just precached, nothing referencing yet
		ce.isOgg = true;
		totalCacheSize += oggData.size();

		return i;
#else
		// Not built with OGG Vorbis support; throw an error
		throw CXAudio2Error(E_FAIL, "OGG Vorbis is not supported by this version of XAudio2.");
#endif
	}
	else {
		// Load WAV (PCM, ADPCM, xWMA)

		// Wave file reading class; from the SDK samples
		CWaveFile wav;

		// Dumb function definition needs an LPSTR, not an LPCSTR
		TCHAR* fileNameStr = new TCHAR[filename.size() + 1];
		memcpy(fileNameStr, filename.c_str(), filename.size() + 1);	// copy null terminator in
		hr = wav.Open(fileNameStr, 0, WAVEFILE_READ);
		delete[] fileNameStr;

		if (FAILED(hr)) throw CXAudio2Error(hr, "Failed to load file from disk.  Check the filename exists and that the file is of a supported format.");

		DWORD size = wav.GetSize();
		BYTE* pBuffer = new BYTE[size];

		// Read WAV data
		hr = wav.Read(pBuffer, size, &size);

		if (FAILED(hr)) {
			delete[] pBuffer;
			throw CXAudio2Error(hr, "Failed to read WAV data.  Check the WAV file encoding is supported.");
		}

		// Make a cache entry of the WAV data now
		// Avoid invocation of CacheEntry copy constructor which copies pBuffer's memory
		//fileCache[filename] = CacheEntry(pwfx, pBuffer, size);
		fileCache[filename] = CacheEntry(this);
		i = fileCache.find(filename);
		CacheEntry& ce = i->second;

		// xWMA
		if (wav.m_bIsXWMA) {

			ce.SetWma((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size, wav.m_nPacketCount, wav.m_aDecodedPacketCumulativeBytes);	
		}
		// PCM or ADPCM
		else {
			// Cache entry now has reference count 1 and responsibility for deleting pBuffer
			ce.Set((GENERICWAVEFILE*)wav.GetFormat(), pBuffer, size);
		}
		ce.refCount = 0;	// Just precached, nothing referencing yet
		totalCacheSize += size;

		return i;
	}
}
Beispiel #8
0
//-----------------------------------------------------------------------------
// Name: OnOpenSoundFile()
// Desc: Called when the user requests to open a sound file
//-----------------------------------------------------------------------------
VOID OnOpenSoundFile( HWND hDlg ) 
{
    GUID    guid3DAlgorithm = GUID_NULL;
    int     nResult;
    HRESULT hr; 

    static TCHAR strFileName[MAX_PATH] = TEXT("");
    static TCHAR strPath[MAX_PATH] = TEXT("");

    // Setup the OPENFILENAME structure
    OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL,
                         TEXT("Wave Files\0*.wav\0All Files\0*.*\0\0"), NULL,
                         0, 1, strFileName, MAX_PATH, NULL, 0, strPath,
                         TEXT("Open Sound File"),
                         OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0,
                         TEXT(".wav"), 0, NULL, NULL };

    // Get the default media path (something like C:\WINDOWS\MEDIA)
    if( '\0' == strPath[0] )
    {
        GetWindowsDirectory( strPath, MAX_PATH );
        if( strcmp( &strPath[strlen(strPath)], TEXT("\\") ) )
            strcat( strPath, TEXT("\\") );
        strcat( strPath, TEXT("MEDIA") );
    }

    if( g_pSound )
    {
        g_pSound->Stop();
        g_pSound->Reset();
    }

    // Update the UI controls to show the sound as loading a file
    EnableWindow( GetDlgItem( hDlg, IDC_PLAY ), FALSE);
    EnableWindow( GetDlgItem( hDlg, IDC_STOP ), FALSE);
    SetDlgItemText( hDlg, IDC_STATUS, TEXT("Loading file...") );

    // Stop the timer while dialogs are displayed
    g_bAllowMovementTimer = FALSE;

    // Display the OpenFileName dialog. Then, try to load the specified file
    if( TRUE != GetOpenFileName( &ofn ) )
    {
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Load aborted.") );
        g_bAllowMovementTimer = TRUE;
        return;
    }

    SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );

    // Free any previous sound, and make a new one
    SAFE_DELETE( g_pSound );

    CWaveFile waveFile;
    waveFile.Open( strFileName, NULL, WAVEFILE_READ );
    WAVEFORMATEX* pwfx = waveFile.GetFormat();
    if( pwfx == NULL )
    {
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Invalid wave file format.") );
        return;
    }

    if( pwfx->nChannels > 1 )
    {
        // Too many channels in wave.  Sound must be mono when using DSBCAPS_CTRL3D
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be mono for 3D control.") );
        SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );
        return;
    }

    if( pwfx->wFormatTag != WAVE_FORMAT_PCM )
    {
        // Sound must be PCM when using DSBCAPS_CTRL3D
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be PCM for 3D control.") );
        SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );
        return;
    }

    // Get the software DirectSound3D emulation algorithm to use
    // Ask the user for this sample, so display the algorithm dialog box.
    nResult = (int)DialogBox( NULL, MAKEINTRESOURCE(IDD_3D_ALGORITHM), 
                              NULL, AlgorithmDlgProc );
    switch( nResult )
    {
    case -1: // User canceled dialog box
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Load aborted.") );
        SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );
        return;

    case 0: // User selected DS3DALG_NO_VIRTUALIZATION  
        guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
        break;

    case 1: // User selected DS3DALG_HRTF_FULL  
        guid3DAlgorithm = DS3DALG_HRTF_FULL;
        break;

    case 2: // User selected DS3DALG_HRTF_LIGHT
        guid3DAlgorithm = DS3DALG_HRTF_LIGHT;
        break;
    }

    // Load the wave file into a DirectSound buffer
    hr = g_pSoundManager->Create( &g_pSound, strFileName, DSBCAPS_CTRL3D, guid3DAlgorithm );  
    if( FAILED( hr ) || hr == DS_NO_VIRTUALIZATION )
    {
        DXTRACE_ERR_NOMSGBOX( TEXT("Create"), hr );
        if( DS_NO_VIRTUALIZATION == hr )
        {
            MessageBox( hDlg, "The 3D virtualization algorithm requested is not supported under this "
                        "operating system.  It is available only on Windows 2000, Windows ME, and Windows 98 with WDM "
                        "drivers and beyond.  Creating buffer with no virtualization.", 
                        "DirectSound Sample", MB_OK );
        }

        // Unknown error, but not a critical failure, so just update the status
        SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Could not create sound buffer.") );
        return; 
    }

    // Get the 3D buffer from the secondary buffer
    if( FAILED( hr = g_pSound->Get3DBufferInterface( 0, &g_pDS3DBuffer ) ) )
    {
        DXTRACE_ERR( TEXT("Get3DBufferInterface"), hr );
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("Could not get 3D buffer.") );
        SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );
        return;
    }

    // Get the 3D buffer parameters
    g_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
    g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams );

    // Set new 3D buffer parameters
    g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
    g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE );

    DSBCAPS dsbcaps;
    ZeroMemory( &dsbcaps, sizeof(DSBCAPS) );
    dsbcaps.dwSize = sizeof(DSBCAPS);

    LPDIRECTSOUNDBUFFER pDSB = g_pSound->GetBuffer( 0 );
    pDSB->GetCaps( &dsbcaps );
    if( ( dsbcaps.dwFlags & DSBCAPS_LOCHARDWARE ) != 0 )
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded using hardware mixing.") );
    else
        SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded using software mixing.") );

    // Update the UI controls to show the sound as the file is loaded
    SetDlgItemText( hDlg, IDC_FILENAME, strFileName );
    EnablePlayUI( hDlg, TRUE );

    g_bAllowMovementTimer = TRUE;

    // Remember the path for next time
    strcpy( strPath, strFileName );
    char* strLastSlash = strrchr( strPath, '\\' );
    strLastSlash[0] = '\0';

    // Set the slider positions
    SetSlidersPos( hDlg, 0.0f, 0.0f, ORBIT_MAX_RADIUS, ORBIT_MAX_RADIUS*2.0f );
    OnSliderChanged( hDlg );
}