]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndfile.cpp
Corrected an HTML typo
[wxWidgets.git] / utils / wxMMedia2 / lib / sndfile.cpp
CommitLineData
526ddb13
GL
1// --------------------------------------------------------------------------
2// Name: sndfile.cpp
3// Purpose:
4// Date: 08/11/1999
d73dd2b2 5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
526ddb13
GL
6// CVSID: $Id$
7// --------------------------------------------------------------------------
6c5e6376
GL
8#include <wx/wxprec.h>
9
10#ifndef WX_PRECOMP
526ddb13 11#include <wx/stream.h>
6c5e6376
GL
12#endif
13
526ddb13
GL
14#include "sndbase.h"
15#include "sndcodec.h"
16#include "sndfile.h"
17#include "sndcpcm.h"
18#include "sndulaw.h"
0662cd32 19#include "sndg72x.h"
526ddb13
GL
20
21// --------------------------------------------------------------------------
22// Sound codec router
27259273
GL
23// A very important class: it ensures that everybody is satisfied.
24// It is supposed to create as many codec as it is necessary to transform
25// a signal in a specific format in an another.
526ddb13 26// --------------------------------------------------------------------------
526ddb13
GL
27wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio)
28 : wxSoundStreamCodec(sndio)
29{
30 m_router = NULL;
31}
32
33wxSoundRouterStream::~wxSoundRouterStream()
34{
35 if (m_router)
36 delete m_router;
37}
38
27259273
GL
39// --------------------------------------------------------------------------
40// Read(void *buffer, wxUint32 len): It reads data synchronously. See sndbase.h
41// for possible errors and behaviours ...
42// --------------------------------------------------------------------------
0662cd32 43wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len)
526ddb13
GL
44{
45 if (m_router) {
46 m_router->Read(buffer, len);
47 m_snderror = m_router->GetError();
48 m_lastcount = m_router->GetLastAccess();
49 } else {
50 m_sndio->Read(buffer, len);
51 m_snderror = m_sndio->GetError();
52 m_lastcount = m_sndio->GetLastAccess();
53 }
54 return *this;
55}
56
27259273
GL
57// --------------------------------------------------------------------------
58// Write(const void *buffer, wxUint32 len): It writes data synchronously
59// --------------------------------------------------------------------------
0662cd32 60wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len)
526ddb13
GL
61{
62 if (m_router) {
63 m_router->Write(buffer, len);
64 m_snderror = m_router->GetError();
65 m_lastcount = m_router->GetLastAccess();
66 } else {
67 m_sndio->Write(buffer, len);
68 m_snderror = m_sndio->GetError();
69 m_lastcount = m_sndio->GetLastAccess();
70 }
71 return *this;
72}
73
27259273
GL
74// --------------------------------------------------------------------------
75// SetSoundFormat(const wxSoundFormatBase& format) first tries to setup the
76// sound driver using the specified format. If this fails, it uses personnal
77// codec converters: for the moment there is a PCM converter (PCM to PCM:
78// with optional resampling, ...), an ULAW converter (ULAW to PCM), a G72X
79// converter (G72X to PCM). If nothing works, it returns FALSE.
80// --------------------------------------------------------------------------
526ddb13
GL
81bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format)
82{
83 if (m_router)
84 delete m_router;
85
86 if (m_sndio->SetSoundFormat(format)) {
87 wxSoundStream::SetSoundFormat(m_sndio->GetSoundFormat());
88 return TRUE;
89 }
90
91 switch(format.GetType()) {
92 case wxSOUND_NOFORMAT:
93 return FALSE;
94 case wxSOUND_PCM:
95 m_router = new wxSoundStreamPcm(*m_sndio);
96 m_router->SetSoundFormat(format);
97 break;
98 case wxSOUND_ULAW:
99 m_router = new wxSoundStreamUlaw(*m_sndio);
100 m_router->SetSoundFormat(format);
101 break;
0662cd32
GL
102 case wxSOUND_G72X:
103 m_router = new wxSoundStreamG72X(*m_sndio);
104 m_router->SetSoundFormat(format);
105 break;
526ddb13
GL
106 }
107 wxSoundStream::SetSoundFormat(m_router->GetSoundFormat());
108 return TRUE;
109}
110
27259273
GL
111// --------------------------------------------------------------------------
112// GetBestSize() returns the specific best buffer size a sound driver
113// can manage. It means that it will be easier for it to manage the buffer
114// and so it will be faster and in some case more accurate for real-time event.
115// --------------------------------------------------------------------------
56dc1ffd
GL
116wxUint32 wxSoundRouterStream::GetBestSize() const
117{
118 if (m_router)
119 return m_router->GetBestSize();
120 else
121 return m_sndio->GetBestSize();
122}
123
27259273
GL
124// --------------------------------------------------------------------------
125// StartProduction(int evt). See sndbase.h
126// --------------------------------------------------------------------------
526ddb13
GL
127bool wxSoundRouterStream::StartProduction(int evt)
128{
129 if (!m_router) {
130 if (m_sndio->StartProduction(evt))
131 return TRUE;
132
133 m_snderror = m_sndio->GetError();
134 m_lastcount = m_sndio->GetLastAccess();
135 return FALSE;
136 }
137
138 if (m_router->StartProduction(evt))
139 return TRUE;
140
141 m_snderror = m_router->GetError();
142 m_lastcount = m_router->GetLastAccess();
143 return FALSE;
144}
145
27259273
GL
146// --------------------------------------------------------------------------
147// StopProduction(). See sndbase.h
148// --------------------------------------------------------------------------
526ddb13
GL
149bool wxSoundRouterStream::StopProduction()
150{
151 if (!m_router) {
152 if (m_sndio->StopProduction())
153 return TRUE;
154
155 m_snderror = m_sndio->GetError();
156 m_lastcount = m_sndio->GetLastAccess();
157 return FALSE;
158 }
159
160 if (m_router->StopProduction())
161 return TRUE;
162
163 m_snderror = m_router->GetError();
164 m_lastcount = m_router->GetLastAccess();
165 return FALSE;
166}
167
168
169// --------------------------------------------------------------------------
170// wxSoundFileStream: generic reader
171// --------------------------------------------------------------------------
172
173wxSoundFileStream::wxSoundFileStream(wxInputStream& stream,
174 wxSoundStream& io_sound)
175 : m_codec(io_sound), m_sndio(&io_sound),
176 m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED)
177{
a31c84f3
GL
178 m_length = 0;
179 m_bytes_left = 0;
180 m_prepared = FALSE;
526ddb13
GL
181}
182
183wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream,
184 wxSoundStream& io_sound)
185 : m_codec(io_sound), m_sndio(&io_sound),
186 m_input(NULL), m_output(&stream), m_state(wxSOUND_FILE_STOPPED)
187{
a31c84f3
GL
188 m_length = 0;
189 m_bytes_left = 0;
190 m_prepared = FALSE;
526ddb13
GL
191}
192
193wxSoundFileStream::~wxSoundFileStream()
194{
195 if (m_state != wxSOUND_FILE_STOPPED)
196 Stop();
197}
198
199bool wxSoundFileStream::Play()
200{
201 if (m_state != wxSOUND_FILE_STOPPED)
202 return FALSE;
203
a31c84f3
GL
204 if (!m_prepared)
205 if (!PrepareToPlay())
206 return FALSE;
526ddb13 207
503aa33d
GL
208 m_state = wxSOUND_FILE_PLAYING;
209
526ddb13
GL
210 if (!StartProduction(wxSOUND_OUTPUT))
211 return FALSE;
212
526ddb13
GL
213 return TRUE;
214}
215
216bool wxSoundFileStream::Record(unsigned long time)
217{
218 if (m_state != wxSOUND_FILE_STOPPED)
219 return FALSE;
220
221 if (!PrepareToRecord(time))
222 return FALSE;
223
a31c84f3 224 FinishPreparation(m_sndformat->GetBytesFromTime(time));
526ddb13 225
503aa33d 226 m_state = wxSOUND_FILE_RECORDING;
526ddb13
GL
227 if (!StartProduction(wxSOUND_INPUT))
228 return FALSE;
229
526ddb13
GL
230 return TRUE;
231}
232
233bool wxSoundFileStream::Stop()
234{
235 if (m_state == wxSOUND_FILE_STOPPED)
236 return FALSE;
237
238 if (!StopProduction())
239 return FALSE;
240
a31c84f3
GL
241 m_prepared = FALSE;
242
526ddb13
GL
243 if (m_state == wxSOUND_FILE_RECORDING)
244 if (!FinishRecording()) {
245 m_state = wxSOUND_FILE_STOPPED;
246 return FALSE;
247 }
27259273
GL
248
249 if (m_input)
250 m_input->SeekI(0, wxFromStart);
251
252 if (m_output)
253 m_output->SeekO(0, wxFromStart);
526ddb13 254
526ddb13
GL
255 m_state = wxSOUND_FILE_STOPPED;
256 return TRUE;
257}
258
259bool wxSoundFileStream::Pause()
260{
261 if (m_state == wxSOUND_FILE_PAUSED || m_state == wxSOUND_FILE_STOPPED)
262 return FALSE;
263
264 if (!StopProduction())
265 return FALSE;
266
267 m_oldstate = m_state;
268 m_state = wxSOUND_FILE_PAUSED;
269 return TRUE;
270}
271
272bool wxSoundFileStream::Resume()
273{
274 if (m_state == wxSOUND_FILE_PLAYING || m_state == wxSOUND_FILE_RECORDING ||
275 m_state == wxSOUND_FILE_STOPPED)
276 return FALSE;
277
278 if (!StartProduction( (m_oldstate == wxSOUND_FILE_PLAYING) ?
279 wxSOUND_OUTPUT : wxSOUND_INPUT))
280 return FALSE;
281
282 m_state = m_oldstate;
283
284 return TRUE;
285}
286
0662cd32 287wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
526ddb13
GL
288{
289 m_lastcount = GetData(buffer, len);
290 return *this;
291}
292
0662cd32 293wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
526ddb13
GL
294{
295 m_lastcount = PutData(buffer, len);
296 return *this;
297}
298
526ddb13
GL
299bool wxSoundFileStream::StartProduction(int evt)
300{
301 m_sndio->SetEventHandler(this);
302
303 if (!m_codec.StartProduction(evt))
304 return FALSE;
305
306 return TRUE;
307}
308
309bool wxSoundFileStream::StopProduction()
310{
311 return m_codec.StopProduction();
312}
313
a31c84f3
GL
314void wxSoundFileStream::FinishPreparation(wxUint32 len)
315{
316 m_bytes_left = m_length = len;
317 m_prepared = TRUE;
318}
319
320wxUint32 wxSoundFileStream::GetLength()
321{
322 if (m_input && !m_prepared && GetError() == wxSOUND_NOERR)
323 return (PrepareToPlay()) ? m_length : 0;
324
325 return m_length;
326}
327
328wxUint32 wxSoundFileStream::GetPosition()
329{
330 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR)
331 PrepareToPlay();
332
333 return m_length-m_bytes_left;
334}
335
d73dd2b2
GL
336wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position)
337{
338 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR)
339 PrepareToPlay();
340
341 if (!m_prepared)
342 return 0;
343
344 if (new_position >= m_length) {
345 m_bytes_left = 0;
346 return m_length;
347 }
348
349 m_bytes_left = m_length-new_position;
350 return new_position;
351}
352
526ddb13
GL
353void wxSoundFileStream::OnSoundEvent(int evt)
354{
56dc1ffd 355 wxUint32 len = m_codec.GetBestSize();
6c5e6376 356 char *buffer;
526ddb13 357
503aa33d 358 buffer = new char[len];
526ddb13
GL
359 wxSoundStream::OnSoundEvent(evt);
360
503aa33d
GL
361 while (!m_sndio->QueueFilled()) {
362 switch(evt) {
363 case wxSOUND_INPUT:
a31c84f3
GL
364 if (len > m_bytes_left)
365 len = m_bytes_left;
503aa33d
GL
366
367 len = m_codec.Read(buffer, len).GetLastAccess();
368 PutData(buffer, len);
a31c84f3
GL
369 m_bytes_left -= len;
370 if (m_bytes_left == 0) {
503aa33d 371 Stop();
56dc1ffd 372 delete[] buffer;
503aa33d
GL
373 return;
374 }
375 break;
376 case wxSOUND_OUTPUT:
a31c84f3
GL
377 if (len > m_bytes_left)
378 len = m_bytes_left;
379
503aa33d 380 len = GetData(buffer, len);
a31c84f3
GL
381 m_bytes_left -= len;
382 if (m_bytes_left == 0) {
503aa33d 383 Stop();
56dc1ffd 384 delete[] buffer;
503aa33d
GL
385 return;
386 }
387 m_codec.Write(buffer, len);
388 break;
526ddb13 389 }
526ddb13 390 }
6c5e6376 391 delete[] buffer;
526ddb13
GL
392}
393
394bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
395{
396 wxSoundStream::SetSoundFormat(format);
397 return m_codec.SetSoundFormat(format);
398}