Wno-implicit-function-declaration no longer needed
[AROS-Contrib.git] / FryingPan / DTLib / rWAVAudio.cpp
blobacbe052f929ff31081f0b8f8ef8db0ae23b442c2
1 /*
2 * FryingPan - Amiga CD/DVD Recording Software (User Interface and supporting Libraries only)
3 * Copyright (C) 2001-2011 Tomasz Wiszkowski Tomasz.Wiszkowski at gmail.com
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "rWAVAudio.h"
21 #include <libclass/dos.h>
22 #include <libclass/exec.h>
23 #include <libclass/utility.h>
24 #include <exec/lists.h>
25 #include <Generic/HookT.h>
27 #define FLIP16(a) ((((a)&0xff00)>>8) | (((a)&0xff)<<8))
29 #define MKID(a,b,c,d) (((a&255)<<24)|((b&255)<<16)|((c&255)<<8)|(d&255))
30 #define ID_RIFF MKID('R','I','F','F')
31 #define ID_WAVE MKID('W','A','V','E')
32 #define ID_fmt MKID('f','m','t',' ')
33 #define ID_data MKID('d','a','t','a')
35 struct WaveHdr
37 unsigned short format;
38 unsigned short channels;
39 unsigned long frequency;
40 unsigned long bytesPerSecond;
41 unsigned short bytesPerSample;
42 unsigned short resolution;
45 IFileReader *rWAVAudio::openRead(const char* sFile, EDtError &rc)
47 rWAVAudio *pSkel = 0;
48 if (true == rWAVAudio::checkFile(sFile, rc))
50 pSkel = new rWAVAudio(sFile, rc);
52 return pSkel;
55 rWAVAudio::rWAVAudio(const char *sName, EDtError &rc)
56 : FileReader(sName, rc)
58 if (rc != DT_OK)
59 return;
61 readHeaders();
62 setBlockSize(2352);
63 setLittleEndian(true);
64 setType(Data_Audio);
67 const char *rWAVAudio::static_getName()
69 return "WAV Audio Track";
72 bool rWAVAudio::static_isAudio()
74 return true;
77 bool rWAVAudio::static_isData()
79 return false;
82 bool rWAVAudio::static_isSession()
84 return false;
87 bool rWAVAudio::isAudio()
89 return static_isAudio();
92 bool rWAVAudio::isData()
94 return static_isData();
97 const char *rWAVAudio::getName()
99 return static_getName();
102 void rWAVAudio::readHeaders()
104 unsigned int buff;
105 int c=0;
107 _D(Lvl_Info, "%s: Reading headers", (int)__PRETTY_FUNCTION__);
108 DOS->Seek(getFile(), 0, OFFSET_BEGINNING);
110 if (DOS->Read(getFile(), &buff, 4)!=4)
112 _D(Lvl_Info, "%s: File seems to be too small.. reading failed.", (int)__PRETTY_FUNCTION__);
113 return;
115 buff = L2BE(buff);
116 if (buff != ID_RIFF)
118 _D(Lvl_Info, "%s: RIFF Wave file header not present (got: %08lx)", (int)__PRETTY_FUNCTION__, buff);
119 return;
122 DOS->Seek(getFile(), 4, OFFSET_CURRENT);
124 if (DOS->Read(getFile(), &buff, 4)!=4)
126 _D(Lvl_Info, "%s: File truncated..?", (int)__PRETTY_FUNCTION__);
127 return;
129 buff = L2BE(buff);
130 if (buff != ID_WAVE)
132 _D(Lvl_Info, "%s: This RIFF is not Wave... (%08lx)", (int)__PRETTY_FUNCTION__, buff);
133 return;
136 for (c=0; c<2;)
138 if (DOS->Read(getFile(), &buff, 4)!=4)
140 _D(Lvl_Info, "%s: File truncated...", (int)__PRETTY_FUNCTION__);
141 return;
144 _D(Lvl_Info, "%s: Read tag: %08lx", (int)__PRETTY_FUNCTION__, buff);
146 buff = L2BE(buff);
148 if (buff == ID_fmt)
150 _D(Lvl_Info, "%s: format tag located.", (int)__PRETTY_FUNCTION__);
151 c++;
153 else if (buff == ID_data)
155 _D(Lvl_Info, "%s: data tag located.", (int)__PRETTY_FUNCTION__);
156 c++;
157 if (DOS->Read(getFile(), &buff, 4)!=4)
159 _D(Lvl_Info, "%s: file truncated.", (int)__PRETTY_FUNCTION__);
160 return;
163 setDataOffset(DOS->Seek(getFile(), 0, OFFSET_CURRENT));
164 buff = L2LE(buff);
165 setDataSize(buff);
166 DOS->Seek(getFile(), -4, OFFSET_CURRENT);
168 if (DOS->Read(getFile(), &buff, 4)!=4)
170 _D(Lvl_Info, "%s: Failed to read chunk size. File truncated.", (int)__PRETTY_FUNCTION__);
171 return;
173 buff = L2LE(buff);
174 _D(Lvl_Info,"%s: chunk size = %ld bytes.", (int)__PRETTY_FUNCTION__, buff);
175 DOS->Seek(getFile(), buff, OFFSET_CURRENT);
178 return;
181 bool rWAVAudio::checkHeader(WaveHdr* pHdr, EDtError &rc)
183 if (W2LE(1) != pHdr->format)
185 rc = DT_FileFormatNotSupported;
186 return false;
188 if (W2LE(2) != pHdr->channels)
190 rc = DT_WrongChannelCount;
191 return false;
193 if (L2LE(44100) != pHdr->frequency)
195 rc = DT_WrongFrequency;
196 return false;
198 if (W2LE(16) != pHdr->resolution)
200 rc = DT_WrongResolution;
201 return false;
203 rc = DT_OK;
204 return true;
207 bool rWAVAudio::checkFile(const char* sFileName, EDtError &rc)
209 unsigned int buff;
210 int c=0, len;
211 BPTR fh;
213 rc = DT_UnableToOpenFile;
215 fh = DOS->Open(const_cast<char*>(sFileName), MODE_OLDFILE);
216 if (0 == fh)
217 return false;
219 DOS->Seek(fh, 0, OFFSET_BEGINNING);
221 if (DOS->Read(fh, &buff, 4)!=4)
223 DOS->Close(fh);
224 rc = DT_FileMalformed;
225 return false;
227 buff = L2BE(buff);
228 if (buff != ID_RIFF)
230 DOS->Close(fh);
231 rc = DT_InvalidFormat;
232 return false;
235 DOS->Seek(fh, 4, OFFSET_CURRENT);
237 if (DOS->Read(fh, &buff, 4)!=4)
239 DOS->Close(fh);
240 rc = DT_FileMalformed;
241 return false;
243 buff = L2BE(buff);
244 if (buff != ID_WAVE)
246 DOS->Close(fh);
247 rc = DT_InvalidFormat;
248 return false;
251 for (c=0;c<2;)
253 if (DOS->Read(fh, &buff, 4)!=4)
255 rc = DT_FileMalformed;
256 DOS->Close(fh);
257 return false;
260 buff = L2BE(buff);
261 if (buff == ID_fmt)
263 WaveHdr *wave_hdr = 0;
264 bool bCorrect = false;
266 buff = 0;
267 DOS->Read(fh, &buff, 4);
268 len = L2LE(buff);
269 wave_hdr = (WaveHdr*)new char[len];
271 if ((NULL != wave_hdr) && (len == DOS->Read(fh, wave_hdr, len)))
273 bCorrect = checkHeader(wave_hdr, rc);
274 delete [] ((char*)wave_hdr);
276 c++;
278 if (false == bCorrect)
280 DOS->Close(fh);
281 return false;
283 continue;
285 else if (buff == ID_data)
287 c++;
290 if (DOS->Read(fh, &buff, 4)!=4)
292 rc = DT_FileMalformed;
293 DOS->Close(fh);
294 return false;
297 buff = L2LE(buff);
298 DOS->Seek(fh, buff, OFFSET_CURRENT);
301 DOS->Close(fh);
302 return true;