the_naive
the_naive

Reputation: 3064

Operation on FILE to operation on QByteArray?

I have the following piece of code to convert a raw audio file to wav file:

int MainWindow::rawToWav(const char *rawfn, const char *wavfn, long samplingRate)
{
    long chunksize=0x10;
    int statusCollect = 0;
    struct
    {
        unsigned short    wFormatTag;
        unsigned short    wChannels;
        unsigned long     dwSamplesPerSec;
        unsigned long     dwAvgBytesPerSec;
        unsigned short    wBlockAlign;
        unsigned short    wBitsPerSample;
    } fmt;

    errno_t err;
    FILE *raw;
    err = fopen_s(&raw, rawfn, "rb");
    if(!raw)
        return -2;

    fseek(raw, 0, SEEK_END);
    long bytes = ftell(raw);
    fseek(raw, 0, SEEK_SET);

    long samplecount = bytes/2;
    long riffsize    = samplecount*2+0x24;
    long datasize    = samplecount*2;

    FILE *wav;
    err = fopen_s(&wav, wavfn, "wb");
    if(!wav)
    {
        fclose(raw);
        return -3;
    }

    fwrite( "RIFF",     1, 4, wav );
    fwrite( &riffsize,  4, 1, wav );
    fwrite( "WAVEfmt ", 1, 8, wav );
    fwrite( &chunksize, 4, 1, wav );

    int bitsPerSample = 16;
    int bytesPerSample = bitsPerSample/8;
    int channel = 2;

    fmt.wFormatTag = 1;      // PCM
    fmt.wChannels  = channel;      // MONO
    fmt.dwSamplesPerSec  = samplingRate;
    fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
    fmt.wBlockAlign      = channel*bytesPerSample;
    fmt.wBitsPerSample   = bitsPerSample;

    fwrite( &fmt,      sizeof(fmt), 1, wav );
    fwrite( "data",    1,           4, wav );
    fwrite( &datasize, 4,           1, wav );
    short buff[1024];
    while( !feof(raw) )
    {
        int cnt=fread(buff,2,1024,raw);
        if( cnt == 0 )
            break;
        fwrite(buff,2,cnt,wav);
    }
    statusCollect = fclose( raw );
    statusCollect += fclose( wav );
    return statusCollect;
}

I want to the exactly same operation not on a FILE type data but on a QByteArray type.

So I am trying the following way. First I try to add the wav header on a QByteArray object. Then I upload the raw audio file on the program. Then I add that raw data to the QByteArray object on which I have already added the wav header. Then I save the QByteArray as a wav file.

void MainWindow::rawToWavQT(QByteArray* arr, long samplingRate, long sizeOfRawFile)
{
    long chunksize=0x10;
    struct
    {
        unsigned short    wFormatTag;
        unsigned short    wChannels;
        unsigned long     dwSamplesPerSec;
        unsigned long     dwAvgBytesPerSec;
        unsigned short    wBlockAlign;
        unsigned short    wBitsPerSample;
    } fmt;

    long samplecount = sizeOfRawFile/2;
    long riffsize    = samplecount*2+0x24;
    long datasize    = samplecount*2;

    arr->append("RIFF");//    fwrite( "RIFF",     1, 4, wav );
    arr->append((const char*)&riffsize);//    fwrite( &riffsize,  4, 1, wav );
    arr->append("WAVEfmt ");//    fwrite( "WAVEfmt ", 1, 8, wav );
    arr->append((const char*)&chunksize);//    fwrite( &chunksize, 4, 1, wav );

    int bitsPerSample = 16;
    int bytesPerSample = bitsPerSample/8;
    int channel = 2;

    fmt.wFormatTag = 1;      // PCM
    fmt.wChannels  = channel;      // MONO
    fmt.dwSamplesPerSec  = samplingRate;
    fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
    fmt.wBlockAlign      = channel*bytesPerSample;
    fmt.wBitsPerSample   = bitsPerSample;

    arr->append((const char*)&fmt);//    fwrite( &fmt,      sizeof(fmt), 1, wav );
    arr->append("data");//    fwrite( "data",    1,           4, wav );
    arr->append((const char*)&datasize);//    fwrite( &datasize, 4,           1, wav );
}

But this way of adding header to the QByteArray and then adding the raw data is not producing the correct type of wav file as it is not able to be played. What do you think I am doing wrong judging from the second function in which I am doing the same operation as that of on the first function but on QByteArray object rather than on FILE object?

Thanks.

Upvotes: 2

Views: 372

Answers (1)

owacoder
owacoder

Reputation: 4873

Your data concatenation functions just stop at the first null byte, losing important data and disrupting alignment. Instead, you want to specify a length to append as well, in a similar manner to fwrite. Solution: Replace your append() statements from single const char * arguments to QByteArrays constructed using both your data and the length of your data.

Change

arr->append((const char*)&riffsize);

to

arr->append(QByteArray((const char*)&riffsize, 4));

and similarly for the other raw data append statements.

Upvotes: 2

Related Questions