]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndwav.cpp
fixed URL parsing problem
[wxWidgets.git] / utils / wxMMedia2 / lib / sndwav.cpp
CommitLineData
526ddb13
GL
1// --------------------------------------------------------------------------
2// Name: sndwav.cpp
3// Purpose:
4// Date: 08/11/1999
5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6// CVSID: $Id$
7// --------------------------------------------------------------------------
8#ifdef __GNUG__
9#pragma implementation "sndwav.cpp"
10#endif
11
6c5e6376
GL
12#include <wx/wxprec.h>
13
526ddb13
GL
14#include <wx/stream.h>
15#include <wx/datstrm.h>
16#include <wx/filefn.h>
6c5e6376 17
526ddb13
GL
18#include "sndbase.h"
19#include "sndcodec.h"
20#include "sndfile.h"
21#include "sndpcm.h"
0662cd32 22#include "sndg72x.h"
526ddb13
GL
23#include "sndwav.h"
24
25#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
26
27#define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
28#define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
29#define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
30#define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
31
32#define HEADER_SIZE 4+4 + 4+4+16 + 4+4
33 // 4+4 => NAME + LEN
34 // 16 => fmt size
35
36wxSoundWave::wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound)
37 : wxSoundFileStream(stream, io_sound)
38{
39}
40
41wxSoundWave::wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound)
42 : wxSoundFileStream(stream, io_sound)
43{
44}
45
46wxSoundWave::~wxSoundWave()
47{
48}
49
50#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
51
52bool wxSoundWave::CanRead()
53{
54 wxUint32 len, signature;
55 m_snderror = wxSOUND_NOERR;
56
57 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
58
59 if (wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE) {
60 m_input->Ungetch(&signature, 4);
61 return FALSE;
62 }
63
64 m_input->Read(&len, 4);
65 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
66
67 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
68 if (wxUINT32_SWAP_ON_BE(signature) != WAVE_SIGNATURE) {
69 m_input->Ungetch(&signature, 4);
70 return FALSE;
71 }
72
73 m_input->Ungetch("RIFF", 4);
74 m_input->Ungetch(&len, 4);
75 m_input->Ungetch("WAVE", 4);
76
77 return TRUE;
78}
79
aa8fb7a0 80bool wxSoundWave::HandleOutputPCM(wxDataInputStream& data, wxUint16 channels,
0662cd32
GL
81 wxUint32 sample_fq, wxUint32 byte_p_sec,
82 wxUint16 byte_p_spl, wxUint16 bits_p_spl)
83{
84 wxSoundFormatPcm sndformat;
85
86 sndformat.SetSampleRate(sample_fq);
87 sndformat.SetBPS(bits_p_spl);
88 sndformat.SetChannels(channels);
89 sndformat.Signed(TRUE);
90 sndformat.SetOrder(wxLITTLE_ENDIAN);
91
92 if (!SetSoundFormat(sndformat))
93 return FALSE;
94
95 return TRUE;
96}
97
aa8fb7a0 98bool wxSoundWave::HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
0662cd32
GL
99 wxUint32 sample_fq, wxUint32 byte_p_sec,
100 wxUint16 byte_p_spl, wxUint16 bits_p_spl)
101{
102 wxSoundFormatG72X sndformat;
103
104 sndformat.SetSampleRate(sample_fq);
105 sndformat.SetG72XType(wxSOUND_G721);
106
107 if (!SetSoundFormat(sndformat))
108 return FALSE;
109
110 return TRUE;
111}
112
526ddb13
GL
113bool wxSoundWave::PrepareToPlay()
114{
115 wxUint32 signature, len;
116 bool end_headers;
117
118 if (!m_input) {
119 m_snderror = wxSOUND_INVSTRM;
120 return FALSE;
121 }
122
123 wxDataInputStream data(*m_input);
124 data.BigEndianOrdered(FALSE);
125
126 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
127 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE, wxSOUND_INVSTRM);
128 // "RIFF"
129
130 len = data.Read32();
131 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
132 // dummy len
133
134 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
135 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != WAVE_SIGNATURE, wxSOUND_INVSTRM);
136 // "WAVE"
137
138 end_headers = FALSE;
139 while (!end_headers) {
140 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
141
142 len = data.Read32();
143 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
144
145 switch (wxUINT32_SWAP_ON_BE(signature)) {
146 case FMT_SIGNATURE: { // "fmt "
147 wxUint16 format, channels, byte_p_spl, bits_p_spl;
148 wxUint32 sample_fq, byte_p_sec;
526ddb13
GL
149
150 data >> format >> channels >> sample_fq
151 >> byte_p_sec >> byte_p_spl >> bits_p_spl;
0662cd32
GL
152
153 switch (format) {
154 case 0x01:
aa8fb7a0 155 if (!HandleOutputPCM(data, channels, sample_fq,
0662cd32
GL
156 byte_p_sec, byte_p_spl, bits_p_spl))
157 return FALSE;
158 break;
159 case 0x40:
aa8fb7a0 160 if (!HandleOutputG721(data, channels, sample_fq,
0662cd32
GL
161 byte_p_sec, byte_p_spl, bits_p_spl))
162 return FALSE;
163 break;
164 default:
165 m_snderror = wxSOUND_NOCODEC;
526ddb13 166 return FALSE;
0662cd32 167 }
526ddb13
GL
168 break;
169 }
170 case DATA_SIGNATURE: // "data"
171 end_headers = TRUE;
172 break;
173 default:
174 m_input->SeekI(len, wxFromCurrent);
175 break;
176 }
177 }
178 return TRUE;
179}
180
aa8fb7a0
GL
181wxSoundFormatBase *wxSoundWave::HandleInputPCM(wxDataOutputStream& data)
182{
183 wxUint16 format, channels, byte_p_spl, bits_p_spl;
184 wxUint32 sample_fq, byte_p_sec;
185 wxSoundFormatPcm *pcm;
186
187 pcm = (wxSoundFormatPcm *)(m_sndformat->Clone());
188
189 // Write block length
190 data.Write32(16);
191
192 sample_fq = pcm->GetSampleRate();
193 bits_p_spl = pcm->GetBPS();
194 channels = pcm->GetChannels();
195 byte_p_spl = pcm->GetBPS() / 8;
196 byte_p_sec = pcm->GetBytesFromTime(1);
197 format = 0x01;
198
199 pcm->Signed(TRUE);
200 pcm->SetOrder(wxLITTLE_ENDIAN);
201
202 data << format << channels << sample_fq
203 << byte_p_sec << byte_p_spl << bits_p_spl;
204
205 return pcm;
206}
207
208wxSoundFormatBase *wxSoundWave::HandleInputG72X(wxDataOutputStream& data)
209{
210 wxUint16 format, channels, byte_p_spl, bits_p_spl;
211 wxUint32 sample_fq, byte_p_sec;
212 wxSoundFormatG72X *g72x;
213
214 // Write block length
215 data.Write32(16);
216
217 g72x = (wxSoundFormatG72X *)(m_sndformat->Clone());
218 if (g72x->GetG72XType() != wxSOUND_G721) {
219 delete g72x;
220 return NULL;
221 }
222
223 sample_fq = g72x->GetSampleRate();
224 bits_p_spl = 4;
225 channels = 1;
226 byte_p_spl = 0;
227 byte_p_sec = g72x->GetBytesFromTime(1);
228 format = 0x40;
229 data << format << channels << sample_fq
230 << byte_p_sec << byte_p_spl << bits_p_spl;
231
232 return g72x;
233}
234
526ddb13
GL
235bool wxSoundWave::PrepareToRecord(unsigned long time)
236{
237#define WRITE_SIGNATURE(sig) \
238signature = sig; \
239signature = wxUINT32_SWAP_ON_BE(signature); \
240FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
241
242 wxUint32 signature, len;
243
244 if (!m_output) {
245 m_snderror = wxSOUND_INVSTRM;
246 return FALSE;
247 }
248
249 wxDataOutputStream data(*m_output);
250 data.BigEndianOrdered(FALSE);
251
622e48cb 252 len = m_sndformat->GetBytesFromTime(time);
526ddb13
GL
253
254 len += HEADER_SIZE;
255
256 WRITE_SIGNATURE(RIFF_SIGNATURE);
257
258 data << len;
259 FAIL_WITH(m_output->LastWrite() != 4, wxSOUND_INVSTRM);
260
261 WRITE_SIGNATURE(WAVE_SIGNATURE);
262
263 {
aa8fb7a0
GL
264 wxSoundFormatBase *frmt;
265
266 WRITE_SIGNATURE(FMT_SIGNATURE);
526ddb13 267
aa8fb7a0
GL
268 switch (m_sndformat->GetType()) {
269 case wxSOUND_PCM:
270 frmt = HandleInputPCM(data);
271 break;
272 case wxSOUND_G72X:
273 frmt = HandleInputG72X(data);
274 break;
275 default:
526ddb13
GL
276 m_snderror = wxSOUND_NOCODEC;
277 return FALSE;
278 }
279
aa8fb7a0 280 FAIL_WITH(!frmt, wxSOUND_NOCODEC);
526ddb13 281
aa8fb7a0
GL
282 if (!SetSoundFormat(*frmt)) {
283 delete frmt;
526ddb13 284 return FALSE;
b83290c3 285 }
526ddb13 286
aa8fb7a0 287 delete frmt;
526ddb13
GL
288 }
289
290 WRITE_SIGNATURE(DATA_SIGNATURE);
622e48cb 291 data.Write32(m_sndformat->GetBytesFromTime(time));
526ddb13
GL
292 return TRUE;
293}
294
295bool wxSoundWave::FinishRecording()
296{
297 // TODO: Update headers when we stop before the specified time (if possible)
298 return TRUE;
299}
300
0662cd32 301wxUint32 wxSoundWave::GetData(void *buffer, wxUint32 len)
526ddb13
GL
302{
303 return m_input->Read(buffer, len).LastRead();
304}
305
0662cd32 306wxUint32 wxSoundWave::PutData(const void *buffer, wxUint32 len)
526ddb13
GL
307{
308 return m_output->Write(buffer, len).LastWrite();
309}