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