Teacher Notes: All HTML pages and CSS for this site was hand typed in a text editor. No development environment was used so that the students learn HTML. Some of the code, such as the blinking links and the CRT TV effect, were copied from developers websites.

Student Notes: This program can only play .wav files at the moment. I am hoping to update the program so that it can play other file formats, such as .mp3.

XAudio2_Test2_playingAfile: Code

Home Code

XAudio2_Test2_playingAfile.cpp

#include < iostream >
#include < string >
#include < tchar.h >
#include < vector >

#include readText.h"
#include pickSound.h"
#include "playVoice.h"

using namespace std;

int main() {

CoInitialize(nullptr);

readText readPaths;
pickSound selectVoice;
playVoice transmitAudio;

int choice = 0;
int soundNumber = 0;
vector < string > soundPaths = readPaths.readSoundPaths();
float volumeVariable = 0.0;
float pan = 0.0f;
float pitchVariable = 0.0;

while (true) {
soundNumber = selectVoice.soundPicker(soundPaths);
system("CLS");

const TCHAR * strFileName = _TEXT(soundPaths[soundNumber].c_str());

cout << "\n Type in the volume that would like this sound to be;" << endl;
cout << " make sure the number is to the tenth's place: " << endl;
cin >> volumeVariable;

cout << "\n Type in a value within the values of -1.0 and 1.0. A number closer to -1.0" << endl;
cout << " will make the sound more towards the left speaker; a number" << endl;
cout << " closer to 1.0 will make the sound more towards the right speaker;" << endl;
cout << " 0.0 will make the sound be 'split' between the left and right speakers: " << endl;
cin >> pan;

cout << "\n Type in the value for the change in pitch of the sound;" << endl;
cout << " again, make sure the number is to the tenth's place: " << endl;
cin >> pitchVariable;

transmitAudio.playAudio(strFileName, volumeVariable, pan, pitchVariable);

cout << "\n Would you like to play another sound; yes, 1, or no, 2: " << endl;
cin >> choice;

system("CLS");

if (choice == 1) {}
else if (choice == 2) {
break;
}
}

cout << "\nThank you for using this work-in-progress audio playing system.";
cout << "\n-------------------------------\n";

system("PAUSE");
return 0;
}


readText.h

#pragma once
#include < iostream >
#include < string >
#include < fstream >
#include < vector >

using namespace std;

class readText
{
public:
readText();
~readText();

vector < string > & readSoundPaths();

private:
vector < string > m_SoundPaths;
};


readText.cpp

#include "readText.h"

readText::readText()
{
}

readText::~readText()
{
}

vector < string > & readText::readSoundPaths()
{
string transferPath;

ifstream reader("soundsArchive.txt");

if (reader.is_open()) {

while (getline(reader, transferPath)) {

m_SoundPaths.push_back(transferPath);
}
}
else {
cout << "\n ERROR " << endl;
return m_SoundPaths;
}
reader.close();

return m_SoundPaths;
}


pickSound.h

#pragma once
#include < iostream >
#include < string >
#include < algorithm >
#include < vector >

using namespace std;

class pickSound
{
public:
pickSound();
~pickSound();

int soundPicker(vector < string > soundPaths);

private:
string transferPath;
int soundNumber = 0;
int numberOfChars = 0;
};


pickSound.cpp

#include "pickSound.h"


pickSound::pickSound()
{
}


pickSound::~pickSound()
{
}

int pickSound::soundPicker(vector < string > soundPaths)
{
cout << "\n Here are " << soundPaths.size() << " sounds to choose from: " << endl;

for (int s = 0; s < soundPaths.size(); s++) {
transferPath = soundPaths[s];
numberOfChars = transferPath.size();
transferPath.replace(numberOfChars - 4, 4, "");

transferPath.replace(0, 7, "");
replace(transferPath.begin(), transferPath.end(), '_', ' ');

cout << " - " << "(" << s << ") " << transferPath << endl;
}

cout << "\n Type in the number of the sound that you would like to hear: " << endl;
cin >> soundNumber;

return soundNumber;
}


playVoice.h

#pragma once
#include < iostream >
#include < string >"
#include < vector >
#include "xaudio2.h"
#include < x3daudio.h >


#pragma comment(lib, "Xaudio2.lib")

using namespace std;

#ifdef _XBOX //Big-Endian
#define fourccRIFF 'RIFF'
#define fourccDATA 'data'
#define fourccFMT 'fmt'
#define fourccWAVE 'WAVE'
#define fourccXWMA 'XWMA'
#define fourccDPDS 'dpds'
#endif

#ifdef _XBOX //Little-Endian
#define fourccRIFF 'FFIR'
#define fourccDATA 'atad'
#define fourccFMT 'tmf'
#define fourccWAVE 'EVAW'
#define fourccXWMA 'AMWX'
#define fourccDPDS 'sdpd'
#endif

#define ISFP INVALID_SET_FILE_POINTER
#define HFW HRESULT_FROM_WIN32(GetLastError());

class playVoice
{
public:
playVoice();
~playVoice();

HRESULT playAudio(const TCHAR * strFileName, float volumeVariable, float pan, float pitchVariable);

private:
HRESULT FindChunk(HANDLE hFile, DWORD fourcc, DWORD & dwChunkSize, DWORD & dwChunkDataPosition)
{
HRESULT hr;
hr = S_OK;

int IsSetFilePointerStatus;
IsSetFilePointerStatus = SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
if (ISFP == IsSetFilePointerStatus) {
return HFW;
}

DWORD dwChunkType;
DWORD dwChunkDataSize;

DWORD dwRIFFDataSize;
dwRIFFDataSize = 0;

DWORD dwFileType;

DWORD bytesRead;
bytesRead = 0;

DWORD dwOffset;
dwOffset = 0;

while (hr == S_OK)
{
DWORD dwRead;

int chunkType;
chunkType = ReadFile(hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL);
if (0 == chunkType) {
hr = HFW;
}

int chunkDataSize;
chunkDataSize = ReadFile(hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL);
if (0 == chunkDataSize) {
hr = HFW;
}

switch (dwChunkType)
{
case fourccRIFF:
dwRIFFDataSize = dwChunkDataSize;
dwChunkDataSize = 4;

int fileType;
fileType = ReadFile(hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL);
if (0 == fileType) {
hr = HFW;
}

break;

default:
if (ISFP == SetFilePointer(hFile, dwChunkDataSize, NULL, FILE_CURRENT)) {
return HFW;
}
}

dwOffset = dwOffset + sizeof(DWORD) * 2;

if (dwChunkType == fourcc)
{
dwChunkSize = dwChunkDataSize;
dwChunkDataPosition = dwOffset;
return S_OK;
}

dwOffset = dwOffset + dwChunkDataSize;

if (bytesRead >= dwRIFFDataSize) {
return S_FALSE;
}

}

return S_OK;
}

HRESULT ReadChunkData(HANDLE hFile, void * buffer, DWORD buffersize, DWORD bufferoffset)
{
HRESULT hr;
hr = S_OK;

if (ISFP == SetFilePointer(hFile, bufferoffset, NULL, FILE_BEGIN)) {
return HFW;
}

DWORD dwRead;

int funcReadFile;
funcReadFile = ReadFile(hFile, buffer, buffersize, &dwRead, NULL);

if (0 == funcReadFile) {
hr = HFW;
}

return hr;
}
};


playVoice.cpp

#include "playVoice.h"


playVoice::playVoice()
{
}


playVoice::~playVoice()
{
}

HRESULT playVoice::playAudio(const TCHAR * strFileName, float volumeVariable, float pan, float pitchVariable)
{
IXAudio2* pXAudio2;
pXAudio2 = NULL;

HRESULT hr;
hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);

bool DidItFail = FAILED(hr);

if (DidItFail) {
return hr;
}

IXAudio2MasteringVoice* pMasterVoice;
pMasterVoice = NULL;
hr = pXAudio2->CreateMasteringVoice(&pMasterVoice);

DidItFail = FAILED(hr);

if (DidItFail)
return hr;

WAVEFORMATEXTENSIBLE wfx = { 0 };
XAUDIO2_BUFFER buffer = { 0 };

#ifdef _XBOX
//char * strFileName = "C:\modules\Paul\sounds\daisy.wav";
#else
// const TCHAR * strFileName = _TEXT("C:\\modules\\Paul\\sounds\\daisy.wav");
// const TCHAR * strFileName = _TEXT("C:\\modules\\Paul\\sounds\\B17_Engine_Startup.wav");
#endif

// The commented out code just above is some previous code that is no longer used by the program.
// The "C:\\modules\\Paul\\sounds\\daisy.wav" and the "C:\\modules\\Paul\\sounds\\B17_Engine_Startup.wav" are file paths that the program used to play the sound effects.
// Now the program "reads" the sound paths from a text file and uses those to find the sounds to play.

HANDLE hFile = CreateFile(strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

if (INVALID_HANDLE_VALUE == hFile) {
cout << "\n Audio Playback: TERMINATED "
cout << "\n ERROR. Could not find file: " << strFileName << endl << endl;

int i = 0;
cin >> i;

return HRESULT_FROM_WIN32(GetLastError());
}

if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) {
return HRESULT_FROM_WIN32(GetLastError());
}

DWORD dwChunkSize;
DWORD dwChunkPosition;

FindChunk(hFile, fourccRIFF, dwChunkSize, dwChunkPosition);
DWORD filetype;
ReadChunkData(hFile, &filetype, sizeof(DWORD), dwChunkPosition);
if (filetype != fourccWAVE) {
return S_FALSE;
}

FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition);
ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);

FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition);


BYTE * pDataBuffer = new BYTE[dwChunkSize];
ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition);

buffer.AudioBytes = dwChunkSize;
buffer.pAudioData = pDataBuffer;
buffer.Flags = XAUDIO2_END_OF_STREAM;

IXAudio2SubmixVoice * pSFXSubmixVoice;
pXAudio2->CreateSubmixVoice(&pSFXSubmixVoice, 1, 44100, 0, 0, 0, 0);

XAUDIO2_SEND_DESCRIPTOR SFXSend = { 0, pSFXSubmixVoice };

XAUDIO2_VOICE_SENDS SFXSendList = { 1, &SFXSend };


DWORD dwChannelMask;
pMasterVoice->GetChannelMask(&dwChannelMask);

float outputMatrix[8];
for (int i = 0; i < 8; i++)
{
outputMatrix[i] = 0;
}

// pan of -1.0 indicates all left speaker
//1.0 is all right speaker, 0.0 is split between left and right

float left = 0.5f - pan / 2;
float right = 0.5f + pan / 2;

switch (dwChannelMask)
{
case SPEAKER_MONO:
outputMatrix[0] = 1.0;
break;
case SPEAKER_STEREO:
case SPEAKER_2POINT1:
case SPEAKER_SURROUND:
outputMatrix[0] = left;
outputMatrix[1] = right;
break;
case SPEAKER_QUAD:
outputMatrix[0] = outputMatrix[2] = left;
outputMatrix[1] = outputMatrix[3] = right;
break;
case SPEAKER_4POINT1:
outputMatrix[0] = outputMatrix[3] = left;
outputMatrix[1] = outputMatrix[4] = right;
break;
case SPEAKER_5POINT1:
case SPEAKER_7POINT1:
case SPEAKER_5POINT1_SURROUND:
outputMatrix[0] = outputMatrix[4] = left;
outputMatrix[1] = outputMatrix[5] = right;
break;
case SPEAKER_7POINT1_SURROUND:
outputMatrix[0] = outputMatrix[4] = outputMatrix[6] = left;
outputMatrix[1] = outputMatrix[5] = outputMatrix[7] = right;
break;
}

XAUDIO2_VOICE_DETAILS VoiceDetails;
pSFXSubmixVoice->GetVoiceDetails(&VoiceDetails);

XAUDIO2_VOICE_DETAILS MasterVoiceDetails;
pMasterVoice->GetVoiceDetails(&MasterVoiceDetails);

pSFXSubmixVoice->SetOutputMatrix(NULL, VoiceDetails.InputChannels, MasterVoiceDetails.InputChannels, outputMatrix);

IXAudio2SourceVoice* pSFXSourceVoice;
if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSFXSourceVoice, (WAVEFORMATEX*)&wfx,
0, XAUDIO2_DEFAULT_FREQ_RATIO, (NULL), &SFXSendList, NULL))) {
return hr;
}

pSFXSubmixVoice->SetVolume(volumeVariable);
pSFXSourceVoice->SetFrequencyRatio(pitchVariable);

if (FAILED(hr = pSFXSourceVoice->SubmitSourceBuffer(&buffer))) {
return hr;
}

if (FAILED(hr = pSFXSourceVoice->Start(0))) {
return hr;
}

cout << "\n Audio Playback: SUCCESS " << endl;
}


Website Notes: The code for the CRT TV effect was copied from this website:

http://aleclownes.com/2017/02/01/crt-display.html

The idea and base of the code that causes a link to blink when it is hovered over come from these websites:

https://html-online.com/articles/blinking-text-css-animation/

https://www.w3schools.com/css/css3_animations.asp