Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / icedax / wav.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)wav.c    1.4 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
14 /***
15  * CopyPolicy: GNU Public License 2 applies
16  * Copyright (C) by Heiko Eissfeldt
17  *
18  *
19  */
20 #include "config.h"
21 #include <stdio.h>
22 #include <unixstd.h>
23 #include "byteorder.h"
24 #include "sndfile.h"
25
26 /***
27  * ---------------------------------------------------------------------
28  *  definitions for RIFF-output (from windows MMSYSTEM)
29  * ---------------------------------------------------------------------
30  */
31
32 typedef unsigned int FOURCC;    /* a four character code */
33
34 typedef struct CHUNKHDR {
35   FOURCC ckid;          /* chunk ID */
36   unsigned int dwSize;  /* chunk size */
37 } CHUNKHDR;
38
39 /* flags for 'wFormatTag' field of WAVEFORMAT */
40 #define WAVE_FORMAT_PCM 1
41
42 /* specific waveform format structure for PCM data */
43 typedef struct pcmwaveformat_tag {
44   unsigned short wFormatTag;    /* format type */
45   unsigned short nChannels;     /* number of channels (i.e. mono, stereo, etc.) */
46   unsigned int nSamplesPerSec; /* sample rate */
47   unsigned int nAvgBytesPerSec;/* for buffer size estimate */
48   unsigned short nBlockAlign;   /* block size of data */
49   unsigned short wBitsPerSample;
50 } PCMWAVEFORMAT;
51 typedef PCMWAVEFORMAT *PPCMWAVEFORMAT;
52
53
54 /* MMIO macros */
55 #define mmioFOURCC(ch0, ch1, ch2, ch3) \
56   ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \
57   ((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24))
58
59 #define FOURCC_RIFF     mmioFOURCC ('R', 'I', 'F', 'F')
60 #define FOURCC_LIST     mmioFOURCC ('L', 'I', 'S', 'T')
61 #define FOURCC_WAVE     mmioFOURCC ('W', 'A', 'V', 'E')
62 #define FOURCC_FMT      mmioFOURCC ('f', 'm', 't', ' ')
63 #define FOURCC_DATA     mmioFOURCC ('d', 'a', 't', 'a')
64
65
66 /* simplified Header for standard WAV files */
67 typedef struct WAVEHDR {
68   CHUNKHDR chkRiff;
69   FOURCC fccWave;
70   CHUNKHDR chkFmt;
71   unsigned short wFormatTag;    /* format type */
72   unsigned short nChannels;     /* number of channels (i.e. mono, stereo, etc.) */
73   unsigned int nSamplesPerSec; /* sample rate */
74   unsigned int nAvgBytesPerSec;/* for buffer estimation */
75   unsigned short nBlockAlign;   /* block size of data */
76   unsigned short wBitsPerSample;
77   CHUNKHDR chkData;
78 } WAVEHDR;
79
80 #define IS_STD_WAV_HEADER(waveHdr) ( \
81   waveHdr.chkRiff.ckid == FOURCC_RIFF && \
82   waveHdr.fccWave == FOURCC_WAVE && \
83   waveHdr.chkFmt.ckid == FOURCC_FMT && \
84   waveHdr.chkData.ckid == FOURCC_DATA && \
85   waveHdr.wFormatTag == WAVE_FORMAT_PCM)
86
87 static WAVEHDR waveHdr;
88
89 static int _InitSound(int audio, long channels, unsigned long rate, 
90                                                          long nBitsPerSample, unsigned long expected_bytes);
91
92 static int _InitSound(int audio, long channels, unsigned long rate, 
93                       long nBitsPerSample, unsigned long expected_bytes)
94 {
95   unsigned long nBlockAlign = channels * ((nBitsPerSample + 7) / 8);
96   unsigned long nAvgBytesPerSec = nBlockAlign * rate;
97   unsigned long temp = expected_bytes + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
98
99   waveHdr.chkRiff.ckid    = cpu_to_le32(FOURCC_RIFF);
100   waveHdr.fccWave         = cpu_to_le32(FOURCC_WAVE);
101   waveHdr.chkFmt.ckid     = cpu_to_le32(FOURCC_FMT);
102   waveHdr.chkFmt.dwSize   = cpu_to_le32(sizeof (PCMWAVEFORMAT));
103   waveHdr.wFormatTag      = cpu_to_le16(WAVE_FORMAT_PCM);
104   waveHdr.nChannels       = cpu_to_le16(channels);
105   waveHdr.nSamplesPerSec  = cpu_to_le32(rate);
106   waveHdr.nBlockAlign     = cpu_to_le16(nBlockAlign);
107   waveHdr.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec);
108   waveHdr.wBitsPerSample  = cpu_to_le16(nBitsPerSample);
109   waveHdr.chkData.ckid    = cpu_to_le32(FOURCC_DATA);
110   waveHdr.chkRiff.dwSize  = cpu_to_le32(temp);
111   waveHdr.chkData.dwSize  = cpu_to_le32(expected_bytes);
112
113   return write (audio, &waveHdr, sizeof (waveHdr));
114 }
115
116 static int _ExitSound(int audio, unsigned long nBytesDone);
117
118 static int _ExitSound(int audio, unsigned long nBytesDone)
119 {
120   unsigned long temp = nBytesDone + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
121
122   waveHdr.chkRiff.dwSize = cpu_to_le32(temp);
123   waveHdr.chkData.dwSize = cpu_to_le32(nBytesDone);
124
125   /* goto beginning */
126   if (lseek(audio, 0L, SEEK_SET) == -1) {
127     return 0;
128   }
129   return write (audio, &waveHdr, sizeof (waveHdr));
130 }
131
132 static unsigned long _GetHdrSize(void);
133
134 static unsigned long _GetHdrSize(void)
135 {
136   return sizeof( waveHdr );
137 }
138
139 static unsigned long InSizeToOutSize(unsigned long BytesToDo);
140
141 static unsigned long InSizeToOutSize(unsigned long BytesToDo)
142 {
143         return BytesToDo;
144 }
145
146 struct soundfile wavsound =
147 {
148         _InitSound,             /* init header method */
149         _ExitSound,             /* exit header method */
150         _GetHdrSize,            /* report header size method */
151         /* get sound samples out */
152         (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo)) write,
153         InSizeToOutSize,        /* compressed? output file size */
154         0                       /* needs big endian samples */
155 };
156
157