0

first post, I'm trying to make a simple pitchshifter using libsamplerate and libsndfile. I have achieved this in the most basic form by making a simple samplerate covnerter and then hacking it, I change pitch by changing the ratio float value. The pitchshifter shifts - sounds pretty much fine on sine tones - if you use it for audio you can hear gaps between blocks of sound occuring - especially if you pitch the file up. I was wondering if there was a way of making the code a little more effective to counter this or some sort of interpolation function or library which I could implement without too much difficulty. I'm very new to C - previously only processing sound through PD and this is my first project - from what I understand libsamplerate isn't really designed for implementing pitch shifting so I know its a bit of a hack to get there.

Thanks

Heres my code

    #include <stdio.h>
    #include </usr/local/include/sndfile.h>
#include </usr/local/include/samplerate.h>

#define BUFFER_LEN 44100 //defines buffer length

#define MAX_CHANNELS 2 //defines max channels 

int main ()
{
    static float datain [BUFFER_LEN]; //static defines as a global variable

    static float dataout [BUFFER_LEN]; //static defines as a global variable

    SNDFILE *infile, *outfile; //determines file open function + pointers

    /*descriptor*/SF_INFO /*sf_open*/ sfinfo, sfinfo2; 

    int readcount;//used to store data in while ((readcount = sf...

    const char *infilename/*pointer*/ = "/tmp/input.wav"; //const means that it is a value that cannot change 
                                               //after initialisation

    const char *outfilename/*pointer*/ = "/tmp/soundchanged.wav"; //const means that it is a value that cannot change 
                                                       //after initialisation

    SRC_DATA src_data; //struct from libsamplerate library
    //http://www.mega-nerd.com/SRC/api_misc.html#SRC_DATA

    infile = sf_open (infilename/*pointer*/, SFM_READ, &sfinfo); //infile declares a file variable, SFM_READ-reads file
                                                     //sfinfo -function of sfopen

    outfile = sf_open (outfilename/*pointer*/, SFM_WRITE, &sfinfo); //outfile declares a file variable, SFM_WRITE-writes file
                                                        //sfinfo -function of sfopen

    src_data.data_in = datain; //used to pass audio data into the converter

    src_data.input_frames = BUFFER_LEN; //supply the converter with the lengths of the arrays 
                                       //(in frames) pointed to by the data_in  

    src_data.data_out = dataout; //supplies the converter with an array to hold the converter's output

    src_data.output_frames = BUFFER_LEN; //supply the converter with the lengths of the arrays 
                                        //(in frames) pointed to by the data_out 

    /*------->*/src_data.src_ratio = 0.2 /*changing this number changes the pitch of the output file*/; 
    //specifies the conversion ratio defined as the input sample rate 
                           //divided by the output sample rate

    src_simple (&src_data/*reference address of src_data*/, SRC_SINC_BEST_QUALITY, 1);//

    while ((readcount = sf_read_float (infile, datain, BUFFER_LEN)))//while readcount is equal to
        //sf_read_float - function call: infile,datain and BUFFER_LEN 
        //this data is then fed into the converter argument below 


    {
        src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1); //selects converter
        //http://www.mega-nerd.com/SRC/api_misc.html#SRC_DATA

        sf_write_float (outfile, dataout, readcount); 
        //write the data in the array pointed to by ptr to the file
    };


    sf_close (infile);
    sf_close (outfile); // closes infile,outfile
    //The close function closes the file, deallocates 
    //its internal buffers and returns 0 on success or an error value otherwise.

    sf_open ("/tmp/soundchanged.wav", SFM_READ, &sfinfo2/*reference address of sfinfo2*/);

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

    return 0;
}
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • 1
    Changing the sample rate (if that's what the library is doing) is not the right approach. And shifting the pitch is not a trivial thing to do easily, cheaply and with high quality. – Alexey Frunze Apr 25 '13 at 13:56
  • Thanks for taking a look. Would you be able to elaborate on how I might go about the right approach? In terms of quality I'm not aiming for anything fantastic - just something that plays without audio blocks missing once processed. – user2119840 Apr 25 '13 at 15:33
  • I won't tell you more than you can find online. Research the topic of [pitch shift](http://en.wikipedia.org/wiki/Pitch_shift). That's just a starting point. There are papers and algorithms and, I'm sure, sample implementations, too. – Alexey Frunze Apr 25 '13 at 15:35
  • What you are doing is not really pitch shifting, but more accurately called vari-speed, changing the playback speed and thereby changing the pitch. What you probably want is speed independent pitch shifting; ie the playback speed remains the same and the pitch changes. For that have a look at librubberband. – Erik de Castro Lopo Apr 27 '13 at 00:25

1 Answers1

0

The way the cheapest time-pitch converters used to work (in old tape players) when pitching up was by simply duplicating blocks of resampled sound, or portions thereof, to fill in the gaps. The slightly less worse ones spliced the blocks together at zero-crossings. This sort-of worked, but was far from high quality sounding.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153