2

I have looked at sample programs that use libsndfile, but could not get any of them to compile. I want to be able to read a .wav file into an array of integers (or doubles) without having to worry about what kind of .wav file it is, or even about anything in the header. I only care about getting the data into an array, so I can do my own processing on the individual samples.

I have downloaded the source code for libsndfile. There are so many files and folders, I don't know where to start. What do I need to include? What methods do I need to use? Does someone have a simple example that actually works?

thb
  • 13,796
  • 3
  • 40
  • 68
Jackson Dean Goodwin
  • 617
  • 3
  • 11
  • 20

4 Answers4

3

I am the main author/maintainer of libsndfile.

The precompiled binary packages contain the windows DLL, the documentation, the header files and some example VC7 and VC9 Project files.

The only reason you would need the source code is to look at the example programs in the examples/ directory if the source code tarball.

3

A bit of an old one, but I figured I'd chime in for future readers.

Neither answer answer the main question: How can I use libsndfile to load a .wav file into an array?

An Answer Using SndFileHandle and C++17 (17 unnecessary really but hey, I like encouraging the use):

#include <sndfile.hh>
std::filesystem::path path = "file/path.wav";
if (std::filesystem::path::is_regular_file(path))
{
  SndfileHandle myf = SndfileHandle(&path.string()[0]);
  std::vector<float> array(myf.frames());
  myf.read(&array[0], int(myf.frames());
}

A bit more can be found here: http://ofdsp.blogspot.com/2011/07/loading-wav-file-with-sndfilehandle.html (this example was inspired by this)

Also note that I chose to read it into a vector of floats. Could be anything just remember what you get out might depend on the bit rate of the wav (or other sound type) file, though I believe libsndfile is written to allow you to largely forget this.

As to the other parts of the initial question, the other answers should suffice.

Rasmus Dall
  • 1,189
  • 8
  • 12
0

Here seems to be libsndfile, precompiled and packaged for easy installation on Windows 7: http://www.mega-nerd.com/libsndfile/libsndfile-1.0.25-w64-setup.exe.

(Of course, nothing prevents you from investigating the source code whenever you like, should it interest you to do so; but, even if the source does interest you, your practice using the precompiled package will help to orient you to the source. It appears that libsndfile's native platform is Debian GNU/Linux, so the source may be a little trickier to work with under Windows. Fortunately however, if the precompiled package suits you, then you need not worry much further about the source.)

thb
  • 13,796
  • 3
  • 40
  • 68
  • Of course, the answer assumes that you've not already installed the precompiled package. Your question didn't seem to say, one way or the other. Good luck. – thb Aug 04 '12 at 11:37
0

Just for everyone getting to this post for me the above solution was not the best so I'm putting this one here too. It reads a wav file into a double array. You need to include the sndfile lib. To do that follow first the cmake installation part and then the cmake inlcude part in the ReadMe

#include <stdio.h>
#include <iostream>
#include <filesystem>
#include <vector>


#include <sndfile.hh>


int main(){
    std::cout << "STARTING MAIN\n" << std::endl;

    SF_INFO info;
    info.format = 0;

    // Open the wave file for reading
    SNDFILE *sndfile = sf_open("absolute path to .wav", SFM_READ, &info);

    if (!sndfile) {
        std::cerr << "Error: could not open file" << std::endl;
        return 1;
    }

    // Print some information about the file
    std::cout << "Sample rate: " << info.samplerate << std::endl;
    std::cout << "Channels: " << info.channels << std::endl;
    std::cout << "Samples: " << info.frames << std::endl;

    // Allocate memory for the samples
    // old: double samples[info.frames * info.channels];
    std::vector<double> samples(info.frames * info.channels);

    // Read the samples into the array
    // old: sf_readf_double(sndfile, samples, info.frames);
    sf_readf_double(sndfile, &samples[0], info.frames);

    // Close the file
    sf_close(sndfile);

    // print the size of the samples and print the first element
    // old: std::cout << "\nElements in samples: " << sizeof(samples)/sizeof(samples[0]) << std::endl;
    std::cout << "\nElements in samples: " << samples.size() << std::endl;

    // Loop through the array until the first position where the value is not 0. Print this value and postion
    for (int i = 0; i < info.frames * info.channels; i++){
        if (samples[i] != 0){
            std::cout << "Samples(" << i << "): " << samples[i] << std::endl;
            break;
        }
    }


    std::cout << "FINISHED MAIN\n" << std::endl;

    return 0;
}
Error404
  • 84
  • 7
  • Variable-length arrays are not in standard C++, and don't work in MSVC. `std::vector` should be used instead. – HolyBlackCat Jan 11 '23 at 13:19
  • 1
    That's a good point. I did that because the sndfile lib wants a `double* array`. I've changed my code s.t. it uses vectors. To track the changes I've commented them out. Also one could improve the code and change `samples[0]`to `samples.at(0)` this would catch out of bounds errors. – Error404 Jan 11 '23 at 14:18