libsndfile / libsndfile

A C library for reading and writing sound files containing sampled audio data.
http://libsndfile.github.io/libsndfile/
GNU Lesser General Public License v2.1
1.39k stars 377 forks source link

limit on comment length when reading WAV files? #889

Open krisfed opened 1 year ago

krisfed commented 1 year ago

We noticed that we cannot read back a comment from a WAV file if it is >= 2046 chars long. It seems to be written ok (I can see it with https://mediaarea.net/MediaInfoOnline), but when I try to read it back with sf_get_string, I get back NULL.

Here is some simple reproduction code:

#include <iostream>
#include "sndfile.h"

int main()
{
    // prepare data to write
    const int audioLength = 70000;
    double originalData[audioLength] = {0};

    const int commentLength = 2046; //2045 works fine
    char originalComment[commentLength];
    for (int i = 0; i<commentLength; i++) {
        originalComment[i] = 'a';
    }
    std::cout << "comment to be written: " << originalComment << std::endl;
    std::cout << "(comment length is " << commentLength << ")" << std::endl;

    // open WAV file for writing
    SF_INFO sndFileInfo;
    sndFileInfo.samplerate = 44100;
    sndFileInfo.channels = 1;
    sndFileInfo.format = SF_FORMAT_WAV | SF_FORMAT_DOUBLE;

    SNDFILE* sndFile = sf_open("mytest.wav", SFM_WRITE, &sndFileInfo);
    sf_command(sndFile, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE);

    // write long comment
    int sferror = sf_set_string(sndFile, SF_STR_COMMENT, originalComment);
    if (sferror != SF_ERR_NO_ERROR)
    {
        std::cout << "Error writing a comment: " << std::endl;
        const char* errorStr = sf_strerror(sndFile);
        std::cout << "errorStr: " << errorStr << std::endl;
        return -1;
    }

    // write audio data
    sf_count_t framesWritten = sf_writef_double(sndFile, originalData, audioLength);
    std::cout << "Written " << framesWritten << " frames." << std::endl;

    // close file
    sferror = sf_close(sndFile);
    if (sferror != SF_ERR_NO_ERROR) {
        std::cout << "Error closing file for writing: "  << std::endl;
        const char* errorStr = sf_strerror(sndFile);
        std::cout << "errorStr: " << errorStr << std::endl;
        return -1;
    }

    // open file for reading
    SF_INFO sndFileInfoRead;
    SNDFILE* sndFileRead = sf_open("mytest.wav", SFM_READ, &sndFileInfoRead);

    // try reading comment back
    const char* readComment = sf_get_string(sndFileRead, SF_STR_COMMENT);
    sferror = sf_error(sndFileRead);
    if (sferror != SF_ERR_NO_ERROR) {
        std::cout << "Error reading the comment: "  << std::endl;
        const char* errorStr = sf_strerror(sndFileRead);
        std::cout << "errorStr: " << errorStr << std::endl;
        return -1;
    }

    if (readComment == NULL) {
        std::cout << "read comment is null" <<  std::endl;
    } else {
        std::cout << "read comment: " << readComment <<  std::endl;
    }

    // close file
    sferror = sf_close(sndFileRead);
    if (sferror != SF_ERR_NO_ERROR) {
        std::cout << "Error closing file for reading: "  << std::endl;
        const char* errorStr = sf_strerror(sndFileRead);
        std::cout << "errorStr: " << errorStr << std::endl;
        return -1;
    }

    return 0;
}

And here is the output:

$ ./a.out 
comment to be written: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
(comment length is 2046)
Written 70000 frames.
read comment is null

If I try a smaller length, the comment can be read back correctly.

This was run on my macOS 12.1 machine, but we are seeing this issue on Windows and unix platforms too. We are using the latest official libsndfile 1.1.0 release.

evpobr commented 1 year ago

Hi @krisfed . I pretty sure it is limited here:

https://github.com/libsndfile/libsndfile/blob/0faf893fd21866bf08a5e64adf2ccf8d7ab0a9de/src/wavlike.c#L954

Probably we need to improve string handling.

krisfed commented 1 year ago

Thank you very much for taking a look! Yes, this seems like an important limitation for one of our users.

krisfed commented 1 year ago

Hi! Just wanted to see - have there been any updates on this issue? I realize it is a pretty rare workflow, but it can be a loss of data problem for some...

krisfed commented 11 months ago

Hi, Just checking in again - any thoughts on looking into this issue? I know resources are tricky and this is low-frequency, but just wanted to see what the status is.

Anbello262 commented 2 months ago

I'm having issues with this as well. Had to find some workarounds. Commenting only to show support on this.