]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia2/lib/sndfile.cpp
eea2ec9043a26b818c203e856e2c49abb55c77d8
[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 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;
102 case wxSOUND_G72X:
103 m_router = new wxSoundStreamG72X(*m_sndio);
104 m_router->SetSoundFormat(format);
105 break;
106 }
107 wxSoundStream::SetSoundFormat(m_router->GetSoundFormat());
108 return TRUE;
109 }
110
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 // --------------------------------------------------------------------------
116 wxUint32 wxSoundRouterStream::GetBestSize() const
117 {
118 if (m_router)
119 return m_router->GetBestSize();
120 else
121 return m_sndio->GetBestSize();
122 }
123
124 // --------------------------------------------------------------------------
125 // StartProduction(int evt). See sndbase.h
126 // --------------------------------------------------------------------------
127 bool 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
146 // --------------------------------------------------------------------------
147 // StopProduction(). See sndbase.h
148 // --------------------------------------------------------------------------
149 bool 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
173 wxSoundFileStream::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 {
178 m_length = 0;
179 m_bytes_left = 0;
180 m_prepared = FALSE;
181 }
182
183 wxSoundFileStream::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 {
188 m_length = 0;
189 m_bytes_left = 0;
190 m_prepared = FALSE;
191 }
192
193 wxSoundFileStream::~wxSoundFileStream()
194 {
195 if (m_state != wxSOUND_FILE_STOPPED)
196 Stop();
197 }
198
199 bool wxSoundFileStream::Play()
200 {
201 if (m_state != wxSOUND_FILE_STOPPED)
202 return FALSE;
203
204 if (!m_prepared)
205 if (!PrepareToPlay())
206 return FALSE;
207
208 m_state = wxSOUND_FILE_PLAYING;
209
210 if (!StartProduction(wxSOUND_OUTPUT))
211 return FALSE;
212
213 return TRUE;
214 }
215
216 bool 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
224 FinishPreparation(m_sndformat->GetBytesFromTime(time));
225
226 m_state = wxSOUND_FILE_RECORDING;
227 if (!StartProduction(wxSOUND_INPUT))
228 return FALSE;
229
230 return TRUE;
231 }
232
233 bool wxSoundFileStream::Stop()
234 {
235 if (m_state == wxSOUND_FILE_STOPPED)
236 return FALSE;
237
238 if (!StopProduction())
239 return FALSE;
240
241 m_prepared = FALSE;
242
243 if (m_state == wxSOUND_FILE_RECORDING)
244 if (!FinishRecording()) {
245 m_state = wxSOUND_FILE_STOPPED;
246 return FALSE;
247 }
248
249 if (m_input)
250 m_input->SeekI(0, wxFromStart);
251
252 if (m_output)
253 m_output->SeekO(0, wxFromStart);
254
255 m_state = wxSOUND_FILE_STOPPED;
256 return TRUE;
257 }
258
259 bool 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
272 bool 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
287 wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
288 {
289 m_lastcount = GetData(buffer, len);
290 return *this;
291 }
292
293 wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
294 {
295 m_lastcount = PutData(buffer, len);
296 return *this;
297 }
298
299 bool 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
309 bool wxSoundFileStream::StopProduction()
310 {
311 return m_codec.StopProduction();
312 }
313
314 void wxSoundFileStream::FinishPreparation(wxUint32 len)
315 {
316 m_bytes_left = m_length = len;
317 m_prepared = TRUE;
318 }
319
320 wxString wxSoundFileStream::GetCodecName() const
321 {
322 return wxString(wxT("wxSoundFileStream base codec"));
323 }
324
325 wxUint32 wxSoundFileStream::GetLength()
326 {
327 if (m_input && !m_prepared && GetError() == wxSOUND_NOERR)
328 return (PrepareToPlay()) ? m_length : 0;
329
330 return m_length;
331 }
332
333 wxUint32 wxSoundFileStream::GetPosition()
334 {
335 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR)
336 PrepareToPlay();
337
338 return m_length-m_bytes_left;
339 }
340
341 wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position)
342 {
343 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR)
344 PrepareToPlay();
345
346 if (!m_prepared)
347 return 0;
348
349 if (new_position >= m_length) {
350 m_bytes_left = 0;
351 return m_length;
352 }
353
354 m_bytes_left = m_length-new_position;
355 return new_position;
356 }
357
358 void wxSoundFileStream::OnSoundEvent(int evt)
359 {
360 wxUint32 len = m_codec.GetBestSize();
361 char *buffer;
362
363 buffer = new char[len];
364 wxSoundStream::OnSoundEvent(evt);
365
366 while (!m_sndio->QueueFilled()) {
367 switch(evt) {
368 case wxSOUND_INPUT:
369 if (len > m_bytes_left)
370 len = m_bytes_left;
371
372 len = m_codec.Read(buffer, len).GetLastAccess();
373 PutData(buffer, len);
374 m_bytes_left -= len;
375 if (m_bytes_left == 0) {
376 Stop();
377 delete[] buffer;
378 return;
379 }
380 break;
381 case wxSOUND_OUTPUT:
382 if (len > m_bytes_left)
383 len = m_bytes_left;
384
385 len = GetData(buffer, len);
386 m_bytes_left -= len;
387 if (m_bytes_left == 0) {
388 Stop();
389 delete[] buffer;
390 return;
391 }
392 m_codec.Write(buffer, len);
393 break;
394 }
395 }
396 delete[] buffer;
397 }
398
399 bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
400 {
401 wxSoundStream::SetSoundFormat(format);
402 return m_codec.SetSoundFormat(format);
403 }