1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
7 // --------------------------------------------------------------------------
9 #pragma implementation "sndcpcm.cpp"
12 #include <wx/wxprec.h>
17 wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream
& sndio
)
18 : wxSoundStreamCodec(sndio
)
21 m_function_out
= NULL
;
24 wxSoundStreamPcm::~wxSoundStreamPcm()
29 #include "converter.def"
31 // -----------------------------------------------------------------------
32 // Main PCM stream converter table
33 // -----------------------------------------------------------------------
34 wxSoundStreamPcm::ConverterType s_converters
[] = {
36 Convert_8_8_sign
, /* 8 -> 8 sign */
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 */
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 */
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 */
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
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
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).
81 wxSoundStream
& wxSoundStreamPcm::Read(void *buffer
, wxUint32 len
)
87 m_sndio
->Read(buffer
, len
);
88 m_lastcount
= m_sndio
->GetLastAccess();
89 m_snderror
= m_sndio
->GetError();
93 real_len
= (m_16_to_8
) ? len
/ 2 : len
;
95 tmp_buf
= new char[real_len
];
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
)
103 m_function_in(tmp_buf
, (char *)buffer
, m_lastcount
);
113 wxSoundStream
& wxSoundStreamPcm::Write(const void *buffer
, wxUint32 len
)
119 return m_sndio
->Write(buffer
, len
);
121 len2
= (m_16_to_8
) ? len
/ 2 : len
;
123 tmp_buf
= new char[len2
];
124 m_function_out((const char *)buffer
, tmp_buf
, len2
);
125 m_sndio
->Write(tmp_buf
, len
);
128 m_lastcount
= (m_16_to_8
) ?
129 (m_sndio
->GetLastAccess() * 2) : m_sndio
->GetLastAccess();
134 bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase
& format
)
136 wxSoundFormatBase
*new_format
;
137 wxSoundFormatPcm
*pcm_format
, *pcm_format2
;
138 ConverterType
*current_table_out
, *current_table_in
;
142 if (m_sndio
->SetSoundFormat(format
)) {
143 m_function_out
= NULL
;
144 m_function_in
= NULL
;
147 if (format
.GetType() != wxSOUND_PCM
) {
148 m_snderror
= wxSOUND_INVFRMT
;
154 new_format
= m_sndio
->GetSoundFormat().Clone();
155 pcm_format
= (wxSoundFormatPcm
*)&format
;
156 pcm_format2
= (wxSoundFormatPcm
*)new_format
;
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
166 if (pcm_format
->GetBPS() != pcm_format2
->GetBPS()) {
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
];
172 current_table_out
= &s_converters
[CONVERT_BASE_8_16
];
173 current_table_in
= &s_converters
[CONVERT_BASE_16_8
];
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
];
179 current_table_out
= &s_converters
[CONVERT_BASE_8_8
];
180 current_table_in
= &s_converters
[CONVERT_BASE_8_8
];
183 change_sign
= (pcm_format2
->Signed() != pcm_format
->Signed());
185 #define MY_ORDER wxBYTE_ORDER
186 #if wxBYTE_ORDER == wxLITTLE_ENDIAN
187 #define OTHER_ORDER wxBIG_ENDIAN
189 #define OTHER_ORDER wxLITTLE_ENDIAN
192 // --------------------------------------------------------
193 // Find the good converter !
196 if (pcm_format
->GetOrder() == OTHER_ORDER
&&
197 pcm_format2
->GetOrder() == OTHER_ORDER
&& change_sign
)
198 index
= CONVERT_SWAP_SIGN_SWAP
;
200 else if (pcm_format
->GetOrder() == OTHER_ORDER
&&
201 pcm_format2
->GetOrder() == MY_ORDER
&& change_sign
)
202 index
= CONVERT_SWAP_SIGN
;
204 else if (pcm_format
->GetOrder() == MY_ORDER
&&
205 pcm_format
->GetOrder() == OTHER_ORDER
&& change_sign
)
206 index
= CONVERT_SIGN_SWAP
;
208 else if (change_sign
)
209 index
= CONVERT_SIGN
;
211 else if (!change_sign
&&
212 pcm_format
->GetOrder() != pcm_format2
->GetOrder())
213 index
= CONVERT_SWAP
;
218 m_function_out
= current_table_out
[index
];
219 m_function_in
= current_table_in
[index
];
221 m_sndio
->SetSoundFormat(*new_format
);
222 m_sndformat
= new_format
;