]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndfile.cpp
Ok. Vidwin works again on Windows.
[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{
794bcc2d 30 m_router = NULL;
526ddb13
GL
31}
32
33wxSoundRouterStream::~wxSoundRouterStream()
34{
794bcc2d
GL
35 if (m_router)
36 delete m_router;
526ddb13
GL
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 44{
794bcc2d
GL
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;
526ddb13
GL
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 61{
794bcc2d
GL
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();
526ddb13
GL
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{
794bcc2d
GL
83 if (m_router)
84 delete m_router;
85
86 // First, we try to setup the sound device
87 if (m_sndio->SetSoundFormat(format)) {
88 // We are lucky, it is working.
89 wxSoundStream::SetSoundFormat(m_sndio->GetSoundFormat());
90 return TRUE;
91 }
92
93 switch(format.GetType()) {
94 case wxSOUND_NOFORMAT:
95 return FALSE;
96 case wxSOUND_PCM:
97 m_router = new wxSoundStreamPcm(*m_sndio);
98 m_router->SetSoundFormat(format);
99 break;
100 case wxSOUND_ULAW:
101 m_router = new wxSoundStreamUlaw(*m_sndio);
102 m_router->SetSoundFormat(format);
103 break;
104 case wxSOUND_G72X:
105 m_router = new wxSoundStreamG72X(*m_sndio);
106 m_router->SetSoundFormat(format);
107 break;
108 }
109 wxSoundStream::SetSoundFormat(m_router->GetSoundFormat());
526ddb13 110 return TRUE;
526ddb13
GL
111}
112
27259273
GL
113// --------------------------------------------------------------------------
114// GetBestSize() returns the specific best buffer size a sound driver
115// can manage. It means that it will be easier for it to manage the buffer
116// and so it will be faster and in some case more accurate for real-time event.
117// --------------------------------------------------------------------------
56dc1ffd
GL
118wxUint32 wxSoundRouterStream::GetBestSize() const
119{
120 if (m_router)
121 return m_router->GetBestSize();
122 else
123 return m_sndio->GetBestSize();
124}
125
27259273
GL
126// --------------------------------------------------------------------------
127// StartProduction(int evt). See sndbase.h
128// --------------------------------------------------------------------------
526ddb13
GL
129bool wxSoundRouterStream::StartProduction(int evt)
130{
794bcc2d
GL
131 if (!m_router) {
132 if (m_sndio->StartProduction(evt))
133 return TRUE;
134
135 m_snderror = m_sndio->GetError();
136 m_lastcount = m_sndio->GetLastAccess();
137 return FALSE;
138 }
139
140 if (m_router->StartProduction(evt))
141 return TRUE;
142
143 m_snderror = m_router->GetError();
144 m_lastcount = m_router->GetLastAccess();
526ddb13 145 return FALSE;
526ddb13
GL
146}
147
27259273
GL
148// --------------------------------------------------------------------------
149// StopProduction(). See sndbase.h
150// --------------------------------------------------------------------------
526ddb13
GL
151bool wxSoundRouterStream::StopProduction()
152{
794bcc2d
GL
153 if (!m_router) {
154 if (m_sndio->StopProduction())
155 return TRUE;
156
157 m_snderror = m_sndio->GetError();
158 m_lastcount = m_sndio->GetLastAccess();
159 return FALSE;
160 }
161
162 if (m_router->StopProduction())
163 return TRUE;
164
165 m_snderror = m_router->GetError();
166 m_lastcount = m_router->GetLastAccess();
526ddb13 167 return FALSE;
526ddb13 168}
526ddb13
GL
169
170// --------------------------------------------------------------------------
171// wxSoundFileStream: generic reader
172// --------------------------------------------------------------------------
173
174wxSoundFileStream::wxSoundFileStream(wxInputStream& stream,
175 wxSoundStream& io_sound)
794bcc2d
GL
176 : m_codec(io_sound), m_sndio(&io_sound),
177 m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED)
526ddb13 178{
794bcc2d
GL
179 m_length = 0;
180 m_bytes_left = 0;
181 m_prepared = FALSE;
526ddb13
GL
182}
183
184wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream,
185 wxSoundStream& io_sound)
186 : m_codec(io_sound), m_sndio(&io_sound),
187 m_input(NULL), m_output(&stream), m_state(wxSOUND_FILE_STOPPED)
188{
a31c84f3
GL
189 m_length = 0;
190 m_bytes_left = 0;
191 m_prepared = FALSE;
526ddb13
GL
192}
193
194wxSoundFileStream::~wxSoundFileStream()
195{
196 if (m_state != wxSOUND_FILE_STOPPED)
197 Stop();
198}
199
200bool wxSoundFileStream::Play()
201{
202 if (m_state != wxSOUND_FILE_STOPPED)
203 return FALSE;
204
a31c84f3
GL
205 if (!m_prepared)
206 if (!PrepareToPlay())
207 return FALSE;
526ddb13 208
503aa33d
GL
209 m_state = wxSOUND_FILE_PLAYING;
210
526ddb13
GL
211 if (!StartProduction(wxSOUND_OUTPUT))
212 return FALSE;
213
526ddb13
GL
214 return TRUE;
215}
216
794bcc2d 217bool wxSoundFileStream::Record(wxUint32 time)
526ddb13
GL
218{
219 if (m_state != wxSOUND_FILE_STOPPED)
220 return FALSE;
221
222 if (!PrepareToRecord(time))
223 return FALSE;
224
a31c84f3 225 FinishPreparation(m_sndformat->GetBytesFromTime(time));
526ddb13 226
503aa33d 227 m_state = wxSOUND_FILE_RECORDING;
526ddb13
GL
228 if (!StartProduction(wxSOUND_INPUT))
229 return FALSE;
230
526ddb13
GL
231 return TRUE;
232}
233
234bool wxSoundFileStream::Stop()
235{
236 if (m_state == wxSOUND_FILE_STOPPED)
237 return FALSE;
238
239 if (!StopProduction())
240 return FALSE;
241
a31c84f3
GL
242 m_prepared = FALSE;
243
526ddb13
GL
244 if (m_state == wxSOUND_FILE_RECORDING)
245 if (!FinishRecording()) {
246 m_state = wxSOUND_FILE_STOPPED;
247 return FALSE;
248 }
27259273
GL
249
250 if (m_input)
251 m_input->SeekI(0, wxFromStart);
252
253 if (m_output)
254 m_output->SeekO(0, wxFromStart);
526ddb13 255
526ddb13
GL
256 m_state = wxSOUND_FILE_STOPPED;
257 return TRUE;
258}
259
260bool wxSoundFileStream::Pause()
261{
262 if (m_state == wxSOUND_FILE_PAUSED || m_state == wxSOUND_FILE_STOPPED)
263 return FALSE;
264
265 if (!StopProduction())
266 return FALSE;
267
268 m_oldstate = m_state;
269 m_state = wxSOUND_FILE_PAUSED;
270 return TRUE;
271}
272
273bool wxSoundFileStream::Resume()
274{
275 if (m_state == wxSOUND_FILE_PLAYING || m_state == wxSOUND_FILE_RECORDING ||
276 m_state == wxSOUND_FILE_STOPPED)
277 return FALSE;
278
279 if (!StartProduction( (m_oldstate == wxSOUND_FILE_PLAYING) ?
280 wxSOUND_OUTPUT : wxSOUND_INPUT))
281 return FALSE;
282
283 m_state = m_oldstate;
284
285 return TRUE;
286}
287
0662cd32 288wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
526ddb13
GL
289{
290 m_lastcount = GetData(buffer, len);
291 return *this;
292}
293
0662cd32 294wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
526ddb13
GL
295{
296 m_lastcount = PutData(buffer, len);
297 return *this;
298}
299
526ddb13
GL
300bool wxSoundFileStream::StartProduction(int evt)
301{
302 m_sndio->SetEventHandler(this);
303
304 if (!m_codec.StartProduction(evt))
305 return FALSE;
306
307 return TRUE;
308}
309
310bool wxSoundFileStream::StopProduction()
311{
312 return m_codec.StopProduction();
313}
314
a31c84f3
GL
315void wxSoundFileStream::FinishPreparation(wxUint32 len)
316{
317 m_bytes_left = m_length = len;
318 m_prepared = TRUE;
319}
320
2018e574
GL
321wxString wxSoundFileStream::GetCodecName() const
322{
323 return wxString(wxT("wxSoundFileStream base codec"));
324}
325
a31c84f3
GL
326wxUint32 wxSoundFileStream::GetLength()
327{
328 if (m_input && !m_prepared && GetError() == wxSOUND_NOERR)
329 return (PrepareToPlay()) ? m_length : 0;
330
331 return m_length;
332}
333
334wxUint32 wxSoundFileStream::GetPosition()
335{
336 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR)
337 PrepareToPlay();
338
339 return m_length-m_bytes_left;
340}
341
d73dd2b2
GL
342wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position)
343{
344 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR)
345 PrepareToPlay();
346
347 if (!m_prepared)
348 return 0;
349
794bcc2d
GL
350 if (!RepositionStream(new_position))
351 return m_length-m_bytes_left;
352
d73dd2b2
GL
353 if (new_position >= m_length) {
354 m_bytes_left = 0;
355 return m_length;
356 }
357
358 m_bytes_left = m_length-new_position;
359 return new_position;
360}
361
526ddb13
GL
362void wxSoundFileStream::OnSoundEvent(int evt)
363{
56dc1ffd 364 wxUint32 len = m_codec.GetBestSize();
6c5e6376 365 char *buffer;
526ddb13 366
503aa33d 367 buffer = new char[len];
526ddb13
GL
368 wxSoundStream::OnSoundEvent(evt);
369
503aa33d
GL
370 while (!m_sndio->QueueFilled()) {
371 switch(evt) {
372 case wxSOUND_INPUT:
a31c84f3
GL
373 if (len > m_bytes_left)
374 len = m_bytes_left;
503aa33d
GL
375
376 len = m_codec.Read(buffer, len).GetLastAccess();
377 PutData(buffer, len);
a31c84f3
GL
378 m_bytes_left -= len;
379 if (m_bytes_left == 0) {
503aa33d 380 Stop();
56dc1ffd 381 delete[] buffer;
503aa33d
GL
382 return;
383 }
384 break;
385 case wxSOUND_OUTPUT:
a31c84f3
GL
386 if (len > m_bytes_left)
387 len = m_bytes_left;
388
503aa33d 389 len = GetData(buffer, len);
a31c84f3
GL
390 m_bytes_left -= len;
391 if (m_bytes_left == 0) {
503aa33d 392 Stop();
56dc1ffd 393 delete[] buffer;
503aa33d
GL
394 return;
395 }
396 m_codec.Write(buffer, len);
397 break;
526ddb13 398 }
526ddb13 399 }
6c5e6376 400 delete[] buffer;
526ddb13
GL
401}
402
403bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
404{
405 wxSoundStream::SetSoundFormat(format);
406 return m_codec.SetSoundFormat(format);
407}