2

I have been building a simple samplerate converter in c using libsndfile and libsamplerate. I just cant seem to get the src_simple function of libsamplerate to work, whatever I try. I have striped back my code to be as simple as possible and it now just outputs a silent audio file of identical sampling rate:

#include <stdio.h>
#include <sndfile.h>
#include <samplerate.h>

#define BUFFER_LEN 1024
#define MAX_CHANNELS 6

int main ()
{
    static double datain [BUFFER_LEN];
    static double dataout [BUFFER_LEN];
    SNDFILE *infile, *outfile;
    SF_INFO     sfinfo, sfinfo2 ;
    int         readcount ;
    const char  *infilename = "C:/Users/Oli/Desktop/MARTYTHM.wav" ;
    const char  *outfilename = "C:/Users/Oli/Desktop/Done.wav" ;
    SRC_DATA    src_data;

    infile = sf_open (infilename, SFM_READ, &sfinfo);
    outfile = sf_open (outfilename, SFM_WRITE, &sfinfo);

    src_data.data_in = datain
    src_data.input_frames = BUFFER_LEN;
    src_data.data_out = dataout;
    src_data.output_frames = BUFFER_LEN;
    src_data.src_ratio = 0.5;

    src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);

    while ((readcount = sf_read_double (infile, datain, BUFFER_LEN)))
    {
        src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
        sf_write_double (outfile, dataout, readcount) ;
    };

    sf_close (infile);
    sf_close (outfile);

    sf_open ("C:/Users/Oli/Desktop/Done.wav", SFM_READ, &sfinfo2);

    printf("%d", sfinfo2.samplerate);

    return 0;
}

It's really starting to stress me out. The program is a uni project and is due very soon, it is making me very anxious as whatever I try seems to result in failure. Can anyone please help me?

Paul R
  • 208,748
  • 37
  • 389
  • 560
OliD
  • 37
  • 1
  • 2
  • 5
  • 1
    Why did you delete the old question and re-post it ? Now the answers and comments have been lost. – Paul R May 11 '12 at 20:37
  • Sorry I thought because it's essentially a different program I should make a new thread. – OliD May 11 '12 at 20:40
  • 1
    Well if you have a genuinely new question then feel free to post it, but don't delete the old one, as the answers may be useful for others in the future. If you just want to add further information to the original question though then just edit it. – Paul R May 11 '12 at 20:42
  • Ok sorry I'll bear that in mind. – OliD May 11 '12 at 20:45
  • 2
    Hi, can you provide the working(fixed) version of the code above? it would be really helpfully to me. Thanks – kc ochibili Oct 20 '14 at 17:42

1 Answers1

4

I'm not an expert on this particular library, but just from looking at the online documentation I see a few problems with your code:

  • src_simple apparently works with floats, yet your buffers are doubles - I think you need to change the buffers to float and use sf_read_float/sf_write_float for I/O.

  • src_simple is the "simple" interface and is intended to be applied to an entire waveform in one call, not in chunks as you are doing - see http://www.mega-nerd.com/SRC/faq.html#Q004 - you should first get the input file size, then allocate sufficient memory, read in the whole file, convert it in one go, then write the converted output data to your output file.

  • when changing sample rate you will get a different number of samples in the output file than in the output file (around half as many in for case), yet you're writing the same number of samples that you read (readcount). You should probably be using src_data.output_frames_gen as the number of frames to write, not readcount.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • Thank you. I realised the double/floater error just a minute ago and fixed it, but thanks. How would I go about applying 'src_simple' in one call? I'm not sure it's necessary for me to do it in chunks. Would I need to change 'src_data.output_frames = BUFFER_LEN;' ? How would I calculate the number of samples? Thank you for you help. – OliD May 11 '12 at 21:21
  • Re-read http://www.mega-nerd.com/SRC/api_simple.html *carefully* - the number of generated samples is returned in `src_data.output_frames_gen` - use this as the number of samples to write to your output file (i.e. pass this as the third parameter in your call to `sf_write_float`). – Paul R May 11 '12 at 21:27
  • Ok I've triend that but I'm not sure if I did it right. I now have sf_write_float (outfile, dataout, src_data.output_frames_gen) ; THis causes the outputed file to play very fast and be about 10 seconds long(it was original 1:47). – OliD May 11 '12 at 21:53
  • SOLVED: Turns out I needed to set up a separate sf_info struct for the outfile, and initialize it with the desired sampling rate so that it would playback at the correct speed. Cheers for your help. – OliD May 11 '12 at 22:29
  • 4
    I'm the main author of libsndfile and libsamplerate. I re-iterate what @PaulR says, re-read the docs on `src_simple`. It *should not* be used the way you are using it the example above. `src_simple` is for converting a whole file in one go. It does *not* give good results when called multiple times on discrete chunks of the file like you are doing. If you want to convert the file in chunks like that, you should be using the `src_process` API. Also be aware that the libsamplerate source code tarball includes sources to a program called sndfile-convert which does what you want. – Erik de Castro Lopo May 14 '12 at 23:44