]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia2/lib/sndfile.cpp
010529d142b150af8a7fdaf7f555df3526248e38
[wxWidgets.git] / utils / wxMMedia2 / lib / sndfile.cpp
1 // --------------------------------------------------------------------------
2 // Name: sndfile.cpp
3 // Purpose:
4 // Date: 08/11/1999
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
6 // CVSID: $Id$
7 // --------------------------------------------------------------------------
8 #include <wx/wxprec.h>
9
10 #ifndef WX_PRECOMP
11 #include <wx/stream.h>
12 #endif
13
14 #include "sndbase.h"
15 #include "sndcodec.h"
16 #include "sndfile.h"
17 #include "sndcpcm.h"
18 #include "sndulaw.h"
19 #include "sndg72x.h"
20
21 // --------------------------------------------------------------------------
22 // Sound codec router
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.
26 // --------------------------------------------------------------------------
27 wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio)
28 : wxSoundStreamCodec(sndio)
29 {
30 m_router = NULL;
31 }
32
33 wxSoundRouterStream::~wxSoundRouterStream()
34 {
35 if (m_router)
36 delete m_router;
37 }
38
39 // --------------------------------------------------------------------------
40 // Read(void *buffer, wxUint32 len): It reads data synchronously. See sndbase.h
41 // for possible errors and behaviours ...
42 // --------------------------------------------------------------------------
43 wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len)
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
57 // --------------------------------------------------------------------------
58 // Write(const void *buffer, wxUint32 len): It writes data synchronously
59 // --------------------------------------------------------------------------
60 wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len)
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
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 // --------------------------------------------------------------------------
81 bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format)
82 {
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());
110 return TRUE;
111 }
112
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 // --------------------------------------------------------------------------
118 wxUint32 wxSoundRouterStream::GetBestSize() const
119 {
120 if (m_router)
121 return m_router->GetBestSize();
122 else
123 return m_sndio->GetBestSize();
124 }
125
126 // --------------------------------------------------------------------------
127 // StartProduction(int evt). See sndbase.h
128 // --------------------------------------------------------------------------
129 bool wxSoundRouterStream::StartProduction(int evt)
130 {
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();
145 return FALSE;
146 }
147
148 // --------------------------------------------------------------------------
149 // StopProduction(). See sndbase.h
150 // --------------------------------------------------------------------------
151 bool wxSoundRouterStream::StopProduction()
152 {
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();
167 return FALSE;
168 }
169
170 // --------------------------------------------------------------------------
171 // wxSoundFileStream: generic reader
172 // --------------------------------------------------------------------------
173
174 wxSoundFileStream::wxSoundFileStream(wxInputStream& stream,
175 wxSoundStream& io_sound)
176 : m_codec(io_sound), m_sndio(&io_sound),
177 m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED)
178 {
179 m_length = 0;
180 m_bytes_left = 0;
181 m_prepared = FALSE;
182 }
183
184 wxSoundFileStream::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 {
189 m_length = 0;
190 m_bytes_left = 0;
191 m_prepared = FALSE;
192 }
193
194 wxSoundFileStream::~wxSoundFileStream()
195 {
196 if (m_state != wxSOUND_FILE_STOPPED)
197 Stop();
198 }
199
200 bool wxSoundFileStream::Play()
201 {
202 if (m_state != wxSOUND_FILE_STOPPED)
203 return FALSE;
204
205 if (!m_prepared)
206 if (!PrepareToPlay())
207 return FALSE;
208
209 m_state = wxSOUND_FILE_PLAYING;
210
211 if (!StartProduction(wxSOUND_OUTPUT))
212 return FALSE;
213
214 return TRUE;
215 }
216
217 bool wxSoundFileStream::Record(wxUint32 time)
218 {
219 if (m_state != wxSOUND_FILE_STOPPED)
220 return FALSE;
221
222 if (!PrepareToRecord(time))
223 return FALSE;
224
225 FinishPreparation(m_sndformat->GetBytesFromTime(time));
226
227 m_state = wxSOUND_FILE_RECORDING;
228 if (!StartProduction(wxSOUND_INPUT))
229 return FALSE;
230
231 return TRUE;
232 }
233
234 bool wxSoundFileStream::Stop()
235 {
236 if (m_state == wxSOUND_FILE_STOPPED)
237 return FALSE;
238
239 if (!StopProduction())
240 return FALSE;
241
242 m_prepared = FALSE;
243
244 if (m_state == wxSOUND_FILE_RECORDING)
245 if (!FinishRecording()) {
246 m_state = wxSOUND_FILE_STOPPED;
247 return FALSE;
248 }
249
250 if (m_input)
251 m_input->SeekI(0, wxFromStart);
252
253 if (m_output)
254 m_output->SeekO(0, wxFromStart);
255
256 m_state = wxSOUND_FILE_STOPPED;
257 return TRUE;
258 }
259
260 bool 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
273 bool 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
288 wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
289 {
290 m_lastcount = GetData(buffer, len);
291 return *this;
292 }
293
294 wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
295 {
296 m_lastcount = PutData(buffer, len);
297 return *this;
298 }
299
300 bool 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
310 bool wxSoundFileStream::StopProduction()
311 {
312 return m_codec.StopProduction();
313 }
314
315 void wxSoundFileStream::FinishPreparation(wxUint32 len)
316 {
317 m_bytes_left = m_length = len;
318 m_prepared = TRUE;
319 }
320
321 wxString wxSoundFileStream::GetCodecName() const
322 {
323 return wxString(wxT("wxSoundFileStream base codec"));
324 }
325
326 wxUint32 wxSoundFileStream::GetLength()
327 {
328 if (m_input && !m_prepared && GetError() == wxSOUND_NOERROR)
329 return (PrepareToPlay()) ? m_length : 0;
330
331 return m_length;
332 }
333
334 wxUint32 wxSoundFileStream::GetPosition()
335 {
336 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR)
337 PrepareToPlay();
338
339 return m_length-m_bytes_left;
340 }
341
342 wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position)
343 {
344 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR)
345 PrepareToPlay();
346
347 if (!m_prepared)
348 return 0;
349
350 if (!RepositionStream(new_position))
351 return m_length-m_bytes_left;
352
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
362 void wxSoundFileStream::OnSoundEvent(int evt)
363 {
364 wxUint32 len = m_codec.GetBestSize();
365 char *buffer;
366
367 buffer = new char[len];
368 wxSoundStream::OnSoundEvent(evt);
369
370 while (!m_sndio->QueueFilled()) {
371 switch(evt) {
372 case wxSOUND_INPUT:
373 if (len > m_bytes_left)
374 len = m_bytes_left;
375
376 len = m_codec.Read(buffer, len).GetLastAccess();
377 PutData(buffer, len);
378 m_bytes_left -= len;
379 if (m_bytes_left == 0) {
380 Stop();
381 delete[] buffer;
382 return;
383 }
384 break;
385 case wxSOUND_OUTPUT:
386 if (len > m_bytes_left)
387 len = m_bytes_left;
388
389 len = GetData(buffer, len);
390 m_bytes_left -= len;
391 if (m_bytes_left == 0) {
392 Stop();
393 delete[] buffer;
394 return;
395 }
396 m_codec.Write(buffer, len);
397 break;
398 }
399 }
400 delete[] buffer;
401 }
402
403 bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
404 {
405 wxSoundStream::SetSoundFormat(format);
406 return m_codec.SetSoundFormat(format);
407 }