]> git.saurik.com Git - wxWidgets.git/blame - src/unix/sound.cpp
Reflect changes in stc.cpp in stc.cpp.in from which it's generated.
[wxWidgets.git] / src / unix / sound.cpp
CommitLineData
9be32e8f 1/////////////////////////////////////////////////////////////////////////////
521bf4ff 2// Name: src/unix/sound.cpp
9be32e8f
VS
3// Purpose: wxSound
4// Author: Marcel Rasche, Vaclav Slavik
5// Modified by:
6// Created: 25/10/98
f156e20c 7// Copyright: (c) Julian Smart, Open Source Applications Foundation
f8a586e0 8// Licence: wxWindows licence
9be32e8f
VS
9/////////////////////////////////////////////////////////////////////////////
10
9be32e8f
VS
11// for compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
9be32e8f 14#if defined(__BORLANDC__)
02761f6c 15 #pragma hdrstop
9be32e8f
VS
16#endif
17
f156e20c 18#if wxUSE_SOUND
9be32e8f
VS
19
20#include <stdio.h>
21#include <unistd.h>
22#include <fcntl.h>
23#include <sys/ioctl.h>
24
83f7f12d 25#ifdef HAVE_SYS_SOUNDCARD_H
9be32e8f
VS
26#include <sys/soundcard.h>
27#endif
28
29#ifndef WX_PRECOMP
30 #include "wx/event.h"
31 #include "wx/intl.h"
32 #include "wx/log.h"
02761f6c 33 #include "wx/module.h"
9be32e8f
VS
34#endif
35
36#include "wx/thread.h"
37#include "wx/file.h"
9be32e8f
VS
38#include "wx/sound.h"
39#include "wx/dynlib.h"
40
83f7f12d
VS
41
42#if wxUSE_THREADS
43// mutex for all wxSound's synchronization
44static wxMutex gs_soundMutex;
45#endif
46
47// ----------------------------------------------------------------------------
48// wxSoundData
49// ----------------------------------------------------------------------------
f8a586e0 50
83f7f12d
VS
51void wxSoundData::IncRef()
52{
53#if wxUSE_THREADS
54 wxMutexLocker locker(gs_soundMutex);
55#endif
56 m_refCnt++;
57}
58
59void wxSoundData::DecRef()
60{
61#if wxUSE_THREADS
62 wxMutexLocker locker(gs_soundMutex);
63#endif
64 if (--m_refCnt == 0)
65 delete this;
66}
67
68wxSoundData::~wxSoundData()
69{
70 delete[] m_dataWithHeader;
71}
72
73
9be32e8f
VS
74// ----------------------------------------------------------------------------
75// wxSoundBackendNull, used in absence of audio API or card
76// ----------------------------------------------------------------------------
77
78class wxSoundBackendNull : public wxSoundBackend
79{
80public:
81 wxString GetName() const { return _("No sound"); }
82 int GetPriority() const { return 0; }
83 bool IsAvailable() const { return true; }
84 bool HasNativeAsyncPlayback() const { return true; }
83f7f12d
VS
85 bool Play(wxSoundData *WXUNUSED(data), unsigned WXUNUSED(flags),
86 volatile wxSoundPlaybackStatus *WXUNUSED(status))
9be32e8f 87 { return true; }
83f7f12d
VS
88 void Stop() {}
89 bool IsPlaying() const { return false; }
9be32e8f
VS
90};
91
92
93// ----------------------------------------------------------------------------
94// wxSoundBackendOSS, for Linux
95// ----------------------------------------------------------------------------
96
97#ifdef HAVE_SYS_SOUNDCARD_H
98
99#ifndef AUDIODEV
100#define AUDIODEV "/dev/dsp" // Default path for audio device
101#endif
102
103class wxSoundBackendOSS : public wxSoundBackend
104{
105public:
9a83f860 106 wxString GetName() const { return wxT("Open Sound System"); }
9be32e8f
VS
107 int GetPriority() const { return 10; }
108 bool IsAvailable() const;
109 bool HasNativeAsyncPlayback() const { return false; }
83f7f12d
VS
110 bool Play(wxSoundData *data, unsigned flags,
111 volatile wxSoundPlaybackStatus *status);
112 void Stop() {}
113 bool IsPlaying() const { return false; }
9be32e8f
VS
114
115private:
116 int OpenDSP(const wxSoundData *data);
544c4a3b 117 bool InitDSP(int dev, const wxSoundData *data);
f8a586e0 118
9be32e8f 119 int m_DSPblkSize; // Size of the DSP buffer
544c4a3b 120 bool m_needConversion;
9be32e8f
VS
121};
122
123bool wxSoundBackendOSS::IsAvailable() const
124{
125 int fd;
126 fd = open(AUDIODEV, O_WRONLY | O_NONBLOCK);
127 if (fd < 0)
128 return false;
129 close(fd);
130 return true;
131}
132
83f7f12d
VS
133bool wxSoundBackendOSS::Play(wxSoundData *data, unsigned flags,
134 volatile wxSoundPlaybackStatus *status)
9be32e8f
VS
135{
136 int dev = OpenDSP(data);
f8a586e0 137
9be32e8f
VS
138 if (dev < 0)
139 return false;
140
141 ioctl(dev, SNDCTL_DSP_SYNC, 0);
544c4a3b 142
9be32e8f
VS
143 do
144 {
145 bool play = true;
146 int i;
147 unsigned l = 0;
148 size_t datasize = data->m_dataBytes;
149
150 do
151 {
83f7f12d
VS
152 if (status->m_stopRequested)
153 {
9a83f860 154 wxLogTrace(wxT("sound"), wxT("playback stopped"));
83f7f12d
VS
155 close(dev);
156 return true;
157 }
158
9be32e8f 159 i= (int)((l + m_DSPblkSize) < datasize ?
544c4a3b 160 m_DSPblkSize : (datasize - l));
9be32e8f
VS
161 if (write(dev, &data->m_data[l], i) != i)
162 {
163 play = false;
164 }
165 l += i;
166 } while (play && l < datasize);
167 } while (flags & wxSOUND_LOOP);
f8a586e0 168
544c4a3b 169 close(dev);
9be32e8f
VS
170 return true;
171}
172
173int wxSoundBackendOSS::OpenDSP(const wxSoundData *data)
174{
175 int dev = -1;
f8a586e0 176
9be32e8f
VS
177 if ((dev = open(AUDIODEV, O_WRONLY, 0)) <0)
178 return -1;
f8a586e0 179
544c4a3b 180 if (!InitDSP(dev, data) || m_needConversion)
9be32e8f
VS
181 {
182 close(dev);
183 return -1;
184 }
185
186 return dev;
187}
188
544c4a3b
RD
189
190bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
9be32e8f 191{
544c4a3b
RD
192 unsigned tmp;
193
194 // Reset the dsp
195 if (ioctl(dev, SNDCTL_DSP_RESET, 0) < 0)
196 {
9a83f860 197 wxLogTrace(wxT("sound"), wxT("unable to reset dsp"));
9be32e8f 198 return false;
544c4a3b
RD
199 }
200
201 m_needConversion = false;
f8a586e0 202
544c4a3b
RD
203 tmp = data->m_bitsPerSample;
204 if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
205 {
9a83f860 206 wxLogTrace(wxT("sound"), wxT("IOCTL failure (SNDCTL_DSP_SAMPLESIZE)"));
9be32e8f 207 return false;
544c4a3b
RD
208 }
209 if (tmp != data->m_bitsPerSample)
210 {
9a83f860
VZ
211 wxLogTrace(wxT("sound"),
212 wxT("Unable to set DSP sample size to %d (wants %d)"),
544c4a3b
RD
213 data->m_bitsPerSample, tmp);
214 m_needConversion = true;
f8a586e0
RL
215 }
216
544c4a3b
RD
217 unsigned stereo = data->m_channels == 1 ? 0 : 1;
218 tmp = stereo;
219 if (ioctl(dev, SNDCTL_DSP_STEREO, &tmp) < 0)
220 {
9a83f860 221 wxLogTrace(wxT("sound"), wxT("IOCTL failure (SNDCTL_DSP_STEREO)"));
9be32e8f 222 return false;
544c4a3b
RD
223 }
224 if (tmp != stereo)
225 {
9a83f860 226 wxLogTrace(wxT("sound"), wxT("Unable to set DSP to %s."), stereo? wxT("stereo"):wxT("mono"));
544c4a3b
RD
227 m_needConversion = true;
228 }
229
230 tmp = data->m_samplingRate;
231 if (ioctl(dev, SNDCTL_DSP_SPEED, &tmp) < 0)
232 {
9a83f860 233 wxLogTrace(wxT("sound"), wxT("IOCTL failure (SNDCTL_DSP_SPEED)"));
544c4a3b
RD
234 return false;
235 }
236 if (tmp != data->m_samplingRate)
237 {
238 // If the rate the sound card is using is not within 1% of what the
239 // data specified then override the data setting. The only reason not
240 // to always override this is because of clock-rounding
241 // problems. Sound cards will sometimes use things like 44101 when you
242 // ask for 44100. No need overriding this and having strange output
243 // file rates for something that we can't hear anyways.
f8a586e0
RL
244 if (data->m_samplingRate - tmp > (tmp * .01) ||
245 tmp - data->m_samplingRate > (tmp * .01)) {
9a83f860
VZ
246 wxLogTrace(wxT("sound"),
247 wxT("Unable to set DSP sampling rate to %d (wants %d)"),
544c4a3b
RD
248 data->m_samplingRate, tmp);
249 m_needConversion = true;
f8a586e0 250 }
544c4a3b
RD
251 }
252
253 // Do this last because some drivers can adjust the buffer sized based on
254 // the sampling rate, etc.
255 if (ioctl(dev, SNDCTL_DSP_GETBLKSIZE, &m_DSPblkSize) < 0)
256 {
9a83f860 257 wxLogTrace(wxT("sound"), wxT("IOCTL failure (SNDCTL_DSP_GETBLKSIZE)"));
9be32e8f 258 return false;
544c4a3b 259 }
9be32e8f
VS
260 return true;
261}
f8a586e0 262
9be32e8f
VS
263#endif // HAVE_SYS_SOUNDCARD_H
264
9be32e8f 265// ----------------------------------------------------------------------------
83f7f12d 266// wxSoundSyncOnlyAdaptor
9be32e8f
VS
267// ----------------------------------------------------------------------------
268
269#if wxUSE_THREADS
270
83f7f12d 271class wxSoundSyncOnlyAdaptor;
9be32e8f
VS
272
273// this class manages asynchronous playback of audio if the backend doesn't
274// support it natively (e.g. OSS backend)
275class wxSoundAsyncPlaybackThread : public wxThread
276{
277public:
83f7f12d 278 wxSoundAsyncPlaybackThread(wxSoundSyncOnlyAdaptor *adaptor,
9be32e8f 279 wxSoundData *data, unsigned flags)
83f7f12d
VS
280 : wxThread(), m_adapt(adaptor), m_data(data), m_flags(flags) {}
281 virtual ExitCode Entry();
f8a586e0 282
9be32e8f 283protected:
83f7f12d 284 wxSoundSyncOnlyAdaptor *m_adapt;
9be32e8f
VS
285 wxSoundData *m_data;
286 unsigned m_flags;
287};
288
289#endif // wxUSE_THREADS
290
83f7f12d
VS
291// This class turns wxSoundBackend that doesn't support asynchronous playback
292// into one that does
293class wxSoundSyncOnlyAdaptor : public wxSoundBackend
294{
295public:
296 wxSoundSyncOnlyAdaptor(wxSoundBackend *backend)
297 : m_backend(backend), m_playing(false) {}
d3c7fc99 298 virtual ~wxSoundSyncOnlyAdaptor()
83f7f12d
VS
299 {
300 delete m_backend;
301 }
302 wxString GetName() const
303 {
304 return m_backend->GetName();
305 }
306 int GetPriority() const
307 {
308 return m_backend->GetPriority();
309 }
310 bool IsAvailable() const
311 {
312 return m_backend->IsAvailable();
313 }
314 bool HasNativeAsyncPlayback() const
315 {
316 return true;
317 }
318 bool Play(wxSoundData *data, unsigned flags,
319 volatile wxSoundPlaybackStatus *status);
320 void Stop();
321 bool IsPlaying() const;
322
323private:
324 friend class wxSoundAsyncPlaybackThread;
325
326 wxSoundBackend *m_backend;
327 bool m_playing;
328#if wxUSE_THREADS
329 // player thread holds this mutex and releases it after it finishes
330 // playing, so that the main thread knows when it can play sound
331 wxMutex m_mutexRightToPlay;
332 wxSoundPlaybackStatus m_status;
333#endif
334};
335
336
337#if wxUSE_THREADS
338wxThread::ExitCode wxSoundAsyncPlaybackThread::Entry()
339{
340 m_adapt->m_backend->Play(m_data, m_flags & ~wxSOUND_ASYNC,
341 &m_adapt->m_status);
342
343 m_data->DecRef();
344 m_adapt->m_playing = false;
345 m_adapt->m_mutexRightToPlay.Unlock();
9a83f860 346 wxLogTrace(wxT("sound"), wxT("terminated async playback thread"));
83f7f12d
VS
347 return 0;
348}
349#endif
350
351bool wxSoundSyncOnlyAdaptor::Play(wxSoundData *data, unsigned flags,
352 volatile wxSoundPlaybackStatus *status)
353{
354 Stop();
355 if (flags & wxSOUND_ASYNC)
356 {
357#if wxUSE_THREADS
358 m_mutexRightToPlay.Lock();
359 m_status.m_playing = true;
360 m_status.m_stopRequested = false;
361 data->IncRef();
362 wxThread *th = new wxSoundAsyncPlaybackThread(this, data, flags);
363 th->Create();
364 th->Run();
9a83f860 365 wxLogTrace(wxT("sound"), wxT("launched async playback thread"));
83f7f12d
VS
366 return true;
367#else
368 wxLogError(_("Unable to play sound asynchronously."));
369 return false;
370#endif
371 }
372 else
373 {
374#if wxUSE_THREADS
375 m_mutexRightToPlay.Lock();
376#endif
377 bool rv = m_backend->Play(data, flags, status);
378#if wxUSE_THREADS
379 m_mutexRightToPlay.Unlock();
380#endif
381 return rv;
382 }
383}
384
385void wxSoundSyncOnlyAdaptor::Stop()
386{
9a83f860 387 wxLogTrace(wxT("sound"), wxT("asking audio to stop"));
f8a586e0 388
a333f34d 389#if wxUSE_THREADS
83f7f12d
VS
390 // tell the player thread (if running) to stop playback ASAP:
391 m_status.m_stopRequested = true;
f8a586e0 392
83f7f12d
VS
393 // acquire the mutex to be sure no sound is being played, then
394 // release it because we don't need it for anything (the effect of this
395 // is that calling thread will wait until playback thread reacts to
396 // our request to interrupt playback):
397 m_mutexRightToPlay.Lock();
398 m_mutexRightToPlay.Unlock();
9a83f860 399 wxLogTrace(wxT("sound"), wxT("audio was stopped"));
a333f34d 400#endif
83f7f12d
VS
401}
402
403bool wxSoundSyncOnlyAdaptor::IsPlaying() const
404{
a333f34d 405#if wxUSE_THREADS
83f7f12d 406 return m_status.m_playing;
a333f34d 407#else
8fbe65e9 408 return false;
a333f34d 409#endif
83f7f12d
VS
410}
411
412
9be32e8f 413// ----------------------------------------------------------------------------
f8a586e0 414// wxSound
9be32e8f
VS
415// ----------------------------------------------------------------------------
416
417wxSoundBackend *wxSound::ms_backend = NULL;
418
419// FIXME - temporary, until we have plugins architecture
420#if wxUSE_LIBSDL
421 #if wxUSE_PLUGINS
422 wxDynamicLibrary *wxSound::ms_backendSDL = NULL;
423 #else
424 extern "C" wxSoundBackend *wxCreateSoundBackendSDL();
425 #endif
426#endif
427
428wxSound::wxSound() : m_data(NULL)
429{
430}
431
432wxSound::wxSound(const wxString& sFileName, bool isResource) : m_data(NULL)
433{
434 Create(sFileName, isResource);
435}
436
c559c4b3 437wxSound::wxSound(size_t size, const void* data) : m_data(NULL)
9be32e8f
VS
438{
439 Create(size, data);
440}
441
442wxSound::~wxSound()
443{
444 Free();
445}
446
3f9ee1cd
VZ
447bool wxSound::Create(const wxString& fileName,
448 bool WXUNUSED_UNLESS_DEBUG(isResource))
9be32e8f
VS
449{
450 wxASSERT_MSG( !isResource,
9a83f860 451 wxT("Loading sound from resources is only supported on Windows") );
f8a586e0 452
9be32e8f 453 Free();
f8a586e0 454
9be32e8f
VS
455 wxFile fileWave;
456 if (!fileWave.Open(fileName, wxFile::read))
f8a586e0
RL
457 {
458 return false;
459 }
9be32e8f 460
c781c316
VZ
461 wxFileOffset lenOrig = fileWave.Length();
462 if ( lenOrig == wxInvalidOffset )
463 return false;
464
465 size_t len = wx_truncate_cast(size_t, lenOrig);
9be32e8f 466 wxUint8 *data = new wxUint8[len];
0586024f 467 if ( fileWave.Read(data, len) != lenOrig )
9be32e8f 468 {
455f6b8d 469 delete [] data;
9be32e8f
VS
470 wxLogError(_("Couldn't load sound data from '%s'."), fileName.c_str());
471 return false;
472 }
473
474 if (!LoadWAV(data, len, false))
475 {
455f6b8d 476 delete [] data;
9be32e8f
VS
477 wxLogError(_("Sound file '%s' is in unsupported format."),
478 fileName.c_str());
479 return false;
480 }
f8a586e0 481
9be32e8f
VS
482 return true;
483}
484
c559c4b3 485bool wxSound::Create(size_t size, const void* data)
9be32e8f
VS
486{
487 wxASSERT( data != NULL );
488
489 Free();
490 if (!LoadWAV(data, size, true))
491 {
492 wxLogError(_("Sound data are in unsupported format."));
493 return false;
494 }
495 return true;
496}
497
498/*static*/ void wxSound::EnsureBackend()
499{
500 if (!ms_backend)
501 {
502 // FIXME -- make this fully dynamic when plugins architecture is in
503 // place
9be32e8f 504#if wxUSE_LIBSDL
3209f765 505 //if (!ms_backend)
9be32e8f
VS
506 {
507#if !wxUSE_PLUGINS
508 ms_backend = wxCreateSoundBackendSDL();
509#else
510 wxString dllname;
9a83f860 511 dllname.Printf(wxT("%s/%s"),
9be32e8f
VS
512 wxDynamicLibrary::GetPluginsDirectory().c_str(),
513 wxDynamicLibrary::CanonicalizePluginName(
9a83f860
VZ
514 wxT("sound_sdl"), wxDL_PLUGIN_BASE).c_str());
515 wxLogTrace(wxT("sound"),
516 wxT("trying to load SDL plugin from '%s'..."),
9be32e8f
VS
517 dllname.c_str());
518 wxLogNull null;
519 ms_backendSDL = new wxDynamicLibrary(dllname, wxDL_NOW);
520 if (!ms_backendSDL->IsLoaded())
521 {
522 wxDELETE(ms_backendSDL);
523 }
524 else
525 {
526 typedef wxSoundBackend *(*wxCreateSoundBackend_t)();
527 wxDYNLIB_FUNCTION(wxCreateSoundBackend_t,
528 wxCreateSoundBackendSDL, *ms_backendSDL);
529 if (pfnwxCreateSoundBackendSDL)
530 {
531 ms_backend = (*pfnwxCreateSoundBackendSDL)();
532 }
533 }
534#endif
535 if (ms_backend && !ms_backend->IsAvailable())
536 {
537 wxDELETE(ms_backend);
538 }
539 }
540#endif
541
3209f765
VS
542#ifdef HAVE_SYS_SOUNDCARD_H
543 if (!ms_backend)
544 {
545 ms_backend = new wxSoundBackendOSS();
546 if (!ms_backend->IsAvailable())
547 {
548 wxDELETE(ms_backend);
549 }
550 }
551#endif
552
9be32e8f
VS
553 if (!ms_backend)
554 ms_backend = new wxSoundBackendNull();
555
83f7f12d
VS
556 if (!ms_backend->HasNativeAsyncPlayback())
557 ms_backend = new wxSoundSyncOnlyAdaptor(ms_backend);
558
9a83f860
VZ
559 wxLogTrace(wxT("sound"),
560 wxT("using backend '%s'"), ms_backend->GetName().c_str());
9be32e8f
VS
561 }
562}
563
564/*static*/ void wxSound::UnloadBackend()
565{
566 if (ms_backend)
567 {
9a83f860 568 wxLogTrace(wxT("sound"), wxT("unloading backend"));
83f7f12d
VS
569
570 Stop();
f8a586e0 571
5276b0a5 572 wxDELETE(ms_backend);
9be32e8f
VS
573#if wxUSE_LIBSDL && wxUSE_PLUGINS
574 delete ms_backendSDL;
575#endif
576 }
577}
578
f156e20c 579bool wxSound::DoPlay(unsigned flags) const
9be32e8f 580{
9a83f860 581 wxCHECK_MSG( IsOk(), false, wxT("Attempt to play invalid wave data") );
9be32e8f
VS
582
583 EnsureBackend();
83f7f12d
VS
584 wxSoundPlaybackStatus status;
585 status.m_playing = true;
586 status.m_stopRequested = false;
587 return ms_backend->Play(m_data, flags, &status);
588}
9be32e8f 589
83f7f12d
VS
590/*static*/ void wxSound::Stop()
591{
592 if (ms_backend)
593 ms_backend->Stop();
594}
595
596/*static*/ bool wxSound::IsPlaying()
597{
598 if (ms_backend)
599 return ms_backend->IsPlaying();
9be32e8f 600 else
83f7f12d 601 return false;
9be32e8f
VS
602}
603
604void wxSound::Free()
605{
9be32e8f
VS
606 if (m_data)
607 m_data->DecRef();
608}
609
610typedef struct
f8a586e0 611{
9be32e8f
VS
612 wxUint32 uiSize;
613 wxUint16 uiFormatTag;
614 wxUint16 uiChannels;
615 wxUint32 ulSamplesPerSec;
616 wxUint32 ulAvgBytesPerSec;
617 wxUint16 uiBlockAlign;
618 wxUint16 uiBitsPerSample;
83f7f12d 619} WAVEFORMAT;
9be32e8f 620
9be32e8f
VS
621#define WAVE_FORMAT_PCM 1
622#define WAVE_INDEX 8
623#define FMT_INDEX 12
624
c559c4b3 625bool wxSound::LoadWAV(const void* data_, size_t length, bool copyData)
9be32e8f 626{
0aa7c441
VZ
627 // the simplest wave file header consists of 44 bytes:
628 //
629 // 0 "RIFF"
630 // 4 file size - 8
631 // 8 "WAVE"
632 //
633 // 12 "fmt "
634 // 16 chunk size |
635 // 20 format tag |
636 // 22 number of channels |
637 // 24 sample rate | WAVEFORMAT
638 // 28 average bytes per second |
639 // 32 bytes per frame |
640 // 34 bits per sample |
02761f6c 641 //
0aa7c441
VZ
642 // 36 "data"
643 // 40 number of data bytes
644 // 44 (wave signal) data
645 //
646 // so check that we have at least as much
647 if ( length < 44 )
9be32e8f
VS
648 return false;
649
c559c4b3
VZ
650 const wxUint8* data = static_cast<const wxUint8*>(data_);
651
0aa7c441 652 WAVEFORMAT waveformat;
9be32e8f
VS
653 memcpy(&waveformat, &data[FMT_INDEX + 4], sizeof(WAVEFORMAT));
654 waveformat.uiSize = wxUINT32_SWAP_ON_BE(waveformat.uiSize);
655 waveformat.uiFormatTag = wxUINT16_SWAP_ON_BE(waveformat.uiFormatTag);
656 waveformat.uiChannels = wxUINT16_SWAP_ON_BE(waveformat.uiChannels);
657 waveformat.ulSamplesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulSamplesPerSec);
658 waveformat.ulAvgBytesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulAvgBytesPerSec);
659 waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign);
660 waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample);
661
0aa7c441
VZ
662 // get the sound data size
663 wxUint32 ul;
664 memcpy(&ul, &data[FMT_INDEX + waveformat.uiSize + 12], 4);
665 ul = wxUINT32_SWAP_ON_BE(ul);
666
667 if ( length < ul + FMT_INDEX + waveformat.uiSize + 16 )
668 return false;
669
9be32e8f
VS
670 if (memcmp(data, "RIFF", 4) != 0)
671 return false;
672 if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0)
673 return false;
674 if (memcmp(&data[FMT_INDEX], "fmt ", 4) != 0)
675 return false;
676 if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
677 return false;
f8a586e0 678
9be32e8f
VS
679 if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
680 return false;
f8a586e0
RL
681
682 if (waveformat.ulSamplesPerSec !=
9be32e8f
VS
683 waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
684 return false;
f8a586e0 685
9be32e8f
VS
686 m_data = new wxSoundData;
687 m_data->m_channels = waveformat.uiChannels;
688 m_data->m_samplingRate = waveformat.ulSamplesPerSec;
689 m_data->m_bitsPerSample = waveformat.uiBitsPerSample;
690 m_data->m_samples = ul / (m_data->m_channels * m_data->m_bitsPerSample / 8);
691 m_data->m_dataBytes = ul;
692
693 if (copyData)
694 {
695 m_data->m_dataWithHeader = new wxUint8[length];
696 memcpy(m_data->m_dataWithHeader, data, length);
697 }
698 else
699 m_data->m_dataWithHeader = (wxUint8*)data;
700
f8a586e0 701 m_data->m_data =
9be32e8f
VS
702 (&m_data->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);
703
704 return true;
705}
706
707
708// ----------------------------------------------------------------------------
709// wxSoundCleanupModule
710// ----------------------------------------------------------------------------
711
712class wxSoundCleanupModule: public wxModule
713{
714public:
715 bool OnInit() { return true; }
716 void OnExit() { wxSound::UnloadBackend(); }
717 DECLARE_DYNAMIC_CLASS(wxSoundCleanupModule)
718};
719
720IMPLEMENT_DYNAMIC_CLASS(wxSoundCleanupModule, wxModule)
721
722#endif