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