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