]>
Commit | Line | Data |
---|---|---|
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 | ||
17 | wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio) | |
18 | : wxSoundStreamCodec(sndio) | |
19 | { | |
20 | m_function_in = NULL; | |
21 | m_function_out = NULL; | |
22 | } | |
23 | ||
24 | wxSoundStreamPcm::~wxSoundStreamPcm() | |
25 | { | |
26 | } | |
27 | ||
28 | ||
526ddb13 | 29 | #include "converter.def" |
526ddb13 | 30 | |
a31c84f3 GL |
31 | // ----------------------------------------------------------------------- |
32 | // Main PCM stream converter table | |
33 | // ----------------------------------------------------------------------- | |
ef366f35 GL |
34 | wxSoundStreamPcm::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 | 81 | wxSoundStream& 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 | 113 | wxSoundStream& 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 | ||
134 | bool 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 | } |