]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndcpcm.cpp
Moved wxMMedia to contrib/src/mmedia
[wxWidgets.git] / utils / wxMMedia2 / lib / sndcpcm.cpp
CommitLineData
526ddb13
GL
1// --------------------------------------------------------------------------
2// Name: sndcpcm.cpp
3// Purpose:
4// Date: 08/11/1999
ef366f35 5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
526ddb13
GL
6// CVSID: $Id$
7// --------------------------------------------------------------------------
8#ifdef __GNUG__
9#pragma implementation "sndcpcm.cpp"
10#endif
6c5e6376 11#include <wx/wxprec.h>
8b33ae2d
GL
12
13#ifndef WX_PRECOMP
14#include <wx/debug.h>
15#include <wx/log.h>
16#endif
17
526ddb13
GL
18#include "sndbase.h"
19#include "sndpcm.h"
20#include "sndcpcm.h"
21
22wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio)
8b33ae2d 23 : wxSoundStreamCodec(sndio)
526ddb13 24{
8b33ae2d
GL
25 m_function_in = NULL;
26 m_function_out = NULL;
27 m_prebuffer = NULL;
28 m_prebuffer_size = 0;
29 m_best_size = 0;
526ddb13
GL
30}
31
32wxSoundStreamPcm::~wxSoundStreamPcm()
33{
8b33ae2d
GL
34 if (m_prebuffer)
35 delete[] m_prebuffer;
526ddb13
GL
36}
37
8b33ae2d
GL
38wxUint32 wxSoundStreamPcm::GetBestSize() const
39{
40 return m_best_size;
41}
526ddb13 42
526ddb13 43#include "converter.def"
526ddb13 44
a31c84f3
GL
45// -----------------------------------------------------------------------
46// Main PCM stream converter table
47// -----------------------------------------------------------------------
8b33ae2d
GL
48// Definition
49// XX -> YY
50// XX -> YY sign
51//
52// XX swapped -> YY
53// XX swapped -> YY sign
54//
55// XX swapped -> YY swapped
56// XX swapped -> YY swapped sign
57//
58// XX stereo -> YY mono
59// XX stereo -> YY mono sign
60//
61// XX swapped stereo -> YY swapped mono
62// XX swapped stereo -> YY swapped mono sign
63//
64// XX swapped stereo -> YY swapped mono
65// XX swapped stereo -> YY swapped mono sign
66
67static wxSoundStreamPcm::ConverterType s_converters[4][3][2] = {
68 {
69 {
70 NULL,
71 Convert_8_8_sign /* 8 -> 8 sign */
72 },
73 {
74 NULL,
75 NULL
76 },
77 {
78 NULL,
79 NULL
80 }
81 },
82 {
83 {
84 Convert_8_16, /* 8 -> 16 */
85 Convert_8_16_sign /* 8 -> 16 sign */
86 },
87 {
88 Convert_8_16_swap, /* 8 -> 16 swapped */
89 Convert_8_16_sign_swap /* 8 -> 16 sign swapped */
90 },
91 {
92 NULL,
93 NULL
94 }
95 },
96 {
97 {
98 Convert_16_8, /* 16 -> 8 */
99 Convert_16_8_sign /* 16 -> 8 sign */
100 },
101 {
102 Convert_16_swap_8, /* 16 swapped -> 8 */
103 Convert_16_swap_8_sign /* 16 swapped -> 8 sign */
104 },
105 {
106 NULL,
107 NULL
108 },
109 },
110
111 {
112 {
113 NULL, /* 16 -> 16 */
114 Convert_16_sign /* 16 -> 16 sign */
115 },
116 {
117 Convert_16_swap, /* 16 swapped -> 16 */
118 Convert_16_swap_16_sign /* 16 swapped -> 16 sign */
119 },
120 {
121 NULL,
122 Convert_16_swap_16_sign_swap /* 16 swapped -> 16 sign swapped */
123 }
124 }
ef366f35 125};
0662cd32 126
8b33ae2d
GL
127// This is the buffer size multiplier. It gives the needed size of the output size.
128static float s_converters_multip[] = {1, 2, 0.5, 1};
56dc1ffd
GL
129
130//
131// TODO: Read() and Write() aren't really safe. If you give it a buffer which
a31c84f3 132// is not aligned on 2, you may crash (See converter.def).
56dc1ffd 133//
526ddb13 134
0662cd32 135wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len)
526ddb13 136{
8b33ae2d
GL
137 wxUint32 in_bufsize;
138
139 // We must have a multiple of 2
140 len &= 0x01;
141
142 if (!m_function_in) {
143 m_sndio->Read(buffer, len);
144 m_lastcount = m_sndio->GetLastAccess();
145 m_snderror = m_sndio->GetError();
146 return *this;
147 }
0662cd32 148
8b33ae2d
GL
149 in_bufsize = GetReadSize(len);
150
151 if (len <= m_best_size) {
152 m_sndio->Read(m_prebuffer, in_bufsize);
153 m_snderror = m_sndio->GetError();
154 if (m_snderror != wxSOUND_NOERROR) {
155 m_lastcount = 0;
156 return *this;
157 }
158
159 m_function_in(m_prebuffer, buffer, m_sndio->GetLastAccess());
160 } else {
161 char *temp_buffer;
162
163 temp_buffer = new char[in_bufsize];
164 m_sndio->Read(temp_buffer, in_bufsize);
165
166 m_snderror = m_sndio->GetError();
167 if (m_snderror != wxSOUND_NOERROR) {
168 m_lastcount = 0;
169 return *this;
170 }
171
172 m_function_in(temp_buffer, buffer, m_sndio->GetLastAccess());
173
174 delete[] temp_buffer;
175 }
176
177 m_lastcount = (wxUint32)(m_sndio->GetLastAccess() * m_multiplier_in);
178
0662cd32 179 return *this;
526ddb13
GL
180}
181
0662cd32 182wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len)
526ddb13 183{
8b33ae2d
GL
184 wxUint32 out_bufsize;
185
186 if (!m_function_out) {
187 m_sndio->Write(buffer, len);
188 m_lastcount = m_sndio->GetLastAccess();
189 m_snderror = m_sndio->GetError();
190 return *this;
191 }
526ddb13 192
8b33ae2d 193 out_bufsize = GetWriteSize(len);
526ddb13 194
8b33ae2d
GL
195 if (len <= m_best_size) {
196 out_bufsize = GetWriteSize(len);
526ddb13 197
8b33ae2d
GL
198 m_function_out(buffer, m_prebuffer, len);
199 m_sndio->Write(m_prebuffer, out_bufsize);
200 m_snderror = m_sndio->GetError();
201 if (m_snderror != wxSOUND_NOERROR) {
202 m_lastcount = 0;
203 return *this;
204 }
205 } else {
206 char *temp_buffer;
207
208 temp_buffer = new char[out_bufsize];
209 m_function_out(buffer, temp_buffer, len);
210
211 m_sndio->Write(temp_buffer, out_bufsize);
212 m_snderror = m_sndio->GetError();
213 if (m_snderror != wxSOUND_NOERROR) {
214 m_lastcount = 0;
215 return *this;
216 }
217
218 delete[] temp_buffer;
219 }
526ddb13 220
8b33ae2d 221 m_lastcount = (wxUint32)(m_sndio->GetLastAccess() / m_multiplier_out);
526ddb13 222
8b33ae2d 223 return *this;
526ddb13
GL
224}
225
226bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format)
227{
8b33ae2d
GL
228 wxSoundFormatBase *new_format;
229 wxSoundFormatPcm *pcm_format, *pcm_format2;
230
231 if (m_sndio->SetSoundFormat(format)) {
232 m_function_out = NULL;
233 m_function_in = NULL;
234 return TRUE;
ef366f35 235 }
8b33ae2d
GL
236 if (format.GetType() != wxSOUND_PCM) {
237 m_snderror = wxSOUND_INVFRMT;
238 return FALSE;
239 }
240 if (m_sndformat)
241 delete m_sndformat;
242
243 new_format = m_sndio->GetSoundFormat().Clone();
244 pcm_format = (wxSoundFormatPcm *)&format;
245 pcm_format2 = (wxSoundFormatPcm *)new_format;
246
247#if 0
248 // ----------------------------------------------------
249 // Test whether we need to resample
250 if (pcm_format->GetSampleRate() != pcm_format2->GetSampleRate()) {
251 wxUint32 src_rate, dst_rate;
252
253 src_rate = pcm_format->GetSampleRate();
254 dst_rate = pcm_format2->GetSampleRate();
255 m_needResampling = TRUE;
256 if (src_rate < dst_rate)
257 m_expandSamples = TRUE;
258 else
259 m_expandSamples = FALSE;
260 m_pitch = (src_rate << FLOATBITS) / dst_rate;
261 }
262#endif
263 // ----------------------------------------------------
264 // Select table to use:
265 // * 8 bits -> 8 bits
266 // * 16 bits -> 8 bits
267 // * 8 bits -> 16 bits
268 // * 16 bits -> 16 bits
269
270 int table_no, table_no2;
271 int i_sign, i_swap;
272
273 switch (pcm_format->GetBPS()) {
274 case 8:
275 table_no = 0;
276 break;
277 case 16:
278 table_no = 1;
279 break;
280 }
281 switch (pcm_format2->GetBPS()) {
282 case 8:
283 table_no2 = 0;
284 break;
285 case 16:
286 table_no2 = 1;
287 break;
288 }
289
290 if (pcm_format2->Signed() != pcm_format->Signed())
291 i_sign = 1;
292 else
293 i_sign = 0;
526ddb13
GL
294
295#define MY_ORDER wxBYTE_ORDER
296#if wxBYTE_ORDER == wxLITTLE_ENDIAN
297#define OTHER_ORDER wxBIG_ENDIAN
298#else
299#define OTHER_ORDER wxLITTLE_ENDIAN
300#endif
301
8b33ae2d
GL
302 // --------------------------------------------------------
303 // Find the good converter !
a31c84f3 304
8b33ae2d
GL
305 if (pcm_format->GetOrder() == OTHER_ORDER) {
306 if (pcm_format->GetOrder() == pcm_format2->GetOrder())
307 i_swap = 2;
308 else
309 i_swap = 1;
310 } else {
311 if (pcm_format->GetOrder() == pcm_format2->GetOrder())
312 i_swap = 0;
313 else
314 i_swap = 1;
315 }
a31c84f3 316
8b33ae2d
GL
317 m_function_out = s_converters[table_no*2+table_no2][i_swap][i_sign];
318 m_function_in = s_converters[table_no2*2+table_no][i_swap][i_sign];
319 m_multiplier_out = s_converters_multip[table_no*2+table_no2];
320 m_multiplier_in = s_converters_multip[table_no2*2+table_no2];
526ddb13 321
8b33ae2d
GL
322 if (m_prebuffer)
323 delete[] m_prebuffer;
526ddb13 324
8b33ae2d
GL
325 // We try to minimize the need of dynamic memory allocation by preallocating a buffer. But
326 // to be sure it will be efficient we minimize the best size.
327 if (m_multiplier_in < m_multiplier_out) {
328 m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_out);
329 m_best_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_in);
330 } else {
331 m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_in);
332 m_best_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_out);
333 }
334
335 m_prebuffer = new char[m_prebuffer_size];
336
337 bool SetSoundFormatReturn;
338
339 SetSoundFormatReturn = m_sndio->SetSoundFormat(*new_format);
340 wxASSERT( SetSoundFormatReturn );
341
342 m_sndformat = new_format;
343 return TRUE;
344}
ef366f35 345
8b33ae2d
GL
346wxUint32 wxSoundStreamPcm::GetWriteSize(wxUint32 len) const
347{
348 // For the moment, it is simple but next time it will become more complicated
349 // (Resampling)
350 return (wxUint32)(len * m_multiplier_out);
351}
526ddb13 352
8b33ae2d
GL
353wxUint32 wxSoundStreamPcm::GetReadSize(wxUint32 len) const
354{
355 return (wxUint32)(len / m_multiplier_in);
356}
357
358// Resampling engine. NOT FINISHED and NOT INCLUDED but this is a first DRAFT.
526ddb13 359
8b33ae2d 360#if 0
526ddb13 361
8b33ae2d
GL
362#define FLOATBITS 16
363#define INTBITS 16
364#define FLOATMASK 0xffff
365#define INTMASK 0xffff0000
526ddb13 366
8b33ae2d
GL
367void ResamplingShrink_##DEPTH##(const void *source, void *destination, wxUint32 len)
368{
369 wxUint##DEPTH## *source_data, *dest_data;
370 wxUint32 pos;
371
372 source_data = (wxUint##DEPTH## *)source;
373 dest_data = (wxUint##DEPTH## *)destination;
374
375 pos = m_saved_pos;
376 while (len > 0) {
377 // Increment the position in the input buffer
378 pos += m_pitch;
379 if (pos & INTMASK) {
380 pos &= FLOATMASK;
381
382 *dest_data ++ = *source_data;
383 }
384 len--;
385 source_data++;
386 }
387 m_saved_pos = pos;
526ddb13 388}
8b33ae2d 389#endif