/* * This file is part of the Advance project. * * Copyright (C) 1999, 2000, 2001, 2002, 2003 Andrea Mazzoleni * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * In addition, as a special exception, Andrea Mazzoleni * gives permission to link the code of this program with * the MAME library (or with modified versions of MAME that use the * same license as MAME), and distribute linked combinations including * the two. You must obey the GNU General Public License in all * respects for all of the code used other than MAME. If you modify * this file, you may extend this exception to your version of the * file, but you are not obligated to do so. If you do not wish to * do so, delete this exception statement from your version. */ #include "portable.h" #include "wave.h" #include "endianrw.h" #include "log.h" #define WAVE_FORMAT_PCM 0x0001 /* Microsoft Pulse Code Modulation (PCM) format */ #define IBM_FORMAT_MULAW 0x0101 /* IBM mu-law format */ #define IBM_FORMAT_ALAW 0x0102 /* IBM a-law format */ #define IBM_FORMAT_ADPCM 0x0103 /* IBM AVC Adaptive Differential Pulse Code Modulation format */ static adv_error le_uint16_fwrite(FILE* f, unsigned v) { unsigned char p[2]; le_uint16_write(p, v); if (fwrite(p, 2, 1, f) != 1) return -1; return 0; } static adv_error le_uint32_fwrite(FILE* f, unsigned v) { unsigned char p[4]; le_uint32_write(p, v); if (fwrite(p, 4, 1, f) != 1) return -1; return 0; } static adv_error wave_write_tag(FILE* f, const char* tag) { if (fwrite(tag, 1, 4, f) != 4) return -1; return 0; } static adv_error wave_write_id(FILE* f, const char* tag, unsigned size) { if (wave_write_tag(f, tag) != 0) return -1; if (le_uint32_fwrite(f, size) != 0) return -1; return 0; } static adv_error wave_write_fmt(FILE* f, unsigned format_tag, unsigned channels, unsigned samples_per_sec, unsigned avg_u8s_per_sec, unsigned block_align) { if (le_uint16_fwrite(f, format_tag) != 0) return -1; if (le_uint16_fwrite(f, channels) != 0) return -1; if (le_uint32_fwrite(f, samples_per_sec) != 0) return -1; if (le_uint32_fwrite(f, avg_u8s_per_sec) != 0) return -1; if (le_uint16_fwrite(f, block_align) != 0) return -1; return 0; } static adv_error wave_write_fmt_PCM(FILE* f, unsigned bits_per_sample) { if (le_uint16_fwrite(f, bits_per_sample) != 0) return -1; return 0; } /** * Write a WAVE header to a file. * \param f File to write. * \param channel Number of channels. * \param bit Bits per sample. * \param size Size of the data in bytes. * \param freq Frequency in Hz. */ adv_error wave_write(FILE* f, unsigned channel, unsigned bit, unsigned size, unsigned freq) { unsigned size_byte; if (bit <= 8) size_byte = 1; else if (bit <= 16) size_byte = 2; else size_byte = 4; if (wave_write_id(f, "RIFF", 0x24 + size) != 0) return -1; if (wave_write_tag(f, "WAVE") != 0) return -1; if (wave_write_id(f, "fmt ", 0x10) != 0) return -1; if (wave_write_fmt(f, WAVE_FORMAT_PCM, channel, freq, size_byte * channel * freq, size_byte * channel) != 0) return -1; if (wave_write_fmt_PCM(f, bit) != 0) return -1; if (wave_write_id(f, "data", size) != 0) return -1; return 0; } /** * Adjust a WAVE header setting the correct size. * \param f File to write. * \param size Number of samples. */ adv_error wave_write_size(FILE* f, unsigned size) { unsigned dsize; dsize = 0x24 + size; if (fseek(f, 4, SEEK_SET) != 0) return -1; if (le_uint32_fwrite(f, dsize) != 0) return -1; dsize = size; if (fseek(f, 0x28, SEEK_SET) != 0) return -1; if (le_uint32_fwrite(f, dsize) != 0) return -1; return 0; } static adv_error wave_read_tag(adv_fz* f, char* tag) { if (fzread(tag, 4, 1, f) != 1) return -1; return 0; } static adv_error wave_skip(adv_fz* f, unsigned num) { unsigned count = 0; while (count