Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dieses Thema ist Teil der Tutorialreihe : Erstelle ein einfaches Spiel für die Universelle Windows-Plattform (UWP) mit DirectX. Das Thema an dieser Verknüpfung legt den Kontext für die Datenreihe fest.
In diesem Thema erstellen wir eine einfache Sound-Engine mit den XAudio2--APIs. Wenn Sie mit XAudio2noch nicht vertraut sind, haben wir unter den Audiokonzepteneine kurze Einführung aufgenommen.
Hinweis
Wenn Sie den neuesten Spielcode für dieses Beispiel nicht heruntergeladen haben, wechseln Sie zu Direct3D-Beispielspiel. Dieses Beispiel ist Teil einer großen Sammlung von UWP-Featurebeispielen. Anweisungen zum Herunterladen des Beispiels finden Sie unter Beispielanwendungen für die Windows-Entwicklung.
Zielsetzung
Fügen Sie Sounds mit XAudio2dem Beispielspiel hinzu.
Definieren des Audiomotors
Im Beispielspiel werden die Audioobjekte und -verhaltensweisen in drei Dateien definiert:
- Audio.h/.cpp: Definiert das Audio--Objekt, das die XAudio2- Ressourcen für die Soundwiedergabe enthält. Außerdem wird die Methode zum Anhalten und Fortsetzen der Audiowiedergabe definiert, wenn das Spiel angehalten oder deaktiviert wird.
- MediaReader.h/.cpp: Definiert die Methoden zum Lesen von Audio- .wav Dateien aus dem lokalen Speicher.
- SoundEffect.h/.cpp: Definiert ein Objekt für die In-Game-Soundwiedergabe.
Überblick
Es gibt drei Hauptkomponenten für die Einrichtung der Audiowiedergabe in Ihrem Spiel.
Sie sind alle in der Simple3DGame::Initialize-Methode definiert. Lassen Sie uns also zunächst diese Methode untersuchen und dann in den einzelnen Abschnitten ausführlichere Details einsehen.
Nach dem Einrichten erfahren wir, wie die Soundeffekte ausgelöst werden, um sie abzuspielen. Weitere Informationen finden Sie unter Wiedergeben des Sounds.
Simple3DGame::Initialize-Methode
In Simple3DGame::Initialize, wobei m_controller und m_renderer ebenfalls initialisiert sind, richten wir das Audiomodul ein und bereiten sie für die Wiedergabe von Sounds bereit.
- Erstellen Sie m_audioController, der eine Instanz der Klasse Audio ist.
- Erstellen Sie mit der Methode Audio::CreateDeviceIndependentResources die erforderlichen Audioressourcen. Hier wurden zwei XAudio2--Objekte erstellt: ein Musik-Engine-Objekt und ein Sound-Engine-Objekt sowie jeweils eine Masterstimme für jedes dieser Objekte. Das Musikmodulobjekt kann verwendet werden, um Hintergrundmusik für Ihr Spiel wiederzugeben. Die Sound-Engine kann verwendet werden, um Soundeffekte in Ihrem Spiel wiederzugeben. Weitere Informationen finden Sie unter Erstellen und Initialisieren der Audioressourcen.
- Erstellen Sie mediaReader-, der eine Instanz der MediaReader--Klasse ist. MediaReader, eine Hilfsklasse für die SoundEffect Klasse, liest kleine Audiodateien synchron vom Dateispeicherort aus und gibt Sounddaten als Bytearray zurück.
- Verwenden Sie MediaReader::LoadMedia, um Sounddateien von seinem Speicherort zu laden und eine targetHitSound- Variable zu erstellen, um die geladenen .wav Sounddaten zu speichern. Weitere Informationen finden Sie unter Laden der Audiodatei.
Soundeffekte sind dem Spielobjekt zugeordnet. Wenn also eine Kollision mit diesem Spielobjekt auftritt, wird der Soundeffekt ausgelöst und abgespielt. In diesem Beispielspiel haben wir Soundeffekte für die Munition (was wir zum Schießen von Zielen verwenden) und für das Ziel.
- In der GameObject Klasse gibt es eine HitSound--Eigenschaft, die verwendet wird, um den Soundeffekt dem Objekt zuzuordnen.
- Erstellen Sie eine neue Instanz der SoundEffect Klasse, und initialisieren Sie sie. Während der Initialisierung wird eine Quellstimme für den Soundeffekt erstellt.
- Diese Klasse gibt einen Sound mit einer Masterstimme ab, die aus der Audio Klasse bereitgestellt wird. Sounddaten werden mithilfe der MediaReader Klasse aus dem Dateispeicherort gelesen. Weitere Informationen finden Sie unter Ton einem Objekt zuordnen.
Hinweis
Der tatsächliche Trigger für die Wiedergabe des Sounds wird durch die Bewegung und Kollision dieser Spielobjekte bestimmt. Daher wird der Aufruf zur tatsächlichen Wiedergabe dieser Sounds in der Simple3DGame::UpdateDynamics-Methode definiert. Weitere Informationen finden Sie unter Wiedergeben des Sounds.
void Simple3DGame::Initialize(
_In_ std::shared_ptr<MoveLookController> const& controller,
_In_ std::shared_ptr<GameRenderer> const& renderer
)
{
// The following member is defined in the header file:
// Audio m_audioController;
...
// Create the audio resources needed.
// Two XAudio2 objects are created - one for music engine,
// the other for sound engine. A mastering voice is also
// created for each of the objects.
m_audioController.CreateDeviceIndependentResources();
m_ammo.resize(GameConstants::MaxAmmo);
...
// Create a media reader which is used to read audio files from its file location.
MediaReader mediaReader;
auto targetHitSoundX = mediaReader.LoadMedia(L"Assets\\hit.wav");
// Instantiate the targets for use in the game.
// Each target has a different initial position, size, and orientation.
// But share a common set of material properties.
for (int a = 1; a < GameConstants::MaxTargets; a++)
{
...
// Create a new sound effect object and associate it
// with the game object's (target) HitSound property.
target->HitSound(std::make_shared<SoundEffect>());
// Initialize the sound effect object with
// the sound effect engine, format of the audio wave, and audio data
// During initialization, source voice of this sound effect is also created.
target->HitSound()->Initialize(
m_audioController.SoundEffectEngine(),
mediaReader.GetOutputWaveFormatEx(),
targetHitSoundX
);
...
}
// Instantiate a set of spheres to be used as ammunition for the game
// and set the material properties of the spheres.
auto ammoHitSound = mediaReader.LoadMedia(L"Assets\\bounce.wav");
for (int a = 0; a < GameConstants::MaxAmmo; a++)
{
m_ammo[a] = std::make_shared<Sphere>();
m_ammo[a]->Radius(GameConstants::AmmoRadius);
m_ammo[a]->HitSound(std::make_shared<SoundEffect>());
m_ammo[a]->HitSound()->Initialize(
m_audioController.SoundEffectEngine(),
mediaReader.GetOutputWaveFormatEx(),
ammoHitSound
);
m_ammo[a]->Active(false);
m_renderObjects.push_back(m_ammo[a]);
}
...
}
Erstellen und Initialisieren der Audioressourcen
- Verwenden Sie XAudio2Create, eine XAudio2-API, um zwei neue XAudio2-Objekte zu erstellen, die die Musik- und Soundeffekt-Engines definieren. Diese Methode gibt einen Zeiger auf die IXAudio2 Schnittstelle des Objekts zurück, die alle Audio-Engine-Zustände, den Audiobearbeitungsthread, den Sprachgraphen und mehr verwaltet.
- Nachdem die Engines instanziiert wurden, verwenden Sie IXAudio2::CreateMasteringVoice, um eine Masterstimme für jedes der Sound-Engine-Objekte zu erstellen.
Weitere Informationen finden Sie unter How to: Initialize XAudio2.
Audio::CreateDeviceIndependentResources-Methode
void Audio::CreateDeviceIndependentResources()
{
UINT32 flags = 0;
winrt::check_hresult(
XAudio2Create(m_musicEngine.put(), flags)
);
HRESULT hr = m_musicEngine->CreateMasteringVoice(&m_musicMasteringVoice);
if (FAILED(hr))
{
// Unable to create an audio device
m_audioAvailable = false;
return;
}
winrt::check_hresult(
XAudio2Create(m_soundEffectEngine.put(), flags)
);
winrt::check_hresult(
m_soundEffectEngine->CreateMasteringVoice(&m_soundEffectMasteringVoice)
);
m_audioAvailable = true;
}
Laden einer Audiodatei
Im Beispielspiel wird der Code zum Lesen von Audiodateien in MediaReader.h/cpp__ definiert. Um eine codierte .wav Audiodatei zu lesen, rufen Sie MediaReader::LoadMediaauf, und übergeben Sie den Dateinamen der .wav als Eingabeparameter.
Methode MediaReader::LoadMedia
Diese Methode verwendet die Media Foundation APIs, um die .wav-Audiodatei in einen Pulse-Code-Modulation (PCM)-Puffer einzulesen.
Quellleser einrichten
- Verwenden Sie MFCreateSourceReaderFromURL zum Erstellen eines Medienquellenlesers (IMFSourceReader).
- Verwenden Sie MFCreateMediaType, um ein Medientyp-(IMFMediaType)-Objekt (mediaType) zu erstellen. Sie stellt eine Beschreibung eines Medienformats dar.
- Geben Sie an, dass die Dekodierungsausgabe des mediaType-PCM-Audio ist, ein Audiotyp, den XAudio2- verwenden kann.
- Legt den dekodierten Ausgabemedientyp für den Quell-Reader fest, indem IMFSourceReader::SetCurrentMediaTypeaufgerufen wird.
Weitere Informationen dazu, warum wir den Quellleser verwenden, finden Sie unter Source Reader.
Beschreiben Sie das Datenformat des Audiodatenstroms
- Verwenden Sie IMFSourceReader::GetCurrentMediaType, um den aktuellen Medientyp für den Datenstrom abzurufen.
- Verwenden Sie IMFMediaType::MFCreateWaveFormatExFromMFMediaType, um den aktuellen Audiomedientyp in einen WAVEFORMATEX- Puffer zu konvertieren, wobei die Ergebnisse des früheren Vorgangs als Eingabe verwendet werden. Diese Struktur gibt das Datenformat des Wellenaudiodatenstroms an, der nach dem Laden von Audio verwendet wird.
Das WAVEFORMATEX--Format kann verwendet werden, um den PCM-Puffer zu beschreiben. Im Vergleich zur WAVEFORMATEXTENSIBLE-Struktur kann man damit nur eine Teilmenge der Audio-Wellenformate beschreiben. Weitere Informationen zu den Unterschieden zwischen WAVEFORMATEX und WAVEFORMATEXTENSIBLEfinden Sie unter Extensible Wave-Format Deskriptors.
Audio-Stream lesen
- Rufen Sie die Dauer des Audiodatenstroms in Sekunden ab, indem Sie IMFSourceReader::GetPresentationAttribute aufrufen und dann die Dauer in Byte konvertieren.
- Lesen Sie die Audiodatei als Stream ein, indem Sie IMFSourceReader::ReadSampleaufrufen. ReadSample liest den nächsten Sample aus der Medienquelle.
- Verwenden Sie IMFSample::ConvertToContiguousBuffer, um den Inhalt des Audio-Sample-Puffers (Sample) in ein Array (mediaBuffer) zu kopieren.
std::vector<byte> MediaReader::LoadMedia(_In_ winrt::hstring const& filename)
{
winrt::check_hresult(
MFStartup(MF_VERSION)
);
// Creates a media source reader.
winrt::com_ptr<IMFSourceReader> reader;
winrt::check_hresult(
MFCreateSourceReaderFromURL(
(m_installedLocationPath + filename).c_str(),
nullptr,
reader.put()
)
);
// Set the decoded output format as PCM.
// XAudio2 on Windows can process PCM and ADPCM-encoded buffers.
// When using MediaFoundation, this sample always decodes into PCM.
winrt::com_ptr<IMFMediaType> mediaType;
winrt::check_hresult(
MFCreateMediaType(mediaType.put())
);
// Define the major category of the media as audio. For more info about major media types,
// go to: https://msdn.microsoft.com/library/windows/desktop/aa367377.aspx
winrt::check_hresult(
mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio)
);
// Define the sub-type of the media as uncompressed PCM audio. For more info about audio sub-types,
// go to: https://msdn.microsoft.com/library/windows/desktop/aa372553.aspx
winrt::check_hresult(
mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM)
);
// Sets the media type for a stream. This media type defines that format that the Source Reader
// produces as output. It can differ from the native format provided by the media source.
// For more info, go to https://msdn.microsoft.com/library/windows/desktop/dd374667.aspx
winrt::check_hresult(
reader->SetCurrentMediaType(static_cast<uint32_t>(MF_SOURCE_READER_FIRST_AUDIO_STREAM), 0, mediaType.get())
);
// Get the current media type for the stream.
// For more info, go to:
// https://msdn.microsoft.com/library/windows/desktop/dd374660.aspx
winrt::com_ptr<IMFMediaType> outputMediaType;
winrt::check_hresult(
reader->GetCurrentMediaType(static_cast<uint32_t>(MF_SOURCE_READER_FIRST_AUDIO_STREAM), outputMediaType.put())
);
// Converts the current media type into the WaveFormatEx buffer structure.
UINT32 size = 0;
WAVEFORMATEX* waveFormat;
winrt::check_hresult(
MFCreateWaveFormatExFromMFMediaType(outputMediaType.get(), &waveFormat, &size)
);
// Copies the waveFormat's block of memory to the starting address of the m_waveFormat variable in MediaReader.
// Then free the waveFormat memory block.
// For more info, go to https://msdn.microsoft.com/library/windows/desktop/aa366535.aspx and
// https://msdn.microsoft.com/library/windows/desktop/ms680722.aspx
CopyMemory(&m_waveFormat, waveFormat, sizeof(m_waveFormat));
CoTaskMemFree(waveFormat);
PROPVARIANT propVariant;
winrt::check_hresult(
reader->GetPresentationAttribute(static_cast<uint32_t>(MF_SOURCE_READER_MEDIASOURCE), MF_PD_DURATION, &propVariant)
);
// 'duration' is in 100ns units; convert to seconds, and round up
// to the nearest whole byte.
LONGLONG duration = propVariant.uhVal.QuadPart;
unsigned int maxStreamLengthInBytes =
static_cast<unsigned int>(
((duration * static_cast<ULONGLONG>(m_waveFormat.nAvgBytesPerSec)) + 10000000) /
10000000
);
std::vector<byte> fileData(maxStreamLengthInBytes);
winrt::com_ptr<IMFSample> sample;
winrt::com_ptr<IMFMediaBuffer> mediaBuffer;
DWORD flags = 0;
int positionInData = 0;
bool done = false;
while (!done)
{
// Read audio data.
...
}
return fileData;
}
Ton einem Objekt zuordnen
Das Zuordnen von Sounds zum Objekt erfolgt, wenn das Spiel initialisiert wird, in der Simple3DGame::Initialize-Methode.
Rekapitulation:
- In der GameObject Klasse gibt es eine HitSound--Eigenschaft, die verwendet wird, um den Soundeffekt dem Objekt zuzuordnen.
- Erstellen Sie eine neue Instanz des SoundEffect- Klassenobjekts, und ordnen Sie es dem Spielobjekt zu. Diese Klasse spielt einen Ton mit XAudio2--APIs ab. Es verwendet eine Masterstimme, die von der Audio Klasse bereitgestellt wird. Die Sounddaten können aus dem Dateispeicherort mit Hilfe der MediaReader Klasse gelesen werden.
SoundEffect::Initialize wird verwendet, um die SoundEffect Instanz mit den folgenden Eingabeparametern zu initialisieren: Zeiger auf das Soundmodulobjekt (IXAudio2-Objekte, die in der Audio::CreateDeviceIndependentResources-Methode erstellt wurden), Zeiger auf das Format der .wav-Datei unter Nutzung von MediaReader::GetOutputWaveFormatExund die mit der MediaReader::LoadMedia-Methode geladenen Sounddaten. Während der Initialisierung wird auch die Quellstimme für den Soundeffekt erstellt.
SoundEffect::Initialize-Methode
void SoundEffect::Initialize(
_In_ IXAudio2* masteringEngine,
_In_ WAVEFORMATEX* sourceFormat,
_In_ std::vector<byte> const& soundData)
{
m_soundData = soundData;
if (masteringEngine == nullptr)
{
// Audio is not available so just return.
m_audioAvailable = false;
return;
}
// Create a source voice for this sound effect.
winrt::check_hresult(
masteringEngine->CreateSourceVoice(
&m_sourceVoice,
sourceFormat
)
);
m_audioAvailable = true;
}
Den Ton abspielen
Trigger zum Wiedergeben von Soundeffekten werden in der Methode Simple3DGame::UpdateDynamics definiert, weil hier die Bewegung der Objekte aktualisiert und die Kollision zwischen den Objekten bestimmt wird.
Da sich die Interaktion zwischen Objekten je nach Spiel stark unterscheidet, werden wir hier nicht über die Dynamik der Spielobjekte diskutieren. Wenn Sie die Implementierung verstehen möchten, gehen Sie zur Simple3DGame::UpdateDynamics Methode.
Prinzipiell wird beim Auftreten einer Kollision der Soundeffekt durch den Aufruf von SoundEffect::PlaySoundausgelöst. Mit dieser Methode werden alle Soundeffekte beendet, die derzeit wiedergegeben werden, und der Speicherpuffer wird mit den gewünschten Sounddaten in die Warteschlange gestellt. Es verwendet Quellstimme, um die Lautstärke festzulegen, Sounddaten zu übermitteln und die Wiedergabe zu starten.
SoundEffect::PlaySound-Methode
- Verwendet das Quellstimmobjekt m_sourceVoice zum Starten der Wiedergabe des Sounddatenpuffers m_soundData
- Erstellt einen XAUDIO2_BUFFER, dem ein Verweis auf den Sounddatenpuffer zugewiesen wird, und übergibt diesen dann mit einem Aufruf von IXAudio2SourceVoice::SubmitSourceBuffer.
- Nachdem die Sounddaten in die Warteschlange eingereiht wurden, wird SoundEffect::PlaySound wiedergegeben, indem IXAudio2SourceVoice::Startaufgerufen wird.
void SoundEffect::PlaySound(_In_ float volume)
{
XAUDIO2_BUFFER buffer = { 0 };
if (!m_audioAvailable)
{
// Audio is not available so just return.
return;
}
// Interrupt sound effect if it is currently playing.
winrt::check_hresult(
m_sourceVoice->Stop()
);
winrt::check_hresult(
m_sourceVoice->FlushSourceBuffers()
);
// Queue the memory buffer for playback and start the voice.
buffer.AudioBytes = (UINT32)m_soundData.size();
buffer.pAudioData = m_soundData.data();
buffer.Flags = XAUDIO2_END_OF_STREAM;
winrt::check_hresult(
m_sourceVoice->SetVolume(volume)
);
winrt::check_hresult(
m_sourceVoice->SubmitSourceBuffer(&buffer)
);
winrt::check_hresult(
m_sourceVoice->Start()
);
}
Simple3DGame::UpdateDynamics-Methode
Die Simple3DGame::UpdateDynamics Methode kümmert sich um die Interaktion und Kollision zwischen Spielobjekten. Wenn Objekte kollidieren (oder sich überschneiden), wird der zugehörige Soundeffekt ausgelöst.
void Simple3DGame::UpdateDynamics()
{
...
// Check for collisions between ammo.
#pragma region inter-ammo collision detection
if (m_ammoCount > 1)
{
...
// Check collision between instances One and Two.
...
if (distanceSquared < (GameConstants::AmmoSize * GameConstants::AmmoSize))
{
// The two ammo are intersecting.
...
// Start playing the sounds for the impact between the two balls.
m_ammo[one]->PlaySound(impact, m_player->Position());
m_ammo[two]->PlaySound(impact, m_player->Position());
}
}
#pragma endregion
#pragma region Ammo-Object intersections
// Check for intersections between the ammo and the other objects in the scene.
// ...
// Ball is in contact with Object.
// ...
// Make sure that the ball is actually headed towards the object. At grazing angles there
// could appear to be an impact when the ball is actually already hit and moving away.
if (impact > 0.0f)
{
...
// Play the sound associated with the Ammo hitting something.
m_objects[i]->PlaySound(impact, m_player->Position());
if (m_objects[i]->Target() && !m_objects[i]->Hit())
{
// The object is a target and isn't currently hit, so mark
// it as hit and play the sound associated with the impact.
m_objects[i]->Hit(true);
m_objects[i]->HitTime(timeTotal);
m_totalHits++;
m_objects[i]->PlaySound(impact, m_player->Position());
}
...
}
#pragma endregion
#pragma region Apply Gravity and world intersection
// Apply gravity and check for collision against enclosing volume.
...
if (position.z < limit)
{
// The ammo instance hit the a wall in the min Z direction.
// Align the ammo instance to the wall, invert the Z component of the velocity and
// play the impact sound.
position.z = limit;
m_ammo[i]->PlaySound(-velocity.z, m_player->Position());
velocity.z = -velocity.z * GameConstants::Physics::GroundRestitution;
}
...
#pragma endregion
}
Nächste Schritte
Wir haben das UWP-Framework, Grafiken, Steuerelemente, Benutzeroberfläche und Audio eines Windows 10-Spiels behandelt. Im nächsten Teil dieses Lernprogramms, Erweitern des Beispielspiels, werden weitere Optionen erläutert, die beim Entwickeln eines Spiels verwendet werden können.
Audiokonzepte
Verwenden Sie für die Entwicklung von Windows 10-Spielen XAudio2, Version 2.9. Diese Version wird mit Windows 10 ausgeliefert. Weitere Informationen finden Sie unter XAudio2 Versions.
AudioX2- ist eine Low-Level-API, die eine Grundlage für Signalverarbeitung und Mischtechnik bereitstellt. Weitere Informationen finden Sie unter XAudio2 Key Concepts.
XAudio2-Stimmen
Es gibt drei Arten von XAudio2-Sprachobjekten: Quell-, Submix- und Masterstimme. Stimmen sind die Objekte, die XAudio2 zum Verarbeiten, Bearbeiten und Wiedergeben von Audiodaten verwenden.
- Quellstimmen verarbeiten Audiodaten, die vom Client bereitgestellt werden.
- Quell- und Submixstimmen senden ihre Ausgabe an eine oder mehrere Submix- oder Masterstimmen.
- Submix- und Masterstimmen mischen die Audiodaten von allen Stimmen, die sie füttern, und arbeiten mit dem Ergebnis.
- Masterstimmen empfangen Daten von Quellstimmen und Submixstimmen und senden diese Daten an die Audiohardware.
Weitere Informationen finden Sie unter XAudio2-Stimmen.
Audiodiagramm
Audiodiagramm ist eine Sammlung von XAudio2-Stimmen. Audio beginnt auf einer Seite eines Audiodiagramms in Quellstimme, übergibt optional eine oder mehrere Submixstimme und endet mit einer Masterstimme. Ein Audiodiagramm enthält eine Quellstimme für jeden aktuell wiedergegebenen Sound, null oder mehr Submixstimmen, und eine Masterstimme. Das einfachste Audiodiagramm und das Mindestmaß, das zum Erstellen eines Rauschens in XAudio2 erforderlich ist, ist eine einzige Quellstimme, die direkt an eine Masterstimme ausgegeben wird. Weitere Informationen finden Sie unter Audiodiagramme.
Weiterführende Lektüre
- So geht's: XAudio2 initialisieren
- Anleitung: Audiodateien in XAudio2 laden
- Anleitung: Einen Sound mit XAudio2 abspielen
Schlüsselaudio-H-Dateien
Audio.h
// Audio:
// This class uses XAudio2 to provide sound output. It creates two
// engines - one for music and the other for sound effects - each as
// a separate mastering voice.
// The SuspendAudio and ResumeAudio methods can be used to stop
// and start all audio playback.
class Audio
{
public:
Audio();
void Initialize();
void CreateDeviceIndependentResources();
IXAudio2* MusicEngine();
IXAudio2* SoundEffectEngine();
void SuspendAudio();
void ResumeAudio();
private:
...
};
MediaReader.h
// MediaReader:
// This is a helper class for the SoundEffect class. It reads small audio files
// synchronously from the package installed folder and returns sound data as a
// vector of bytes.
class MediaReader
{
public:
MediaReader();
std::vector<byte> LoadMedia(_In_ winrt::hstring const& filename);
WAVEFORMATEX* GetOutputWaveFormatEx();
private:
winrt::Windows::Storage::StorageFolder m_installedLocation{ nullptr };
winrt::hstring m_installedLocationPath;
WAVEFORMATEX m_waveFormat;
};
SoundEffect.h
// SoundEffect:
// This class plays a sound using XAudio2. It uses a mastering voice provided
// from the Audio class. The sound data can be read from disk using the MediaReader
// class.
class SoundEffect
{
public:
SoundEffect();
void Initialize(
_In_ IXAudio2* masteringEngine,
_In_ WAVEFORMATEX* sourceFormat,
_In_ std::vector<byte> const& soundData
);
void PlaySound(_In_ float volume);
private:
...
};