create wav file without running out of ram

100 views Asked by At

Hi i am trying to record from a board and i have successfully record 4 seconds. Problem is when i try to record for more time, i got an error telling me that there not enough memory. my target is to record a 5 minutes file. Until now i have create a buffer named snIn[256] where are the samples. i send it to a big buffer of [16K * 4sec] and when it is full, i create the wav file.

#define WAVFILE_SAMPLES_PER_SECOND 16000
#define REC_TIME 4

const int NUM_SAMPLES = WAVFILE_SAMPLES_PER_SECOND * REC_TIME;
Array<int16_t> my_buffer(NUM_SAMPLES);

int rec(const char *filename, Array<int16_t> my_buffer) {   

    WavFileResult result;
    wavfile_info_t info;
    wavfile_data_t data;

    // code for filling the info of the wav file: sample rate, byte rate , channels etc..

    WAVFILE *wf = wavfile_open(filename, WavFileModeWrite, &result);
    WAVFILE_DATA_NUM_CHANNELS(&data) = 1; rp = 0;
    wavfile_write_info(wf, &info);


    while ( rp < NUM_SAMPLES ) {
        WAVFILE_DATA_CHANNEL_DATA(&data, 0) = my_buffer[rp];//fill the data of the wav file       
        wavfile_write_data(wf, &data);
        rp += 1;
    }
    wavfile_close(wf);
    return 0;
}

void fill_buffer (Array<int16_t> snIn , int &j) {

        for (int i=0 ; i < SEG_SIZE ; i++) {
            my_buffer[j] = snIn[i]; //puts all the 256 values in my_buffer
            j++; }

            if (sent_array == ((int)NUM_SAMPLES/SEG_SIZE)){ // if my_buffer is full, go to rec and make a wav file
                rec (target_filename , my_buffer ); }
}

int main()
{
        Array<int16_t> snIn(256);

            for (int n=0; n<256 ; n++)
            { //snIn gets new 256 values }
        sent_array ++;
        fill_buffer (snIn , j);
}

I thought about a possible solution, to fill directly the "data field" of the wavefile with the snIn[256] buffer (instead of using my_buffer) again and again and at the end close the wavfile. Please let me know what you think about that and other solutions.

1

There are 1 answers

0
dimid On BEST ANSWER

Your byte rate isn't calculated correctly. You need to follow the formula

num_channels * sample_rate * (bits_per_sample / 8)

Also you haven't called wavfile_write_info to write the metadata. BTW, you should make yourself a habit of checking the return value. I.e. something like

result = wavfile_write_data(wf, &data);
if (result != WavFileResultOK) {
    wavfile_result_string(result, res_buf, RES_STR_SIZE);
    printf("%s", res_buf);
    return result;
}

where res_buf is allocated before. You should probably factor it to a function.

Here's the full code (I stripped the embedded specific code to run it on my computer):

    rp = 0;
    WAVFILE_DATA_NUM_CHANNELS(&data) = 1;
    while (rp<100) {
        WAVFILE_DATA_CHANNEL_DATA(&data, 0) = buffer[rp];
        result = wavfile_write_data(wf, &data);
        if (result != WavFileResultOK) {
            wavfile_result_string(result, res_buf, RES_STR_SIZE);
            printf("%s", res_buf);
            return result;
        }
        rp += 1;
    }
    result = wavfile_close(wf);
    if (result != WavFileResultOK) {
        wavfile_result_string(result, res_buf, RES_STR_SIZE);
        printf("%s", res_buf);
        return result;
    }
    printf("Success rec !\r\n");
    return 0;

}

int main(void)
{
    static const char *target_filename = "rectest.wav";
    for (int t=0 ; t<100 ; t++){
        buffer[t]= sin(2*3.14*t);
    }

    int res = rec(target_filename);
    if (res != 0) {
        return 1;
    }

    printf("success program!\r\n");
    return 0;
}