]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia2/lib/sndcpcm.cpp
* Added IsPaused() to wxSoundFileStream
[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 // -----------------------------------------------------------------------
32 // Main PCM stream converter table
33 // -----------------------------------------------------------------------
34 wxSoundStreamPcm::ConverterType s_converters[] = {
35 NULL,
36 Convert_8_8_sign, /* 8 -> 8 sign */
37 NULL,
38 NULL,
39 NULL,
40 NULL,
41
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,
47 NULL,
48
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 */
53 NULL,
54 NULL,
55
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 };
63
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
70
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
75
76 //
77 // TODO: Read() and Write() aren't really safe. If you give it a buffer which
78 // is not aligned on 2, you may crash (See converter.def).
79 //
80
81 wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len)
82 {
83 wxUint32 real_len;
84 char *tmp_buf;
85
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
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);
98 m_lastcount = m_sndio->GetLastAccess();
99 m_snderror = m_sndio->GetError();
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
110 return *this;
111 }
112
113 wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len)
114 {
115 char *tmp_buf;
116 wxUint32 len2;
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];
124 m_function_out((const char *)buffer, tmp_buf, len2);
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;
138 ConverterType *current_table_out, *current_table_in;
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
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
165 m_16_to_8 = FALSE;
166 if (pcm_format->GetBPS() != pcm_format2->GetBPS()) {
167 m_16_to_8 = TRUE;
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 }
175 } else if (pcm_format->GetBPS() == 16) {
176 current_table_out = &s_converters[CONVERT_BASE_16_16];
177 current_table_in = &s_converters[CONVERT_BASE_16_16];
178 } else {
179 current_table_out = &s_converters[CONVERT_BASE_8_8];
180 current_table_in = &s_converters[CONVERT_BASE_8_8];
181 }
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
192 // --------------------------------------------------------
193 // Find the good converter !
194
195
196 if (pcm_format->GetOrder() == OTHER_ORDER &&
197 pcm_format2->GetOrder() == OTHER_ORDER && change_sign)
198 index = CONVERT_SWAP_SIGN_SWAP;
199
200 else if (pcm_format->GetOrder() == OTHER_ORDER &&
201 pcm_format2->GetOrder() == MY_ORDER && change_sign)
202 index = CONVERT_SWAP_SIGN;
203
204 else if (pcm_format->GetOrder() == MY_ORDER &&
205 pcm_format->GetOrder() == OTHER_ORDER && change_sign)
206 index = CONVERT_SIGN_SWAP;
207
208 else if (change_sign)
209 index = CONVERT_SIGN;
210
211 else if (!change_sign &&
212 pcm_format->GetOrder() != pcm_format2->GetOrder())
213 index = CONVERT_SWAP;
214
215 else
216 index = CONVERT_BPS;
217
218 m_function_out = current_table_out[index];
219 m_function_in = current_table_in[index];
220
221 m_sndio->SetSoundFormat(*new_format);
222 m_sndformat = new_format;
223 return TRUE;
224 }