\membersection{wxSoundFileStream::RepositionStream}\label{wxsoundfilestreamrepositionstream}
\func{bool}{RepositionStream}{\param{wxUint32 }{position}}
+This is called by wxSoundFileStream::SetPosition to seek the input stream
+to the right position. This must be overidden by the file codec class.
+The position is relative to the beginning of the samples.
+If it is impossible (as for a piped input stream), you must return FALSE.
\membersection{wxSoundFileStream::FinishPreparation}\label{wxsoundfilestreamfinishpreparation}
\func{void}{FinishPreparation}{\param{wxUint32 }{len}}
+This is an internal function but it must called by the file codec class when
+the "playing" preparation is finished and you know the size of the stream.
+If it is an {\it infinite} stream, you should set this to wxSOUND\_INFINITE\_TIME.
\membersection{wxSoundFileStream::GetData}\label{wxsoundfilestreamgetdata}
\func{wxUint32}{GetData}{\param{void* }{buffer}, \param{wxUint32 }{len}}
+This is called by wxSoundFileStream when it needs to get new sound data to
+send to the device driver (or to a conversion codec). This must be eventually
+overidden by the file codec class. The default behaviour is simply to read from
+the input stream.
\membersection{wxSoundFileStream::PutData}\label{wxsoundfilestreamputdata}
\func{wxUint32}{PutData}{\param{const void* }{buffer}, \param{wxUint32 }{len}}
+This is called by wxSoundFileStream when it needs to put new sound data received
+from the device driver (or from a conversion codec). This must be eventually
+overidden by the file codec class. The default behaviour is simply to write to
+the input stream.
\section{\class{wxSoundRouterStream}}\label{wxsoundrouterstream}
-
-Codec router class
+This is the router "codec" class. It should do codec routing when the device
+driver does not deal with a format.
\wxheading{Derived from}
\latexignore{\rtfignore{\wxheading{Members}}}
-
\membersection{wxSoundRouterStream::wxSoundRouterStream}\label{wxsoundrouterstreamwxsoundrouterstream}
-
\func{}{wxSoundRouterStream}{\param{wxSoundStream\& }{sndio}}
+\helpref{wxSoundCodec}{wxsoundcodec}
-\membersection{wxSoundRouterStream::\destruct{wxSoundRouterStream}}\label{wxsoundrouterstreamdtor}
+\membersection{wxSoundRouterStream::\destruct{wxSoundRouterStream}}\label{wxsoundrouterstreamdtor}
\func{}{\destruct{wxSoundRouterStream}}{\void}
-
-\membersection{wxSoundRouterStream::Read}\label{wxsoundrouterstreamread}
-
-\func{wxSoundStream\&}{Read}{\param{void* }{buffer}, \param{wxUint32 }{len}}
-
-
-\membersection{wxSoundRouterStream::Write}\label{wxsoundrouterstreamwrite}
-
-\func{wxSoundStream\&}{Write}{\param{const void* }{buffer}, \param{wxUint32 }{len}}
-
+Destructor.
\membersection{wxSoundRouterStream::SetSoundFormat}\label{wxsoundrouterstreamsetsoundformat}
-
\func{bool}{SetSoundFormat}{\param{const wxSoundFormatBase\& }{format}}
-
-\membersection{wxSoundRouterStream::StartProduction}\label{wxsoundrouterstreamstartproduction}
-
-\func{bool}{StartProduction}{\param{int }{evt}}
-
-
-\membersection{wxSoundRouterStream::StopProduction}\label{wxsoundrouterstreamstopproduction}
-
-\func{bool}{StopProduction}{\void}
-
-
-\membersection{wxSoundRouterStream::GetBestSize}\label{wxsoundrouterstreamgetbestsize}
-
-\constfunc{wxUint32}{GetBestSize}{\void}
-
+SetSoundFormat will first try to setup the device driver with the specified
+format. If this fails, it will try to find a codec which will convert the
+input format to a valid format for the device driver. It uses an internal
+codec database.
public:
typedef enum { PLAYING, PAUSED, STOPPED } CDstatus;
// Table of contents manager
- class CDtoc {
+ class WXDLLEXPORT CDtoc {
protected:
wxCDtime *tracks_time, *tracks_pos;
wxCDtime total_time;
// AIFF codec
//
-class wxSoundAiff: public wxSoundFileStream {
+class WXDLLEXPORT wxSoundAiff: public wxSoundFileStream {
public:
wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound);
wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound);
// Base class for sound streams
//
-class wxSoundStream {
+class WXDLLEXPORT wxSoundStream {
public:
wxSoundStream();
virtual ~wxSoundStream();
#include "wx/defs.h"
#include "wx/mmedia/sndbase.h"
-class wxSoundStreamCodec: public wxSoundStream {
+class WXDLLEXPORT wxSoundStreamCodec: public wxSoundStream {
public:
wxSoundStreamCodec(wxSoundStream& snd_io);
~wxSoundStreamCodec();
// PCM converter class
//
-class wxSoundStreamPcm: public wxSoundStreamCodec {
+class WXDLLEXPORT wxSoundStreamPcm: public wxSoundStreamCodec {
public:
typedef void (*ConverterType)(const void *buf_in, void *buf_out,
wxUint32 len);
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 2000
// CVSID: $Id$
// --------------------------------------------------------------------------
-#ifndef _WX_SNDULAW_H
-#define _WX_SNDULAW_H
+#ifndef _WX_SNDMSAD_H
+#define _WX_SNDMSAD_H
#ifdef __GNUG__
#pragma interface "sndmsad.h"
#include "wx/mmedia/sndcodec.h"
#include "wx/mmedia/sndbase.h"
-WX_DEFINE_EXPORTED_ARRAY(wxUint16, wxMSAdpcmCoeffs);
+WX_DEFINE_EXPORTED_ARRAY(wxInt16, wxMSAdpcmCoeffs);
//
// MSADPCM format
//
class WXDLLEXPORT wxSoundFormatMSAdpcm: public wxSoundFormatBase {
- public:
- wxSoundFormatMSAdpcm();
- ~wxSoundFormatMSAdpcm();
-
- void SetSampleRate(wxUint32 srate);
- wxUint32 GetSampleRate() const;
-
- void SetSamplesBlock(wxUint16 sampblock);
- wxUint16 GetSamplesBlock() const;
-
- void SetCoefs(wxMSAdpcmCoefs& coefs);
- wxMSAdpcmCoefs& GetCoefs() const;
-
- wxSoundFormatType GetType() const { return wxSOUND_ULAW; }
- wxSoundFormatBase *Clone() const;
-
- wxUint32 GetTimeFromBytes(wxUint32 bytes) const;
- wxUint32 GetBytesFromTime(wxUint32 time) const;
+public:
+ wxSoundFormatMSAdpcm();
+ ~wxSoundFormatMSAdpcm();
+
+ void SetSampleRate(wxUint32 srate);
+ wxUint32 GetSampleRate() const;
+
+ void SetCoefs(wxInt16 **coefs, wxUint16 ncoefs, wxUint16 coefs_len);
+ void GetCoefs(wxInt16 **&coefs, wxUint16& ncoefs,
+ wxUint16& coefs_len) const;
- bool operator !=(const wxSoundFormatBase& frmt2) const;
+ void SetBlockSize(wxUint16 block_size);
+ wxUint16 GetBlockSize() const;
+
+ void SetChannels(wxUint16 channels);
+ wxUint16 GetChannels() const;
+
+ wxSoundFormatType GetType() const { return wxSOUND_MSADPCM; }
+ wxSoundFormatBase *Clone() const;
+
+ wxUint32 GetTimeFromBytes(wxUint32 bytes) const;
+ wxUint32 GetBytesFromTime(wxUint32 time) const;
+
+ bool operator !=(const wxSoundFormatBase& frmt2) const;
- protected:
- wxUint32 m_srate;
- wxMSAdpcmCoefs *m_coefs;
+protected:
+ wxUint32 m_srate, m_nchannels;
+ wxInt16 **m_coefs;
+ wxUint16 m_ncoefs, m_coefs_len;
+ wxUint16 m_block_size;
};
//
// MS ADPCM converter class
//
class WXDLLEXPORT wxSoundRouterStream;
-class WXDLLEXPORT wxSoundStreamAdpcm: public wxSoundStreamCodec {
+class WXDLLEXPORT wxSoundStreamMSAdpcm: public wxSoundStreamCodec {
public:
- wxSoundStreamAdpcm(wxSoundStream& sndio);
- ~wxSoundStreamAdpcm();
+ wxSoundStreamMSAdpcm(wxSoundStream& sndio);
+ ~wxSoundStreamMSAdpcm();
wxSoundStream& Read(void *buffer, wxUint32 len);
wxSoundStream& Write(const void *buffer, wxUint32 len);
protected:
wxSoundRouterStream *m_router;
+
+ typedef struct {
+ wxInt32 predictor;
+ wxInt16 samp1;
+ wxInt16 samp2;
+ wxInt16 coeff[2];
+ wxInt32 iDelta;
+ } AdpcmState;
+
+ AdpcmState m_state[1];
+
+ bool m_got_header;
+ bool m_stereo;
+ wxInt16 **m_coefs;
+ wxUint16 m_block_size;
+ wxUint16 m_ncoefs;
+ wxUint16 m_next_block;
+
+protected:
+ wxUint32 DecodeMonoADPCM(const void *in_buffer, void *out_buffer,
+ wxUint32 in_len);
+ wxUint32 DecodeStereoADPCM(const void *in_buffer, void *out_buffer,
+ wxUint32 in_len);
+ void Nibble(wxInt8 nyb,
+ AdpcmState *state,
+ wxInt16 **out_buffer);
};
#endif
// OSS output class
//
-class wxSoundStreamOSS : public wxSoundStream {
+class WXDLLEXPORT wxSoundStreamOSS : public wxSoundStream {
public:
wxSoundStreamOSS(const wxString& dev_name = wxT("/dev/dsp"));
~wxSoundStreamOSS();
wxUint32 GetData(void *buffer, wxUint32 len);
wxUint32 PutData(const void *buffer, wxUint32 len);
- bool HandleOutputPCM(wxDataInputStream& data, wxUint16 channels,
- wxUint32 sample_fq, wxUint32 byte_p_sec,
- wxUint16 byte_p_spl, wxUint16 bits_p_spl);
- bool HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
- wxUint32 sample_fq, wxUint32 byte_p_sec,
- wxUint16 byte_p_spl, wxUint16 bits_p_spl);
+ bool HandleOutputPCM(wxDataInputStream& data, wxUint32 len,
+ wxUint16 channels, wxUint32 sample_fq,
+ wxUint32 byte_p_sec, wxUint16 byte_p_spl,
+ wxUint16 bits_p_spl);
+ bool HandleOutputMSADPCM(wxDataInputStream& data, wxUint32 len,
+ wxUint16 channels, wxUint32 sample_fq,
+ wxUint32 byte_p_sec, wxUint16 byte_p_spl,
+ wxUint16 bits_p_spl);
+ bool HandleOutputG721(wxDataInputStream& data, wxUint32 len,
+ wxUint16 channels, wxUint32 sample_fq,
+ wxUint32 byte_p_sec, wxUint16 byte_p_spl,
+ wxUint16 bits_p_spl);
wxSoundFormatBase *HandleInputPCM(wxDataOutputStream& data);
wxSoundFormatBase *HandleInputG72X(wxDataOutputStream& data);
#include "wx/mmedia/sndaiff.h"
#include "wx/mmedia/sndpcm.h"
#include "wx/mmedia/sndulaw.h"
+#include "wx/mmedia/sndmsad.h"
#ifdef __UNIX__
#include "wx/mmedia/sndoss.h"
break;
}
+ case wxSOUND_MSADPCM: {
+ wxSoundFormatMSAdpcm *adpcm_format = (wxSoundFormatMSAdpcm *)format;
+
+ info += wxString::Format(wxT("Microsoft ADPCM\n"));
+ info += wxString::Format(wxT("Sampling Rate: %d\n")
+ wxT("Number of channels: %d\n"),
+ adpcm_format->GetSampleRate(),
+ adpcm_format->GetChannels());
+ break;
+ }
case wxSOUND_ULAW: {
wxSoundFormatUlaw *ulaw_format = (wxSoundFormatUlaw *)format;
info += wxT("ULAW\n");
delete dev;
// We test the OSS (Open Sound System) support.
- // WARNING: There is a conflict between ESD and ALSA
-
+ // WARNING: There is a conflict between ESD and ALSA. We may be interrested
+ // in disabling the auto detection of OSS is ESD has been detected.
+#if 1
+ if (!(caps & MM_SOUND_ESD)) {
+#endif
+
dev = new wxSoundStreamOSS();
if (dev->GetError() == wxSOUND_NOERROR)
caps |= MM_SOUND_OSS;
delete dev;
+#if 1
+ }
+#endif
+
#endif
#ifdef __WIN32__
# any VPATH assignment not containing ':'
VPATH = :$(top_srcdir)/src/mmedia # ':' for autoconf
-APPEXTRADEFS=-I$(top_srcdir)/include
+APPEXTRADEFS=-I$(top_srcdir)/include -I$(top_srcdir)/../include
include $(top_builddir)/src/makelib.env
#endif
#include <wx/wxprec.h>
+
+#ifndef WX_PRECOMP
+#include "wx/defs.h"
+#include "wx/string.h"
+#include "wx/log.h"
+#endif
+
#include "wx/mmedia/sndbase.h"
wxSoundFormatBase *wxSoundFormatBase::Clone() const
{
- return NULL;
+ wxLogFatalError(wxT("In wxSoundFormatBase::Clone() but I should"
+ " not be there"));
+ return NULL;
}
bool wxSoundFormatBase::operator!=(const wxSoundFormatBase& frmt2) const
{
- return (GetType() != frmt2.GetType());
+ return (GetType() != frmt2.GetType());
}
// ---------------------------------------------------------------------------
wxSoundStream::wxSoundStream()
{
- int i;
-
- // Reset all variables to their neutral value.
- m_sndformat = NULL;
- m_handler = NULL;
- m_snderror = wxSOUND_NOERROR;
- m_lastcount = 0;
- for (i=0;i<2;i++)
- m_callback[i] = NULL;
+ int i;
+
+ // Reset all variables to their neutral value.
+ m_sndformat = NULL;
+ m_handler = NULL;
+ m_snderror = wxSOUND_NOERROR;
+ m_lastcount = 0;
+ for (i=0;i<2;i++)
+ m_callback[i] = NULL;
}
wxSoundStream::~wxSoundStream()
{
if (m_sndformat)
- delete m_sndformat;
+ delete m_sndformat;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool wxSoundStream::SetSoundFormat(const wxSoundFormatBase& format)
{
- // delete the previous prepared format
- if (m_sndformat)
- delete m_sndformat;
-
- // create a new one by cloning the format passed in parameter
- m_sndformat = format.Clone();
- return TRUE;
+ // delete the previous prepared format
+ if (m_sndformat)
+ delete m_sndformat;
+
+ // create a new one by cloning the format passed in parameter
+ m_sndformat = format.Clone();
+ return TRUE;
}
// We try to minimize the need of dynamic memory allocation by preallocating a buffer. But
// to be sure it will be efficient we minimize the best size.
if (m_multiplier_in < m_multiplier_out) {
- m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_out);
- m_best_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_in);
+ m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() *
+ m_multiplier_out);
+ m_best_size = (wxUint32)(m_sndio->GetBestSize() *
+ m_multiplier_in);
} else {
- m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_in);
- m_best_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_out);
+ m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() *
+ m_multiplier_in);
+ m_best_size = (wxUint32)(m_sndio->GetBestSize() *
+ m_multiplier_out);
}
m_prebuffer = new char[m_prebuffer_size];
#include "wx/mmedia/sndcpcm.h"
#include "wx/mmedia/sndulaw.h"
#include "wx/mmedia/sndg72x.h"
+#include "wx/mmedia/sndmsad.h"
// --------------------------------------------------------------------------
// Sound codec router
m_router = new wxSoundStreamG72X(*m_sndio);
m_router->SetSoundFormat(format);
break;
+ case wxSOUND_MSADPCM:
+ m_router = new wxSoundStreamMSAdpcm(*m_sndio);
+ m_router->SetSoundFormat(format);
+ break;
default:
return FALSE;
// CVSID: $Id$
// --------------------------------------------------------------------------
#ifdef __GNUG__
-#pragma implementation "sndulaw.cpp"
+#pragma implementation "sndmsad.cpp"
#endif
#include <wx/wxprec.h>
+
+#ifndef WX_PRECOMP
+ #include "wx/defs.h"
+ #include "wx/memory.h"
+ #include "wx/log.h"
+#endif
+
#include "wx/mmedia/sndbase.h"
#include "wx/mmedia/sndfile.h"
#include "wx/mmedia/sndpcm.h"
wxSoundFormatMSAdpcm::wxSoundFormatMSAdpcm()
: m_srate(22050)
{
- m_coefs = new wxMSAdpcmCoefs();
+ m_ncoefs = 0;
+ m_coefs_len = 0;
+ m_coefs = NULL;
}
wxSoundFormatMSAdpcm::~wxSoundFormatMSAdpcm()
{
- delete m_coefs;
+ if (m_ncoefs) {
+ wxUint16 i;
+
+ for (i=0;i<m_ncoefs;i++)
+ delete[] m_coefs[i];
+ delete[] m_coefs;
+ }
+
}
void wxSoundFormatMSAdpcm::SetSampleRate(wxUint32 srate)
return m_srate;
}
+void wxSoundFormatMSAdpcm::SetChannels(wxUint16 nchannels)
+{
+ m_nchannels = nchannels;
+}
+
+wxUint16 wxSoundFormatMSAdpcm::GetChannels() const
+{
+ return m_nchannels;
+}
+
+void wxSoundFormatMSAdpcm::SetCoefs(wxInt16 **coefs, wxUint16 ncoefs,
+ wxUint16 coefs_len)
+{
+ wxUint16 i;
+
+ if (m_ncoefs) {
+ for (i=0;i<m_ncoefs;i++)
+ delete[] (m_coefs[i]);
+ delete[] m_coefs;
+ }
+ // TODO: Add some memory checking here
+ m_coefs = new (wxInt16 *)[ncoefs];
+
+ for (i=0;i<ncoefs;i++)
+ m_coefs[i] = new wxInt16[coefs_len];
+
+ m_ncoefs = ncoefs;
+ m_coefs_len = coefs_len;
+}
+
+void wxSoundFormatMSAdpcm::GetCoefs(wxInt16 **& coefs, wxUint16& ncoefs,
+ wxUint16& coefs_len) const
+{
+ coefs = m_coefs;
+ ncoefs = m_ncoefs;
+ coefs_len = m_coefs_len;
+}
+
+void wxSoundFormatMSAdpcm::SetBlockSize(wxUint16 block_size)
+{
+ m_block_size = block_size;
+}
+
+wxUint16 wxSoundFormatMSAdpcm::GetBlockSize() const
+{
+ return m_block_size;
+}
+
wxSoundFormatBase *wxSoundFormatMSAdpcm::Clone() const
{
wxSoundFormatMSAdpcm *adpcm = new wxSoundFormatMSAdpcm();
- adpcm->m_srate = m_srate;
- adpcm->m_coefs = new wxMSAdpcmCoefs();
- *(adpcm->m_coefs) = *m_coefs;
+ adpcm->m_srate = m_srate;
+ adpcm->SetCoefs(m_coefs, m_ncoefs, m_coefs_len);
+ adpcm->m_nchannels = m_nchannels;
+ adpcm->m_block_size = m_block_size;
return adpcm;
}
wxUint32 wxSoundFormatMSAdpcm::GetTimeFromBytes(wxUint32 bytes) const
{
- return 0;
+ return 2 * bytes / (m_nchannels * m_srate);
}
wxUint32 wxSoundFormatMSAdpcm::GetBytesFromTime(wxUint32 time) const
{
- return 0;
+ return time * m_nchannels * m_srate / 2;
}
bool wxSoundFormatMSAdpcm::operator !=(const wxSoundFormatBase& frmt2) const
{
- wxSoundFormatUlaw *adpcm = (wxSoundFormatMSAdpcm *)&frmt2;
+ const wxSoundFormatMSAdpcm *adpcm = (const wxSoundFormatMSAdpcm *)&frmt2;
if (frmt2.GetType() != wxSOUND_MSADPCM)
return TRUE;
- return (adpcm->m_srate != m_srate) && 0;
+ return (adpcm->m_srate != m_srate) && (adpcm->m_nchannels != m_nchannels);
}
// --------------------------------------------------------------------------
// PCM converter
m_router = new wxSoundRouterStream(sndio);
m_got_header = FALSE;
+ m_stereo = FALSE;
}
wxSoundStreamMSAdpcm::~wxSoundStreamMSAdpcm()
}
static wxInt16 gl_ADPCMcoeff_delta[] = {
- 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230
+ 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307,
+ 230, 230, 230
};
-static wxInt16 gl_ADPCMcoeff_1[] = {
- 256, 512, 0, 192, 240, 460, 392
-};
-
-static wxInt16 gl_ADPCMcoeff_2[] = {
- 0, -256, 0, 64, 0, -208, -232
-};
-
-wxSoundStream& wxSoundStreamMSAdpcm::Write(const void *buffer, wxUint32 len)
+wxUint32 wxSoundStreamMSAdpcm::DecodeMonoADPCM(const void *in_buffer,
+ void *out_buffer,
+ wxUint32 in_len)
{
- wxInt16 delta;
- wxUint8 ADPCMdata;
- wxUint16 *PCMdata;
- wxInt16 coeff1, coeff2;
-
-#define GET_DATA_16 (*ADPCMdata++ | ((wxUint32)(*ADPCMdata++) << 8);
-#define GET_DATA_8 (*ADPCMdata++)
-
- if (!m_got_header) {
- i_predict = GET_DATA_8;
- delta = GET_DATA_16;
- samp1 = GET_DATA_16;
- PCMdata = GET_DATA_16;
- len -= 3*2 + 1;
- m_got_header = TRUE;
-
- coeff1 = gl_ADPCMcoeff_1[i_predict];
- coeff2 = gl_ADPCMcoeff_2[i_predict];
+ wxUint8 *ADPCMdata;
+ wxInt16 *PCMdata;
+ AdpcmState *state;
+ wxUint32 out_len;
+
+ ADPCMdata = (wxUint8 *)in_buffer;
+ PCMdata = (wxInt16 *)out_buffer;
+ state = &m_state[0];
+
+#define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
+#define GET_DATA_8(i) i = (*ADPCMdata++)
+
+ out_len = 0;
+ while (in_len != 0) {
+ if (m_next_block == 0) {
+ GET_DATA_8(state->predictor);
+ GET_DATA_16(state->iDelta);
+
+ GET_DATA_16(state->samp1);
+ GET_DATA_16(state->samp2);
+
+ state->coeff[0] = state->coeff[1] = m_coefs[0][ state->predictor ];
+
+ *PCMdata++ = state->samp2;
+ *PCMdata++ = state->samp1;
+ in_len -= 7;
+ out_len += 4;
+ m_next_block = m_block_size;
+ continue;
+ }
+
+ while (in_len != 0 && m_next_block != 0) {
+ wxUint8 nib[2];
+
+ GET_DATA_8(nib[0]);
+ nib[1] = (nib[0] >> 4) & 0x0f;
+ nib[0] &= 0x0f;
+
+ Nibble(nib[0], state, &PCMdata);
+ Nibble(nib[1], state, &PCMdata);
+
+ in_len -= 4;
+ out_len += 4;
+ m_next_block -= 4;
+ }
}
+
+ return out_len;
+
+#undef GET_DATA_16
+#undef GET_DATA_8
+}
+
+wxUint32 wxSoundStreamMSAdpcm::DecodeStereoADPCM(const void *in_buffer,
+ void *out_buffer,
+ wxUint32 in_len)
+{
+ wxUint8 *ADPCMdata;
+ wxInt16 *PCMdata;
+ AdpcmState *state0, *state1;
+ wxUint32 out_len;
- while (len > 0) {
- nyb1 = GET_DATA_8;
- nyb0 = (nyb1 & 0xf0) >> 4;
- nyb1 &= 0x0f;
+ ADPCMdata = (wxUint8 *)in_buffer;
+ PCMdata = (wxInt16 *)out_buffer;
+
+ state0 = &m_state[0];
+ state1 = &m_state[1];
+
+#define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
+#define GET_DATA_8(i) i = (*ADPCMdata++)
+
+ out_len = 0;
+ while (in_len != 0) {
+ if (!m_next_block) {
+ GET_DATA_8(state0->predictor);
+ GET_DATA_8(state1->predictor);
+
+ GET_DATA_16(state0->iDelta);
+ GET_DATA_16(state1->iDelta);
+ GET_DATA_16(state0->samp1);
+ GET_DATA_16(state1->samp1);
+ GET_DATA_16(state0->samp2);
+ GET_DATA_16(state1->samp2);
+ *PCMdata++ = state0->samp2;
+ *PCMdata++ = state1->samp2;
+ *PCMdata++ = state0->samp1;
+ *PCMdata++ = state1->samp1;
+
+ in_len -= 14;
+ out_len += 8;
+ m_next_block = m_block_size;
+ continue;
+ }
+
+ while (in_len != 0 && m_next_block > 0) {
+ wxUint8 nib[2];
+
+ GET_DATA_8(nib[0]);
+ nib[1] = (nib[0] >> 4) & 0x0f;
+ nib[0] &= 0x0f;
+
+ Nibble(nib[0], state0, &PCMdata);
+ Nibble(nib[1], state1, &PCMdata);
+
+ in_len -= 4;
+ out_len += 4;
+ m_next_block -= 4;
+ }
+ }
+
+ return out_len;
+
+#undef GET_DATA_16
+#undef GET_DATA_8
+}
+
+void wxSoundStreamMSAdpcm::Nibble(wxInt8 nyb,
+ AdpcmState *state,
+ wxInt16 **out_buffer)
+{
+ wxUint32 new_delta;
+ wxInt32 new_sample;
+
+ // First: compute the next delta value
+ new_delta = (state->iDelta * gl_ADPCMcoeff_delta[nyb]) >> 8;
+ // If null, minor it by 16
+ if (!new_delta)
+ new_delta = 16;
+
+ // Barycentre
+ new_sample = (state->samp1 * state->coeff[0] +
+ state->samp2 * state->coeff[1]) / 256;
+
+ // Regenerate the sign
+ if (nyb & 0x08)
+ nyb -= 0x10;
+
+ new_sample += state->iDelta * nyb;
+
+ // Samples must be in [-32767, 32768]
+ if (new_sample < -32768)
+ new_sample = -32768;
+ else if (new_sample > 32767)
+ new_sample = 32767;
+
+ state->iDelta = new_delta;
+ state->samp2 = state->samp1;
+ state->samp1 = new_sample;
+
+ *(*out_buffer)++ = new_sample;
+}
+
+wxSoundStream& wxSoundStreamMSAdpcm::Write(const void *buffer, wxUint32 len)
+{
+ wxUint8 *out_buf;
+ wxUint32 new_len;
+
+ // TODO: prealloc the output buffer
+ out_buf = new wxUint8[len*2];
+
+ if (!m_stereo)
+ new_len = DecodeMonoADPCM(buffer, out_buf, len);
+ else
+ new_len = DecodeStereoADPCM(buffer, out_buf, len);
+
+ m_router->Write(out_buf, new_len);
+
+ m_lastcount = len;
+ m_snderror = wxSOUND_NOERROR;
+
+ delete[] out_buf;
+
return *this;
}
bool wxSoundStreamMSAdpcm::SetSoundFormat(const wxSoundFormatBase& format)
{
- if (format.GetType() != wxSOUND_ULAW) {
+ if (format.GetType() != wxSOUND_MSADPCM) {
m_snderror = wxSOUND_INVFRMT;
return FALSE;
}
wxSoundFormatPcm pcm;
- wxSoundFormatUlaw *ulaw;
+ wxSoundFormatMSAdpcm *adpcm;
+ wxUint16 ncoefs, coefs_len;
wxSoundStreamCodec::SetSoundFormat(format);
- ulaw = (wxSoundFormatMSAdpcm *)m_sndformat;
+ adpcm = (wxSoundFormatMSAdpcm *)m_sndformat;
+
+ adpcm->GetCoefs(m_coefs, ncoefs, coefs_len);
+
+ if (!ncoefs) {
+ wxLogError(__FILE__ ":%d: Number of ADPCM coefficients"
+ " must be non null", __LINE__);
+ return FALSE;
+ }
pcm.SetSampleRate(adpcm->GetSampleRate());
pcm.SetBPS(16);
pcm.SetChannels(adpcm->GetChannels());
pcm.Signed(TRUE);
pcm.SetOrder(wxBYTE_ORDER);
+
+ m_stereo = (adpcm->GetChannels() == 2);
+ m_block_size = adpcm->GetBlockSize();
+ m_next_block = 0;
m_router->SetSoundFormat(pcm);
return FALSE;
}
- // As the codec only support 16 bits, Mono we must use a wxSoundRouter to filter the data and
- // to translate them to a format supported by the sound card.
+ // As the codec only support 16 bits, Mono we must use a wxSoundRouter
+ // to filter the data and to translate them to a format supported
+ // by the sound card.
wxSoundFormatPcm pcm;
wxSoundFormatUlaw *ulaw;
#include "wx/mmedia/sndfile.h"
#include "wx/mmedia/sndpcm.h"
#include "wx/mmedia/sndg72x.h"
+#include "wx/mmedia/sndmsad.h"
#include "wx/mmedia/sndwav.h"
#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
return TRUE;
}
-bool wxSoundWave::HandleOutputPCM(wxDataInputStream& data, wxUint16 channels,
+bool wxSoundWave::HandleOutputPCM(wxDataInputStream& data, wxUint32 len,
+ wxUint16 channels,
wxUint32 sample_fq, wxUint32 byte_p_sec,
wxUint16 byte_p_spl, wxUint16 bits_p_spl)
{
if (!SetSoundFormat(sndformat))
return FALSE;
+ m_input->SeekI(len, wxFromCurrent);
+
return TRUE;
}
-bool wxSoundWave::HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
+bool wxSoundWave::HandleOutputMSADPCM(wxDataInputStream& data, wxUint32 len,
+ wxUint16 channels,
+ wxUint32 sample_fq, wxUint32 byte_p_sec,
+ wxUint16 byte_p_spl, wxUint16 bits_p_spl)
+{
+ wxSoundFormatMSAdpcm sndformat;
+ wxInt16 *coefs[2];
+ wxUint16 coefs_len, i;
+ wxUint16 block_size;
+
+ sndformat.SetSampleRate(sample_fq);
+ sndformat.SetChannels(channels);
+
+ block_size = data.Read16();
+ coefs_len = data.Read16();
+
+ coefs[0] = new wxInt16[coefs_len];
+ coefs[1] = new wxInt16[coefs_len];
+
+ for (i=0;i<coefs_len;i++) {
+ coefs[0][i] = data.Read16();
+ coefs[1][i] = data.Read16();
+ }
+
+ sndformat.SetCoefs(coefs, 2, coefs_len);
+ sndformat.SetBlockSize(block_size);
+
+ delete[] coefs[0];
+ delete[] coefs[1];
+
+ if (!SetSoundFormat(sndformat))
+ return FALSE;
+
+ len -= coefs_len*4 + 4;
+
+ m_input->SeekI(len, wxFromCurrent);
+
+ return TRUE;
+}
+
+bool wxSoundWave::HandleOutputG721(wxDataInputStream& data, wxUint32 len,
+ wxUint16 channels,
wxUint32 sample_fq, wxUint32 byte_p_sec,
wxUint16 byte_p_spl, wxUint16 bits_p_spl)
{
if (!SetSoundFormat(sndformat))
return FALSE;
+ m_input->SeekI(len, wxFromCurrent);
+
return TRUE;
}
// Get the common parameters
data >> format >> channels >> sample_fq
>> byte_p_sec >> byte_p_spl >> bits_p_spl;
+ len -= 16;
switch (format) {
case 0x01: // PCM
- if (!HandleOutputPCM(data, channels, sample_fq,
- byte_p_sec, byte_p_spl, bits_p_spl))
+ if (!HandleOutputPCM(data, len, channels, sample_fq,
+ byte_p_sec, byte_p_spl,
+ bits_p_spl))
+ return FALSE;
+ break;
+ case 0x02: // MS ADPCM
+ if (!HandleOutputMSADPCM(data, len,
+ channels, sample_fq,
+ byte_p_sec, byte_p_spl,
+ bits_p_spl))
return FALSE;
break;
case 0x40: // G721
- if (!HandleOutputG721(data, channels, sample_fq,
- byte_p_sec, byte_p_spl, bits_p_spl))
+ if (!HandleOutputG721(data, len,
+ channels, sample_fq,
+ byte_p_sec, byte_p_spl,
+ bits_p_spl))
return FALSE;
break;
default:
m_video_output->SetSize(vibrato_size);
vibrato_size.SetWidth(vibrato_size.GetWidth()-1);
m_video_output->SetSize(vibrato_size);
- // Very useful ! Actually it sends a SETSIZE event to XAnim
+ // Very useful ! Actually it "should" sends a SETSIZE event to XAnim
+ // FIXME: This event is not sent !!
m_paused = FALSE;
# any VPATH assignment not containing ':'
VPATH = :$(top_srcdir)/src/ogl # ':' for autoconf
-APPEXTRADEFS=-I$(top_srcdir)/include
+APPEXTRADEFS=-I$(top_srcdir)/include -I$(top_srcdir)/../include
include $(top_builddir)/src/makelib.env
Style.o \
ViewStyle.o
-APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/include
+APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/include -I$(top_srcdir)/../include
include $(top_builddir)/src/makelib.env
Style.o \
ViewStyle.o
-APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/include
+APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/include -I$(top_srcdir)/../include
include $(top_builddir)/src/makelib.env