/////////////////////////////////////////////////////////////////////////////
-// Name: sound.cpp
+// Name: src/unix/sound.cpp
// Purpose: wxSound
// Author: Marcel Rasche, Vaclav Slavik
// Modified by:
// Created: 25/10/98
// RCS-ID: $Id$
// Copyright: (c) Julian Smart, Open Source Applications Foundation
-// Licence: wxWidgets licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-#pragma implementation "sound.h"
-#pragma implementation "soundbase.h"
-#endif
-
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-#include "wx/setup.h"
-
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
// ----------------------------------------------------------------------------
// wxSoundData
// ----------------------------------------------------------------------------
-
+
void wxSoundData::IncRef()
{
#if wxUSE_THREADS
private:
int OpenDSP(const wxSoundData *data);
bool InitDSP(int dev, const wxSoundData *data);
-
+
int m_DSPblkSize; // Size of the DSP buffer
bool m_needConversion;
};
volatile wxSoundPlaybackStatus *status)
{
int dev = OpenDSP(data);
-
+
if (dev < 0)
return false;
l += i;
} while (play && l < datasize);
} 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, data) || m_needConversion)
{
close(dev);
}
m_needConversion = false;
-
+
tmp = data->m_bitsPerSample;
if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
{
_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)
}
if (tmp != stereo)
{
- wxLogTrace(_T("sound"), _T("Unable to set DSP to %s."), stereo? _T("stereo"):_T("mono"));
+ wxLogTrace(_T("sound"), _T("Unable to set DSP to %s."), stereo? _T("stereo"):_T("mono"));
m_needConversion = true;
}
// 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"),
+ 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
}
return true;
}
-
+
#endif // HAVE_SYS_SOUNDCARD_H
// ----------------------------------------------------------------------------
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
#if wxUSE_THREADS
return m_status.m_playing;
#else
- return FALSE;
+ return false;
#endif
}
// ----------------------------------------------------------------------------
-// wxSound
+// wxSound
// ----------------------------------------------------------------------------
wxSoundBackend *wxSound::ms_backend = NULL;
Free();
}
-bool wxSound::Create(const wxString& fileName, bool isResource)
+bool wxSound::Create(const wxString& fileName,
+ bool WXUNUSED_UNLESS_DEBUG(isResource))
{
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;
+ }
+
+ wxFileOffset lenOrig = fileWave.Length();
+ if ( lenOrig == wxInvalidOffset )
+ return false;
- size_t len = fileWave.Length();
+ size_t len = wx_truncate_cast(size_t, lenOrig);
wxUint8 *data = new wxUint8[len];
- if (fileWave.Read(data, len) != len)
+ if ( fileWave.Read(data, len) != lenOrig )
{
+ delete [] data;
wxLogError(_("Couldn't load sound data from '%s'."), fileName.c_str());
return false;
}
if (!LoadWAV(data, len, false))
{
+ delete [] data;
wxLogError(_("Sound file '%s' is in unsupported format."),
fileName.c_str());
return false;
}
-
+
return true;
}
wxLogTrace(_T("sound"), _T("unloading backend"));
Stop();
-
+
delete ms_backend;
ms_backend = NULL;
#if wxUSE_LIBSDL && wxUSE_PLUGINS
}
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
bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
{
- WAVEFORMAT waveformat;
- wxUint32 ul;
-
- if (length < 32 + sizeof(WAVEFORMAT))
+ // the simplest wave file header consists of 44 bytes:
+ //
+ // 0 "RIFF"
+ // 4 file size - 8
+ // 8 "WAVE"
+ //
+ // 12 "fmt "
+ // 16 chunk size |
+ // 20 format tag |
+ // 22 number of channels |
+ // 24 sample rate | WAVEFORMAT
+ // 28 average bytes per second |
+ // 32 bytes per frame |
+ // 34 bits per sample |
+ //
+ // 36 "data"
+ // 40 number of data bytes
+ // 44 (wave signal) data
+ //
+ // so check that we have at least as much
+ if ( length < 44 )
return false;
+ WAVEFORMAT waveformat;
memcpy(&waveformat, &data[FMT_INDEX + 4], sizeof(WAVEFORMAT));
waveformat.uiSize = wxUINT32_SWAP_ON_BE(waveformat.uiSize);
waveformat.uiFormatTag = wxUINT16_SWAP_ON_BE(waveformat.uiFormatTag);
waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign);
waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample);
+ // get the sound data size
+ wxUint32 ul;
+ memcpy(&ul, &data[FMT_INDEX + waveformat.uiSize + 12], 4);
+ ul = wxUINT32_SWAP_ON_BE(ul);
+
+ if ( length < ul + FMT_INDEX + waveformat.uiSize + 16 )
+ return false;
+
if (memcmp(data, "RIFF", 4) != 0)
return false;
if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0)
return false;
if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
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;