// Modified by:
// Created: 25/10/98
// RCS-ID: $Id$
-// Copyright: (c) Julian Smart, Vaclav Slavik
-// Licence: wxWindows licence
+// Copyright: (c) Julian Smart, Open Source Applications Foundation
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma hdrstop
#endif
-#if wxUSE_WAVE
+#if wxUSE_SOUND
#include <stdio.h>
#include <unistd.h>
// ----------------------------------------------------------------------------
// wxSoundData
// ----------------------------------------------------------------------------
-
+
void wxSoundData::IncRef()
{
#if wxUSE_THREADS
private:
int OpenDSP(const wxSoundData *data);
- bool InitDSP(int dev, int iDataBits, int iChannel,
- unsigned long ulSamplingRate);
-
+ bool InitDSP(int dev, const wxSoundData *data);
+
int m_DSPblkSize; // Size of the DSP buffer
+ bool m_needConversion;
};
bool wxSoundBackendOSS::IsAvailable() const
volatile wxSoundPlaybackStatus *status)
{
int dev = OpenDSP(data);
-
+
if (dev < 0)
return false;
ioctl(dev, SNDCTL_DSP_SYNC, 0);
-
+
do
{
bool play = true;
}
i= (int)((l + m_DSPblkSize) < datasize ?
- m_DSPblkSize : (datasize - l));
+ m_DSPblkSize : (datasize - l));
if (write(dev, &data->m_data[l], i) != i)
{
play = false;
} while (flags & wxSOUND_LOOP);
close(dev);
-
return true;
}
int wxSoundBackendOSS::OpenDSP(const wxSoundData *data)
{
int dev = -1;
-
+
if ((dev = open(AUDIODEV, O_WRONLY, 0)) <0)
return -1;
-
- if (!InitDSP(dev,
- (int)data->m_bitsPerSample,
- data->m_channels == 1 ? 0 : 1,
- data->m_samplingRate))
+
+ if (!InitDSP(dev, data) || m_needConversion)
{
close(dev);
return -1;
return dev;
}
-bool wxSoundBackendOSS::InitDSP(int dev, int iDataBits, int iChannel,
- unsigned long ulSamplingRate)
+
+bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
{
- if (ioctl(dev, SNDCTL_DSP_GETBLKSIZE, &m_DSPblkSize) < 0)
- return false;
- wxLogTrace(_T("sound"), _T("OSS block size: %i"), m_DSPblkSize);
- if (m_DSPblkSize < 4096 || m_DSPblkSize > 65536)
+ unsigned tmp;
+
+ // Reset the dsp
+ if (ioctl(dev, SNDCTL_DSP_RESET, 0) < 0)
+ {
+ wxLogTrace(_T("sound"), _T("unable to reset dsp"));
return false;
- if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &iDataBits) < 0)
+ }
+
+ m_needConversion = false;
+
+ tmp = data->m_bitsPerSample;
+ if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
+ {
+ wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_SAMPLESIZE)"));
return false;
- if (ioctl(dev, SNDCTL_DSP_STEREO, &iChannel) < 0)
+ }
+ if (tmp != data->m_bitsPerSample)
+ {
+ wxLogTrace(_T("sound"),
+ _T("Unable to set DSP sample size to %d (wants %d)"),
+ data->m_bitsPerSample, tmp);
+ m_needConversion = true;
+ }
+
+ unsigned stereo = data->m_channels == 1 ? 0 : 1;
+ tmp = stereo;
+ if (ioctl(dev, SNDCTL_DSP_STEREO, &tmp) < 0)
+ {
+ wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_STEREO)"));
return false;
- if (ioctl(dev, SNDCTL_DSP_SPEED, &ulSamplingRate) < 0)
+ }
+ if (tmp != stereo)
+ {
+ wxLogTrace(_T("sound"), _T("Unable to set DSP to %s."), stereo? _T("stereo"):_T("mono"));
+ m_needConversion = true;
+ }
+
+ tmp = data->m_samplingRate;
+ if (ioctl(dev, SNDCTL_DSP_SPEED, &tmp) < 0)
+ {
+ wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_SPEED)"));
+ return false;
+ }
+ if (tmp != data->m_samplingRate)
+ {
+ // If the rate the sound card is using is not within 1% of what the
+ // data specified then override the data setting. The only reason not
+ // to always override this is because of clock-rounding
+ // problems. Sound cards will sometimes use things like 44101 when you
+ // ask for 44100. No need overriding this and having strange output
+ // file rates for something that we can't hear anyways.
+ if (data->m_samplingRate - tmp > (tmp * .01) ||
+ tmp - data->m_samplingRate > (tmp * .01)) {
+ wxLogTrace(_T("sound"),
+ _T("Unable to set DSP sampling rate to %d (wants %d)"),
+ data->m_samplingRate, tmp);
+ m_needConversion = true;
+ }
+ }
+
+ // Do this last because some drivers can adjust the buffer sized based on
+ // the sampling rate, etc.
+ if (ioctl(dev, SNDCTL_DSP_GETBLKSIZE, &m_DSPblkSize) < 0)
+ {
+ wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_GETBLKSIZE)"));
return false;
+ }
return true;
}
wxSoundData *data, unsigned flags)
: wxThread(), m_adapt(adaptor), m_data(data), m_flags(flags) {}
virtual ExitCode Entry();
-
+
protected:
wxSoundSyncOnlyAdaptor *m_adapt;
wxSoundData *m_data;
void wxSoundSyncOnlyAdaptor::Stop()
{
wxLogTrace(_T("sound"), _T("asking audio to stop"));
+
+#if wxUSE_THREADS
// tell the player thread (if running) to stop playback ASAP:
m_status.m_stopRequested = true;
-
+
// acquire the mutex to be sure no sound is being played, then
// release it because we don't need it for anything (the effect of this
// is that calling thread will wait until playback thread reacts to
m_mutexRightToPlay.Lock();
m_mutexRightToPlay.Unlock();
wxLogTrace(_T("sound"), _T("audio was stopped"));
+#endif
}
bool wxSoundSyncOnlyAdaptor::IsPlaying() const
{
+#if wxUSE_THREADS
return m_status.m_playing;
+#else
+ return false;
+#endif
}
// ----------------------------------------------------------------------------
-// wxSound
+// wxSound
// ----------------------------------------------------------------------------
wxSoundBackend *wxSound::ms_backend = NULL;
{
wxASSERT_MSG( !isResource,
_T("Loading sound from resources is only supported on Windows") );
-
+
Free();
-
+
wxFile fileWave;
if (!fileWave.Open(fileName, wxFile::read))
- {
- return false;
- }
+ {
+ return false;
+ }
- size_t len = fileWave.Length();
+ wxFileOffset len = fileWave.Length();
wxUint8 *data = new wxUint8[len];
if (fileWave.Read(data, len) != len)
{
fileName.c_str());
return false;
}
-
+
return true;
}
{
// FIXME -- make this fully dynamic when plugins architecture is in
// place
-#ifdef HAVE_SYS_SOUNDCARD_H
- ms_backend = new wxSoundBackendOSS();
- if (!ms_backend->IsAvailable())
- {
- wxDELETE(ms_backend);
- }
-#endif
-
#if wxUSE_LIBSDL
- if (!ms_backend)
+ //if (!ms_backend)
{
#if !wxUSE_PLUGINS
ms_backend = wxCreateSoundBackendSDL();
}
#endif
+#ifdef HAVE_SYS_SOUNDCARD_H
+ if (!ms_backend)
+ {
+ ms_backend = new wxSoundBackendOSS();
+ if (!ms_backend->IsAvailable())
+ {
+ wxDELETE(ms_backend);
+ }
+ }
+#endif
+
if (!ms_backend)
ms_backend = new wxSoundBackendNull();
wxLogTrace(_T("sound"), _T("unloading backend"));
Stop();
-
+
delete ms_backend;
ms_backend = NULL;
#if wxUSE_LIBSDL && wxUSE_PLUGINS
}
}
-bool wxSound::DoPlay(unsigned flags)
+bool wxSound::DoPlay(unsigned flags) const
{
- wxASSERT_MSG( (flags & wxSOUND_LOOP) == 0 || (flags & wxSOUND_ASYNC) != 0,
- _T("sound can only be looped asynchronously") );
wxCHECK_MSG( IsOk(), false, _T("Attempt to play invalid wave data") );
EnsureBackend();
}
typedef struct
-{
+{
wxUint32 uiSize;
wxUint16 uiFormatTag;
wxUint16 uiChannels;
wxUint16 uiBitsPerSample;
} WAVEFORMAT;
-#define MONO 1 // and stereo is 2 by wav format
#define WAVE_FORMAT_PCM 1
#define WAVE_INDEX 8
#define FMT_INDEX 12
return false;
memcpy(&ul,&data[FMT_INDEX + waveformat.uiSize + 12], 4);
ul = wxUINT32_SWAP_ON_BE(ul);
-
+
//WAS: if (ul + FMT_INDEX + waveformat.uiSize + 16 != length)
if (ul + FMT_INDEX + waveformat.uiSize + 16 > length)
return false;
-
+
if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
return false;
-
- if (waveformat.ulSamplesPerSec !=
+
+ if (waveformat.ulSamplesPerSec !=
waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
return false;
-
+
m_data = new wxSoundData;
m_data->m_channels = waveformat.uiChannels;
m_data->m_samplingRate = waveformat.ulSamplesPerSec;
else
m_data->m_dataWithHeader = (wxUint8*)data;
- m_data->m_data =
+ m_data->m_data =
(&m_data->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);
return true;