1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
8 // --------------------------------------------------------------------------
10 #pragma implementation "sndmsad.cpp"
13 #include "wx/wxprec.h"
17 #include "wx/memory.h"
21 #include "wx/mmedia/sndbase.h"
22 #include "wx/mmedia/sndfile.h"
23 #include "wx/mmedia/sndpcm.h"
24 #include "wx/mmedia/sndmsad.h"
26 // --------------------------------------------------------------------------
27 // wxSoundFormatMSAdpcm
28 // --------------------------------------------------------------------------
30 wxSoundFormatMSAdpcm::wxSoundFormatMSAdpcm()
38 wxSoundFormatMSAdpcm::~wxSoundFormatMSAdpcm()
43 for (i
=0;i
<m_ncoefs
;i
++)
50 void wxSoundFormatMSAdpcm::SetSampleRate(wxUint32 srate
)
55 wxUint32
wxSoundFormatMSAdpcm::GetSampleRate() const
60 void wxSoundFormatMSAdpcm::SetChannels(wxUint16 nchannels
)
62 m_nchannels
= nchannels
;
65 wxUint16
wxSoundFormatMSAdpcm::GetChannels() const
70 void wxSoundFormatMSAdpcm::SetCoefs(wxInt16
**WXUNUSED(coefs
), wxUint16 ncoefs
,
76 for (i
=0;i
<m_ncoefs
;i
++)
77 delete[] (m_coefs
[i
]);
80 // TODO: Add some memory checking here
81 m_coefs
= new wxInt16
*[ncoefs
];
83 for (i
=0;i
<ncoefs
;i
++)
84 m_coefs
[i
] = new wxInt16
[coefs_len
];
87 m_coefs_len
= coefs_len
;
90 void wxSoundFormatMSAdpcm::GetCoefs(wxInt16
**& coefs
, wxUint16
& ncoefs
,
91 wxUint16
& coefs_len
) const
95 coefs_len
= m_coefs_len
;
98 void wxSoundFormatMSAdpcm::SetBlockSize(wxUint16 block_size
)
100 m_block_size
= block_size
;
103 wxUint16
wxSoundFormatMSAdpcm::GetBlockSize() const
108 wxSoundFormatBase
*wxSoundFormatMSAdpcm::Clone() const
110 wxSoundFormatMSAdpcm
*adpcm
= new wxSoundFormatMSAdpcm();
112 adpcm
->m_srate
= m_srate
;
113 adpcm
->SetCoefs(m_coefs
, m_ncoefs
, m_coefs_len
);
114 adpcm
->m_nchannels
= m_nchannels
;
115 adpcm
->m_block_size
= m_block_size
;
119 wxUint32
wxSoundFormatMSAdpcm::GetTimeFromBytes(wxUint32 bytes
) const
121 return 2 * bytes
/ (m_nchannels
* m_srate
);
124 wxUint32
wxSoundFormatMSAdpcm::GetBytesFromTime(wxUint32 time
) const
126 return time
* m_nchannels
* m_srate
/ 2;
129 bool wxSoundFormatMSAdpcm::operator !=(const wxSoundFormatBase
& frmt2
) const
131 const wxSoundFormatMSAdpcm
*adpcm
= (const wxSoundFormatMSAdpcm
*)&frmt2
;
133 if (frmt2
.GetType() != wxSOUND_MSADPCM
)
136 return (adpcm
->m_srate
!= m_srate
) && (adpcm
->m_nchannels
!= m_nchannels
);
139 // --------------------------------------------------------------------------
140 // wxSoundStreamMSAdpcm
141 // --------------------------------------------------------------------------
142 wxSoundStreamMSAdpcm::wxSoundStreamMSAdpcm(wxSoundStream
& sndio
)
143 : wxSoundStreamCodec(sndio
)
146 m_router
= new wxSoundRouterStream(sndio
);
147 m_got_header
= false;
151 wxSoundStreamMSAdpcm::~wxSoundStreamMSAdpcm()
156 wxSoundStream
& wxSoundStreamMSAdpcm::Read(void *WXUNUSED(buffer
), wxUint32
WXUNUSED(len
))
158 m_snderror
= wxSOUND_NOCODEC
;
163 static wxInt16 gl_ADPCMcoeff_delta
[] = {
164 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307,
168 wxUint32
wxSoundStreamMSAdpcm::DecodeMonoADPCM(const void *in_buffer
,
177 ADPCMdata
= (wxUint8
*)in_buffer
;
178 PCMdata
= (wxInt16
*)out_buffer
;
181 #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
182 #define GET_DATA_8(i) i = (*ADPCMdata++)
185 while (in_len
!= 0) {
186 if (m_next_block
== 0) {
187 GET_DATA_8(state
->predictor
);
188 GET_DATA_16(state
->iDelta
);
190 GET_DATA_16(state
->samp1
);
191 GET_DATA_16(state
->samp2
);
193 state
->coeff
[0] = state
->coeff
[1] = m_coefs
[0][ state
->predictor
];
195 *PCMdata
++ = state
->samp2
;
196 *PCMdata
++ = state
->samp1
;
199 m_next_block
= m_block_size
;
203 while (in_len
!= 0 && m_next_block
!= 0) {
207 nib
[1] = (nib
[0] >> 4) & 0x0f;
210 Nibble(nib
[0], state
, &PCMdata
);
211 Nibble(nib
[1], state
, &PCMdata
);
225 wxUint32
wxSoundStreamMSAdpcm::DecodeStereoADPCM(const void *in_buffer
,
231 AdpcmState
*state0
, *state1
;
234 ADPCMdata
= (wxUint8
*)in_buffer
;
235 PCMdata
= (wxInt16
*)out_buffer
;
237 state0
= &m_state
[0];
238 state1
= &m_state
[1];
240 #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
241 #define GET_DATA_8(i) i = (*ADPCMdata++)
244 while (in_len
!= 0) {
246 GET_DATA_8(state0
->predictor
);
247 GET_DATA_8(state1
->predictor
);
249 GET_DATA_16(state0
->iDelta
);
250 GET_DATA_16(state1
->iDelta
);
252 GET_DATA_16(state0
->samp1
);
253 GET_DATA_16(state1
->samp1
);
254 GET_DATA_16(state0
->samp2
);
255 GET_DATA_16(state1
->samp2
);
257 *PCMdata
++ = state0
->samp2
;
258 *PCMdata
++ = state1
->samp2
;
259 *PCMdata
++ = state0
->samp1
;
260 *PCMdata
++ = state1
->samp1
;
264 m_next_block
= m_block_size
;
268 while (in_len
!= 0 && m_next_block
> 0) {
272 nib
[1] = (nib
[0] >> 4) & 0x0f;
275 Nibble(nib
[0], state0
, &PCMdata
);
276 Nibble(nib
[1], state1
, &PCMdata
);
290 void wxSoundStreamMSAdpcm::Nibble(wxInt8 nyb
,
292 wxInt16
**out_buffer
)
297 // First: compute the next delta value
298 new_delta
= (state
->iDelta
* gl_ADPCMcoeff_delta
[nyb
]) >> 8;
299 // If null, minor it by 16
304 new_sample
= (state
->samp1
* state
->coeff
[0] +
305 state
->samp2
* state
->coeff
[1]) / 256;
307 // Regenerate the sign
311 new_sample
+= state
->iDelta
* nyb
;
313 // Samples must be in [-32767, 32768]
314 if (new_sample
< -32768)
316 else if (new_sample
> 32767)
319 state
->iDelta
= new_delta
;
320 state
->samp2
= state
->samp1
;
321 state
->samp1
= new_sample
;
323 *(*out_buffer
)++ = new_sample
;
326 wxSoundStream
& wxSoundStreamMSAdpcm::Write(const void *buffer
, wxUint32 len
)
331 // TODO: prealloc the output buffer
332 out_buf
= new wxUint8
[len
*2];
335 new_len
= DecodeMonoADPCM(buffer
, out_buf
, len
);
337 new_len
= DecodeStereoADPCM(buffer
, out_buf
, len
);
339 m_router
->Write(out_buf
, new_len
);
342 m_snderror
= wxSOUND_NOERROR
;
349 wxUint32
wxSoundStreamMSAdpcm::GetBestSize() const
351 return m_sndio
->GetBestSize() / 2;
354 bool wxSoundStreamMSAdpcm::SetSoundFormat(const wxSoundFormatBase
& format
)
356 if (format
.GetType() != wxSOUND_MSADPCM
) {
357 m_snderror
= wxSOUND_INVFRMT
;
361 wxSoundFormatPcm pcm
;
362 wxSoundFormatMSAdpcm
*adpcm
;
363 wxUint16 ncoefs
, coefs_len
;
365 wxSoundStreamCodec::SetSoundFormat(format
);
367 adpcm
= (wxSoundFormatMSAdpcm
*)m_sndformat
;
369 adpcm
->GetCoefs(m_coefs
, ncoefs
, coefs_len
);
372 wxLogError(wxT("Number of ADPCM coefficients must be non null"));
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
);