Files
wxWidgets/utils/wxMMedia2/lib/sndcpcm.cpp
Guilhem Lavaux a31c84f389 * Various fixes
* Introduced FinishPreparation() in wxSoundFileStream as a conclusion
  to PrepareToPlay()


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6010 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2000-02-14 18:09:24 +00:00

225 lines
5.7 KiB
C++

// --------------------------------------------------------------------------
// Name: sndcpcm.cpp
// Purpose:
// Date: 08/11/1999
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
// CVSID: $Id$
// --------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "sndcpcm.cpp"
#endif
#include <wx/wxprec.h>
#include "sndbase.h"
#include "sndpcm.h"
#include "sndcpcm.h"
wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio)
: wxSoundStreamCodec(sndio)
{
m_function_in = NULL;
m_function_out = NULL;
}
wxSoundStreamPcm::~wxSoundStreamPcm()
{
}
#include "converter.def"
// -----------------------------------------------------------------------
// Main PCM stream converter table
// -----------------------------------------------------------------------
wxSoundStreamPcm::ConverterType s_converters[] = {
NULL,
Convert_8_8_sign, /* 8 -> 8 sign */
NULL,
NULL,
NULL,
NULL,
Convert_8_16, /* 8 -> 16 */
Convert_8_16_sign, /* 8 -> 16 sign */
Convert_8_16_swap, /* 8 -> 16 swapped */
Convert_8_16_sign_swap, /* 8 -> 16 sign swapped */
NULL,
NULL,
Convert_16_8, /* 16 -> 8 */
Convert_16_8_sign, /* 16 -> 8 sign */
Convert_16_swap_8, /* 16 swapped -> 8 */
Convert_16_swap_8_sign, /* 16 swapped -> 8 sign */
NULL,
NULL,
NULL, /* 16 -> 16 */
Convert_16_sign, /* 16 -> 16 sign */
Convert_16_swap, /* 16 swapped -> 16 */
Convert_16_swap_16_sign, /* 16 swapped -> 16 sign */
Convert_16_sign_16_swap, /* 16 sign -> 16 swapped */
Convert_16_swap_16_sign_swap /* 16 swapped -> 16 sign swapped */
};
#define CONVERT_BPS 0
#define CONVERT_SIGN 1
#define CONVERT_SWAP 2
#define CONVERT_SIGN_SWAP 3
#define CONVERT_SWAP_SIGN 4
#define CONVERT_SWAP_SIGN_SWAP 5
#define CONVERT_BASE_8_8 0
#define CONVERT_BASE_8_16 6
#define CONVERT_BASE_16_8 12
#define CONVERT_BASE_16_16 18
//
// TODO: Read() and Write() aren't really safe. If you give it a buffer which
// is not aligned on 2, you may crash (See converter.def).
//
wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len)
{
wxUint32 real_len;
char *tmp_buf;
if (!m_function_in) {
m_sndio->Read(buffer, len);
m_lastcount = m_sndio->GetLastAccess();
m_snderror = m_sndio->GetError();
return *this;
}
real_len = (m_16_to_8) ? len / 2 : len;
tmp_buf = new char[real_len];
m_sndio->Read(tmp_buf, real_len);
m_lastcount = m_sndio->GetLastAccess();
m_snderror = m_sndio->GetError();
if (m_snderror != wxSOUND_NOERR)
return *this;
m_function_in(tmp_buf, (char *)buffer, m_lastcount);
delete[] tmp_buf;
if (m_16_to_8)
m_lastcount *= 2;
return *this;
}
wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len)
{
char *tmp_buf;
wxUint32 len2;
if (!m_function_out)
return m_sndio->Write(buffer, len);
len2 = (m_16_to_8) ? len / 2 : len;
tmp_buf = new char[len2];
m_function_out((const char *)buffer, tmp_buf, len);
m_sndio->Write(tmp_buf, len);
delete[] tmp_buf;
m_lastcount = (m_16_to_8) ?
(m_sndio->GetLastAccess() * 2) : m_sndio->GetLastAccess();
return *this;
}
bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format)
{
wxSoundFormatBase *new_format;
wxSoundFormatPcm *pcm_format, *pcm_format2;
ConverterType *current_table_out, *current_table_in;
int index;
bool change_sign;
if (m_sndio->SetSoundFormat(format)) {
m_function_out = NULL;
m_function_in = NULL;
return TRUE;
}
if (format.GetType() != wxSOUND_PCM) {
m_snderror = wxSOUND_INVFRMT;
return FALSE;
}
if (m_sndformat)
delete m_sndformat;
new_format = m_sndio->GetSoundFormat().Clone();
pcm_format = (wxSoundFormatPcm *)&format;
pcm_format2 = (wxSoundFormatPcm *)new_format;
// ----------------------------------------------------
// Select table to use:
// * 8 bits -> 8 bits
// * 16 bits -> 8 bits
// * 8 bits -> 16 bits
// * 16 bits -> 16 bits
m_16_to_8 = FALSE;
if (pcm_format->GetBPS() != pcm_format2->GetBPS()) {
m_16_to_8 = TRUE;
if (pcm_format2->GetBPS() == 8) {
current_table_out = &s_converters[CONVERT_BASE_16_8];
current_table_in = &s_converters[CONVERT_BASE_8_16];
} else {
current_table_out = &s_converters[CONVERT_BASE_8_16];
current_table_in = &s_converters[CONVERT_BASE_16_8];
}
} else if (pcm_format->GetBPS() == 16) {
current_table_out = &s_converters[CONVERT_BASE_16_16];
current_table_in = &s_converters[CONVERT_BASE_16_16];
} else {
current_table_out = &s_converters[CONVERT_BASE_8_8];
current_table_in = &s_converters[CONVERT_BASE_8_8];
}
change_sign = (pcm_format2->Signed() != pcm_format->Signed());
#define MY_ORDER wxBYTE_ORDER
#if wxBYTE_ORDER == wxLITTLE_ENDIAN
#define OTHER_ORDER wxBIG_ENDIAN
#else
#define OTHER_ORDER wxLITTLE_ENDIAN
#endif
// --------------------------------------------------------
// Find the good converter !
if (pcm_format->GetOrder() == OTHER_ORDER &&
pcm_format2->GetOrder() == OTHER_ORDER && change_sign)
index = CONVERT_SWAP_SIGN_SWAP;
else if (pcm_format->GetOrder() == OTHER_ORDER &&
pcm_format2->GetOrder() == MY_ORDER && change_sign)
index = CONVERT_SWAP_SIGN;
else if (pcm_format->GetOrder() == MY_ORDER &&
pcm_format->GetOrder() == OTHER_ORDER && change_sign)
index = CONVERT_SIGN_SWAP;
else if (change_sign)
index = CONVERT_SIGN;
else if (!change_sign &&
pcm_format->GetOrder() != pcm_format2->GetOrder())
index = CONVERT_SWAP;
else
index = CONVERT_BPS;
m_function_out = current_table_out[index];
m_function_in = current_table_in[index];
m_sndio->SetSoundFormat(*new_format);
m_sndformat = new_format;
return TRUE;
}