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