]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia2/lib/sndfile.cpp
Added a lot of comments
[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
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 }
179
180 wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream,
181 wxSoundStream& io_sound)
182 : m_codec(io_sound), m_sndio(&io_sound),
183 m_input(NULL), m_output(&stream), m_state(wxSOUND_FILE_STOPPED)
184 {
185 }
186
187 wxSoundFileStream::~wxSoundFileStream()
188 {
189 if (m_state != wxSOUND_FILE_STOPPED)
190 Stop();
191 }
192
193 bool wxSoundFileStream::Play()
194 {
195 if (m_state != wxSOUND_FILE_STOPPED)
196 return FALSE;
197
198 if (!PrepareToPlay())
199 return FALSE;
200
201 m_state = wxSOUND_FILE_PLAYING;
202
203 if (!StartProduction(wxSOUND_OUTPUT))
204 return FALSE;
205
206 return TRUE;
207 }
208
209 bool wxSoundFileStream::Record(unsigned long time)
210 {
211 if (m_state != wxSOUND_FILE_STOPPED)
212 return FALSE;
213
214 if (!PrepareToRecord(time))
215 return FALSE;
216
217 m_len = m_sndformat->GetBytesFromTime(time);
218
219 m_state = wxSOUND_FILE_RECORDING;
220 if (!StartProduction(wxSOUND_INPUT))
221 return FALSE;
222
223 return TRUE;
224 }
225
226 bool wxSoundFileStream::Stop()
227 {
228 if (m_state == wxSOUND_FILE_STOPPED)
229 return FALSE;
230
231 if (!StopProduction())
232 return FALSE;
233
234 if (m_state == wxSOUND_FILE_RECORDING)
235 if (!FinishRecording()) {
236 m_state = wxSOUND_FILE_STOPPED;
237 return FALSE;
238 }
239
240 if (m_input)
241 m_input->SeekI(0, wxFromStart);
242
243 if (m_output)
244 m_output->SeekO(0, wxFromStart);
245
246 m_state = wxSOUND_FILE_STOPPED;
247 return TRUE;
248 }
249
250 bool wxSoundFileStream::Pause()
251 {
252 if (m_state == wxSOUND_FILE_PAUSED || m_state == wxSOUND_FILE_STOPPED)
253 return FALSE;
254
255 if (!StopProduction())
256 return FALSE;
257
258 m_oldstate = m_state;
259 m_state = wxSOUND_FILE_PAUSED;
260 return TRUE;
261 }
262
263 bool wxSoundFileStream::Resume()
264 {
265 if (m_state == wxSOUND_FILE_PLAYING || m_state == wxSOUND_FILE_RECORDING ||
266 m_state == wxSOUND_FILE_STOPPED)
267 return FALSE;
268
269 if (!StartProduction( (m_oldstate == wxSOUND_FILE_PLAYING) ?
270 wxSOUND_OUTPUT : wxSOUND_INPUT))
271 return FALSE;
272
273 m_state = m_oldstate;
274
275 return TRUE;
276 }
277
278 wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
279 {
280 m_lastcount = GetData(buffer, len);
281 return *this;
282 }
283
284 wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
285 {
286 m_lastcount = PutData(buffer, len);
287 return *this;
288 }
289
290 void wxSoundFileStream::SetDuplexMode(bool duplex)
291 {
292 }
293
294 bool wxSoundFileStream::StartProduction(int evt)
295 {
296 m_sndio->SetEventHandler(this);
297
298 if (!m_codec.StartProduction(evt))
299 return FALSE;
300
301 return TRUE;
302 }
303
304 bool wxSoundFileStream::StopProduction()
305 {
306 return m_codec.StopProduction();
307 }
308
309 void wxSoundFileStream::OnSoundEvent(int evt)
310 {
311 wxUint32 len = m_codec.GetBestSize();
312 char *buffer;
313
314 buffer = new char[len];
315 wxSoundStream::OnSoundEvent(evt);
316
317 while (!m_sndio->QueueFilled()) {
318 switch(evt) {
319 case wxSOUND_INPUT:
320 if (len > m_len)
321 len = m_len;
322
323 len = m_codec.Read(buffer, len).GetLastAccess();
324 PutData(buffer, len);
325 m_len -= len;
326 if (m_len == 0) {
327 Stop();
328 delete[] buffer;
329 return;
330 }
331 break;
332 case wxSOUND_OUTPUT:
333 len = GetData(buffer, len);
334 if (len == 0) {
335 Stop();
336 delete[] buffer;
337 return;
338 }
339 m_codec.Write(buffer, len);
340 break;
341 }
342 }
343 delete[] buffer;
344 }
345
346 bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
347 {
348 wxSoundStream::SetSoundFormat(format);
349 return m_codec.SetSoundFormat(format);
350 }