Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
File last commit:
Show/Diff file:
Action:
FNA/lib/FAudio/utils/testxwma/testxwma.cpp
246 lines | 6.5 KiB | text/x-c | CppLexer
#include <stdio.h>
#include <SDL.h>
#include <FAudio.h>
float argPlayBegin = 0.0f;
float argPlayLength = 0.0f;
float argLoopBegin = 0.0f;
float argLoopLength = 0.0f;
uint32_t argLoopCount = 0;
FAudio *faudio = NULL;
FAudioMasteringVoice *mastering_voice = NULL;
FAudioSourceVoice *source_voice = NULL;
FAudioWaveFormatExtensible *wfx = NULL;
FAudioBuffer buffer = {0};
FAudioBufferWMA buffer_wma = {0};
/* based on https://docs.microsoft.com/en-us/windows/desktop/xaudio2/how-to--load-audio-data-files-in-xaudio2 */
#define fourccRIFF *((uint32_t *) "RIFF")
#define fourccDATA *((uint32_t *) "data")
#define fourccFMT *((uint32_t *) "fmt ")
#define fourccWAVE *((uint32_t *) "WAVE")
#define fourccXWMA *((uint32_t *) "XWMA")
#define fourccDPDS *((uint32_t *) "dpds")
uint32_t FindChunk(FILE *hFile, uint32_t fourcc, uint32_t *dwChunkSize, uint32_t *dwChunkDataPosition)
{
uint32_t hr = 0;
if (fseek(hFile, 0, SEEK_SET) != 0)
{
return -1;
}
uint32_t dwChunkType;
uint32_t dwChunkDataSize;
uint32_t dwRIFFDataSize = 0;
uint32_t dwFileType;
uint32_t bytesRead = 0;
uint32_t dwOffset = 0;
while (hr == 0)
{
if (fread(&dwChunkType, sizeof(uint32_t), 1, hFile) < 1)
hr = 1;
if (fread(&dwChunkDataSize, sizeof(uint32_t), 1, hFile) < 1)
hr = 1;
if (dwChunkType == fourccRIFF)
{
dwRIFFDataSize = dwChunkDataSize;
dwChunkDataSize = 4;
if (fread(&dwFileType, sizeof(uint32_t), 1, hFile) < 1)
hr = 1;
}
else
{
if (fseek(hFile, dwChunkDataSize, SEEK_CUR) != 0)
return 1;
}
dwOffset += sizeof(uint32_t) * 2;
if (dwChunkType == fourcc)
{
*dwChunkSize = dwChunkDataSize;
*dwChunkDataPosition = dwOffset;
return 0;
}
dwOffset += dwChunkDataSize;
if (bytesRead >= dwRIFFDataSize)
return 1;
}
return 1;
}
uint32_t ReadChunkData(FILE *hFile, void * buffer, uint32_t buffersize, uint32_t bufferoffset)
{
uint32_t hr = 0;
if (fseek(hFile, bufferoffset, SEEK_SET) != 0)
return 1;
if (fread(buffer, buffersize, 1, hFile) < 1)
hr = 1;
return hr;
}
uint32_t load_data(const char *filename)
{
/* open the audio file */
FILE *hFile = fopen(filename, "rb");
if (!hFile)
return 1;
fseek(hFile, 0, SEEK_SET);
/* Locate the 'RIFF' chunk in the audio file, and check the file type. */
uint32_t dwChunkSize;
uint32_t dwChunkPosition;
uint32_t filetype;
FindChunk(hFile,fourccRIFF, &dwChunkSize, &dwChunkPosition);
ReadChunkData(hFile, &filetype, sizeof(uint32_t), dwChunkPosition);
if (filetype != fourccWAVE && filetype != fourccXWMA)
return 1;
/* Locate the 'fmt ' chunk, and copy its contents into a WAVEFORMATEXTENSIBLE structure. */
FindChunk(hFile,fourccFMT, &dwChunkSize, &dwChunkPosition );
if (dwChunkSize > sizeof(FAudioWaveFormatExtensible))
{
wfx = (FAudioWaveFormatExtensible *) malloc(dwChunkSize);
printf("chunk-size exceeds wfx size, allocating more: %u > %u\n", dwChunkSize, sizeof(FAudioWaveFormatExtensible));
}
else
{
wfx = (FAudioWaveFormatExtensible *) malloc(sizeof(FAudioWaveFormatExtensible));
printf("chunk-size equal or less than wfx size, capping: %u <= %u\n", dwChunkSize, sizeof(FAudioWaveFormatExtensible));
}
ReadChunkData(hFile, wfx, dwChunkSize, dwChunkPosition );
/* Locate the 'data' chunk, and read its contents into a buffer. */
FindChunk(hFile, fourccDATA, &dwChunkSize, &dwChunkPosition);
uint8_t *pDataBuffer = (uint8_t *) malloc(dwChunkSize);
ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition);
printf("data chunk size: %u\n", dwChunkSize);
buffer.AudioBytes = dwChunkSize; //buffer containing audio data
buffer.pAudioData = pDataBuffer; //size of the audio buffer in bytes
buffer.Flags = FAUDIO_END_OF_STREAM; // tell the source voice not to expect any data after this buffer
/* Locate the 'dpds' chunk, and read its contents into a buffer. */
if (FindChunk(hFile, fourccDPDS, &dwChunkSize, &dwChunkPosition) == 0)
{
uint32_t *cumulBytes = (uint32_t *) malloc(dwChunkSize);
ReadChunkData(hFile, cumulBytes, dwChunkSize, dwChunkPosition);
buffer_wma.pDecodedPacketCumulativeBytes = cumulBytes;
buffer_wma.PacketCount = dwChunkSize / sizeof(uint32_t);
}
fclose(hFile);
return 0;
}
void faudio_setup() {
uint32_t hr = FAudioCreate(&faudio, 0, FAUDIO_DEFAULT_PROCESSOR);
if (hr != 0) {
return;
}
hr = FAudio_CreateMasteringVoice(faudio, &mastering_voice, 2, 44100, 0, 0, NULL);
if (hr != 0) {
return;
}
hr = FAudio_CreateSourceVoice(
faudio,
&source_voice,
(FAudioWaveFormatEx *) wfx,
FAUDIO_VOICE_USEFILTER,
FAUDIO_MAX_FREQ_RATIO,
NULL, NULL, NULL
);
}
void play(void) {
buffer.PlayBegin = argPlayBegin * wfx->Format.nSamplesPerSec;
buffer.PlayLength = argPlayLength * wfx->Format.nSamplesPerSec;
buffer.LoopBegin = argLoopBegin * wfx->Format.nSamplesPerSec;
buffer.LoopLength = argLoopLength * wfx->Format.nSamplesPerSec;
buffer.LoopCount = argLoopCount;
if (buffer_wma.pDecodedPacketCumulativeBytes != NULL)
FAudioSourceVoice_SubmitSourceBuffer(source_voice, &buffer, &buffer_wma);
else
FAudioSourceVoice_SubmitSourceBuffer(source_voice, &buffer, NULL);
uint32_t hr = FAudioSourceVoice_Start(source_voice, 0, FAUDIO_COMMIT_NOW);
int is_running = 1;
while (hr == 0 && is_running) {
FAudioVoiceState state;
FAudioSourceVoice_GetState(source_voice, &state, 0);
is_running = (state.BuffersQueued > 0) != 0;
SDL_Delay(10);
}
FAudioVoice_DestroyVoice(source_voice);
/* free allocated space for FAudioWafeFormatExtensible */
free(wfx);
}
int main(int argc, char *argv[]) {
/* process command line arguments. This is just a test program, didn't go too nuts with validation. */
if (argc < 2 || (argc > 4 && argc != 7)) {
printf("Usage: %s filename [PlayBegin] [PlayLength] [LoopBegin LoopLength LoopCount]\n", argv[0]);
printf(" - filename (required): can be either a WAV or xWMA audio file.\n");
printf(" - PlayBegin (optional): start playing at this offset. (in seconds)\n");
printf(" - PlayLength (optional): duration of the region to be played. (in seconds)\n");
printf(" - LoopBegin (optional): start looping at this offset. (in seconds)\n");
printf(" - LoopLength (optional): duration of the loop (in seconds)\n");
printf(" - LoopCount (optional): number of times to loop\n");
return -1;
}
switch (argc)
{
case 7:
sscanf(argv[6], "%d", &argLoopCount);
sscanf(argv[5], "%f", &argLoopLength);
sscanf(argv[4], "%f", &argLoopBegin);
case 4:
sscanf(argv[3], "%f", &argPlayLength);
case 3:
sscanf(argv[2], "%f", &argPlayBegin);
}
if (load_data(argv[1]) != 0)
{
printf("Error loading data\n");
return -1;
}
faudio_setup();
play();
return 0;
}