1// -------------------------------------------------------------------------- 2// Name: sndg72x.cpp 3// Purpose: 4// Date: 08/26/1999 5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999 6// CVSID: $Id: sndg72x.cpp 35650 2005-09-23 12:56:45Z MR $ 7// wxWindows licence 8// -------------------------------------------------------------------------- 9 10#include "wx/wxprec.h" 11 12#ifndef WX_PRECOMP 13 #include "wx/defs.h" 14#endif 15 16#include "wx/mmedia/sndbase.h" 17#include "wx/mmedia/sndfile.h" 18#include "wx/mmedia/sndpcm.h" 19#include "wx/mmedia/sndg72x.h" 20#include "wx/mmedia/internal/g72x.h" 21 22// -------------------------------------------------------------------------- 23// wxSoundFormatG72X 24// -------------------------------------------------------------------------- 25 26wxSoundFormatG72X::wxSoundFormatG72X() 27 : m_srate(22050) 28{ 29} 30 31wxSoundFormatG72X::~wxSoundFormatG72X() 32{ 33} 34 35void wxSoundFormatG72X::SetSampleRate(wxUint32 srate) 36{ 37 m_srate = srate; 38} 39 40wxUint32 wxSoundFormatG72X::GetSampleRate() const 41{ 42 return m_srate; 43} 44 45void wxSoundFormatG72X::SetG72XType(wxSoundG72XType type) 46{ 47 m_g72x_type = type; 48} 49 50wxSoundFormatBase *wxSoundFormatG72X::Clone() const 51{ 52 wxSoundFormatG72X *g72x = new wxSoundFormatG72X(); 53 54 g72x->m_srate = m_srate; 55 g72x->m_g72x_type = m_g72x_type; 56 return g72x; 57} 58 59wxUint32 wxSoundFormatG72X::GetTimeFromBytes(wxUint32 bytes) const 60{ 61 int n_bits; 62 63 switch (m_g72x_type) { 64 case wxSOUND_G721: 65 n_bits = 4; 66 break; 67 case wxSOUND_G723_24: 68 n_bits = 3; 69 break; 70 case wxSOUND_G723_40: 71 n_bits = 5; 72 break; 73 default: 74 n_bits = 0; 75 break; 76 } 77 return (wxUint32)((bytes / m_srate) * n_bits) / 8; 78} 79 80wxUint32 wxSoundFormatG72X::GetBytesFromTime(wxUint32 time) const 81{ 82 int n_bits; 83 84 switch (m_g72x_type) { 85 case wxSOUND_G721: 86 n_bits = 4; 87 break; 88 case wxSOUND_G723_24: 89 n_bits = 3; 90 break; 91 case wxSOUND_G723_40: 92 n_bits = 5; 93 break; 94 default: 95 n_bits = 0; 96 } 97 return (wxUint32)((time * m_srate * n_bits) / 8); 98} 99 100bool wxSoundFormatG72X::operator !=(const wxSoundFormatBase& frmt2) const 101{ 102 wxSoundFormatG72X *g72x = (wxSoundFormatG72X *)&frmt2; 103 104 if (frmt2.GetType() != wxSOUND_G72X) 105 return true; 106 107 return (g72x->m_srate != m_srate || g72x->m_g72x_type != m_g72x_type); 108} 109 110// -------------------------------------------------------------------------- 111// wxSoundStreamG72X 112// -------------------------------------------------------------------------- 113 114wxSoundStreamG72X::wxSoundStreamG72X(wxSoundStream& sndio) 115 : wxSoundStreamCodec(sndio) 116{ 117 // PCM converter 118 m_router = new wxSoundRouterStream(sndio); 119 m_state = new g72state; 120 g72x_init_state(m_state); 121} 122 123wxSoundStreamG72X::~wxSoundStreamG72X() 124{ 125 delete m_router; 126} 127 128wxSoundStream& wxSoundStreamG72X::Read(void *buffer, wxUint32 len) 129{ 130 wxUint16 *old_linear; 131 register wxUint16 *linear_buffer; 132 register wxUint32 real_len; 133 register wxUint32 countdown = len; 134 135 real_len = (len * 8 / m_n_bits); 136 137 old_linear = linear_buffer = new wxUint16[real_len]; 138 139 m_router->Read(linear_buffer, real_len); 140 141 real_len = (wxUint32)(m_router->GetLastAccess() * ((float)m_n_bits / 8)); 142 if (!real_len) 143 return *m_router; 144 145 m_io_buffer = (wxUint8 *)buffer; 146 m_current_b_pos = 0; 147 148 while (countdown != 0) { 149 PutBits(m_coder(*linear_buffer++, AUDIO_ENCODING_LINEAR, m_state)); 150 countdown--; 151 } 152 m_lastcount = real_len; 153 m_snderror = m_router->GetError(); 154 155 delete[] old_linear; 156 157 return *this; 158} 159 160wxSoundStream& wxSoundStreamG72X::Write(const void *buffer, wxUint32 len) 161{ 162 wxUint16 *old_linear; 163 register wxUint16 *linear_buffer; 164 register wxUint32 countdown = len; 165 register wxUint32 real_len; 166 167 // Compute the real length (PCM format) to sendt to the sound card 168 real_len = (len * m_n_bits / 8); 169 170 // Allocate a temporary buffer 171 old_linear = linear_buffer = new wxUint16[real_len]; 172 173 // Bad, we override the const 174 m_io_buffer = (wxUint8 *)buffer; 175 m_current_b_pos = 0; 176 177 // Decode the datas 178 while (countdown != 0) { 179 *linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state); 180 countdown--; 181 } 182 m_lastcount = len; 183 184 // Send them to the sound card 185 m_router->Write(old_linear, real_len); 186 187 // Destroy the temporary buffer 188 delete[] old_linear; 189 190 return *m_router; 191} 192 193bool wxSoundStreamG72X::SetSoundFormat(const wxSoundFormatBase& format) 194{ 195 if (format.GetType() != wxSOUND_G72X) { 196 m_snderror = wxSOUND_INVFRMT; 197 return false; 198 } 199 200 wxSoundFormatPcm pcm; 201 wxSoundFormatG72X *g72x; 202 203 wxSoundStreamCodec::SetSoundFormat(format); 204 205 g72x = (wxSoundFormatG72X *)m_sndformat; 206 207 // Set PCM as the output format of the codec 208 pcm.SetSampleRate(g72x->GetSampleRate()); 209 pcm.SetBPS(16); 210 pcm.SetChannels(1); // Only mono supported 211 pcm.Signed(true); 212 pcm.SetOrder(wxBYTE_ORDER); 213 214 // Look for the correct codec to use and set its bit width 215 switch (g72x->GetG72XType()) { 216 case wxSOUND_G721: 217 m_n_bits = 4; 218 m_coder = g721_encoder; 219 m_decoder = g721_decoder; 220 break; 221 case wxSOUND_G723_24: 222 m_n_bits = 3; 223 m_coder = g723_24_encoder; 224 m_decoder = g723_24_decoder; 225 break; 226 case wxSOUND_G723_40: 227 m_n_bits = 5; 228 m_coder = g723_40_encoder; 229 m_decoder = g723_40_decoder; 230 break; 231 } 232 233 // Let the router finish the work 234 m_router->SetSoundFormat(pcm); 235 236 return true; 237} 238 239#define BYTE_SIZE 8 240 241wxUint8 wxSoundStreamG72X::GetBits() 242{ 243 register wxUint8 bits; 244 245 // We have two bytes to compute 246 if (m_current_b_pos < m_n_bits) { 247 register wxUint8 b_left; 248 249 // TRANSLATE the mask 250 m_current_mask >>= m_current_b_pos; 251 252 // GET the last bits: 0001..1 253 bits = (m_current_byte & m_current_mask) << (m_n_bits - m_current_b_pos); 254 255 // GEN: 1. n times .1000 256 b_left = BYTE_SIZE-m_n_bits; 257 m_current_mask = ((1 << m_n_bits) - 1) << b_left; 258 259 // GET the next byte 260 m_current_byte = *m_io_buffer++; 261 262 register wxUint8 tmp_mask; 263 264 // COMPUTE a new temporary mask to get the last bits 265 b_left = m_n_bits - b_left; 266 tmp_mask = (1 << b_left) - 1; 267 // TRANSLATE the old mask to get ready for the next time 268 m_current_mask >>= b_left; 269 270 // COMPUTE the new bit position 271 b_left = BYTE_SIZE - b_left; 272 m_current_b_pos = b_left; 273 tmp_mask <<= b_left; 274 275 // GET the last bits 276 bits |= (m_current_byte & tmp_mask) >> b_left; 277 } else { 278 m_current_mask >>= m_n_bits; 279 m_current_b_pos -= m_n_bits; 280 bits = (m_current_byte & m_current_mask) >> m_current_b_pos; 281 } 282 return bits; 283} 284 285void wxSoundStreamG72X::PutBits(wxUint8 bits) 286{ 287 if (m_current_b_pos < m_n_bits) { 288 register wxUint8 tmp_mask; 289 register wxUint8 diff; 290 291 diff = m_n_bits - m_current_b_pos; 292 // Pack bits and put the byte in the buffer 293 m_current_byte |= bits >> diff; 294 *m_io_buffer++ = m_current_byte; 295 296 // Gen a mask 297 tmp_mask = ~((1 << diff) - 1); 298 299 m_current_b_pos = BYTE_SIZE - (m_n_bits - m_current_b_pos); 300 301 m_current_byte = (bits & (tmp_mask)) << m_current_b_pos; 302 } else { 303 m_current_b_pos -= m_n_bits; 304 bits <<= m_current_b_pos; 305 m_current_byte |= bits; 306 } 307} 308