Giter VIP home page Giter VIP logo

audiofile's Introduction

AudioFile

Version License Language

A simple header-only C++ library for reading and writing audio files.

Current supported formats:

  • WAV
  • AIFF

Author

AudioFile is written and maintained by Adam Stark.

http://www.adamstark.co.uk

Usage

Create an AudioFile object:

#include "AudioFile.h"

AudioFile<double> audioFile;

Load an audio file:

audioFile.load ("/path/to/my/audiofile.wav");

Get some information about the loaded audio:

int sampleRate = audioFile.getSampleRate();
int bitDepth = audioFile.getBitDepth();

int numSamples = audioFile.getNumSamplesPerChannel();
double lengthInSeconds = audioFile.getLengthInSeconds();

int numChannels = audioFile.getNumChannels();
bool isMono = audioFile.isMono();
bool isStereo = audioFile.isStereo();

// or, just use this quick shortcut to print a summary to the console
audioFile.printSummary();

Access the samples directly:

int channel = 0;
int numSamples = audioFile.getNumSamplesPerChannel();

for (int i = 0; i < numSamples; i++)
{
	double currentSample = audioFile.samples[channel][i];
}

Replace the AudioFile audio buffer with another

// 1. Create an AudioBuffer 
// (BTW, AudioBuffer is just a vector of vectors)

AudioFile<double>::AudioBuffer buffer;

// 2. Set to (e.g.) two channels
buffer.resize (2);

// 3. Set number of samples per channel
buffer[0].resize (100000);
buffer[1].resize (100000);

// 4. do something here to fill the buffer with samples, e.g.

#include <math.h> // somewhere earler (for M_PI and sinf())

// then...

int numChannels = 2;
int numSamplesPerChannel = 100000;
float sampleRate = 44100.f;
float frequency = 440.f;

for (int i = 0; i < numSamplesPerChannel; i++)
{
    float sample = sinf (2. * M_PI * ((float) i / sampleRate) * frequency) ;
    
    for (int channel = 0; channel < numChannels; channel++)
         buffer[channel][i] = sample * 0.5;
}

// 5. Put into the AudioFile object
bool ok = audioFile.setAudioBuffer (buffer);

Resize the audio buffer

// Set both the number of channels and number of samples per channel
audioFile.setAudioBufferSize (numChannels, numSamples);

// Set the number of samples per channel
audioFile.setNumSamplesPerChannel (numSamples);

// Set the number of channels
audioFile.setNumChannels (numChannels);

Set bit depth and sample rate

audioFile.setBitDepth (24);
audioFile.setSampleRate (44100);

Save the audio file to disk

// Wave file (implicit)
audioFile.save ("path/to/desired/audioFile.wav");

// Wave file (explicit)
audioFile.save ("path/to/desired/audioFile.wav", AudioFileFormat::Wave);

// Aiff file
audioFile.save ("path/to/desired/audioFile.aif", AudioFileFormat::Aiff);

Examples

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:

For example

AudioFile<float> audioFile;

...or double precision...

AudioFile<double> audioFile;

...or an integer type:

AudioFile<int> audioFile;	

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:

  • 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 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.

The following table details the sample range for each bit-depth:

Type 8-bit Audio 16-bit Audio 24-bit Audio 32-bit Audio
float [-1.0, 1.0] [-1.0, 1.0] [-1.0, 1.0] [-1.0, 1.0]
double [-1.0, 1.0] [-1.0, 1.0] [-1.0, 1.0] [-1.0, 1.0]
int8_t [-127, 127] ❌ (type too small) ❌ (type too small) ❌ (type too small)
uint8_t [1, 255] ❌ (type too small) ❌ (type too small) ❌ (type too small)
int16_t [-127, 127] [-32767, 32767] ❌ (type too small) ❌ (type too small)
uint16_t [1, 255] [1, 65535] ❌ (type too small) ❌ (type too small)
int32_t [-127, 127] [-32767, 32767] [-8388607, 8388607] [-2147483647, 2147483647]
uint32_t [1, 255] [1, 65535] [1, 16777215] [1, 4294967295]
int64_t [-127, 127] [-32767, 32767] [-8388607, 8388607] [-2147483647, 2147483647]
uint64_t [1, 255] [1, 65535] [1, 16777215] [1, 4294967295]

Error Messages

By default, the library logs error messages to the console to provide information on what has gone wrong (e.g. a file we tried to load didn't exist).

If you prefer not to see these messages, you can disable this error logging behaviour using:

audioFile.shouldLogErrorsToConsole (false);

Versions

1.1.1 - 4th April 2023
  • Support for integer formats
  • Improved unit testing
  • Many bug fixes
1.1.0 - 15th January 2022
  • Moved project to MIT licence
  • Added option to load an audio file already in memory
  • CI Workflow improvements and bug fixes
1.0.9 - 23rd January 2021
  • Faster loading of audio files
  • Bug fixes
1.0.8 - 18th October 2020
  • CMake support
  • Construct instances with a file path
  • Bug fixes
1.0.7 - 3rd July 2020
  • Support for 32-bit audio files
  • Support for multi-channel audio files
  • Reading/writing of iXML data chunks
1.0.6 - 29th February 2020
  • Made error logging to the console optional
  • Fixed lots of compiler warnings
1.0.5 - 14th October 2019
  • Added include of to better support Visual Studio
1.0.4 - 13th October 2019
  • Changed to a header-only library. Now you can just include AudioFile.h
  • Bug fixes
1.0.3 - 28th October 2018
  • Bug fixes
  • Documentation updates
1.0.2 - 6th June 2017
  • Bug fixes

Contributions

Many thanks to the following people for their contributions to this library:

Want to Contribute?

If you would like to submit a pull request for this library, please do! But kindly follow the following simple guidelines...

  • Make the changes as concise as is possible for the change you are proposing
  • Avoid unnecessarily changing a large number of lines - e.g. commits changing the number of spaces in indentations on all lines (and so on)
  • Keep to the code style of this library which is the JUCE Coding Standards
  • Make the changes relative to the develop branch of the library (as this may have advanced beyond the master branch)

License

MIT License

Copyright (c) 2017 Adam Stark

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

audiofile's People

Contributors

abhinav1997 avatar adamstark avatar alxarsenault avatar benjaminhinchliff avatar emiro85 avatar heartofrain avatar helloimmatt avatar mrpossoms avatar mynameisjohn avatar sidelobe avatar sschaetz avatar yhcrown avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

audiofile's Issues

Thread Safety

Since loading some large audio files can take some time, and I don't want it to block my main thread, I was trying to load it from another thread. However, it threw std::bad_alloc every time I tried to do so. I'm wondering if this library doesn't support multi-threading or if I was doing something wrong.

Write int16_t samples

Hey, I'm trying to write out int16 samples at 8khz into my audio file (by appending them continously). My code looks like this:

AudioFile<Float> inputFile;

void setup()
{
        inputFile.setNumChannels(1);
        inputFile.setSampleRate(8000);
        inputFile.setBitDepth(16);
}

void append(const int16_t *inputData, uint32_t samples)
{
    for (int i = 0; i < samples; i++)
    {
        float sample = inputData[i] / 32768;
        inputFile.samples[0].push_back(sample);
    }
}

void close()
{
    inputFile.printSummary();
    inputFile.save ("input.wav");
}

The file is created correctly, but i can't hear any sound at all. Any suggestions what i'm doing wrong? The summary also prints correct information

Warnings of "warning: dereferencing type-punned pointer will break strict-aliasing rules"

I'd love for these to get addressed! Much appreciated!

src/Common/AudioFile.h: In instantiation of 'bool AudioFile::decodeWaveFile(std::vector&) [with T = float]':
src/Common/AudioFile.h:460:16: required from 'bool AudioFile::load(std::string) [with T = float; std::string = std::__cxx11::basic_string]'
src/Common/sample.hpp:75:29: required from here
src/Common/AudioFile.h:585:59: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
585 | sample = (T)reinterpret_cast<float&> (sampleAsInt);

Saving file as it is streamed

I am working on a project in which data keeps streaming in and I need to save the frames to wav as they come in. I cannot wait until I have all the data to save and the sequence load_wav-add_samplesa-save_wav seems wasteful and I may lose frames.
Is there a better way to "flush" the frames to disk without having to close the file all the time?

Set sample rate does not change number of samples

Changing the sample rate does not change the total number of samples, it changes the duration of audio instead.

Code

    AudioFile<double> audioFile;
    audioFile.load(inputAudioFile);
    cout << "Summary before changing sample rate\n";
    audioFile.printSummary();
    audioFile.setSampleRate(16000);
    cout << "\n\nSummary after changing sample rate\n";
    audioFile.printSummary();

Output

Summary before changing sample rate
|======================================|
Num Channels: 2
Num Samples Per Channel: 2880000
Sample Rate: 48000
Bit Depth: 16
Length in Seconds: 60
|======================================|


Summary after changing sample rate
|======================================|
Num Channels: 2
Num Samples Per Channel: 2880000
Sample Rate: 16000
Bit Depth: 16
Length in Seconds: 180
|======================================|

Expected behavior is that Num Samples Per Channel should get one third.

Does not compile out of the box on Ubuntu 22.04 - doctest.h needs to be upgraded to 2.4.10

When I try and compile it get an error in doctest.h

cmake --build .
[ 25%] Built target Examples
Consolidate compiler generated dependencies of target Tests
[ 37%] Building CXX object tests/CMakeFiles/Tests.dir/main.cpp.o
In file included from /home/paulw/AudioFile/tests/main.cpp:3:
/home/paulw/AudioFile/tests/doctest/doctest.h:4032:47: error: size of array ‘altStackMem’ is not an integral constant-expression
4032 | static char altStackMem[4 * SIGSTKSZ];
| ^
gmake[2]: *** [tests/CMakeFiles/Tests.dir/build.make:76: tests/CMakeFiles/Tests.dir/main.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:142: tests/CMakeFiles/Tests.dir/all] Error 2
gmake: *** [Makefile:101: all] Error 2

This is because there is a problem with the doctest.h file, upgrading doctest.h to the latest version 2.4.10 solves the problem and it builds okay.

cmake --build .
[ 12%] Building CXX object examples/CMakeFiles/Examples.dir/examples.cpp.o
[ 25%] Linking CXX executable Examples
[ 25%] Built target Examples
[ 37%] Building CXX object tests/CMakeFiles/Tests.dir/main.cpp.o
[ 50%] Building CXX object tests/CMakeFiles/Tests.dir/GeneralTests.cpp.o
[ 62%] Building CXX object tests/CMakeFiles/Tests.dir/WavLoadingTests.cpp.o
[ 75%] Building CXX object tests/CMakeFiles/Tests.dir/AiffLoadingTests.cpp.o
[ 87%] Building CXX object tests/CMakeFiles/Tests.dir/FileWritingTests.cpp.o
[100%] Linking CXX executable Tests
[100%] Built target Tests

Backwards compatibility ?

Here's a preview of some of the error log that i faced.

In file included from /usr/include/c++/5/unordered_map:35:0,
                 from AudioFile.h:31,
                 from debug.cpp:9:
/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
 #error This file requires compiler and library support \
  ^
In file included from debug.cpp:9:0:
AudioFile.h:57:1: warning: scoped enums only available with -std=c++11 or -std=gnu++11
 enum class AudioFileFormat
 ^
AudioFile.h:160:5: warning: scoped enums only available with -std=c++11 or -std=gnu++11
     enum class Endianness
     ^
In file included from debug.cpp:9:0:
AudioFile.h:212:34: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
     bool logErrorsToConsole {true};
                                  ^

My g++ version is

$ g++ -v

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.11' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.11)

How should i modify the AudioFile.h to resolve this issue ?

Max-int overflow

Hi Adam,

In a short test, filling the buffer with some sine values, I noticed the resulting wave had a negative peak value, where it should have been the max positive value. It seems to be that a 1.0 float value in the buffer is saved as 32768 (for the 16-bit format). This is the piece of code for saving the file:

            else if (bitDepth == 16)
            {
                int16_t sampleAsInt = (int16_t) (samples[channel][i] * (T)32768.);
                addInt16ToFileData (fileData, sampleAsInt);
            }

The easiest solution would be to replace the 32768 value by a 32767, hereby 'losing' the max nagative -32768 value. Or using an intermediate 32-bit value, which is clipped between 32767 and -32768 afterwards.

Regards and thanks for your code,

Ruud

unordered_map link problem

There is a link problem in AudioFile.cpp at aiffSampleRateTable, please change the class in unordered_map
template definition from int to long or uint32_t, etc..., to fix it.

std::unordered_map <long, std::vector<uint8_t> > aiffSampleRateTable

Nice code btw.

Can I get the Header size?

Hello , this is a good tool.If I want to get the header size of a wav file ,maybe 44 bytes or else , can this tool help me?

Any support for short type?

Hi, i met a error when using short type,
"This version of AudioFile only supports floating point sample formats"

Will AudioFile support short type in the future?
Thanks.

Unit test

I do not know if this is fixed by the XCode environment but I had issues running the FileWritingTests on Linux:

  • the filepath of created files is not relative
    I had to edit lines 39 and 44 to return audioFile.save ("./audio-write-tests/...
  • the repertory audio-write-tests does not exist.
    I had to create it.

Again this may be due to the environment. Great work

Only one hpp file

Due to the fact that you're implementing a Template, to avoid issues with different compilers, you should consider having only one .hpp file with the full template definition there.

Problem with max() function under Windows

There are several locations where the codebase uses the max() function, such as this one

            int32_t sampleAsInt = (int32_t) (samples[channel][i] * std::numeric_limits<int32_t>::max());

the problem, as documented here [ https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax ] is that Windows defines max() and min() macro's, which don't expand nicely and aren't what we want. The solution is one suggested, to disable macro expansion by doing this

            int32_t sampleAsInt = (int32_t) (samples[channel][i] * (std::numeric_limits<int32_t>::max)());

... which once done in the various places that min() and max() are called fix the issue ...

Add isOpen() function

Maybe add a function isOpen() to know if the file has been correctly opened like std::basic_fstream::is_open.

Or thrown exception inside load() is the file cannot be load but when I am wrong in the file name just all value are 0, no way of knowing that the file is not loading.
For the moment I have to do this:

AudioFile<float> audioFile;
audioFile.load(fileName);

if(audioFile.getNumSamplesPerChannel() == 0)
    throw std::runtime_error("Cannot open " + fileName + ".");

But it is not very clean.

MIT License

Would you consider releasing this project under MIT or similar ?

Support for higher bitrates?

Hello!

I recently replaced dr_wav with your wonderful AudioFile library. I've been getting reports from some of my users that .wav files that previously loaded and play fine no longer work. I've found that the reason is that the .wav files that they were using were greater than than 24-bit.

The bitrates supported by dr_wav are:

Unsigned 8-bit PCM
Signed 12-bit PCM
Signed 16-bit PCM
Signed 24-bit PCM
Signed 32-bit PCM
IEEE 32-bit floating point
IEEE 64-bit floating point

Would it be possible to support these .wav file formats?

Thanks!
Bret

Overload AudioFile::load to accept a memory load

It would be very helpful for directly loading decrypted .wav files. I noted it is almost done with AudioFile::decodeWaveFile, but it is a private method, so maybe an overloaded option of AudioFile::load would be great, accepting (void* data, size_t size) or std::vector<uint8_t>
Thanks for this awesome library

Use-of-uninitialized-value waring with MSAN in AudioFile

Hi, Adam:
When I use msan to run AudioFile's exmaple program, it outputs the following error message:

Uninitialized bytes in MemcmpInterceptorCommon at offset 48 inside [0x7fffcb727450, 256)
==89831==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x5627f25d0a0e in __interceptor_memcmp (/workspace/test/msan/AudioFile/examples/Examples+0x5da0e) (BuildId: d090aa71c8d408cc1981b1bbc768ff7bf3daf5a3)
    #1 0x7f3f4348d071 in std::ctype<char>::_M_widen_init() const (/lib/x86_64-linux-gnu/libstdc++.so.6+0xd7071) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)
    #2 0x7f3f434f280f in std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x13c80f) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)
    #3 0x5627f2620132 in examples::writeSineWaveToAudioFile() (/workspace/test/msan/AudioFile/AudioFile/Examples+0xad132) (BuildId: d090aa71c8d408cc1981b1bbc768ff7bf3daf5a3)
    #4 0x5627f2620010 in main (/workspace/test/msan/AudioFile/examples/Examples+0xad010) (BuildId: d090aa71c8d408cc1981b1bbc768ff7bf3daf5a3)
    #5 0x7f3f430b0d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 89c3cb85f9e55046776471fed05ec441581d1969)
    #6 0x7f3f430b0e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 89c3cb85f9e55046776471fed05ec441581d1969)
    #7 0x5627f2597ee4 in _start (/workspace/test/msan/AudioFile/examples/Examples+0x24ee4) (BuildId: d090aa71c8d408cc1981b1bbc768ff7bf3daf5a3)

SUMMARY: MemorySanitizer: use-of-uninitialized-value (/workspace/test/msan/AudioFile/examples/Examples+0x5da0e) (BuildId: d090aa71c8d408cc1981b1bbc768ff7bf3daf5a3) in __interceptor_memcmp
Exiting

Although this does not necessarily bring any high-risk effects, I still think it is an abnormal result, and hope to get your attention

Verification steps:

git clone https://github.com/adamstark/AudioFile.git
cd AudioFile/
git checkout develop
mkdir check_build && cd check_build
cmake ../ -DCMAKE_C_COMPILER=clang  -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="-fsanitize=memory" -DCMAKE_CXX_FLAGS="-fsanitize=memory" 
make -j 
cd examples
./Examples

enviroment:
Ubuntu 22.04 LTS
Linux lab-pro 4.15.0-147-generic
gcc (Ubuntu 11.2.0-19ubuntu1) 11.2.0
Ubuntu clang version 14.0.6

Thanks & Best regards !

Two heap-buffer-overflow, the first one in function decodeWaveFile() at AudioFile.h:502, and the second one in function determineAudioFileFormat() at AudioFile.h:1148.

Describe

Two heap-buffer-overflow were discovered in AudioFile. The first one is being triggered in function decodeWaveFile() at AudioFile.h:502, and the second one is being triggered in function determineAudioFileFormat() at AudioFile.h:1148.

Reproduce

test program
just little change in examples.cpp

#include <iostream>
#define _USE_MATH_DEFINES
#include <cmath>
#include "AudioFile.h"

//=======================================================================
namespace examples
{
    void writeSineWaveToAudioFile();
    void loadAudioFileAndPrintSummary(char *);
    void loadAudioFileAndProcessSamples(char *);
} // namespace examples

//=======================================================================
int main(int argc, char **argv)
{
    //---------------------------------------------------------------
    /** Writes a sine wave to an audio file */
    //examples::writeSineWaveToAudioFile();

    //__AFL_LOOP() used in AFL Persistent mode, if u don't use AFL compile, just comment 
    while (__AFL_LOOP(10000))
    {
        //---------------------------------------------------------------
        /** Loads an audio file and prints key details to the console*/
        examples::loadAudioFileAndPrintSummary(argv[1]);

        //---------------------------------------------------------------
        /** Loads an audio file and processess the samples */
        examples::loadAudioFileAndProcessSamples(argv[1]);
    }
    return 0;
}

//=======================================================================
namespace examples
{
    //=======================================================================
    void writeSineWaveToAudioFile()
    {
        //---------------------------------------------------------------
        std::cout << "**********************" << std::endl;
        std::cout << "Running Example: Write Sine Wave To Audio File" << std::endl;
        std::cout << "**********************" << std::endl
                  << std::endl;

        //---------------------------------------------------------------
        // 1. Let's setup our AudioFile instance

        AudioFile<float> a;
        a.setNumChannels(2);
        a.setNumSamplesPerChannel(44100);

        //---------------------------------------------------------------
        // 2. Create some variables to help us generate a sine wave

        const float sampleRate = 44100.f;
        const float frequencyInHz = 440.f;

        //---------------------------------------------------------------
        // 3. Write the samples to the AudioFile sample buffer

        for (int i = 0; i < a.getNumSamplesPerChannel(); i++)
        {
            for (int channel = 0; channel < a.getNumChannels(); channel++)
            {
                a.samples[channel][i] = sin((static_cast<float>(i) / sampleRate) * frequencyInHz * 2.f * M_PI);
            }
        }

        //---------------------------------------------------------------
        // 4. Save the AudioFile

        std::string filePath = "sine-wave.wav"; // change this to somewhere useful for you
        a.save("sine-wave.wav", AudioFileFormat::Wave);
    }

    //=======================================================================
    void loadAudioFileAndPrintSummary(char *file)
    {
        //---------------------------------------------------------------
        std::cout << "**********************" << std::endl;
        std::cout << "Running Example: Load Audio File and Print Summary" << std::endl;
        std::cout << "**********************" << std::endl
                  << std::endl;

        //---------------------------------------------------------------
        // 1. Set a file path to an audio file on your machine
        const std::string filePath = std::string(file);

        //---------------------------------------------------------------
        // 2. Create an AudioFile object and load the audio file

        AudioFile<float> a;
        bool loadedOK = a.load(filePath);

        /** If you hit this assert then the file path above
         probably doesn't refer to a valid audio file */
        assert(loadedOK);

        //---------------------------------------------------------------
        // 3. Let's print out some key details

        std::cout << "Bit Depth: " << a.getBitDepth() << std::endl;
        std::cout << "Sample Rate: " << a.getSampleRate() << std::endl;
        std::cout << "Num Channels: " << a.getNumChannels() << std::endl;
        std::cout << "Length in Seconds: " << a.getLengthInSeconds() << std::endl;
        std::cout << std::endl;
    }

    //=======================================================================
    void loadAudioFileAndProcessSamples(char *file)
    {
        //---------------------------------------------------------------
        std::cout << "**********************" << std::endl;
        std::cout << "Running Example: Load Audio File and Process Samples" << std::endl;
        std::cout << "**********************" << std::endl
                  << std::endl;

        //---------------------------------------------------------------
        // 1. Set a file path to an audio file on your machine
        const std::string inputFilePath = std::string(file);

        //---------------------------------------------------------------
        // 2. Create an AudioFile object and load the audio file

        AudioFile<float> a;
        bool loadedOK = a.load(inputFilePath);

        /** If you hit this assert then the file path above
         probably doesn't refer to a valid audio file */
        assert(loadedOK);

        //---------------------------------------------------------------
        // 3. Let's apply a gain to every audio sample

        float gain = 0.5f;

        for (int i = 0; i < a.getNumSamplesPerChannel(); i++)
        {
            for (int channel = 0; channel < a.getNumChannels(); channel++)
            {
                a.samples[channel][i] = a.samples[channel][i] * gain;
            }
        }

        //---------------------------------------------------------------
        // 4. Write audio file to disk

        //std::string outputFilePath = "quieter-audio-filer.wav"; // change this to somewhere useful for you
        //a.save(outputFilePath, AudioFileFormat::Aiff);
    }
} // namespace examples

Tested in parrot 4.9, 64bit.
Compile test program with address sanitizer with this command:

g++ -g -fsanitize=address -o asantry examples.cpp AudioFile.h
You can get program here.

ASan Reports

The first one

./asantry ./out/default/crashes/id\:000005\,sig\:06\,src\:000006\,time\:84641\,op\:havoc\,rep\:2

Get ASan reports

**********************
Running Example: Load Audio File and Print Summary
**********************

=================================================================
==23==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000738 at pc 0x55da0cb245e9 bp 0x7ffc6e244e90 sp 0x7ffc6e244e80
READ of size 1 at 0x602000000738 thread T0
    #0 0x55da0cb245e8 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy_chars<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(char*, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >) /usr/include/c++/10/bits/basic_string.h:379
    #1 0x55da0cb226a7 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::forward_iterator_tag) /usr/include/c++/10/bits/basic_string.tcc:225
    #2 0x55da0cb1fba7 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::__false_type) /usr/include/c++/10/bits/basic_string.h:247
    #3 0x55da0cb1cfd5 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >) /usr/include/c++/10/bits/basic_string.h:266
    #4 0x55da0cb19e45 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, void>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<char> const&) /usr/include/c++/10/bits/basic_string.h:628
    #5 0x55da0cb11fcd in AudioFile<float>::decodeWaveFile(std::vector<unsigned char, std::allocator<unsigned char> >&) /src/AudioFile.h:502
    #6 0x55da0cb0d359 in AudioFile<float>::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /src/AudioFile.h:481
    #7 0x55da0cb0554d in examples::loadAudioFileAndPrintSummary(char*) /src/examples.cpp:95
    #8 0x55da0cb04d0e in main /src/examples.cpp:26
    #9 0x7fede8fdb0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #10 0x55da0cb04c0d in _start (/src/asantry+0x4c0d)

0x602000000738 is located 2 bytes to the right of 6-byte region [0x602000000730,0x602000000736)
allocated by thread T0 here:
    #0 0x7fede95a2f17 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.6+0xb1f17)
    #1 0x55da0cb1da08 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) /usr/include/c++/10/ext/new_allocator.h:115
    #2 0x55da0cb1ac79 in std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) /usr/include/c++/10/bits/alloc_traits.h:460
    #3 0x55da0cb16819 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) /usr/include/c++/10/bits/stl_vector.h:346
    #4 0x55da0cb195b6 in std::vector<unsigned char, std::allocator<unsigned char> >::_M_default_append(unsigned long) /usr/include/c++/10/bits/vector.tcc:635
    #5 0x55da0cb11896 in std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long) /usr/include/c++/10/bits/stl_vector.h:940
    #6 0x55da0cb0d192 in AudioFile<float>::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /src/AudioFile.h:465
    #7 0x55da0cb0554d in examples::loadAudioFileAndPrintSummary(char*) /src/examples.cpp:95
    #8 0x55da0cb04d0e in main /src/examples.cpp:26
    #9 0x7fede8fdb0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/include/c++/10/bits/basic_string.h:379 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy_chars<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(char*, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >)
Shadow bytes around the buggy address:
  0x0c047fff8090: fa fa fd fd fa fa fd fd fa fa 00 02 fa fa 00 02
  0x0c047fff80a0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff80b0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff80c0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff80d0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
=>0x0c047fff80e0: fa fa 00 02 fa fa 06[fa]fa fa fa fa fa fa fa fa
  0x0c047fff80f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==23==ABORTING

Poc

Poc file is here.

The second one

./asantry ./out/default/crashes/id\:000000\,sig\:06\,src\:000006\,time\:291\,op\:havoc\,rep\:16

Get ASan reports

**********************
Running Example: Load Audio File and Print Summary
**********************

=================================================================
==13==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000731 at pc 0x561c434c55e9 bp 0x7ffeb0ea5a50 sp 0x7ffeb0ea5a40
READ of size 1 at 0x602000000731 thread T0
    #0 0x561c434c55e8 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy_chars<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(char*, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >) /usr/include/c++/10/bits/basic_string.h:379
    #1 0x561c434c36a7 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::forward_iterator_tag) /usr/include/c++/10/bits/basic_string.tcc:225
    #2 0x561c434c0ba7 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::__false_type) /usr/include/c++/10/bits/basic_string.h:247
    #3 0x561c434bdfd5 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >) /usr/include/c++/10/bits/basic_string.h:266
    #4 0x561c434bae45 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, void>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<char> const&) /usr/include/c++/10/bits/basic_string.h:628
    #5 0x561c434b2a75 in AudioFile<float>::determineAudioFileFormat(std::vector<unsigned char, std::allocator<unsigned char> >&) /src/AudioFile.h:1148
    #6 0x561c434ae2ee in AudioFile<float>::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /src/AudioFile.h:477
    #7 0x561c434a654d in examples::loadAudioFileAndPrintSummary(char*) /src/examples.cpp:95
    #8 0x561c434a5d0e in main /src/examples.cpp:26
    #9 0x7f99260b30b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #10 0x561c434a5c0d in _start (/src/asantry+0x4c0d)

0x602000000731 is located 0 bytes to the right of 1-byte region [0x602000000730,0x602000000731)
allocated by thread T0 here:
    #0 0x7f992667af17 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.6+0xb1f17)
    #1 0x561c434bea08 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) /usr/include/c++/10/ext/new_allocator.h:115
    #2 0x561c434bbc79 in std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) /usr/include/c++/10/bits/alloc_traits.h:460
    #3 0x561c434b7819 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) /usr/include/c++/10/bits/stl_vector.h:346
    #4 0x561c434ba5b6 in std::vector<unsigned char, std::allocator<unsigned char> >::_M_default_append(unsigned long) /usr/include/c++/10/bits/vector.tcc:635
    #5 0x561c434b2896 in std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long) /usr/include/c++/10/bits/stl_vector.h:940
    #6 0x561c434ae192 in AudioFile<float>::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /src/AudioFile.h:465
    #7 0x561c434a654d in examples::loadAudioFileAndPrintSummary(char*) /src/examples.cpp:95
    #8 0x561c434a5d0e in main /src/examples.cpp:26
    #9 0x7f99260b30b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/include/c++/10/bits/basic_string.h:379 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy_chars<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(char*, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >)
Shadow bytes around the buggy address:
  0x0c047fff8090: fa fa fd fd fa fa fd fd fa fa 00 02 fa fa 00 02
  0x0c047fff80a0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff80b0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff80c0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff80d0: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
=>0x0c047fff80e0: fa fa 00 02 fa fa[01]fa fa fa fa fa fa fa fa fa
  0x0c047fff80f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==13==ABORTING

Poc

Poc file is here.

Fuzzer & Testcase

Fuzzer is AFLplusplus.
Testcase is in here.
I use your testcase in file tests/test-audio/ and I choose .wav files. Then I use afl-cmin to minisize these files.

conversion from 48.0 kHz to 44.1 kHz sample rate conversion

Hi there,

Thanks so much for this brilliant library. I'm using it with great success so far. I know next to nothing about this stuff which speaks to how simple to use this library is.

I was wondering if you might have some pointers for me, I'm trying to convert a file's sample rate from 48.0 kHz to 44.1 kHz

When I load a file 48.0 kHz, use a.setSampleRate(44100); and then save the file.
If I play back the file, it sounds slower and lower pitched.

Would you consider adding this scenario to your examples section>?

Example Fucntion "loadAudioFileAndProcessSamples" Returning Corrupted File

Hi Adam,

In your examples.cpp file, the "loadAudioFileAndProcessSamples" function, on line 144, the audio file is incorrectly saved as an Aiff rather than a Wave file. This results in a corrupted audio file output.

Thank You for this library and the provided examples. Very helpful for new programmers.

Normalize after loading wav file

Hey! Thanks for the lib, it really helps!

A question/feature, more than an issue. I was wondering if you are normalizing the .wav input after loading the file and if this can be disabled somehow.

Best

-Wsign-compare warnings

When using this library, I get a few warnings related to -Wsign-compare. Are there any plans on fixing it? It shouldn't be too hard.

In file included from src/main.cpp:3:
src/../include/AudioFile.h: In instantiation of ‘bool AudioFile<T>::decodeWaveFile(std::vector<unsigned char>&) [with T = double]’:
src/../include/AudioFile.h:403:16:   required from ‘bool AudioFile<T>::load(std::string) [with T = double; std::string = std::__cxx11::basic_string<char>]’
src/main.cpp:20:40:   required from here
src/../include/AudioFile.h:468:28: warning: comparison of integer expressions of different signedness: ‘int32_t’ {aka ‘int’} and ‘uint32_t’ {aka ‘unsigned int’
} [-Wsign-compare]
  468 |     if ((numBytesPerSecond != (numChannels * sampleRate * bitDepth) / 8) || (numBytesPerBlock != (numChannels * numBytesPerSample)))
      |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/../include/AudioFile.h: In instantiation of ‘bool AudioFile<T>::decodeAiffFile(std::vector<unsigned char>&) [with T = double]’:
src/../include/AudioFile.h:407:16:   required from ‘bool AudioFile<T>::load(std::string) [with T = double; std::string = std::__cxx11::basic_string<char>]’
src/main.cpp:20:40:   required from here
src/../include/AudioFile.h:599:90: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<unsigned char>::size_type’ {aka
long unsigned int’} [-Wsign-compare]
  599 |     if ((soundDataChunkSize - 8) != totalNumAudioSampleBytes || totalNumAudioSampleBytes > (fileData.size() - samplesStartIndex))
      |                                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/../include/AudioFile.h: In instantiation of ‘int AudioFile<T>::getIndexOfString(std::vector<unsigned char>&, std::string) [with T = double; std::string = s
td::__cxx11::basic_string<char>]’:
src/../include/AudioFile.h:428:28:   required from ‘bool AudioFile<T>::decodeWaveFile(std::vector<unsigned char>&) [with T = double]’
src/../include/AudioFile.h:403:16:   required from ‘bool AudioFile<T>::load(std::string) [with T = double; std::string = std::__cxx11::basic_string<char>]’
src/main.cpp:20:40:   required from here
src/../include/AudioFile.h:1007:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<unsigned char>::size_type’ {aka
‘long unsigned int’} [-Wsign-compare]
 1007 |     for (int i = 0; i < source.size() - stringLength;i++)
      |                     ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/../include/AudioFile.h: In instantiation of ‘void AudioFile<T>::clearAudioBuffer() [with T = double]’:
src/../include/AudioFile.h:490:5:   required from ‘bool AudioFile<T>::decodeWaveFile(std::vector<unsigned char>&) [with T = double]’
src/../include/AudioFile.h:403:16:   required from ‘bool AudioFile<T>::load(std::string) [with T = double; std::string = std::__cxx11::basic_string<char>]’
src/main.cpp:20:40:   required from here
src/../include/AudioFile.h:950:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<double, std::allocato
r<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  950 |     for (int i = 0; i < samples.size();i++)

Great job on the library by the way!! Super useful and lightweight :)

Multiple inclusion

Hi Adam,

This is a nice header-only library.

Quick Q: If the header is included in two different cpp files, won't you get two independent copies of the aiff sample rate table, because the static will be scoped to within the cpp file that included it?

// Pre-defined 10-byte representations of common sample rates
static std::unordered_map <uint32_t, std::vector<uint8_t>> aiffSampleRateTable = {
    {8000, {64, 11, 250, 0, 0, 0, 0, 0, 0, 0}},

[Bug]heap-buffer-overflow in function fouBytesToInt():AudioFile.h:1196

Description

A heap-buffer-overflow was discovered in function fouBytesToInt():AudioFile.h:1196
The issue is being triggered in function getIndexOfChunk()

Version

Version 004065d (Lastest commit)

Environment

Ubuntu 18.04, 64bit

Reproduce

Command

git clone the Lastest Version firstly.
mkdir build
cd build && cmake ..
g++ -g -fsanitize=address -o valibin a.cpp AudioFile.h
./ poc

program

#include <iostream>
#define _USE_MATH_DEFINES
#include <cmath>
#include "AudioFile.h"

namespace examples

{

    void writeSineWaveToAudioFile();

    void loadAudioFileAndPrintSummary(char *);

    void loadAudioFileAndProcessSamples(char *);

} // namespace examples

int main(int argc, char **argv)

{
        examples::loadAudioFileAndPrintSummary(argv[1]);
        examples::loadAudioFileAndProcessSamples(argv[1]);
}





namespace examples

{

    void writeSineWaveToAudioFile()

    {
  

        AudioFile<float> a;

        a.setNumChannels(2);

        a.setNumSamplesPerChannel(44100);



        //---------------------------------------------------------------

        // 2. Create some variables to help us generate a sine wave



        const float sampleRate = 44100.f;

        const float frequencyInHz = 440.f;



        //---------------------------------------------------------------

        // 3. Write the samples to the AudioFile sample buffer



        for (int i = 0; i < a.getNumSamplesPerChannel(); i++)

        {

            for (int channel = 0; channel < a.getNumChannels(); channel++)

            {

                a.samples[channel][i] = sin((static_cast<float>(i) / sampleRate) * frequencyInHz * 2.f * M_PI);

            }

        }



        //---------------------------------------------------------------

        // 4. Save the AudioFile



        std::string filePath = "sine-wave.wav"; // change this to somewhere useful for you

        a.save("sine-wave.wav", AudioFileFormat::Wave);

    }



    //=======================================================================

    void loadAudioFileAndPrintSummary(char *file)

    {
        const std::string filePath = std::string(file);

        AudioFile<float> a;

        bool loadedOK = a.load(filePath);



        /** If you hit this assert then the file path above

         probably doesn't refer to a valid audio file */

        assert(loadedOK);



        //---------------------------------------------------------------

        // 3. Let's print out some key details



        std::cout << "Bit Depth: " << a.getBitDepth() << std::endl;

        std::cout << "Sample Rate: " << a.getSampleRate() << std::endl;

        std::cout << "Num Channels: " << a.getNumChannels() << std::endl;

        std::cout << "Length in Seconds: " << a.getLengthInSeconds() << std::endl;

        std::cout << std::endl;

    }



    //=======================================================================

    void loadAudioFileAndProcessSamples(char *file)

    {

        //---------------------------------------------------------------

        std::cout << "**********************" << std::endl;

        std::cout << "Running Example: Load Audio File and Process Samples" << std::endl;

        std::cout << "**********************" << std::endl

                  << std::endl;



        //---------------------------------------------------------------

        // 1. Set a file path to an audio file on your machine

        const std::string inputFilePath = std::string(file);



        //---------------------------------------------------------------

        // 2. Create an AudioFile object and load the audio file



        AudioFile<float> a;

        bool loadedOK = a.load(inputFilePath);



        /** If you hit this assert then the file path above

         probably doesn't refer to a valid audio file */

        assert(loadedOK);



        //---------------------------------------------------------------

        // 3. Let's apply a gain to every audio sample



        float gain = 0.5f;



        for (int i = 0; i < a.getNumSamplesPerChannel(); i++)

        {

            for (int channel = 0; channel < a.getNumChannels(); channel++)

            {

                a.samples[channel][i] = a.samples[channel][i] * gain;

            }

        }



        //---------------------------------------------------------------

        // 4. Write audio file to disk



        //std::string outputFilePath = "quieter-audio-filer.wav"; // change this to somewhere useful for you

        //a.save(outputFilePath, AudioFileFormat::Aiff);

    }

} // namespace examples

POC file at the bottom of this report.

ASAN Report

image

image

POC

POC

Any issue plz contact with me:
[email protected]
OR:
twitter: @Asteriska8

Can't compile AudioFile with Clang14.0.6

Hi adam:
Recently I want to use fuzz to test this program, but it can't be compiled correctly in my enviroment (Ubuntu 22.04, clang version 14.0.6). The error message is here:

In file included from /workspace/AudioFile/tests/main.cpp:3:
/workspace/AudioFile/tests/doctest/doctest.h:4032:33: error: variable length array declaration not allowed at file scope
        static char             altStackMem[4 * SIGSTKSZ];
                                ^           ~~~~~~~~~~~~
1 error generated.
gmake[2]: *** [tests/CMakeFiles/Tests.dir/build.make:76: tests/CMakeFiles/Tests.dir/main.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:142: tests/CMakeFiles/Tests.dir/all] Error 2
gmake: *** [Makefile:101: all] Error 2

according to adishavit/argh#66
This issue seems to be related to doctest. I guess we need to upgrade the doctest version to 2.46. If you don't mind, I'll propose a PR on this issue.
Thanks & Best regards!

Make AudioFile.h compatible with more compilation options.

Make AudioFile.h compatible with -Wall -Wextra -pedantic -Werror compilation options for GCC (And /W4 and /WX for MSVC).
This will make it easier project compatible with many projects.
You can use GitHub Actions to easly run tests on Linux, Windows and Mac.

Unresolved external symbol

Error LNK2019 unresolved external symbol "public: __thiscall AudioFile::AudioFile(void)" (??0?$AudioFile@N@@QAE@XZ) referenced in function _main Project1

When trying to create object AudioFile. Does this have to do something with templates being declarated in cpp files, instead of the .h file?

Compiler error on VS2019

I'm on Visual Studio Community 2019 v16.8.3 and I get some errors on compiling, in Audiofile.h.

C2062, C2144, C2059 and C2589.
All on both lines 619 and 764.

The max() function seems to be the problem, as shows the C2589 error.

I was able to compile successfully with an older version of 2020 (with two files, Audiofile.h and Audiofile.cpp).

Is partial loading possible?

I would like to load just an interval of a given .wav file aiming to avoid bringing the full audio to memory. Is it possible?
When I call .load(filepath) it seems to bring everything at once. Am I right?

Thank you for this awesome lib!

Can Play ?

Hello, it's possible to play with the AudioBuffer in AudioFile ?

Add documentation on how to fill a buffer with samples

// 1. Create an AudioBuffer
// (BTW, AudioBuffer is just a vector of vectors)

AudioFile::AudioBuffer buffer;

// 2. Set to (e.g.) two channels
buffer.resize (2);

// 3. Set number of samples per channel
buffer[0].resize (100000);
buffer[1].resize (100000);

// 4. do something here to fill the buffer with samples

// 5. Put into the AudioFile object
bool ok = audioFile.setAudioBuffer (buffer);

Step 4 is way too vague. How do I actually add samples?

build errors

Hello,

Thanks for the repo! I'm trying to use it and I get an error when I try to load a wav file. Do you know what the issue might be?

In file included from main.cpp:9:
./AudioFile.h:37:6: warning: scoped enumerations are a C++11 extension [-Wc++11-extensions]
enum class AudioFileFormat
     ^
./AudioFile.h:131:10: warning: scoped enumerations are a C++11 extension [-Wc++11-extensions]
    enum class Endianness
         ^
./AudioFile.h:67:63: warning: use of enumeration in a nested name specifier is a C++11
      extension [-Wc++11-extensions]
    bool save (std::string filePath, AudioFileFormat format = AudioFileFormat::Wave);
                                                              ^
3 warnings generated.
Undefined symbols for architecture x86_64:
  "AudioFile<double>::load(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
      _main in main-57de2a.o
  "AudioFile<double>::AudioFile()", referenced from:
      ___cxx_global_var_init in main-57de2a.o
  "AudioFile<double>::printSummary() const", referenced from:
      _main in main-57de2a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Thanks!

Get size of AudioFile, to assign to OpenAL Soft buffer

Hi Mr. Adam Stark,

May I know how to get the size of an AudioFile because I want to assign to OpenAL Soft generated buffer to store the AudioBuffer. I am referring to the tutorial here (LINE 157, 163, 169). Sorry for the inconvenience.

Thank you Mr. Adam Stark

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.