Thread: Writing audio to file

  1. #1
    Registered User
    Join Date
    Aug 2016
    Posts
    2

    Writing audio to file

    Hello,

    I've been researching some audio and trying a few implementations. I've hit a wall I can't solve, and wanted to see if anybody had any ideas. I'm generating samples off a sine wave, formatting the wave file, and everything is going great. When I actually write the information to a file, it seems that every so often the information gets corrupted. "Every so often" meaning consistently and in the same places every time.

    I was able to narrow it down to the fwrite calls by checking every short that was generated, and each that was written. When it's writing, all of the values are correct. When I open the file and read it to double check, there are tons of samples that have different values than it calculated. Here's a picture:

    Writing audio to file-weird_wave-jpg

    The sine wave is in there, it's just got what looks like random noise. The audio does play, it just sounds like it looks like it sounds. Here is the relevant code:
    Code:
    typedef struct
    {
        CHUNK_HEADER header;
        //uint8_t* byteArray; // for 8 bit sound
        short* shortArray; // for 16 bit sound
    } DATA_CHUNK;
    
    format.header.dwChunkSize = 16;
        format.wFormatTag = 1;
        format.wChannels = 1;
        format.dwSamplesPerSec = 44100;
        format.dwBitsPerSample = 16;
        format.wBlockAlign = format.wChannels * (format.dwBitsPerSample / 8);
        format.dwAvgBytesPerSec = format.wBlockAlign * format.dwSamplesPerSec;
    
    
        data.shortArray = (short*)malloc((seconds * format.dwSamplesPerSec) * sizeof(short));
        memset(data.shortArray, '0', seconds * format.dwSamplesPerSec * sizeof(short));
        data.header.dwChunkSize = seconds * format.dwAvgBytesPerSec;
        populate_samples(data.shortArray, &format, seconds, check_bytes);
        main_header.dwFileLength = 4 + 16 + (format.dwAvgBytesPerSec * seconds);
    
    
        FILE *wav_file = fopen(FILENAME, "w+");
        FILE *check_file;
        fwrite(&main_header, 1, sizeof(main_header), wav_file);
        fwrite(&format, 1, sizeof(format), wav_file);
        fwrite(&data.header, 1, 8, wav_file);
        fwrite(data.shortArray, 2, (format.dwSamplesPerSec * seconds), wav_file);
        fclose(wav_file);
    I'm stumped. Any ideas?
    Attached Images Attached Images Writing audio to file-what_wave-jpg 

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Have you packed the structs? The following should work for both MSVC and gcc (unless your gcc is old). Put it before the structs.
    Code:
    #pragma pack(1)
    For better portability, you should avoid packing and write each member of the structs individually.

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    505
    It's impossible that there should be a bug in fwrite itself.

    Firstly, you're not helping yourself by writing the file in a platform-dependent way.
    Set up two functions, fput16le (I believe wav files have to be little-endian,
    obviously, check) fput32le, which write 16 and 32 bit integers in binary
    format. Then simply write the file format byte by byte.

    The fwrite turns into a loop that calls fput16le for each audio sample.
    Now insert a diagnostic printf and print out the
    values as you write them. Whilst you'll be overwhelmed with data, if the
    output has sharp discontinutities in it, you will be aware.
    Check the function by writing trivial files (ten samples or so, all zero,
    all min, all max, ascending, descending, then do the same for a
    larger file).
    The data is probably being corrupted somewhere, but I can't spot
    the bug by visual inspection of the source. Likely the real problem
    is elsewhere.
    Last edited by Malcolm McLean; 08-27-2016 at 09:24 PM. Reason: typo
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  4. #4
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    One pretty obvious problem is that you're not opening the file in binary mode. On Windows text mode is the default with the system CRT and unlike some other systems, actually matters.

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    505
    Oh that's it, obviously.
    That's why you have sections which appear to be coherent and sections which aren't, when the shorts get
    in and out of synch.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  6. #6
    Registered User
    Join Date
    Aug 2016
    Posts
    2

    Fixed!

    OH, yeah, that fixed it. For anybody interested, the only change I had to make was changing this line:

    Code:
    FILE*wav_file = fopen(FILENAME, "w+");
    To this:

    Code:
    FILE*wav_file = fopen(FILENAME, "wb+");
    And you get this!

    Writing audio to file-fixed-jpg

    Thanks for the responses, I appreciate the help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Open an audio file using c language
    By guru lakshmi in forum C Programming
    Replies: 2
    Last Post: 09-06-2013, 08:24 AM
  2. How To Generate Audio Data From A Wav File
    By mrchu in forum C++ Programming
    Replies: 10
    Last Post: 03-06-2008, 03:00 PM
  3. Audio File
    By IceBall in forum Tech Board
    Replies: 4
    Last Post: 08-14-2003, 10:36 AM
  4. Audio CD File Extension
    By sean in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 02-17-2003, 10:47 PM
  5. Playing an Audio Wav File
    By Robert_Ingleby in forum C++ Programming
    Replies: 2
    Last Post: 12-02-2001, 06:29 PM

Tags for this Thread