]>
Commit | Line | Data |
---|---|---|
0662cd32 | 1 | // -------------------------------------------------------------------------- |
aa95f52e | 2 | // Name: sndg72x.cpp |
0662cd32 | 3 | // Purpose: |
aa95f52e | 4 | // Date: 08/26/1999 |
0662cd32 GL |
5 | // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999 |
6 | // CVSID: $Id$ | |
7 | // -------------------------------------------------------------------------- | |
8 | #ifdef __GNUG__ | |
aa95f52e | 9 | #pragma implementation "sndg72x.cpp" |
0662cd32 GL |
10 | #endif |
11 | ||
12 | #include <wx/wxprec.h> | |
13 | #include "sndbase.h" | |
14 | #include "sndfile.h" | |
15 | #include "sndpcm.h" | |
0662cd32 GL |
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 | return *this; | |
127 | } | |
128 | ||
129 | wxSoundStream& wxSoundStreamG72X::Write(const void *buffer, wxUint32 len) | |
130 | { | |
131 | wxUint16 *old_linear; | |
132 | register wxUint16 *linear_buffer; | |
133 | register wxUint32 countdown = len; | |
134 | register wxUint32 real_len; | |
135 | ||
136 | real_len = (wxUint32)(len * ((float)m_n_bits / 8)); | |
137 | ||
138 | old_linear = linear_buffer = new wxUint16[real_len]; | |
139 | ||
140 | // Bad, we override the const | |
141 | m_io_buffer = (wxUint8 *)buffer; | |
142 | m_current_b_pos = 0; | |
143 | ||
144 | while (countdown != 0) { | |
145 | *linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state); | |
146 | countdown--; | |
147 | } | |
148 | m_lastcount = len; | |
149 | ||
150 | m_router->Write(old_linear, real_len); | |
151 | ||
152 | delete[] old_linear; | |
153 | ||
154 | return *m_router; | |
155 | } | |
156 | ||
157 | bool wxSoundStreamG72X::SetSoundFormat(const wxSoundFormatBase& format) | |
158 | { | |
159 | if (format.GetType() != wxSOUND_G72X) { | |
160 | m_snderror = wxSOUND_INVFRMT; | |
161 | return FALSE; | |
162 | } | |
163 | ||
164 | wxSoundFormatPcm pcm; | |
165 | wxSoundFormatG72X *g72x; | |
166 | ||
167 | wxSoundStreamCodec::SetSoundFormat(format); | |
168 | ||
169 | g72x = (wxSoundFormatG72X *)m_sndformat; | |
170 | ||
171 | pcm.SetSampleRate(g72x->GetSampleRate()); | |
172 | pcm.SetBPS(16); | |
173 | pcm.SetChannels(1); | |
174 | pcm.Signed(TRUE); | |
175 | pcm.SetOrder(wxBYTE_ORDER); | |
176 | ||
177 | switch (g72x->GetG72XType()) { | |
178 | case wxSOUND_G721: | |
179 | m_n_bits = 4; | |
180 | m_coder = g721_encoder; | |
181 | m_decoder = g721_decoder; | |
182 | break; | |
183 | case wxSOUND_G723_24: | |
184 | m_n_bits = 3; | |
185 | m_coder = g723_24_encoder; | |
186 | m_decoder = g723_24_decoder; | |
187 | break; | |
188 | case wxSOUND_G723_40: | |
189 | m_n_bits = 5; | |
190 | m_coder = g723_40_encoder; | |
191 | m_decoder = g723_40_decoder; | |
192 | break; | |
193 | } | |
194 | ||
195 | m_router->SetSoundFormat(pcm); | |
196 | ||
197 | return TRUE; | |
198 | } | |
199 | ||
200 | #define BYTE_SIZE 8 | |
201 | ||
202 | wxUint8 wxSoundStreamG72X::GetBits() | |
203 | { | |
204 | register wxUint8 bits; | |
205 | ||
206 | if (m_current_b_pos < m_n_bits) { | |
207 | register wxUint8 b_left; | |
208 | ||
209 | // TRANSLATE the mask | |
210 | m_current_mask >>= m_current_b_pos; | |
211 | ||
212 | // GET the last bits: 0001..1 | |
213 | bits = (m_current_byte & m_current_mask) << (m_n_bits - m_current_b_pos); | |
214 | ||
215 | // GEN: 1. n times .1000 | |
216 | b_left = BYTE_SIZE-m_n_bits; | |
217 | m_current_mask = ((1 << m_n_bits) - 1) << b_left; | |
218 | ||
219 | // GET the next byte | |
220 | m_current_byte = *m_io_buffer++; | |
221 | ||
222 | register wxUint8 tmp_mask; | |
223 | ||
224 | // COMPUTE a new temporary mask to get the last bits | |
225 | b_left = m_n_bits - b_left; | |
226 | tmp_mask = (1 << b_left) - 1; | |
227 | // TRANSLATE the old mask to get ready for the next time | |
228 | m_current_mask >>= b_left; | |
229 | ||
230 | // COMPUTE the new bit position | |
231 | b_left = BYTE_SIZE - b_left; | |
232 | m_current_b_pos = b_left; | |
233 | tmp_mask <<= b_left; | |
234 | ||
235 | // GET the last bits | |
236 | bits |= (m_current_byte & tmp_mask) >> b_left; | |
237 | } else { | |
238 | m_current_mask >>= m_n_bits; | |
239 | m_current_b_pos -= m_n_bits; | |
240 | bits = (m_current_byte & m_current_mask) >> m_current_b_pos; | |
241 | } | |
242 | return bits; | |
243 | } | |
244 | ||
245 | void wxSoundStreamG72X::PutBits(wxUint8 bits) | |
246 | { | |
247 | if (m_current_b_pos < m_n_bits) { | |
248 | register wxUint8 tmp_mask; | |
249 | register wxUint8 diff; | |
250 | ||
251 | diff = m_n_bits - m_current_b_pos; | |
252 | // Pack bits and put the byte in the buffer | |
253 | m_current_byte |= bits >> diff; | |
254 | *m_io_buffer++ = m_current_byte; | |
255 | ||
256 | // Gen a mask | |
257 | tmp_mask = ~((1 << diff) - 1); | |
258 | ||
259 | m_current_b_pos = BYTE_SIZE - (m_n_bits - m_current_b_pos); | |
260 | ||
261 | m_current_byte = (bits & (tmp_mask)) << m_current_b_pos; | |
262 | } else { | |
263 | m_current_b_pos -= m_n_bits; | |
264 | bits <<= m_current_b_pos; | |
265 | m_current_byte |= bits; | |
266 | } | |
267 | } |