> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用 XAudio2 播放音效

> 使用 XAudio2 播放音效

在 XBOX One 上使用 `XAudio2` 載入並播放 .wav 檔案。

下列各節說明如何在 XBOX One 開發套件上使用 `XAudio2` 載入並播放音效。

* [重要的 XAudio2 資料類型](#ID4ELB)
* [初始化 XAudio2](#ID4EXC)
* [載入 .wav 檔案](#ID4E1D)
* [設定 .wav 檔案的檔案路徑](#ID4E2H)
* [播放 .wav 檔案](#ID4EAF)
* [終止 .wav 檔案](#ID4E2F)

如需可運作的 `XAudio2` 範例，請從 Microsoft Game Development Kit (GDK) 範例下載 SimplePlaySound 範例。

<a id="ID4ELB" />

## 重要的 XAudio2 資料類型

`XAudio2` 提供數種資料類型，協助您在 XBOX One 上播放音效。若要播放 .wav 檔案，您至少需要下列資料類型。

* `IXAudio2`：這是 `XAudio2` 物件的介面，此物件會管理所有音訊引擎狀態、音訊處理執行緒、語音圖形等。

* `IXAudio2SourceVoice`：使用來源語音將音訊資料提交至 `XAudio2` 處理管線。語音資料必須傳送至主控語音才能被聽見。

* `IXAudio2MasteringVoice`：使用此資料類型來代表音訊輸出裝置。資料緩衝區無法直接提交至主控語音。不過，提交至其他類型語音的資料必須導向至主控語音才能被聽見。

此外，您可能會發現下列資料類型很實用。

* `PlaySoundVoiceContext`：使用此資料類型在處理後釋放音訊緩衝區。

* `IXAudio2VoiceCallback`：此資料類型包含在特定 `IXAudio2SourceVoice` 中發生某些事件時通知用戶端的方法。

<a id="ID4EXC" />

## 初始化 XAudio2

`CoInitializeEx()` 會初始化元件物件模型 (COM)，供目前的執行緒使用。將第一個參數設定為 `NULL`。將第二個參數設定為 `COINIT_MULTITHREADED`。

`XAudio2Create()` 會建立新的 `XAudio2` 物件，並傳回其 `IXAudio2` 介面的指標。請確定 `XAUDIO2_PROCESSOR` 設定為有效值。建議使用 `XAUDIO2_USE_DEFAULT_PROCESSOR` 值，讓作業系統根據硬體平台選擇理想的處理器。

`IXAudio2::CreateMasteringVoice()` 會建立並設定主控語音，並以使用者提供的指標指向它。

#### C++

```cpp theme={null}
CoInitializeEx( NULL, COINIT_MULTITHREADED );

// Create an XAudio2 device.
DX::ThrowIfFailed( XAudio2Create( &m_pXAudio2, 0, XAUDIO2_USE_DEFAULT_PROCESSOR, NULL ) );

// Create an XAudio2 mastering voice, and store the result.
DX::ThrowIfFailed( m_pXAudio2->CreateMasteringVoice( &m_pMasteringVoice ) );  
```

<a id="ID4E1D" />

## 載入 .wav 檔案

若要存取音訊檔案，請使用 `WaveFile` 類別的執行個體。

\* 若要開啟 .wav 檔案並擷取儲存在檔案標頭中的部分資訊，請呼叫 `WaveFile::Open(LPCWSTR strFileName)`。

* 若要判斷 .wav 檔案的格式，請呼叫 `WaveFile::GetFormat()`。
* 若要判斷 .wav 檔案中的位元組數和樣本數，請呼叫 `WaveFile::GetDuration()`。
* 若要將樣本資料讀入記憶體，請呼叫 `WaveFile::ReadSample()`。

#### C++

```cpp theme={null}
// Read the .wav file.
WaveFile WaveFile;

// Append the file name and location to the end of the installation location.
WCHAR FilenameAndLocation[ 1024 ];
_snwprintf_s( FilenameAndLocation, _countof( FilenameAndLocation ), _TRUNCATE, L"%s%s", g_strCommonFileRoot, szFilename );

DX::ThrowIfFailed( WaveFile.Open( FilenameAndLocation ) );

// Read the format header.
BYTE header[64];
WAVEFORMATEX* pbWfx = reinterpret_cast<WAVEFORMATEX*>(header);

DX::ThrowIfFailed( WaveFile.GetFormat( pbWfx, sizeof(header) ) );

// Calculate the number of bytes and samples in the .wav file. 
DWORD cbWaveSize = WaveFile.GetDuration();

// Read the sample data into memory.
BYTE* pbWaveData = new BYTE[ cbWaveSize ];
DX::ThrowIfFailed( WaveFile.ReadSample( 0, pbWaveData, cbWaveSize, &cbWaveSize ) );  
```

<a id="ID4E2H" />

## 設定 .wav 檔案的檔案路徑

若要載入並使用音訊檔案，請使用下列程式碼在本機裝置上尋找專案的安裝位置。將安裝位置儲存在字串中。將音訊檔案的位置附加到安裝位置字串的結尾。

#### C++

```cpp theme={null}
std::wstring installFolder = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();  
```

<a id="ID4EAF" />

## 播放 .wav 檔案

建立 `IXAudio2::CreateSourceVoice()` 類別，然後使用它將音訊資料提交至 `XAudio2` 處理管線。若要讓語音資料被聽見，您必須將其直接傳送至主控語音，或透過中繼子混音語音傳送。若要儲存音訊檔案的詳細資料，請建立 `XAUDIO2_BUFFER`。

建立並初始化 `XAudio2` 緩衝區和來源語音之後，請呼叫 `IXAudio2SourceVoice::SubmitSourceBuffer()` 將音訊緩衝區加入語音輸入佇列。請注意，`XAUDIO2_BUFFER::pAudioData` 所指向的音訊資料必須保持有效，直到 `XAudio2` 完成播放緩衝區的內容為止。

填入語音輸入佇列之後，請呼叫 `IXAudio2SourceVoice::Start()` 以播放佇列中的下一個音效。

#### C++

```cpp theme={null}
// Play the .wav file by using a new XAudio2SourceVoice.
// Create the source voice.
DX::ThrowIfFailed( pXaudio2->CreateSourceVoice( &m_pSourceVoice, pbWfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &m_VoiceContext ) );

// Submit the .wav sample data by using an XAUDIO2_BUFFER structure.
XAUDIO2_BUFFER buffer = {0};
buffer.pAudioData     = pbWaveData;
buffer.Flags          = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes     = cbWaveSize;
buffer.pContext       = pbWaveData;

// Add the audio buffer to the voice input queue.
DX::ThrowIfFailed( m_pSourceVoice->SubmitSourceBuffer( &buffer ) );

// Play the next audio buffer in the queue.
DX::ThrowIfFailed( m_pSourceVoice->Start( 0 ) );  
```

<a id="ID4E2F" />

## 終止 .wav 檔案

若要判斷 .wav 檔案是否已播放完畢，您需要來源語音的目前狀態。建立 `XAUDIO2_VOICE_STATE` 結構，然後呼叫 `IXAudio2SourceVoice::GetState()`。如果音訊已播放完畢，請呼叫 `IXAudio2SourceVoice::DestroyVoice()`。

#### C++

```cpp theme={null}
// Determine whether the sound effect has been played to completion, and handle an appropriate termination.
XAUDIO2_VOICE_STATE state;
m_pSourceVoice->GetState( &state, XAUDIO2_VOICE_NOSAMPLESPLAYED );
if( state.BuffersQueued == 0 )
{
  // Destroy the current sound effect.
  m_pSourceVoice->DestroyVoice();
}  
```

## 另請參閱

[XAudio2 概觀](/zh-TW/build/console-features/audio/overviews/xaudio2-overview)
[ADPCM 概觀](/zh-TW/build/console-features/audio/overviews/adpcm-overview)
[ADPCM 命令列編碼器](/zh-TW/build/console-features/audio/tools/adpcmencoder-tools)


## Related topics

- [使用 XAudio2 播放声音](/zh-CN/build/console-features/audio/overviews/xaudio2-play-sound.md)
- [XAudio2CreateWithSharedContexts](/zh-CN/reference/audio/xaudio2xbox/functions/xaudio2createwithsharedcontexts.md)
- [ADPCM 概述](/zh-CN/build/console-features/audio/overviews/adpcm-overview.md)
- [XAudio2 帮助程序 API](/zh-CN/reference/audio/atoc-xaudio2helperapis-reference.md)
- [ADPCM 命令行编码器](/zh-CN/build/console-features/audio/tools/adpcmencoder-tools.md)
