aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorJamie Bullock <jamie@jamiebullock.com>2014-06-04 18:09:43 +0100
committerJamie Bullock <jamie@jamiebullock.com>2014-06-04 18:10:59 +0100
commit8d6a75dddfedb54db4f70a3600013530df2acda1 (patch)
tree383198e125920d62553ce4aeb5c50672ef987b4f /examples
parentcff6ba15377fa37bd7801cba4b71ae2e64e1ad5f (diff)
downloadLibXtract-8d6a75dddfedb54db4f70a3600013530df2acda1.tar.gz
LibXtract-8d6a75dddfedb54db4f70a3600013530df2acda1.tar.bz2
LibXtract-8d6a75dddfedb54db4f70a3600013530df2acda1.zip
Add WaveFile class for loading audio files in simpletest
Diffstat (limited to 'examples')
-rw-r--r--examples/simpletest/WaveFile.cpp172
-rw-r--r--examples/simpletest/WaveFile.h66
2 files changed, 238 insertions, 0 deletions
diff --git a/examples/simpletest/WaveFile.cpp b/examples/simpletest/WaveFile.cpp
new file mode 100644
index 0000000..6f127ae
--- /dev/null
+++ b/examples/simpletest/WaveFile.cpp
@@ -0,0 +1,172 @@
+#include "WaveFile.h"
+
+#include <fstream>
+#include <iostream>
+#include <cstdint>
+#include <cassert>
+#include <cstring>
+
+namespace
+{
+ struct RIFFChunk
+ {
+ std::uint32_t chunkID;
+ std::uint32_t chunkSize;
+ std::uint32_t format;
+ };
+ struct fmtChunk
+ {
+ std::uint32_t chunkID;
+ std::uint32_t chunkSize;
+ std::uint16_t audioFormat;
+ std::uint16_t numChannels;
+ std::uint32_t sampleRate;
+ std::uint32_t byteRate;
+ std::uint16_t blockAlign;
+ std::uint16_t bitsPerSample;
+ };
+ struct WaveHeader
+ {
+ RIFFChunk riff;
+ fmtChunk fmt;
+ };
+}
+
+WaveFile::WaveFile() : data(nullptr), size(0)
+{
+}
+WaveFile::WaveFile(const std::string &filename) : data(nullptr), size(0)
+{
+ Load(filename);
+}
+WaveFile::~WaveFile()
+{
+ Unload();
+}
+
+bool WaveFile::Load(const std::string &filename)
+{
+ if (IsLoaded())
+ {
+ Unload();
+ }
+
+ std::fstream file(filename, std::ios::in | std::ios::binary);
+
+ if (!file.is_open())
+ {
+ std::cerr << "Error: Could not open file." << std::endl;
+ return false;
+ }
+
+ WaveHeader header;
+ std::memset(&header, 0, sizeof(WaveHeader));
+
+ while (file.peek() != std::char_traits<char>::eof())
+ {
+ std::uint32_t chunkID;
+ std::uint32_t chunkSize;
+
+ file.read(reinterpret_cast<char*>(&chunkID), sizeof(std::uint32_t));
+ file.read(reinterpret_cast<char*>(&chunkSize), sizeof(std::uint32_t));
+
+ switch (chunkID)
+ {
+ case 'FFIR':
+ {
+ header.riff.chunkID = chunkID;
+ header.riff.chunkSize = chunkSize;
+ file.read(reinterpret_cast<char*>(&header.riff.format), sizeof(std::uint32_t));
+
+ if (header.riff.format != 'EVAW')
+ {
+ std::cerr << "Error: Not a valid WAVE file." << std::endl;
+ return false;
+ }
+
+ break;
+ }
+ case ' tmf':
+ {
+ header.fmt.chunkID = chunkID;
+ header.fmt.chunkSize = chunkSize;
+ file.read(reinterpret_cast<char*>(&header.fmt.audioFormat), sizeof(std::uint16_t));
+ file.read(reinterpret_cast<char*>(&header.fmt.numChannels), sizeof(std::uint16_t));
+ file.read(reinterpret_cast<char*>(&header.fmt.sampleRate), sizeof(std::uint32_t));
+ file.read(reinterpret_cast<char*>(&header.fmt.byteRate), sizeof(std::uint32_t));
+ file.read(reinterpret_cast<char*>(&header.fmt.blockAlign), sizeof(std::uint16_t));
+ file.read(reinterpret_cast<char*>(&header.fmt.bitsPerSample), sizeof(std::uint16_t));
+
+ if (header.fmt.audioFormat != PCM &&
+ header.fmt.audioFormat != WAVE_FORMAT_IEEE_FLOAT)
+ {
+ std::cerr << "Error: Not in valid format" << std::endl;
+ return false;
+ }
+ if (header.fmt.bitsPerSample % 2 != 0)
+ {
+ std::cerr << "Error: Invalid number of bits per sample" << std::endl;
+ return false;
+ }
+ if (header.fmt.byteRate != (header.fmt.sampleRate * header.fmt.numChannels * header.fmt.bitsPerSample / 8))
+ {
+ std::cerr << "Error: Invalid byte rate" << std::endl;
+ return false;
+ }
+ if (header.fmt.blockAlign != (header.fmt.numChannels * header.fmt.bitsPerSample / 8))
+ {
+ std::cerr << "Error: Invalid block align" << std::endl;
+ return false;
+ }
+
+ break;
+ }
+ case 'atad':
+ {
+ assert(data == nullptr);
+ size = chunkSize;
+ data = new char[size];
+ file.read(data, chunkSize);
+
+ break;
+ }
+ default:
+ {
+ file.ignore(chunkSize);
+
+ break;
+ }
+ }
+ }
+
+ // Check that we got all chunks
+ if (header.riff.chunkID != 'FFIR')
+ {
+ std::cerr << "Error: Missing RIFF chunk." << std::endl;
+ return false;
+ }
+ if (header.fmt.chunkID != ' tmf')
+ {
+ std::cerr << "Error: Missing fmt chunk." << std::endl;
+ return false;
+ }
+ if (data == nullptr || size == 0)
+ {
+ std::cerr << "Error: Missing data chunk." << std::endl;
+ return false;
+ }
+
+ // Fill meta struct
+ meta.audioFormat = static_cast<AudioFormat>(header.fmt.audioFormat);
+ meta.numChannels = header.fmt.numChannels;
+ meta.sampleRate = header.fmt.sampleRate;
+ meta.bitsPerSample = header.fmt.bitsPerSample;
+
+ return true;
+}
+void WaveFile::Unload()
+{
+ delete[] data;
+ data = nullptr;
+ size = 0;
+}
diff --git a/examples/simpletest/WaveFile.h b/examples/simpletest/WaveFile.h
new file mode 100644
index 0000000..b684b41
--- /dev/null
+++ b/examples/simpletest/WaveFile.h
@@ -0,0 +1,66 @@
+#ifndef WaveFile_h__
+#define WaveFile_h__
+
+#include <string>
+
+///\note All meta data is undefined if IsLoaded() == false
+class WaveFile
+{
+public:
+ enum AudioFormat
+ {
+ PCM = 1,
+ WAVE_FORMAT_IEEE_FLOAT = 3
+ };
+
+ WaveFile();
+ WaveFile(const std::string &filename);
+ ~WaveFile();
+
+ bool Load(const std::string &filename);
+ void Unload();
+
+ inline bool IsLoaded() const
+ {
+ return (data != nullptr && size != 0);
+ }
+
+ inline AudioFormat GetAudioFormat() const
+ {
+ return meta.audioFormat;
+ }
+ inline unsigned int GetNumChannels() const
+ {
+ return meta.numChannels;
+ }
+ inline unsigned int GetSampleRate() const
+ {
+ return meta.sampleRate;
+ }
+ inline unsigned int GetBitsPerSample() const
+ {
+ return meta.bitsPerSample;
+ }
+
+ inline const char *GetData() const
+ {
+ return data;
+ }
+ inline std::size_t GetDataSize() const
+ {
+ return size;
+ }
+
+private:
+ struct Meta
+ {
+ AudioFormat audioFormat;
+ unsigned int numChannels;
+ unsigned int sampleRate;
+ unsigned int bitsPerSample;
+ } meta;
+ char *data;
+ std::size_t size;
+};
+
+#endif // WaveFile_h__