Skip to content

Commit

Permalink
Merge branch 'develop' into static_function_and_const_vector
Browse files Browse the repository at this point in the history
  • Loading branch information
adamstark authored Nov 7, 2023
2 parents 5080af2 + 4ceb09b commit 322f218
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 66 deletions.
106 changes: 44 additions & 62 deletions AudioFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,18 @@ class AudioFile
AudioFile();

/** Constructor, using a given file path to load a file */
AudioFile (std::string filePath);
AudioFile (const std::string& filePath);

//=============================================================
/** Loads an audio file from a given file path.
* @Returns true if the file was successfully loaded
*/
bool load (std::string filePath);
bool load (const std::string& filePath);

/** Saves an audio file to a given file path.
* @Returns true if the file was successfully saved
*/
bool save (std::string filePath, AudioFileFormat format = AudioFileFormat::Wave);
bool save (const std::string& filePath, AudioFileFormat format = AudioFileFormat::Wave);

//=============================================================
/** Loads an audio file from data in memory */
Expand Down Expand Up @@ -137,26 +137,26 @@ class AudioFile
/** Set the audio buffer for this AudioFile by copying samples from another buffer.
* @Returns true if the buffer was copied successfully.
*/
bool setAudioBuffer (AudioBuffer& newBuffer);
bool setAudioBuffer (const AudioBuffer& newBuffer);

/** Sets the audio buffer to a given number of channels and number of samples per channel. This will try to preserve
* the existing audio, adding zeros to any new channels or new samples in a given channel.
*/
void setAudioBufferSize (int numChannels, int numSamples);
void setAudioBufferSize (const int numChannels, const int numSamples);

/** Sets the number of samples per channel in the audio buffer. This will try to preserve
* the existing audio, adding zeros to new samples in a given channel if the number of samples is increased.
*/
void setNumSamplesPerChannel (int numSamples);
void setNumSamplesPerChannel (const int numSamples);

/** Sets the number of channels. New channels will have the correct number of samples and be initialised to zero */
void setNumChannels (int numChannels);
void setNumChannels (const int numChannels);

/** Sets the bit depth for the audio file. If you use the save() function, this bit depth rate will be used */
void setBitDepth (int numBitsPerSample);
void setBitDepth (const int numBitsPerSample);

/** Sets the sample rate for the audio file. If you use the save() function, this sample rate will be used */
void setSampleRate (uint32_t newSampleRate);
void setSampleRate (const uint32_t newSampleRate);

//=============================================================
/** Sets whether the library should log error messages to the console. By default this is true */
Expand Down Expand Up @@ -189,8 +189,8 @@ class AudioFile
bool decodeAiffFile (const std::vector<uint8_t>& fileData);

//=============================================================
bool saveToWaveFile (std::string filePath);
bool saveToAiffFile (std::string filePath);
bool saveToWaveFile (const std::string& filePath);
bool saveToAiffFile (const std::string& filePath);

//=============================================================
void clearAudioBuffer();
Expand All @@ -217,7 +217,7 @@ class AudioFile
static inline bool writeDataToFile (const std::vector<uint8_t>& fileData, std::string filePath);

//=============================================================
void reportError (std::string errorMessage);
void reportError (const std::string& errorMessage);

//=============================================================
AudioFileFormat audioFileFormat;
Expand Down Expand Up @@ -329,7 +329,7 @@ AudioFile<T>::AudioFile()

//=============================================================
template <class T>
AudioFile<T>::AudioFile (std::string filePath)
AudioFile<T>::AudioFile (const std::string& filePath)
: AudioFile<T>()
{
load (filePath);
Expand Down Expand Up @@ -391,18 +391,18 @@ double AudioFile<T>::getLengthInSeconds() const
template <class T>
void AudioFile<T>::printSummary() const
{
std::cout << "|======================================|" << std::endl;
std::cout << "Num Channels: " << getNumChannels() << std::endl;
std::cout << "Num Samples Per Channel: " << getNumSamplesPerChannel() << std::endl;
std::cout << "Sample Rate: " << sampleRate << std::endl;
std::cout << "Bit Depth: " << bitDepth << std::endl;
std::cout << "Length in Seconds: " << getLengthInSeconds() << std::endl;
std::cout << "|======================================|" << std::endl;
std::cerr << "|======================================|" << std::endl;
std::cerr << "Num Channels: " << getNumChannels() << std::endl;
std::cerr << "Num Samples Per Channel: " << getNumSamplesPerChannel() << std::endl;
std::cerr << "Sample Rate: " << sampleRate << std::endl;
std::cerr << "Bit Depth: " << bitDepth << std::endl;
std::cerr << "Length in Seconds: " << getLengthInSeconds() << std::endl;
std::cerr << "|======================================|" << std::endl;
}

//=============================================================
template <class T>
bool AudioFile<T>::setAudioBuffer (AudioBuffer& newBuffer)
bool AudioFile<T>::setAudioBuffer (const AudioBuffer& newBuffer)
{
int numChannels = (int)newBuffer.size();

Expand Down Expand Up @@ -500,7 +500,7 @@ void AudioFile<T>::shouldLogErrorsToConsole (bool logErrors)

//=============================================================
template <class T>
bool AudioFile<T>::load (std::string filePath)
bool AudioFile<T>::load (const std::string& filePath)
{
std::ifstream file (filePath, std::ios::binary);

Expand Down Expand Up @@ -919,7 +919,7 @@ void AudioFile<T>::addSampleRateToAiffData (std::vector<uint8_t>& fileData, uint

//=============================================================
template <class T>
bool AudioFile<T>::save (std::string filePath, AudioFileFormat format)
bool AudioFile<T>::save (const std::string& filePath, AudioFileFormat format)
{
if (format == AudioFileFormat::Wave)
{
Expand All @@ -935,7 +935,7 @@ bool AudioFile<T>::save (std::string filePath, AudioFileFormat format)

//=============================================================
template <class T>
bool AudioFile<T>::saveToWaveFile (std::string filePath)
bool AudioFile<T>::saveToWaveFile (const std::string& filePath)
{
std::vector<uint8_t> fileData;

Expand Down Expand Up @@ -1052,7 +1052,7 @@ bool AudioFile<T>::saveToWaveFile (std::string filePath)

//=============================================================
template <class T>
bool AudioFile<T>::saveToAiffFile (std::string filePath)
bool AudioFile<T>::saveToAiffFile (const std::string& filePath)
{
std::vector<uint8_t> fileData;

Expand Down Expand Up @@ -1160,21 +1160,15 @@ template <class T>
bool AudioFile<T>::writeDataToFile (const std::vector<uint8_t>& fileData, std::string filePath)
{
std::ofstream outputFile (filePath, std::ios::binary);
if (outputFile.is_open())

if (!outputFile.is_open())
{
for (size_t i = 0; i < fileData.size(); i++)
{
char value = (char) fileData[i];
outputFile.write (&value, sizeof (char));
}

outputFile.close();

return true;
return false;
}

return false;

outputFile.write ((const char*)fileData.data(), fileData.size());
outputFile.close();
return true;
}

//=============================================================
Expand Down Expand Up @@ -1247,6 +1241,9 @@ void AudioFile<T>::clearAudioBuffer()
template <class T>
AudioFileFormat AudioFile<T>::determineAudioFileFormat (const std::vector<uint8_t>& fileData)
{
if (fileData.size() < 4)
return AudioFileFormat::Error;

std::string header (fileData.begin(), fileData.begin() + 4);

if (header == "RIFF")
Expand Down Expand Up @@ -1293,27 +1290,6 @@ int16_t AudioFile<T>::twoBytesToInt (const std::vector<uint8_t>& source, int sta
return result;
}

//=============================================================
template <class T>
int AudioFile<T>::getIndexOfString (const std::vector<uint8_t>& source, std::string stringToSearchFor)
{
int index = -1;
int stringLength = (int)stringToSearchFor.length();

for (size_t i = 0; i < source.size() - stringLength;i++)
{
std::string section (source.begin() + i, source.begin() + i + stringLength);

if (section == stringToSearchFor)
{
index = static_cast<int> (i);
break;
}
}

return index;
}

//=============================================================
template <class T>
int AudioFile<T>::getIndexOfChunk (const std::vector<uint8_t>& source, const std::string& chunkHeaderID, int startIndex, Endianness endianness)
Expand All @@ -1340,7 +1316,13 @@ int AudioFile<T>::getIndexOfChunk (const std::vector<uint8_t>& source, const std
if ((i + 4) >= source.size())
return -1;

auto chunkSize = fourBytesToInt (source, i, endianness);
int32_t chunkSize = fourBytesToInt (source, i, endianness);
// Assume chunk size is invalid if it's greater than the number of bytes remaining in source
if (chunkSize > (source.size() - i - dataLen) || (chunkSize < 0))
{
assert (false && "Invalid chunk size");
return -1;
}
i += (dataLen + chunkSize);
}

Expand All @@ -1349,10 +1331,10 @@ int AudioFile<T>::getIndexOfChunk (const std::vector<uint8_t>& source, const std

//=============================================================
template <class T>
void AudioFile<T>::reportError (std::string errorMessage)
void AudioFile<T>::reportError (const std::string& errorMessage)
{
if (logErrorsToConsole)
std::cout << errorMessage << std::endl;
std::cerr << errorMessage << std::endl;
}

//=============================================================
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ Please see the `examples` folder for some examples on library usage.
A Note On Types
-----------------

AudioFile is a template class and so it can be instantiated using floating point precision:
AudioFile is a template class and so it can be instantiated using different types to represent the audio samples.

For example
For example, we can use floating point precision...

AudioFile<float> audioFile;

Expand All @@ -147,13 +147,15 @@ For example

This simply reflects the data type you would like to use to store the underlying audio samples.

When you use an integer type to store the samples (e.g. `int` or `int8_t` or `int16_t` or `uint32_t`), the library will read in the integer sample values directly from the audio file. A couple of notes on integer types:
When you use an integer type to store the samples (e.g. `int` or `int8_t` or `int16_t` or `uint32_t`), the library will read in the integer sample values directly from the audio file.

A couple of notes on integer types:

* The range of samples is designed to be symmetric. This means that for (e.g.) an signed 8-bit integer (`int8_t`) we will use the range `[-127, 127]` for storing samples representing the `[-1., 1.]` range. The value `-128` is possible here given the `int8_t` type, but this is interpreted as a value slightly lower than `-1` (specifically `-1.007874015748`).

* In the case of unsigned types, we obviously can't store samples as negative values. Therefore, we used the equivalent range of the unsigned type in use. E.g. if with a 8-bit signed integer (`int8_t`) the range would be `[-127, 127]`, for an 8-bit unsigned integer we would use the range `[1, 255]`. Note that we don't use `-128` for `int8_t` or `0` in `uint8_t`.

* If you try to read an audio file with a larger bit-depth than the type you are using to store samples, the attempt to read the file will fail. Put more simply, you can't read a 16-bit audio file into an 8-bit integer.
* If you try to read an audio file with a larger bit-depth than the type you are using to store samples, the attempt to read the file will fail. Put more simply, you can't read a 16-bit audio sample into an 8-bit integer.

* If you are writing audio samples in integer formats, you should use the correct sample range for both a) the type you are using to store samples; and b) the bit depth of the audio you want to write.

Expand Down Expand Up @@ -245,9 +247,11 @@ Many thanks to the following people for their contributions to this library:
* [Abhinav1997](https://github.com/Abhinav1997)
* [alxarsenault](https://github.com/alxarsenault)
* [BenjaminHinchliff](https://github.com/BenjaminHinchliff)
* [BesselJ](https://github.com/BesselJ)
* [emiro85](https://github.com/emiro85)
* [heartofrain](https://github.com/heartofrain)
* [helloimmatt](https://github.com/helloimmatt/)
* [leocstone](https://github.com/leocstone)
* [MatthieuHernandez](https://github.com/MatthieuHernandez)
* [mrpossoms](https://github.com/mrpossoms)
* [mynameisjohn](https://github.com/mynameisjohn)
Expand Down
9 changes: 9 additions & 0 deletions tests/GeneralTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,13 @@ TEST_SUITE ("General Tests")

checkFilesAreExactlyTheSame<int16_t> (a, b);
}

//=============================================================
TEST_CASE ("GeneralTests::Empty Data")
{
AudioFile<float> a;
a.shouldLogErrorsToConsole (false);
bool result = a.loadFromMemory (std::vector<uint8_t>());
CHECK_EQ (result, false);
}
}

0 comments on commit 322f218

Please sign in to comment.