19
R-C-D
6y

Hi android devs!
How can I record a double[] or byte[] into a pcm in order to convert it to a wav file?
My life depends on this one 😬

Comments
  • 2
    You just spit out a WAV file header and then the data: http://soundfile.sapp.org/doc/...

    C header definition: https://gist.github.com/Jon-Schneid...
  • 0
    @Fast-Nop how can i apply since it is a c++ lib?
  • 1
    @R1100 You'd build up that structure in memory and then write it to disk via file I/O. Here a C function for writing the header of a 16 bit mono WAV, that's how I did it 20 years ago (error handling omitted):

    (The crazy shifting stuff is to make sure it works regardless of endianess.)
  • 1
    @R1100

    void write_wave_header(FILE *wav_file, long wav_cnt, unsigned long s_freq)

    {

    unsigned long totalsize,bytespersec;

    fprintf(wav_file,"RIFF");

    totalsize = 2 * wav_cnt + 36;

    fputc((totalsize & 0x000000ff),wav_file); /* File size */

    fputc((totalsize & 0x0000ff00) >> 8,wav_file);

    fputc((totalsize & 0x00ff0000) >> 16,wav_file);

    fputc((totalsize & 0xff000000) >> 24,wav_file);

    fprintf(wav_file,"WAVE");

    fprintf(wav_file,"fmt "); /* fmt_ chunk */

    fputc(16,wav_file); /* Chunk size */

    fputc(0,wav_file);

    fputc(0,wav_file);

    fputc(0,wav_file);

    fputc(1,wav_file); /* Format tag - uncompressed */

    fputc(0,wav_file);

    fputc(1,wav_file); /* Channels */

    fputc(0,wav_file);
  • 1
    @R1100

    fputc((s_freq & 0x000000ff),wav_file); /* Sample frequency (Hz) */

    fputc((s_freq & 0x0000ff00) >> 8,wav_file);

    fputc((s_freq & 0x00ff0000) >> 16,wav_file);

    fputc((s_freq & 0xff000000) >> 24,wav_file);

    bytespersec = 2 * s_freq;

    fputc((bytespersec & 0x000000ff),wav_file); /* Average bytes per second */

    fputc((bytespersec & 0x0000ff00) >> 8,wav_file);

    fputc((bytespersec & 0x00ff0000) >> 16,wav_file);

    fputc((bytespersec & 0xff000000) >> 24,wav_file);

    fputc(2,wav_file); /* Block alignment */

    fputc(0,wav_file);

    fputc(16,wav_file); /* Bits per sample */

    fputc(0,wav_file);

    fprintf(wav_file,"data");

    totalsize = 2 * wav_cnt;

    fputc((totalsize & 0x000000ff),wav_file); /* Data size */

    fputc((totalsize & 0x0000ff00) >> 8,wav_file);

    fputc((totalsize & 0x00ff0000) >> 16,wav_file);

    fputc((totalsize & 0xff000000) >> 24,wav_file);

    }
  • 1
    @Fast-Nop thanks bro !
    U saved me 😀
  • 0
    @Fast-Nop can i convert it to java to be able to use it as a class?
  • 1
    @R1100 Java should already have that since Java has classes for everything. Is that one here available?

    http://labbookpages.co.uk/audio/...

    https://pamguard.org/devDocs/...
  • 1
    @Fast-Nop yesss!
    There is a lib named wavfiles
    Hope it works
  • 1
    Do my homework 😭
  • 1
    @Fast-Nop Shouldn’t that gist contain an aligned attribute or maybe switch to uint32 instead of char[4] to ensure the correct alignment is used? That first char array might not be guaranteed to be placed on a 32-bit aligned address and if not might result in extra pad bytes to be inserted which would likely result in a malformed header.
  • 2
    @aether the overall alignment of a struct is always the alignment of the biggest elementary data type that it contains. If a struct contains a 4 byte integer, the struct will always start at an address that is divisible by 4 even if that integer is not the first element.

    The issue why the Github gist is a little sloppy is that it assumes int to be 4 bytes, but the C standard guarantees only 2 bytes. That should have been done with the C99 data types. However, on PCs and Android, int is 4 bytes so that it will work.
  • 2
    @Fast-Nop ah right you are. I mixed up the rule in my head.
Add Comment