]>
Commit | Line | Data |
---|---|---|
e8482f24 GL |
1 | // -------------------------------------------------------------------------- |
2 | // Name: sndg72x.cpp | |
3 | // Purpose: | |
4 | // Date: 08/26/1999 | |
5 | // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999 | |
6 | // CVSID: $Id$ | |
58b9c9ba | 7 | // wxWindows licence |
e8482f24 | 8 | // -------------------------------------------------------------------------- |
e8482f24 | 9 | |
92a19c2e | 10 | #include "wx/wxprec.h" |
e8482f24 GL |
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 | ||
26 | wxSoundFormatG72X::wxSoundFormatG72X() | |
27 | : m_srate(22050) | |
28 | { | |
29 | } | |
30 | ||
31 | wxSoundFormatG72X::~wxSoundFormatG72X() | |
32 | { | |
33 | } | |
34 | ||
35 | void wxSoundFormatG72X::SetSampleRate(wxUint32 srate) | |
36 | { | |
37 | m_srate = srate; | |
38 | } | |
39 | ||
40 | wxUint32 wxSoundFormatG72X::GetSampleRate() const | |
41 | { | |
42 | return m_srate; | |
43 | } | |
44 | ||
45 | void wxSoundFormatG72X::SetG72XType(wxSoundG72XType type) | |
46 | { | |
47 | m_g72x_type = type; | |
48 | } | |
49 | ||
50 | wxSoundFormatBase *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 | ||
59 | wxUint32 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 | ||
80 | wxUint32 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 | ||
100 | bool wxSoundFormatG72X::operator !=(const wxSoundFormatBase& frmt2) const | |
101 | { | |
102 | wxSoundFormatG72X *g72x = (wxSoundFormatG72X *)&frmt2; | |
103 | ||
104 | if (frmt2.GetType() != wxSOUND_G72X) | |
dea7e44a | 105 | return true; |
e8482f24 GL |
106 | |
107 | return (g72x->m_srate != m_srate || g72x->m_g72x_type != m_g72x_type); | |
108 | } | |
109 | ||
110 | // -------------------------------------------------------------------------- | |
111 | // wxSoundStreamG72X | |
112 | // -------------------------------------------------------------------------- | |
113 | ||
114 | wxSoundStreamG72X::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 | ||
123 | wxSoundStreamG72X::~wxSoundStreamG72X() | |
124 | { | |
125 | delete m_router; | |
126 | } | |
127 | ||
128 | wxSoundStream& 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 | ||
160 | wxSoundStream& 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 | ||
193 | bool wxSoundStreamG72X::SetSoundFormat(const wxSoundFormatBase& format) | |
194 | { | |
195 | if (format.GetType() != wxSOUND_G72X) { | |
196 | m_snderror = wxSOUND_INVFRMT; | |
dea7e44a | 197 | return false; |
e8482f24 GL |
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 | |
dea7e44a | 211 | pcm.Signed(true); |
e8482f24 GL |
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 | ||
dea7e44a | 236 | return true; |
e8482f24 GL |
237 | } |
238 | ||
239 | #define BYTE_SIZE 8 | |
240 | ||
241 | wxUint8 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 | ||
285 | void 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 | } |