1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
8 // --------------------------------------------------------------------------
10 #include "wx/wxprec.h"
14 #include "wx/memory.h"
18 #include "wx/mmedia/sndbase.h"
19 #include "wx/mmedia/sndfile.h"
20 #include "wx/mmedia/sndpcm.h"
21 #include "wx/mmedia/sndmsad.h"
23 // --------------------------------------------------------------------------
24 // wxSoundFormatMSAdpcm
25 // --------------------------------------------------------------------------
27 wxSoundFormatMSAdpcm::wxSoundFormatMSAdpcm()
35 wxSoundFormatMSAdpcm::~wxSoundFormatMSAdpcm()
40 for (i
=0;i
<m_ncoefs
;i
++)
47 void wxSoundFormatMSAdpcm::SetSampleRate(wxUint32 srate
)
52 wxUint32
wxSoundFormatMSAdpcm::GetSampleRate() const
57 void wxSoundFormatMSAdpcm::SetChannels(wxUint16 nchannels
)
59 m_nchannels
= nchannels
;
62 wxUint16
wxSoundFormatMSAdpcm::GetChannels() const
67 void wxSoundFormatMSAdpcm::SetCoefs(wxInt16
**WXUNUSED(coefs
), wxUint16 ncoefs
,
73 for (i
=0;i
<m_ncoefs
;i
++)
74 delete[] (m_coefs
[i
]);
77 // TODO: Add some memory checking here
78 m_coefs
= new wxInt16
*[ncoefs
];
80 for (i
=0;i
<ncoefs
;i
++)
81 m_coefs
[i
] = new wxInt16
[coefs_len
];
84 m_coefs_len
= coefs_len
;
87 void wxSoundFormatMSAdpcm::GetCoefs(wxInt16
**& coefs
, wxUint16
& ncoefs
,
88 wxUint16
& coefs_len
) const
92 coefs_len
= m_coefs_len
;
95 void wxSoundFormatMSAdpcm::SetBlockSize(wxUint16 block_size
)
97 m_block_size
= block_size
;
100 wxUint16
wxSoundFormatMSAdpcm::GetBlockSize() const
105 wxSoundFormatBase
*wxSoundFormatMSAdpcm::Clone() const
107 wxSoundFormatMSAdpcm
*adpcm
= new wxSoundFormatMSAdpcm();
109 adpcm
->m_srate
= m_srate
;
110 adpcm
->SetCoefs(m_coefs
, m_ncoefs
, m_coefs_len
);
111 adpcm
->m_nchannels
= m_nchannels
;
112 adpcm
->m_block_size
= m_block_size
;
116 wxUint32
wxSoundFormatMSAdpcm::GetTimeFromBytes(wxUint32 bytes
) const
118 return 2 * bytes
/ (m_nchannels
* m_srate
);
121 wxUint32
wxSoundFormatMSAdpcm::GetBytesFromTime(wxUint32 time
) const
123 return time
* m_nchannels
* m_srate
/ 2;
126 bool wxSoundFormatMSAdpcm::operator !=(const wxSoundFormatBase
& frmt2
) const
128 const wxSoundFormatMSAdpcm
*adpcm
= (const wxSoundFormatMSAdpcm
*)&frmt2
;
130 if (frmt2
.GetType() != wxSOUND_MSADPCM
)
133 return (adpcm
->m_srate
!= m_srate
) && (adpcm
->m_nchannels
!= m_nchannels
);
136 // --------------------------------------------------------------------------
137 // wxSoundStreamMSAdpcm
138 // --------------------------------------------------------------------------
139 wxSoundStreamMSAdpcm::wxSoundStreamMSAdpcm(wxSoundStream
& sndio
)
140 : wxSoundStreamCodec(sndio
)
143 m_router
= new wxSoundRouterStream(sndio
);
144 m_got_header
= false;
148 wxSoundStreamMSAdpcm::~wxSoundStreamMSAdpcm()
153 wxSoundStream
& wxSoundStreamMSAdpcm::Read(void *WXUNUSED(buffer
), wxUint32
WXUNUSED(len
))
155 m_snderror
= wxSOUND_NOCODEC
;
160 static wxInt16 gl_ADPCMcoeff_delta
[] = {
161 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307,
165 wxUint32
wxSoundStreamMSAdpcm::DecodeMonoADPCM(const void *in_buffer
,
174 ADPCMdata
= (wxUint8
*)in_buffer
;
175 PCMdata
= (wxInt16
*)out_buffer
;
178 #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
179 #define GET_DATA_8(i) i = (*ADPCMdata++)
182 while (in_len
!= 0) {
183 if (m_next_block
== 0) {
184 GET_DATA_8(state
->predictor
);
185 GET_DATA_16(state
->iDelta
);
187 GET_DATA_16(state
->samp1
);
188 GET_DATA_16(state
->samp2
);
190 state
->coeff
[0] = state
->coeff
[1] = m_coefs
[0][ state
->predictor
];
192 *PCMdata
++ = state
->samp2
;
193 *PCMdata
++ = state
->samp1
;
196 m_next_block
= m_block_size
;
200 while (in_len
!= 0 && m_next_block
!= 0) {
204 nib
[1] = (nib
[0] >> 4) & 0x0f;
207 Nibble(nib
[0], state
, &PCMdata
);
208 Nibble(nib
[1], state
, &PCMdata
);
222 wxUint32
wxSoundStreamMSAdpcm::DecodeStereoADPCM(const void *in_buffer
,
228 AdpcmState
*state0
, *state1
;
231 ADPCMdata
= (wxUint8
*)in_buffer
;
232 PCMdata
= (wxInt16
*)out_buffer
;
234 state0
= &m_state
[0];
235 state1
= &m_state
[1];
237 #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)
238 #define GET_DATA_8(i) i = (*ADPCMdata++)
241 while (in_len
!= 0) {
243 GET_DATA_8(state0
->predictor
);
244 GET_DATA_8(state1
->predictor
);
246 GET_DATA_16(state0
->iDelta
);
247 GET_DATA_16(state1
->iDelta
);
249 GET_DATA_16(state0
->samp1
);
250 GET_DATA_16(state1
->samp1
);
251 GET_DATA_16(state0
->samp2
);
252 GET_DATA_16(state1
->samp2
);
254 *PCMdata
++ = state0
->samp2
;
255 *PCMdata
++ = state1
->samp2
;
256 *PCMdata
++ = state0
->samp1
;
257 *PCMdata
++ = state1
->samp1
;
261 m_next_block
= m_block_size
;
265 while (in_len
!= 0 && m_next_block
> 0) {
269 nib
[1] = (nib
[0] >> 4) & 0x0f;
272 Nibble(nib
[0], state0
, &PCMdata
);
273 Nibble(nib
[1], state1
, &PCMdata
);
287 void wxSoundStreamMSAdpcm::Nibble(wxInt8 nyb
,
289 wxInt16
**out_buffer
)
294 // First: compute the next delta value
295 new_delta
= (state
->iDelta
* gl_ADPCMcoeff_delta
[nyb
]) >> 8;
296 // If null, minor it by 16
301 new_sample
= (state
->samp1
* state
->coeff
[0] +
302 state
->samp2
* state
->coeff
[1]) / 256;
304 // Regenerate the sign
308 new_sample
+= state
->iDelta
* nyb
;
310 // Samples must be in [-32767, 32768]
311 if (new_sample
< -32768)
313 else if (new_sample
> 32767)
316 state
->iDelta
= new_delta
;
317 state
->samp2
= state
->samp1
;
318 state
->samp1
= new_sample
;
320 *(*out_buffer
)++ = new_sample
;
323 wxSoundStream
& wxSoundStreamMSAdpcm::Write(const void *buffer
, wxUint32 len
)
328 // TODO: prealloc the output buffer
329 out_buf
= new wxUint8
[len
*2];
332 new_len
= DecodeMonoADPCM(buffer
, out_buf
, len
);
334 new_len
= DecodeStereoADPCM(buffer
, out_buf
, len
);
336 m_router
->Write(out_buf
, new_len
);
339 m_snderror
= wxSOUND_NOERROR
;
346 wxUint32
wxSoundStreamMSAdpcm::GetBestSize() const
348 return m_sndio
->GetBestSize() / 2;
351 bool wxSoundStreamMSAdpcm::SetSoundFormat(const wxSoundFormatBase
& format
)
353 if (format
.GetType() != wxSOUND_MSADPCM
) {
354 m_snderror
= wxSOUND_INVFRMT
;
358 wxSoundFormatPcm pcm
;
359 wxSoundFormatMSAdpcm
*adpcm
;
360 wxUint16 ncoefs
, coefs_len
;
362 wxSoundStreamCodec::SetSoundFormat(format
);
364 adpcm
= (wxSoundFormatMSAdpcm
*)m_sndformat
;
366 adpcm
->GetCoefs(m_coefs
, ncoefs
, coefs_len
);
369 wxLogError(wxT("Number of ADPCM coefficients must be non null"));
373 pcm
.SetSampleRate(adpcm
->GetSampleRate());
375 pcm
.SetChannels(adpcm
->GetChannels());
377 pcm
.SetOrder(wxBYTE_ORDER
);
379 m_stereo
= (adpcm
->GetChannels() == 2);
380 m_block_size
= adpcm
->GetBlockSize();
383 m_router
->SetSoundFormat(pcm
);