]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndwav.cpp
Inserted "stdio catch" in wxExecute. The activation is controlled by wxProcess.
[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>
56dc1ffd 17#include <wx/mstream.h>
6c5e6376 18
526ddb13
GL
19#include "sndbase.h"
20#include "sndcodec.h"
21#include "sndfile.h"
22#include "sndpcm.h"
0662cd32 23#include "sndg72x.h"
526ddb13
GL
24#include "sndwav.h"
25
26#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
27
28#define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
29#define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
30#define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
31#define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
32
33#define HEADER_SIZE 4+4 + 4+4+16 + 4+4
794bcc2d
GL
34// 4+4 => NAME + LEN
35// 16 => fmt size
526ddb13
GL
36
37wxSoundWave::wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound)
794bcc2d 38 : wxSoundFileStream(stream, io_sound)
526ddb13 39{
794bcc2d 40 m_base_offset = wxInvalidOffset;
526ddb13
GL
41}
42
43wxSoundWave::wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound)
794bcc2d 44 : wxSoundFileStream(stream, io_sound)
526ddb13 45{
794bcc2d 46 m_base_offset = wxInvalidOffset;
526ddb13
GL
47}
48
49wxSoundWave::~wxSoundWave()
50{
51}
52
2018e574
GL
53wxString wxSoundWave::GetCodecName() const
54{
55 return wxString(wxT("wxSoundWave codec"));
56}
57
526ddb13
GL
58#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
59
60bool wxSoundWave::CanRead()
61{
794bcc2d 62 wxUint32 len, signature1, signature2;
8b33ae2d 63 m_snderror = wxSOUND_NOERROR;
794bcc2d
GL
64
65 // Test the main signatures:
66 // "RIFF"
67 FAIL_WITH(m_input->Read(&signature1, 4).LastRead() != 4, wxSOUND_INVSTRM);
68
69 if (wxUINT32_SWAP_ON_BE(signature1) != RIFF_SIGNATURE) {
70 m_input->Ungetch(&signature1, 4);
71 return FALSE;
72 }
526ddb13 73
794bcc2d
GL
74 // Pass the global length
75 m_input->Read(&len, 4);
76 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
526ddb13 77
794bcc2d
GL
78 // Get the second signature
79 FAIL_WITH(m_input->Read(&signature2, 4).LastRead() != 4, wxSOUND_INVSTRM);
80 // Ungetch all
81 m_input->Ungetch(&signature2, 4);
82 m_input->Ungetch(&len, 4);
56dc1ffd 83 m_input->Ungetch(&signature1, 4);
56dc1ffd 84
794bcc2d
GL
85 // Test the second signature
86 if (wxUINT32_SWAP_ON_BE(signature2) != WAVE_SIGNATURE)
87 return FALSE;
88
89 return TRUE;
526ddb13
GL
90}
91
aa8fb7a0 92bool wxSoundWave::HandleOutputPCM(wxDataInputStream& data, wxUint16 channels,
794bcc2d
GL
93 wxUint32 sample_fq, wxUint32 byte_p_sec,
94 wxUint16 byte_p_spl, wxUint16 bits_p_spl)
0662cd32 95{
794bcc2d
GL
96 wxSoundFormatPcm sndformat;
97
98 sndformat.SetSampleRate(sample_fq);
99 sndformat.SetBPS(bits_p_spl);
100 sndformat.SetChannels(channels);
101 sndformat.Signed(TRUE);
102 sndformat.SetOrder(wxLITTLE_ENDIAN);
103
104 if (!SetSoundFormat(sndformat))
105 return FALSE;
106
107 return TRUE;
0662cd32
GL
108}
109
aa8fb7a0 110bool wxSoundWave::HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
794bcc2d
GL
111 wxUint32 sample_fq, wxUint32 byte_p_sec,
112 wxUint16 byte_p_spl, wxUint16 bits_p_spl)
0662cd32 113{
794bcc2d
GL
114 wxSoundFormatG72X sndformat;
115
116 sndformat.SetSampleRate(sample_fq);
117 sndformat.SetG72XType(wxSOUND_G721);
118
119 if (!SetSoundFormat(sndformat))
120 return FALSE;
121
122 return TRUE;
0662cd32
GL
123}
124
526ddb13
GL
125bool wxSoundWave::PrepareToPlay()
126{
794bcc2d
GL
127 wxUint32 signature, len;
128 bool end_headers;
129
130 if (!m_input) {
131 m_snderror = wxSOUND_INVSTRM;
132 return FALSE;
133 }
134
135 wxDataInputStream data(*m_input);
136 data.BigEndianOrdered(FALSE);
526ddb13 137
794bcc2d 138 // Get the first signature
526ddb13 139 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
794bcc2d
GL
140 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE, wxSOUND_INVSTRM);
141 // "RIFF"
142
526ddb13
GL
143 len = data.Read32();
144 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
794bcc2d 145 // dummy len
526ddb13 146
794bcc2d
GL
147 // Get the second signature
148 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
149 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != WAVE_SIGNATURE, wxSOUND_INVSTRM);
150 // "WAVE"
151
152 end_headers = FALSE;
153 // Chunk loop
154 while (!end_headers) {
155 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
156
157 len = data.Read32();
158 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
159
160 switch (wxUINT32_SWAP_ON_BE(signature)) {
161 case FMT_SIGNATURE: { // "fmt "
162 wxUint16 format, channels, byte_p_spl, bits_p_spl;
163 wxUint32 sample_fq, byte_p_sec;
164
165 // Get the common parameters
166 data >> format >> channels >> sample_fq
167 >> byte_p_sec >> byte_p_spl >> bits_p_spl;
168
169 switch (format) {
170 case 0x01: // PCM
171 if (!HandleOutputPCM(data, channels, sample_fq,
172 byte_p_sec, byte_p_spl, bits_p_spl))
173 return FALSE;
174 break;
175 case 0x40: // G721
176 if (!HandleOutputG721(data, channels, sample_fq,
177 byte_p_sec, byte_p_spl, bits_p_spl))
178 return FALSE;
179 break;
180 default:
181 m_snderror = wxSOUND_NOCODEC;
182 return FALSE;
183 }
184 break;
185 }
186 case DATA_SIGNATURE: // "data"
187 m_base_offset = m_input->TellI();
188 end_headers = TRUE;
189 FinishPreparation(len);
190 break;
191 default:
192 // We pass the chunk
193 m_input->SeekI(len, wxFromCurrent);
194 break;
195 }
526ddb13 196 }
794bcc2d 197 return TRUE;
526ddb13
GL
198}
199
aa8fb7a0
GL
200wxSoundFormatBase *wxSoundWave::HandleInputPCM(wxDataOutputStream& data)
201{
794bcc2d
GL
202 wxUint16 format, channels, byte_p_spl, bits_p_spl;
203 wxUint32 sample_fq, byte_p_sec;
204 wxSoundFormatPcm *pcm;
205
206 pcm = (wxSoundFormatPcm *)(m_sndformat->Clone());
207
208 // Write block length
209 data.Write32(16);
210
211 sample_fq = pcm->GetSampleRate();
212 bits_p_spl = pcm->GetBPS();
213 channels = pcm->GetChannels();
214 byte_p_spl = pcm->GetBPS() / 8;
215 byte_p_sec = pcm->GetBytesFromTime(1);
216 format = 0x01;
217
218 pcm->Signed(TRUE);
219 pcm->SetOrder(wxLITTLE_ENDIAN);
220
221 data << format << channels << sample_fq
222 << byte_p_sec << byte_p_spl << bits_p_spl;
223
224 return pcm;
aa8fb7a0
GL
225}
226
227wxSoundFormatBase *wxSoundWave::HandleInputG72X(wxDataOutputStream& data)
228{
794bcc2d
GL
229 wxUint16 format, channels, byte_p_spl, bits_p_spl;
230 wxUint32 sample_fq, byte_p_sec;
231 wxSoundFormatG72X *g72x;
232
233 // Write block length
234 data.Write32(16);
235
236 g72x = (wxSoundFormatG72X *)(m_sndformat->Clone());
237 if (g72x->GetG72XType() != wxSOUND_G721) {
238 delete g72x;
239 return NULL;
240 }
241
242 sample_fq = g72x->GetSampleRate();
243 bits_p_spl = 4;
244 channels = 1;
245 byte_p_spl = 0;
246 byte_p_sec = g72x->GetBytesFromTime(1);
247 format = 0x40;
248 data << format << channels << sample_fq
249 << byte_p_sec << byte_p_spl << bits_p_spl;
250
251 return g72x;
aa8fb7a0
GL
252}
253
794bcc2d 254bool wxSoundWave::PrepareToRecord(wxUint32 time)
526ddb13 255{
56dc1ffd 256#define WRITE_SIGNATURE(s,sig) \
526ddb13
GL
257signature = sig; \
258signature = wxUINT32_SWAP_ON_BE(signature); \
56dc1ffd 259FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
794bcc2d
GL
260
261 wxUint32 signature;
262 wxMemoryOutputStream fmt_data;
263
264 if (!m_output) {
265 m_snderror = wxSOUND_INVSTRM;
266 return FALSE;
526ddb13 267 }
794bcc2d
GL
268
269 wxDataOutputStream data(*m_output);
270 wxDataOutputStream fmt_d_data(fmt_data);
271
272 data.BigEndianOrdered(FALSE);
273 fmt_d_data.BigEndianOrdered(FALSE);
274
275 WRITE_SIGNATURE(m_output, RIFF_SIGNATURE);
276
277 FAIL_WITH(m_output->LastWrite() != 4, wxSOUND_INVSTRM);
278
279 WRITE_SIGNATURE((&fmt_data), WAVE_SIGNATURE);
280
281 {
282 wxSoundFormatBase *frmt;
283
284 WRITE_SIGNATURE((&fmt_data), FMT_SIGNATURE);
285
286 switch (m_sndformat->GetType()) {
287 case wxSOUND_PCM:
288 frmt = HandleInputPCM(fmt_d_data);
289 break;
290 case wxSOUND_G72X:
291 frmt = HandleInputG72X(fmt_d_data);
292 break;
293 default:
294 m_snderror = wxSOUND_NOCODEC;
295 return FALSE;
296 }
297
298 FAIL_WITH(!frmt, wxSOUND_NOCODEC);
299
300 if (!SetSoundFormat(*frmt)) {
301 delete frmt;
302 return FALSE;
303 }
304
305 delete frmt;
b83290c3 306 }
794bcc2d
GL
307
308 data << (fmt_data.GetSize() + m_sndformat->GetBytesFromTime(time));
309
310 // We, finally, copy the header block to the output stream
311 {
312 char *out_buf;
313 out_buf = new char[fmt_data.GetSize()];
314
315 fmt_data.CopyTo(out_buf, fmt_data.GetSize());
316 m_output->Write(out_buf, fmt_data.GetSize());
317
318 delete[] out_buf;
319 }
320
321 WRITE_SIGNATURE(m_output, DATA_SIGNATURE);
322 data.Write32(m_sndformat->GetBytesFromTime(time));
323 return TRUE;
526ddb13
GL
324}
325
326bool wxSoundWave::FinishRecording()
327{
794bcc2d
GL
328 if (m_output->SeekO(0, wxFromStart) == wxInvalidOffset)
329 // We can't but there is no error.
330 return TRUE;
331
332 if (m_bytes_left == 0)
333 return TRUE;
334
335 // TODO: Update headers when we stop before the specified time (if possible)
27259273 336 return TRUE;
794bcc2d 337}
27259273 338
794bcc2d
GL
339bool wxSoundWave::RepositionStream(wxUint32 position)
340{
341 if (m_base_offset == wxInvalidOffset)
342 return FALSE;
343 m_input->SeekI(m_base_offset, wxFromStart);
27259273 344 return TRUE;
526ddb13
GL
345}
346
0662cd32 347wxUint32 wxSoundWave::GetData(void *buffer, wxUint32 len)
526ddb13 348{
794bcc2d 349 return m_input->Read(buffer, len).LastRead();
526ddb13
GL
350}
351
0662cd32 352wxUint32 wxSoundWave::PutData(const void *buffer, wxUint32 len)
526ddb13 353{
794bcc2d 354 return m_output->Write(buffer, len).LastWrite();
526ddb13 355}