<commit_before>/**
 * Aften: A/52 audio encoder
 * Copyright (c) 2006 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file wav.c
 * WAV file format
 */

#include "common.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "pcm.h"

/* chunk id's */
#define RIFF_ID     0x46464952
#define WAVE_ID     0x45564157
#define FMT__ID     0x20746D66
#define DATA_ID     0x61746164

/**
 * Reads a 4-byte little-endian word from the input stream
 */
static inline uint32_t
read4le(PcmFile *pf)
{
    uint32_t x;
    if(byteio_read(&x, 4, &pf->io) != 4)
        return 0;
    pf->filepos += 4;
    return le2me_32(x);
}

/**
 * Reads a 2-byte little-endian word from the input stream
 */
static inline uint16_t
read2le(PcmFile *pf)
{
    uint16_t x;
    if(byteio_read(&x, 2, &pf->io) != 2)
        return 0;
    pf->filepos += 2;
    return le2me_16(x);
}

int
pcmfile_probe_wave(uint8_t *data, int size)
{
    int id;

    if(!data || size < 12)
        return 0;
    id = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
    if(id != RIFF_ID) {
        return 0;
    }
    id = data[8] | (data[9] << 8) | (data[10] << 16) | (data[11] << 24);
    if(id != WAVE_ID) {
        return 0;
    }
    return 100;
}

int
pcmfile_init_wave(PcmFile *pf)
{
    int id, found_data, found_fmt, chunksize;

    // read RIFF id. ignore size.
    id = read4le(pf);
    if(id != RIFF_ID) {
        fprintf(stderr, "invalid RIFF id in wav header\n");
        return -1;
    }
    read4le(pf);

    // read WAVE id. ignore size.
    id = read4le(pf);
    if(id != WAVE_ID) {
        fprintf(stderr, "invalid WAVE id in wav header\n");
        return -1;
    }

    // read all header chunks. skip unknown chunks.
    found_data = found_fmt = 0;
    while(!found_data) {
        id = read4le(pf);
        chunksize = read4le(pf);
        switch(id) {
            case FMT__ID:
                if(chunksize < 16) {
                    fprintf(stderr, "invalid fmt chunk in wav header\n");
                    return -1;
                }
                pf->internal_fmt = read2le(pf);
                pf->channels = read2le(pf);
                if(pf->channels == 0) {
                    fprintf(stderr, "invalid number of channels in wav header\n");
                    return -1;
                }
                pf->sample_rate = read4le(pf);
                if(pf->sample_rate == 0) {
                    fprintf(stderr, "invalid sample rate in wav header\n");
                    return -1;
                }
                read4le(pf);
                read2le(pf);
                pf->bit_width = read2le(pf);
                if(pf->bit_width == 0) {
                    fprintf(stderr, "invalid sample bit width in wav header\n");
                    return -1;
                }
                chunksize -= 16;

                // WAVE_FORMAT_EXTENSIBLE data
                pf->ch_mask = pcm_get_default_ch_mask(pf->channels);
                if(pf->internal_fmt == WAVE_FORMAT_EXTENSIBLE && chunksize >= 10) {
                    read4le(pf);    // skip CbSize and ValidBitsPerSample
                    pf->ch_mask = read4le(pf);
                    pf->internal_fmt = read2le(pf);
                    chunksize -= 10;
                }

                // set sample type based on wFormatTag
                if(pf->internal_fmt == WAVE_FORMAT_IEEEFLOAT) {
                    pf->sample_type = PCM_SAMPLE_TYPE_FLOAT;
                } else if(pf->internal_fmt == WAVE_FORMAT_PCM) {
                    pf->sample_type = PCM_SAMPLE_TYPE_INT;
                } else {
                    fprintf(stderr, "unsupported wFormatTag: 0x%02X\n",
                            pf->internal_fmt);
                    return -1;
                }

                // override block alignment in header
                pf->block_align = MAX(1, ((pf->bit_width + 7) >> 3) * pf->channels);
<commit_msg>rearrange WAVE header parsing. read first, then validate<commit_after>/**
 * Aften: A/52 audio encoder
 * Copyright (c) 2006 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file wav.c
 * WAV file format
 */

#include "common.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "pcm.h"

/* chunk id's */
#define RIFF_ID     0x46464952
#define WAVE_ID     0x45564157
#define FMT__ID     0x20746D66
#define DATA_ID     0x61746164

/**
 * Reads a 4-byte little-endian word from the input stream
 */
static inline uint32_t
read4le(PcmFile *pf)
{
    uint32_t x;
    if(byteio_read(&x, 4, &pf->io) != 4)
        return 0;
    pf->filepos += 4;
    return le2me_32(x);
}

/**
 * Reads a 2-byte little-endian word from the input stream
 */
static inline uint16_t
read2le(PcmFile *pf)
{
    uint16_t x;
    if(byteio_read(&x, 2, &pf->io) != 2)
        return 0;
    pf->filepos += 2;
    return le2me_16(x);
}

int
pcmfile_probe_wave(uint8_t *data, int size)
{
    int id;

    if(!data || size < 12)
        return 0;
    id = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
    if(id != RIFF_ID) {
        return 0;
    }
    id = data[8] | (data[9] << 8) | (data[10] << 16) | (data[11] << 24);
    if(id != WAVE_ID) {
        return 0;
    }
    return 100;
}

int
pcmfile_init_wave(PcmFile *pf)
{
    int id, found_data, found_fmt, chunksize;

    // read RIFF id. ignore size.
    id = read4le(pf);
    if(id != RIFF_ID) {
        fprintf(stderr, "invalid RIFF id in wav header\n");
        return -1;
    }
    read4le(pf);

    // read WAVE id. ignore size.
    id = read4le(pf);
    if(id != WAVE_ID) {
        fprintf(stderr, "invalid WAVE id in wav header\n");
        return -1;
    }

    // read all header chunks. skip unknown chunks.
    found_data = found_fmt = 0;
    while(!found_data) {
        id = read4le(pf);
        chunksize = read4le(pf);
        switch(id) {
            case FMT__ID:
                if(chunksize < 16) {
                    fprintf(stderr, "invalid fmt chunk in wav header\n");
                    return -1;
                }
                pf->internal_fmt = read2le(pf);
                pf->channels = read2le(pf);
                pf->ch_mask = pcm_get_default_ch_mask(pf->channels);
                pf->sample_rate = read4le(pf);
                read4le(pf);
                read2le(pf);
                pf->bit_width = read2le(pf);
                pf->block_align = MAX(1, ((pf->bit_width + 7) >> 3) * pf->channels);
                chunksize -= 16;

                // WAVE_FORMAT_EXTENSIBLE data
                if(pf->internal_fmt == WAVE_FORMAT_EXTENSIBLE && chunksize >= 10) {
                    read4le(pf);    // skip CbSize and ValidBitsPerSample
                    pf->ch_mask = read4le(pf);
                    pf->internal_fmt = read2le(pf);
                    chunksize -= 10;
                }

                // set sample type based on wFormatTag
                if(pf->internal_fmt == WAVE_FORMAT_IEEEFLOAT) {
                    pf->sample_type = PCM_SAMPLE_TYPE_FLOAT;
                } else if(pf->internal_fmt == WAVE_FORMAT_PCM) {
                    pf->sample_type = PCM_SAMPLE_TYPE_INT;
                } else {
                    fprintf(stderr, "unsupported wFormatTag: 0x%02X\n",
                            pf->internal_fmt);
                    return -1;
                }
                // validate format parameters
                if(pf->channels == 0) {
                    fprintf(stderr, "invalid number of channels in wav header\n");
                    return -1;
                }
                if(pf->sample_rate == 0) {
                    fprintf(stderr, "invalid sample rate in wav header\n");
                    return -1;
                }
                if(pf->bit_width == 0) {
                    fprintf(stderr, "invalid sample bit width in wav header\n");
                    return -1;
                }

{'fraction_non_alphanumeric': 0.11235712745309467, 'fraction_numerical': 0.031701531162389475, 'mean_word_length': 1.755496137849079, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2577153', 'n_tokens_mistral': 3185, 'n_tokens_neox': 2878, 'n_words': 841}