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