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 wxSoundStreamPcm::ConverterType s_converters
[] = {
33 Convert_8_8_sign
, /* 8 -> 8 sign */
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 */
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 */
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 */
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
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
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).
78 wxSoundStream
& wxSoundStreamPcm::Read(void *buffer
, wxUint32 len
)
84 m_sndio
->Read(buffer
, len
);
85 m_lastcount
= m_sndio
->GetLastAccess();
86 m_snderror
= m_sndio
->GetError();
90 real_len
= (m_16_to_8
) ? len
/ 2 : len
;
92 tmp_buf
= new char[real_len
];
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
)
100 m_function_in(tmp_buf
, (char *)buffer
, m_lastcount
);
110 wxSoundStream
& wxSoundStreamPcm::Write(const void *buffer
, wxUint32 len
)
116 return m_sndio
->Write(buffer
, len
);
118 len2
= (m_16_to_8
) ? len
/ 2 : len
;
120 tmp_buf
= new char[len2
];
121 m_function_out((const char *)buffer
, tmp_buf
, len
);
122 m_sndio
->Write(tmp_buf
, len
);
125 m_lastcount
= (m_16_to_8
) ?
126 (m_sndio
->GetLastAccess() * 2) : m_sndio
->GetLastAccess();
131 bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase
& format
)
133 wxSoundFormatBase
*new_format
;
134 wxSoundFormatPcm
*pcm_format
, *pcm_format2
;
135 ConverterType
*current_table_out
, *current_table_in
;
139 if (m_sndio
->SetSoundFormat(format
)) {
140 m_function_out
= NULL
;
141 m_function_in
= NULL
;
144 if (format
.GetType() != wxSOUND_PCM
) {
145 m_snderror
= wxSOUND_INVFRMT
;
151 new_format
= m_sndio
->GetSoundFormat().Clone();
152 pcm_format
= (wxSoundFormatPcm
*)&format
;
153 pcm_format2
= (wxSoundFormatPcm
*)new_format
;
156 if (pcm_format
->GetBPS() != pcm_format2
->GetBPS()) {
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
];
162 current_table_out
= &s_converters
[CONVERT_BASE_8_16
];
163 current_table_in
= &s_converters
[CONVERT_BASE_16_8
];
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
];
169 current_table_out
= &s_converters
[CONVERT_BASE_8_8
];
170 current_table_in
= &s_converters
[CONVERT_BASE_8_8
];
173 change_sign
= (pcm_format2
->Signed() != pcm_format
->Signed());
175 #define MY_ORDER wxBYTE_ORDER
176 #if wxBYTE_ORDER == wxLITTLE_ENDIAN
177 #define OTHER_ORDER wxBIG_ENDIAN
179 #define OTHER_ORDER wxLITTLE_ENDIAN
182 if (pcm_format
->GetOrder() == OTHER_ORDER
&&
183 pcm_format2
->GetOrder() == OTHER_ORDER
&& change_sign
)
184 index
= CONVERT_SWAP_SIGN_SWAP
;
186 else if (pcm_format
->GetOrder() == OTHER_ORDER
&&
187 pcm_format2
->GetOrder() == MY_ORDER
&& change_sign
)
188 index
= CONVERT_SWAP_SIGN
;
190 else if (pcm_format
->GetOrder() == MY_ORDER
&&
191 pcm_format
->GetOrder() == OTHER_ORDER
&& change_sign
)
192 index
= CONVERT_SIGN_SWAP
;
194 else if (change_sign
)
195 index
= CONVERT_SIGN
;
197 else if (!change_sign
&&
198 pcm_format
->GetOrder() != pcm_format2
->GetOrder())
199 index
= CONVERT_SWAP
;
204 m_function_out
= current_table_out
[index
];
205 m_function_in
= current_table_in
[index
];
207 m_sndio
->SetSoundFormat(*new_format
);
208 m_sndformat
= new_format
;