1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
7 // --------------------------------------------------------------------------
9 #pragma implementation "sndmsad.cpp"
12 #include <wx/wxprec.h>
16 #include "wx/memory.h"
20 #include "wx/mmedia/sndbase.h"
21 #include "wx/mmedia/sndfile.h"
22 #include "wx/mmedia/sndpcm.h"
23 #include "wx/mmedia/sndmsad.h"
25 // --------------------------------------------------------------------------
26 // wxSoundFormatMSAdpcm
27 // --------------------------------------------------------------------------
29 wxSoundFormatMSAdpcm::wxSoundFormatMSAdpcm()
37 wxSoundFormatMSAdpcm::~wxSoundFormatMSAdpcm()
42 for (i
=0;i
<m_ncoefs
;i
++)
49 void wxSoundFormatMSAdpcm::SetSampleRate(wxUint32 srate
)
54 wxUint32
wxSoundFormatMSAdpcm::GetSampleRate() const
59 void wxSoundFormatMSAdpcm::SetChannels(wxUint16 nchannels
)
61 m_nchannels
= nchannels
;
64 wxUint16
wxSoundFormatMSAdpcm::GetChannels() const
69 void wxSoundFormatMSAdpcm::SetCoefs(wxInt16
**coefs
, wxUint16 ncoefs
,
75 for (i
=0;i
<m_ncoefs
;i
++)
76 delete[] (m_coefs
[i
]);
79 // TODO: Add some memory checking here
80 m_coefs
= new (wxInt16
*)[ncoefs
];
82 for (i
=0;i
<ncoefs
;i
++)
83 m_coefs
[i
] = new wxInt16
[coefs_len
];
86 m_coefs_len
= coefs_len
;
89 void wxSoundFormatMSAdpcm::GetCoefs(wxInt16
**& coefs
, wxUint16
& ncoefs
,
90 wxUint16
& coefs_len
) const
94 coefs_len
= m_coefs_len
;
97 void wxSoundFormatMSAdpcm::SetBlockSize(wxUint16 block_size
)
99 m_block_size
= block_size
;
102 wxUint16
wxSoundFormatMSAdpcm::GetBlockSize() const
107 wxSoundFormatBase
*wxSoundFormatMSAdpcm::Clone() const
109 wxSoundFormatMSAdpcm
*adpcm
= new wxSoundFormatMSAdpcm();
111 adpcm
->m_srate
= m_srate
;
112 adpcm
->SetCoefs(m_coefs
, m_ncoefs
, m_coefs_len
);
113 adpcm
->m_nchannels
= m_nchannels
;
114 adpcm
->m_block_size
= m_block_size
;
118 wxUint32
wxSoundFormatMSAdpcm::GetTimeFromBytes(wxUint32 bytes
) const
120 return 2 * bytes
/ (m_nchannels
* m_srate
);
123 wxUint32
wxSoundFormatMSAdpcm::GetBytesFromTime(wxUint32 time
) const
125 return time
* m_nchannels
* m_srate
/ 2;
128 bool wxSoundFormatMSAdpcm::operator !=(const wxSoundFormatBase
& frmt2
) const
130 const wxSoundFormatMSAdpcm
*adpcm
= (const wxSoundFormatMSAdpcm
*)&frmt2
;
132 if (frmt2
.GetType() != wxSOUND_MSADPCM
)
135 return (adpcm
->m_srate
!= m_srate
) && (adpcm
->m_nchannels
!= m_nchannels
);
138 // --------------------------------------------------------------------------
139 // wxSoundStreamMSAdpcm
140 // --------------------------------------------------------------------------
141 wxSoundStreamMSAdpcm::wxSoundStreamMSAdpcm(wxSoundStream
& sndio
)
142 : wxSoundStreamCodec(sndio
)
145 m_router
= new wxSoundRouterStream(sndio
);
146 m_got_header
= FALSE
;
150 wxSoundStreamMSAdpcm::~wxSoundStreamMSAdpcm()
155 wxSoundStream
& wxSoundStreamMSAdpcm::Read(void *buffer
, wxUint32 len
)
157 m_snderror
= wxSOUND_NOCODEC
;
162 static wxInt16 gl_ADPCMcoeff_delta
[] = {
163 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307,
167 wxUint32
wxSoundStreamMSAdpcm::DecodeMonoADPCM(const void *in_buffer
,
176 ADPCMdata
= (wxUint8
*)in_buffer
;
177 PCMdata
= (wxInt16
*)out_buffer
;
180 #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
181 #define GET_DATA_8(i) i = (*ADPCMdata++)
184 while (in_len
!= 0) {
185 if (m_next_block
== 0) {
186 GET_DATA_8(state
->predictor
);
187 GET_DATA_16(state
->iDelta
);
189 GET_DATA_16(state
->samp1
);
190 GET_DATA_16(state
->samp2
);
192 state
->coeff
[0] = state
->coeff
[1] = m_coefs
[0][ state
->predictor
];
194 *PCMdata
++ = state
->samp2
;
195 *PCMdata
++ = state
->samp1
;
198 m_next_block
= m_block_size
;
202 while (in_len
!= 0 && m_next_block
!= 0) {
206 nib
[1] = (nib
[0] >> 4) & 0x0f;
209 Nibble(nib
[0], state
, &PCMdata
);
210 Nibble(nib
[1], state
, &PCMdata
);
224 wxUint32
wxSoundStreamMSAdpcm::DecodeStereoADPCM(const void *in_buffer
,
230 AdpcmState
*state0
, *state1
;
233 ADPCMdata
= (wxUint8
*)in_buffer
;
234 PCMdata
= (wxInt16
*)out_buffer
;
236 state0
= &m_state
[0];
237 state1
= &m_state
[1];
239 #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
240 #define GET_DATA_8(i) i = (*ADPCMdata++)
243 while (in_len
!= 0) {
245 GET_DATA_8(state0
->predictor
);
246 GET_DATA_8(state1
->predictor
);
248 GET_DATA_16(state0
->iDelta
);
249 GET_DATA_16(state1
->iDelta
);
251 GET_DATA_16(state0
->samp1
);
252 GET_DATA_16(state1
->samp1
);
253 GET_DATA_16(state0
->samp2
);
254 GET_DATA_16(state1
->samp2
);
256 *PCMdata
++ = state0
->samp2
;
257 *PCMdata
++ = state1
->samp2
;
258 *PCMdata
++ = state0
->samp1
;
259 *PCMdata
++ = state1
->samp1
;
263 m_next_block
= m_block_size
;
267 while (in_len
!= 0 && m_next_block
> 0) {
271 nib
[1] = (nib
[0] >> 4) & 0x0f;
274 Nibble(nib
[0], state0
, &PCMdata
);
275 Nibble(nib
[1], state1
, &PCMdata
);
289 void wxSoundStreamMSAdpcm::Nibble(wxInt8 nyb
,
291 wxInt16
**out_buffer
)
296 // First: compute the next delta value
297 new_delta
= (state
->iDelta
* gl_ADPCMcoeff_delta
[nyb
]) >> 8;
298 // If null, minor it by 16
303 new_sample
= (state
->samp1
* state
->coeff
[0] +
304 state
->samp2
* state
->coeff
[1]) / 256;
306 // Regenerate the sign
310 new_sample
+= state
->iDelta
* nyb
;
312 // Samples must be in [-32767, 32768]
313 if (new_sample
< -32768)
315 else if (new_sample
> 32767)
318 state
->iDelta
= new_delta
;
319 state
->samp2
= state
->samp1
;
320 state
->samp1
= new_sample
;
322 *(*out_buffer
)++ = new_sample
;
325 wxSoundStream
& wxSoundStreamMSAdpcm::Write(const void *buffer
, wxUint32 len
)
330 // TODO: prealloc the output buffer
331 out_buf
= new wxUint8
[len
*2];
334 new_len
= DecodeMonoADPCM(buffer
, out_buf
, len
);
336 new_len
= DecodeStereoADPCM(buffer
, out_buf
, len
);
338 m_router
->Write(out_buf
, new_len
);
341 m_snderror
= wxSOUND_NOERROR
;
348 wxUint32
wxSoundStreamMSAdpcm::GetBestSize() const
350 return m_sndio
->GetBestSize() / 2;
353 bool wxSoundStreamMSAdpcm::SetSoundFormat(const wxSoundFormatBase
& format
)
355 if (format
.GetType() != wxSOUND_MSADPCM
) {
356 m_snderror
= wxSOUND_INVFRMT
;
360 wxSoundFormatPcm pcm
;
361 wxSoundFormatMSAdpcm
*adpcm
;
362 wxUint16 ncoefs
, coefs_len
;
364 wxSoundStreamCodec::SetSoundFormat(format
);
366 adpcm
= (wxSoundFormatMSAdpcm
*)m_sndformat
;
368 adpcm
->GetCoefs(m_coefs
, ncoefs
, coefs_len
);
371 wxLogError(__FILE__
":%d: Number of ADPCM coefficients"
372 " must be non null", __LINE__
);
376 pcm
.SetSampleRate(adpcm
->GetSampleRate());
378 pcm
.SetChannels(adpcm
->GetChannels());
380 pcm
.SetOrder(wxBYTE_ORDER
);
382 m_stereo
= (adpcm
->GetChannels() == 2);
383 m_block_size
= adpcm
->GetBlockSize();
386 m_router
->SetSoundFormat(pcm
);