Commit Description:
UI fixes.
Commit Description:
UI fixes.
File last commit:
Show/Diff file:
Action:
FNA/lib/FAudio/utils/showriffheader/showriffheader.cpp
369 lines | 12.2 KiB | text/x-c | CppLexer
#include <stdio.h>
#include <SDL.h>
#include <FAudio.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <array>
std::array<uint8_t, 2> fill_char_buffer(const uint16_t x)
{
std::array<uint8_t, 2> buf;
buf[0] = static_cast<uint8_t> (x >> 8);
buf[1] = static_cast<uint8_t> (x >> 0);
return buf;
}
std::array<uint8_t, 4> fill_char_buffer(const uint32_t x)
{
std::array<uint8_t, 4> buf;
buf[0] = static_cast<uint8_t> (x >> 24);
buf[1] = static_cast<uint8_t> (x >> 16);
buf[2] = static_cast<uint8_t> (x >> 8);
buf[3] = static_cast<uint8_t> (x >> 0);
return buf;
}
char printable_char (char c)
{
return (std::isprint(c) ? c : ' ');
}
std::string uint8_to_charstr(const uint8_t x)
{
std::stringstream ss;
ss << "|"
<< printable_char(static_cast<char>(x))
<< " |"
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned int>(x) << " |"
<< std::setfill(' ') << std::setw(8)
<< "0x"
<< std::setfill('0') << std::setw(2)
<< static_cast<unsigned int>(x)
<< "|"
<< std::setfill(' ') << std::setw(10)
<< std::dec << static_cast<unsigned int>(x)
<< "|";
return ss.str();
}
std::string uint16_to_charstr(const uint16_t x)
{
std::array<uint8_t, 2> buf = fill_char_buffer(x);
std::stringstream ss;
ss << "|"
<< printable_char(static_cast<char>(buf[1]))
<< printable_char(static_cast<char>(buf[0]))
<< " |"
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned>(buf[1]) << "."
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned>(buf[0]) << " |"
<< std::setfill(' ') << std::setw(6)
<< "0x"
<< std::setfill('0') << std::setw(4)
<< x
<< "|"
<< std::setfill(' ') << std::setw(10)
<< std::dec << x
<< "|";
return ss.str();
}
std::string uint32_to_charstr(const uint32_t x)
{
std::array<uint8_t, 4> buf = fill_char_buffer(x);
std::stringstream ss;
ss << "|"
<< printable_char(static_cast<char>(buf[3]))
<< printable_char(static_cast<char>(buf[2]))
<< printable_char(static_cast<char>(buf[1]))
<< printable_char(static_cast<char>(buf[0]))
<< "|"
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned>(buf[3]) << "."
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned>(buf[2]) << "."
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned>(buf[1]) << "."
<< std::hex << std::setfill('0') << std::setw(2)
<< static_cast<unsigned>(buf[0]) << "|"
<< std::setfill('0') << std::setw(2)
<< "0x"
<< std::setfill('0') << std::setw(8)
<< x
<< "|"
<< std::setfill(' ') << std::setw(10)
<< std::dec << x
<< "|";
return ss.str();
}
/* 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 load_data(const char *filename)
{
/* open the audio file */
FILE *hFile = fopen(filename, "rb");
if (!hFile)
return 1;
fseek(hFile, 0, SEEK_SET);
uint32_t chunkID;
uint32_t dwChunkPosition = 0;
// search for 'RIFF' chunk
bool foundRIFF = false;
while (fread(&chunkID, sizeof(uint32_t), 1, hFile) > 0)
{
dwChunkPosition += sizeof (uint32_t);
if (chunkID == fourccRIFF)
{
foundRIFF = true;
std::cout << "found 'RIFF' at: " << dwChunkPosition - sizeof(uint32_t) << std::endl;
break;
}
}
if (!foundRIFF)
{
std::cout << "missing RIFF header" << std::endl;
return 1;
}
{
std::cout << "RIFF: "
<< uint32_to_charstr(chunkID) << std::endl;
uint32_t filesize;
uint32_t format;
if (fread(&filesize, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read RIFF filesize");
dwChunkPosition += sizeof (uint32_t);
std::cout << "ChunkSize: "
<< uint32_to_charstr(filesize) << std::endl;
if (fread(&format, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read RIFF format");
dwChunkPosition += sizeof (uint32_t);
std::cout << "Format: "
<< uint32_to_charstr(format) << std::endl;
}
uint32_t fmt_chunk_start = dwChunkPosition;
uint32_t fmt_chunk_size = 0;
{ /* fmt sub-chunk 24 */
if (fread(&chunkID, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt chunkID");
dwChunkPosition += sizeof (uint32_t);
std::cout << "fmt: "
<< uint32_to_charstr(chunkID) << std::endl;
if (chunkID != fourccFMT)
{
std::cout << "expected chunkID 'fmt '" << std::endl;
return 1;
}
if (fread(&fmt_chunk_size, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt chunkSize");
dwChunkPosition += sizeof (uint32_t);
std::cout << "ChunkSize: "
<< uint32_to_charstr(fmt_chunk_size) << std::endl;
uint16_t audio_format;
if (fread(&audio_format, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt AudioFormat");
dwChunkPosition += sizeof (uint16_t);
auto audio_format_str = [](const uint16_t format)
{
if (format == FAUDIO_FORMAT_PCM) // 1
return "FAUDIO_FORMAT_PCM";
if (format == FAUDIO_FORMAT_MSADPCM) // 2
return "FAUDIO_FORMAT_MSADPCM";
if (format == FAUDIO_FORMAT_IEEE_FLOAT) // 3
return "FAUDIO_FORMAT_IEEE_FLOAT";
if (format == FAUDIO_FORMAT_WMAUDIO2) // 0x0161
return "FAUDIO_FORMAT_WMAUDIO2";
if (format == FAUDIO_FORMAT_WMAUDIO3) // 0x0162
return "FAUDIO_FORMAT_WMAUDIO3";
if (format == FAUDIO_FORMAT_WMAUDIO_LOSSLESS) // 0x0163
return "FAUDIO_FORMAT_WMAUDIO_LOSSLESS";
if (format == FAUDIO_FORMAT_XMAUDIO2) // 0x0166
return "FAUDIO_FORMAT_XMAUDIO2";
if (format == FAUDIO_FORMAT_EXTENSIBLE) // 0xFFE
return "FAUDIO_FORMAT_";
return "FAUDIO_FORMAT_UNKNOWN";
};
std::cout << "fmt AudioFormat: "
<< uint16_to_charstr(audio_format)
<< " " << audio_format_str(audio_format) << std::endl;
uint16_t NumChannels;
if (fread(&NumChannels, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt NumChannels");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt NumChannels: "
<< uint16_to_charstr(NumChannels) << std::endl;
uint32_t SampleRate;
if (fread(&SampleRate, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt SampleRate");
std::cout << "fmt SampleRate: "
<< uint32_to_charstr(SampleRate) << std::endl;
uint32_t ByteRate;
if (fread(&ByteRate, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ByteRate");
dwChunkPosition += sizeof (uint32_t);
std::cout << "fmt ByteRate: "
<< uint32_to_charstr(ByteRate) << std::endl;
uint16_t BloackAlign;
if (fread(&BloackAlign, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt BloackAlign");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt BloackAlign: "
<< uint16_to_charstr(BloackAlign) << std::endl;
uint16_t BitsPerSample;
if (fread(&BitsPerSample, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt BitsPerSample");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt BitsPerSample:"
<< uint16_to_charstr(BitsPerSample) << std::endl;
}
/* in case of extensible audio format write the additional data to the file */
if (fmt_chunk_size > 16)
{
std::cout << "fmt chunk position: " << dwChunkPosition - fmt_chunk_start << std::endl;
uint16_t cb_size;
if (fread(&cb_size, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt cbSize");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt cbSize: "
<< uint32_to_charstr(cb_size) << std::endl;
if (cb_size >= 22)
{
uint16_t ValidBitsPerSample;
if (fread(&ValidBitsPerSample, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ex ValidBitsPerSample");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt ValidBitsPerS:"
<< uint16_to_charstr(ValidBitsPerSample) << std::endl;
uint32_t dwChannelMask;
if (fread(&dwChannelMask, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ex dwChannelMask");
dwChunkPosition += sizeof (uint32_t);
std::cout << "fmt dwChannelMask:"
<< uint32_to_charstr(dwChannelMask) << std::endl;
uint32_t Data1;
if (fread(&Data1, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ex Data1");
dwChunkPosition += sizeof (uint32_t);
std::cout << "fmt Data1: "
<< uint32_to_charstr(Data1) << std::endl;
uint16_t Data2;
if (fread(&Data2, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ex Data2");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt Data2: "
<< uint16_to_charstr(Data2) << std::endl;
uint16_t Data3;
if (fread(&Data3, sizeof(uint16_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ex Data3");
dwChunkPosition += sizeof (uint16_t);
std::cout << "fmt Data3: "
<< uint16_to_charstr(Data3) << std::endl;
uint8_t Data4[8];
if (fread(&Data4, sizeof(uint8_t), 8, hFile) < 1)
throw std::runtime_error("can't read fmt ex Data4");
dwChunkPosition += sizeof (uint8_t)*8;
for (uint8_t i=0; i<8; i++)
{
std::cout << "fmt Data4["<<static_cast<uint16_t>(i)<<"]: "
<< uint8_to_charstr(Data4[i]) << std::endl;
}
uint16_t remaining_fmt_data = cb_size - 22;
uint8_t dummy;
std::cout << "fmt remaining data: " << remaining_fmt_data << std::endl;
for (uint16_t i=0; i<remaining_fmt_data; i++)
{
if (fread(&dummy, sizeof(uint8_t), 1, hFile) < 1)
throw std::runtime_error("can't read fmt ex padding");
dwChunkPosition += sizeof (uint8_t);
std::cout << "fmt dummy["<<i<<"]: "
<< uint8_to_charstr(dummy) << std::endl;
}
} // end if cbSize > 22
std::cout << "fmt chunk position: " << dwChunkPosition - fmt_chunk_start << std::endl;
}
// ignore data until we find sub-chunk data
auto print_sub_chunk = [&]()
{ /* data sub-chunk - 8 bytes + data */
uint32_t chunkSize;
if (fread(&chunkID, sizeof(uint32_t), 1, hFile) < 1)
{
if (feof(hFile))
{
std::cout << "reached end of file at: " << dwChunkPosition << std::endl;
return;
}
throw std::runtime_error("can't read chunkID");
}
dwChunkPosition += sizeof (uint32_t);
if (chunkID == fourccDATA)
{
std::cout << "data chunk position: " << dwChunkPosition - sizeof(uint32_t) << std::endl;
std::cout << "data: "
<< uint32_to_charstr(chunkID) << std::endl;
if (fread(&chunkSize, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read chunkSize");
dwChunkPosition += sizeof (uint32_t);
std::cout << "data chunkSize: "
<< uint32_to_charstr(chunkSize) << std::endl;
// skip the rest
fseek(hFile, chunkSize, SEEK_CUR);
dwChunkPosition += chunkSize;
}
else if (chunkID == fourccDPDS)
{
std::cout << "dpds chunk position: " << dwChunkPosition - sizeof(uint32_t) << std::endl;
std::cout << "dpds: "
<< uint32_to_charstr(chunkID) << std::endl;
if (fread(&chunkSize, sizeof(uint32_t), 1, hFile) < 1)
throw std::runtime_error("can't read chunkSize");
dwChunkPosition += sizeof (uint32_t);
std::cout << "dpds chunkSize: "
<< uint32_to_charstr(chunkSize) << std::endl;
// skip the rest
fseek(hFile, chunkSize, SEEK_CUR);
dwChunkPosition += chunkSize;
}
else
{
std::cout << "unknown chunkID at position: " << dwChunkPosition - sizeof(uint32_t) << std::endl;
std::cout << "unhandled chunk: "
<< uint32_to_charstr(chunkID) << std::endl;
}
};
if (!feof(hFile))
print_sub_chunk();
if (!feof(hFile))
print_sub_chunk();
return 0;
}
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) {
printf("Usage: %s filename\n", argv[0]);
printf(" - filename (required): can be either a WAV or xWMA audio file.\n");
return -1;
}
if (load_data(argv[1]) != 0)
{
printf("Error loading data\n");
return -1;
}
printf("success\n");
return 0;
}