]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndcpcm.cpp
Ok. Vidwin works again on Windows.
[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
11
6c5e6376 12#include <wx/wxprec.h>
526ddb13
GL
13#include "sndbase.h"
14#include "sndpcm.h"
15#include "sndcpcm.h"
16
17wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio)
18 : wxSoundStreamCodec(sndio)
19{
20 m_function_in = NULL;
21 m_function_out = NULL;
22}
23
24wxSoundStreamPcm::~wxSoundStreamPcm()
25{
26}
27
28
526ddb13 29#include "converter.def"
526ddb13 30
a31c84f3
GL
31// -----------------------------------------------------------------------
32// Main PCM stream converter table
33// -----------------------------------------------------------------------
ef366f35
GL
34wxSoundStreamPcm::ConverterType s_converters[] = {
35 NULL,
36 Convert_8_8_sign, /* 8 -> 8 sign */
37 NULL,
526ddb13
GL
38 NULL,
39 NULL,
526ddb13 40 NULL,
526ddb13 41
ef366f35
GL
42 Convert_8_16, /* 8 -> 16 */
43 Convert_8_16_sign, /* 8 -> 16 sign */
44 Convert_8_16_swap, /* 8 -> 16 swapped */
45 Convert_8_16_sign_swap, /* 8 -> 16 sign swapped */
46 NULL,
526ddb13 47 NULL,
526ddb13 48
ef366f35
GL
49 Convert_16_8, /* 16 -> 8 */
50 Convert_16_8_sign, /* 16 -> 8 sign */
51 Convert_16_swap_8, /* 16 swapped -> 8 */
52 Convert_16_swap_8_sign, /* 16 swapped -> 8 sign */
0662cd32
GL
53 NULL,
54 NULL,
0662cd32 55
ef366f35
GL
56 NULL, /* 16 -> 16 */
57 Convert_16_sign, /* 16 -> 16 sign */
58 Convert_16_swap, /* 16 swapped -> 16 */
59 Convert_16_swap_16_sign, /* 16 swapped -> 16 sign */
60 Convert_16_sign_16_swap, /* 16 sign -> 16 swapped */
61 Convert_16_swap_16_sign_swap /* 16 swapped -> 16 sign swapped */
62};
0662cd32 63
ef366f35
GL
64#define CONVERT_BPS 0
65#define CONVERT_SIGN 1
66#define CONVERT_SWAP 2
67#define CONVERT_SIGN_SWAP 3
68#define CONVERT_SWAP_SIGN 4
69#define CONVERT_SWAP_SIGN_SWAP 5
0662cd32 70
ef366f35
GL
71#define CONVERT_BASE_8_8 0
72#define CONVERT_BASE_8_16 6
73#define CONVERT_BASE_16_8 12
74#define CONVERT_BASE_16_16 18
56dc1ffd
GL
75
76//
77// TODO: Read() and Write() aren't really safe. If you give it a buffer which
a31c84f3 78// is not aligned on 2, you may crash (See converter.def).
56dc1ffd 79//
526ddb13 80
0662cd32 81wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len)
526ddb13 82{
0662cd32
GL
83 wxUint32 real_len;
84 char *tmp_buf;
85
526ddb13
GL
86 if (!m_function_in) {
87 m_sndio->Read(buffer, len);
88 m_lastcount = m_sndio->GetLastAccess();
89 m_snderror = m_sndio->GetError();
90 return *this;
91 }
92
0662cd32
GL
93 real_len = (m_16_to_8) ? len / 2 : len;
94
95 tmp_buf = new char[real_len];
96
97 m_sndio->Read(tmp_buf, real_len);
526ddb13
GL
98 m_lastcount = m_sndio->GetLastAccess();
99 m_snderror = m_sndio->GetError();
0662cd32
GL
100 if (m_snderror != wxSOUND_NOERR)
101 return *this;
102
103 m_function_in(tmp_buf, (char *)buffer, m_lastcount);
104
105 delete[] tmp_buf;
106
107 if (m_16_to_8)
108 m_lastcount *= 2;
109
526ddb13
GL
110 return *this;
111}
112
0662cd32 113wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len)
526ddb13
GL
114{
115 char *tmp_buf;
0662cd32 116 wxUint32 len2;
526ddb13
GL
117
118 if (!m_function_out)
119 return m_sndio->Write(buffer, len);
120
121 len2 = (m_16_to_8) ? len / 2 : len;
122
123 tmp_buf = new char[len2];
5bee458a 124 m_function_out((const char *)buffer, tmp_buf, len2);
526ddb13
GL
125 m_sndio->Write(tmp_buf, len);
126 delete[] tmp_buf;
127
128 m_lastcount = (m_16_to_8) ?
129 (m_sndio->GetLastAccess() * 2) : m_sndio->GetLastAccess();
130
131 return *this;
132}
133
134bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format)
135{
136 wxSoundFormatBase *new_format;
137 wxSoundFormatPcm *pcm_format, *pcm_format2;
0662cd32 138 ConverterType *current_table_out, *current_table_in;
526ddb13
GL
139 int index;
140 bool change_sign;
141
142 if (m_sndio->SetSoundFormat(format)) {
143 m_function_out = NULL;
144 m_function_in = NULL;
145 return TRUE;
146 }
147 if (format.GetType() != wxSOUND_PCM) {
148 m_snderror = wxSOUND_INVFRMT;
149 return FALSE;
150 }
151 if (m_sndformat)
152 delete m_sndformat;
153
154 new_format = m_sndio->GetSoundFormat().Clone();
155 pcm_format = (wxSoundFormatPcm *)&format;
156 pcm_format2 = (wxSoundFormatPcm *)new_format;
157
a31c84f3
GL
158 // ----------------------------------------------------
159 // Select table to use:
160 // * 8 bits -> 8 bits
161 // * 16 bits -> 8 bits
162 // * 8 bits -> 16 bits
163 // * 16 bits -> 16 bits
164
526ddb13 165 m_16_to_8 = FALSE;
aa95f52e 166 if (pcm_format->GetBPS() != pcm_format2->GetBPS()) {
526ddb13 167 m_16_to_8 = TRUE;
ef366f35
GL
168 if (pcm_format2->GetBPS() == 8) {
169 current_table_out = &s_converters[CONVERT_BASE_16_8];
170 current_table_in = &s_converters[CONVERT_BASE_8_16];
171 } else {
172 current_table_out = &s_converters[CONVERT_BASE_8_16];
173 current_table_in = &s_converters[CONVERT_BASE_16_8];
174 }
0662cd32 175 } else if (pcm_format->GetBPS() == 16) {
ef366f35
GL
176 current_table_out = &s_converters[CONVERT_BASE_16_16];
177 current_table_in = &s_converters[CONVERT_BASE_16_16];
0662cd32 178 } else {
ef366f35
GL
179 current_table_out = &s_converters[CONVERT_BASE_8_8];
180 current_table_in = &s_converters[CONVERT_BASE_8_8];
0662cd32 181 }
526ddb13
GL
182
183 change_sign = (pcm_format2->Signed() != pcm_format->Signed());
184
185#define MY_ORDER wxBYTE_ORDER
186#if wxBYTE_ORDER == wxLITTLE_ENDIAN
187#define OTHER_ORDER wxBIG_ENDIAN
188#else
189#define OTHER_ORDER wxLITTLE_ENDIAN
190#endif
191
a31c84f3
GL
192 // --------------------------------------------------------
193 // Find the good converter !
194
195
526ddb13
GL
196 if (pcm_format->GetOrder() == OTHER_ORDER &&
197 pcm_format2->GetOrder() == OTHER_ORDER && change_sign)
ef366f35 198 index = CONVERT_SWAP_SIGN_SWAP;
526ddb13
GL
199
200 else if (pcm_format->GetOrder() == OTHER_ORDER &&
201 pcm_format2->GetOrder() == MY_ORDER && change_sign)
ef366f35 202 index = CONVERT_SWAP_SIGN;
526ddb13
GL
203
204 else if (pcm_format->GetOrder() == MY_ORDER &&
205 pcm_format->GetOrder() == OTHER_ORDER && change_sign)
ef366f35
GL
206 index = CONVERT_SIGN_SWAP;
207
208 else if (change_sign)
209 index = CONVERT_SIGN;
526ddb13
GL
210
211 else if (!change_sign &&
212 pcm_format->GetOrder() != pcm_format2->GetOrder())
ef366f35 213 index = CONVERT_SWAP;
526ddb13
GL
214
215 else
ef366f35 216 index = CONVERT_BPS;
526ddb13 217
0662cd32
GL
218 m_function_out = current_table_out[index];
219 m_function_in = current_table_in[index];
526ddb13
GL
220
221 m_sndio->SetSoundFormat(*new_format);
222 m_sndformat = new_format;
223 return TRUE;
224}