diff options
Diffstat (limited to 'icedax/wav.c')
-rw-r--r-- | icedax/wav.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/icedax/wav.c b/icedax/wav.c new file mode 100644 index 0000000..b30ed9b --- /dev/null +++ b/icedax/wav.c @@ -0,0 +1,157 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)wav.c 1.4 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */ +/*** + * CopyPolicy: GNU Public License 2 applies + * Copyright (C) by Heiko Eissfeldt + * + * + */ +#include "config.h" +#include <stdio.h> +#include <unixstd.h> +#include "byteorder.h" +#include "sndfile.h" + +/*** + * --------------------------------------------------------------------- + * definitions for RIFF-output (from windows MMSYSTEM) + * --------------------------------------------------------------------- + */ + +typedef unsigned int FOURCC; /* a four character code */ + +typedef struct CHUNKHDR { + FOURCC ckid; /* chunk ID */ + unsigned int dwSize; /* chunk size */ +} CHUNKHDR; + +/* flags for 'wFormatTag' field of WAVEFORMAT */ +#define WAVE_FORMAT_PCM 1 + +/* specific waveform format structure for PCM data */ +typedef struct pcmwaveformat_tag { + unsigned short wFormatTag; /* format type */ + unsigned short nChannels; /* number of channels (i.e. mono, stereo, etc.) */ + unsigned int nSamplesPerSec; /* sample rate */ + unsigned int nAvgBytesPerSec;/* for buffer size estimate */ + unsigned short nBlockAlign; /* block size of data */ + unsigned short wBitsPerSample; +} PCMWAVEFORMAT; +typedef PCMWAVEFORMAT *PPCMWAVEFORMAT; + + +/* MMIO macros */ +#define mmioFOURCC(ch0, ch1, ch2, ch3) \ + ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \ + ((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24)) + +#define FOURCC_RIFF mmioFOURCC ('R', 'I', 'F', 'F') +#define FOURCC_LIST mmioFOURCC ('L', 'I', 'S', 'T') +#define FOURCC_WAVE mmioFOURCC ('W', 'A', 'V', 'E') +#define FOURCC_FMT mmioFOURCC ('f', 'm', 't', ' ') +#define FOURCC_DATA mmioFOURCC ('d', 'a', 't', 'a') + + +/* simplified Header for standard WAV files */ +typedef struct WAVEHDR { + CHUNKHDR chkRiff; + FOURCC fccWave; + CHUNKHDR chkFmt; + unsigned short wFormatTag; /* format type */ + unsigned short nChannels; /* number of channels (i.e. mono, stereo, etc.) */ + unsigned int nSamplesPerSec; /* sample rate */ + unsigned int nAvgBytesPerSec;/* for buffer estimation */ + unsigned short nBlockAlign; /* block size of data */ + unsigned short wBitsPerSample; + CHUNKHDR chkData; +} WAVEHDR; + +#define IS_STD_WAV_HEADER(waveHdr) ( \ + waveHdr.chkRiff.ckid == FOURCC_RIFF && \ + waveHdr.fccWave == FOURCC_WAVE && \ + waveHdr.chkFmt.ckid == FOURCC_FMT && \ + waveHdr.chkData.ckid == FOURCC_DATA && \ + waveHdr.wFormatTag == WAVE_FORMAT_PCM) + +static WAVEHDR waveHdr; + +static int _InitSound(int audio, long channels, unsigned long rate, + long nBitsPerSample, unsigned long expected_bytes); + +static int _InitSound(int audio, long channels, unsigned long rate, + long nBitsPerSample, unsigned long expected_bytes) +{ + unsigned long nBlockAlign = channels * ((nBitsPerSample + 7) / 8); + unsigned long nAvgBytesPerSec = nBlockAlign * rate; + unsigned long temp = expected_bytes + sizeof(WAVEHDR) - sizeof(CHUNKHDR); + + waveHdr.chkRiff.ckid = cpu_to_le32(FOURCC_RIFF); + waveHdr.fccWave = cpu_to_le32(FOURCC_WAVE); + waveHdr.chkFmt.ckid = cpu_to_le32(FOURCC_FMT); + waveHdr.chkFmt.dwSize = cpu_to_le32(sizeof (PCMWAVEFORMAT)); + waveHdr.wFormatTag = cpu_to_le16(WAVE_FORMAT_PCM); + waveHdr.nChannels = cpu_to_le16(channels); + waveHdr.nSamplesPerSec = cpu_to_le32(rate); + waveHdr.nBlockAlign = cpu_to_le16(nBlockAlign); + waveHdr.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec); + waveHdr.wBitsPerSample = cpu_to_le16(nBitsPerSample); + waveHdr.chkData.ckid = cpu_to_le32(FOURCC_DATA); + waveHdr.chkRiff.dwSize = cpu_to_le32(temp); + waveHdr.chkData.dwSize = cpu_to_le32(expected_bytes); + + return write (audio, &waveHdr, sizeof (waveHdr)); +} + +static int _ExitSound(int audio, unsigned long nBytesDone); + +static int _ExitSound(int audio, unsigned long nBytesDone) +{ + unsigned long temp = nBytesDone + sizeof(WAVEHDR) - sizeof(CHUNKHDR); + + waveHdr.chkRiff.dwSize = cpu_to_le32(temp); + waveHdr.chkData.dwSize = cpu_to_le32(nBytesDone); + + /* goto beginning */ + if (lseek(audio, 0L, SEEK_SET) == -1) { + return 0; + } + return write (audio, &waveHdr, sizeof (waveHdr)); +} + +static unsigned long _GetHdrSize(void); + +static unsigned long _GetHdrSize(void) +{ + return sizeof( waveHdr ); +} + +static unsigned long InSizeToOutSize(unsigned long BytesToDo); + +static unsigned long InSizeToOutSize(unsigned long BytesToDo) +{ + return BytesToDo; +} + +struct soundfile wavsound = +{ + _InitSound, /* init header method */ + _ExitSound, /* exit header method */ + _GetHdrSize, /* report header size method */ + /* get sound samples out */ + (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo)) write, + InSizeToOutSize, /* compressed? output file size */ + 0 /* needs big endian samples */ +}; + + |