]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/mmedia/sndg72x.cpp
GetBestFittingSize --> GetEffectiveMinSize
[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
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
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)
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
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;
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
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 }