0

I am trying to implement a program with pitch corrects inputted audio signals.

I have taken a .wav file, used autocorrelation to find the period of the signal every 0.04s. I now have an array of amplitude points which take the period length of the signal every 0.04s and repeat those values up until the next 0.04s. (I know that the signal has not been stretched yet, this is the final step).

How can I use libsnd file to write these values back to the original .wav file so that it can be played?

I tried something like:

SF_INFO sfinfo;
sfinfo.frames;

const char* path = "Vocal3.wav";

SNDFILE * outfile = sf_open(path, SFM_WRITE, &sfinfo);

for (k = 0; k < num; ++k) {
    sf_count_t count = sf_write_float(outfile, &array[k], num);
    sf_write_sync(outfile);
}
sf_close(outfile);

but it creates a .wav file of 0 bytes that won't open. Do I have to create wav file from scratch? Does this mean creating the header too? Some pointers on how to do this would be much appreciated.

EDIT:

I now think I understand the syntax of libsndfile a bit better, and I tried something like:

SF_INFO sfinfo;
SNDFILE* outfile;
outfile = sf_open(filename, SFM_RDWR, &sfinfo);
sf_count_t count = sf_writef_float(outfile, array, sfinfo.frames);
const char* error = sf_strerror(outfile);
std::cout << error << "\n";
sf_close(outfile);

Which doesn't overwrite the file, it instead appends the new amplitude values to the original file. Is there a way the original values can be removed?

EDIT 2:

The original files can be removed using the seek functions - http://www.mega-nerd.com/libsndfile/api.html#seek - thanks to Matthias for the help

Tom_Anks
  • 47
  • 9
  • RTFM (http://www.mega-nerd.com/libsndfile/api.html#open), check the return value of `sf_open()` for errors, come back here if you still don't know what's wrong. I guess you think that `SFM_WRITE` somehow reads the file ...? It doesn't, it destroys its contents without looking at them. – Matthias Mar 18 '17 at 19:24
  • So I'll have to create the new wav file from scratch essentially? – Tom_Anks Mar 18 '17 at 19:25
  • No, you don't have to. You can also open it in `SFM_RDWR` mode. But seriously, RTFM! – Matthias Mar 18 '17 at 19:27
  • I did, but I was pretty lost as it didn't offer much in the way of examples, which I would've liked – Tom_Anks Mar 18 '17 at 19:28
  • Apart from checking all function calls for potential errors (you should always do that!), you should also think about what you are doing to your `array`. When you loop over it, what should the third argument to `sf_write_float()` be? Why do you even loop over it when you can write multiple values at once? – Matthias Mar 18 '17 at 19:35
  • I eventually got it working with a bit of trial-and-error, the error string definitely helped solve a few issues. Although the code now just adds the adjusted values onto the end of the original wav file, but surely there must be a way to overwrite the old values? – Tom_Anks Mar 20 '17 at 19:21
  • About your EDIT: You still don't check the return values in your code example! You should at least add a comment explaining what should be checked in real code. About your new question: You should get familiar with the concept of "read pointer" and "write pointer" and how you can use "seek" to move them: http://www.mega-nerd.com/libsndfile/api.html#seek. Then you can move the write pointer anywhere you want and overwrite to your heart's content! – Matthias Mar 21 '17 at 15:15
  • Sorry, I removed them from the code I pasted but they're still in my code! Also that's brilliant and exactly what I want, thank you – Tom_Anks Mar 21 '17 at 15:16
  • I'm happy to help. You should still mention the error checking for the sake of people who stumble upon your question, otherwise when they try your code they might have the same problems as you initially had ... – Matthias Mar 21 '17 at 15:21
  • Good point, I'll add it back in – Tom_Anks Mar 21 '17 at 15:22

0 Answers0