m_o_streambuf = new wxStreamBuffer(wxStreamBuffer::write);
if (data)
m_o_streambuf->SetBufferIO(data, data+len);
- m_o_streambuf->Fixed(TRUE);
+ m_o_streambuf->Fixed(FALSE);
+ m_o_streambuf->Flushable(FALSE);
}
wxMemoryOutputStream::~wxMemoryOutputStream()
size_t s_toput = m_buffer_end-m_buffer_pos;
if (s_toput < size && !m_fixed) {
- m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size+size);
- // I round a bit
- m_buffer_size += size;
- m_buffer_end = m_buffer_start+m_buffer_size;
+ if (!m_buffer_start)
+ SetBufferIO(size);
+ else {
+ size_t delta = m_buffer_pos-m_buffer_start;
+
+ m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size+size);
+ m_buffer_pos = m_buffer_start + delta;
+ // I round a bit
+ m_buffer_size += size;
+ m_buffer_end = m_buffer_start+m_buffer_size;
+ }
s_toput = size;
}
if (s_toput > size)
// ------------------
m_stream->m_lasterror = wxStream_NOERROR;
- if (!m_buffer_size)
+ if (!m_buffer_size && m_fixed)
return (m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size));
// ------------------
// First case: the buffer to write is larger than the stream buffer,
// we split it
- if (size > buf_left) {
+ // NB: If stream buffer isn't fixed (as for wxMemoryOutputStream),
+ // we always go to the second case.
+ if (size > buf_left && m_fixed) {
PutToBuffer(buffer, buf_left);
size -= buf_left;
buffer = (char *)buffer + buf_left; // ANSI C++ violation.
if (!temp_b)
return NULL;
m_wback = temp_b;
- m_wbackcur += needed_size;
memmove(m_wback+needed_size, m_wback, old_size);
size_t wxInputStream::GetWBack(char *buf, size_t bsize)
{
- size_t s_toget = m_wbackcur;
+ size_t s_toget = m_wbacksize-m_wbackcur;
if (!m_wback)
return 0;
if (bsize < s_toget)
s_toget = bsize;
- memcpy(buf, (m_wback+m_wbackcur-bsize), s_toget);
+ memcpy(buf, (m_wback+m_wbackcur), s_toget);
- m_wbackcur -= s_toget;
- if (m_wbackcur == 0) {
+ m_wbackcur += s_toget;
+ if (m_wbackcur == m_wbacksize) {
free(m_wback);
m_wback = (char *)NULL;
m_wbacksize = 0;
-To build Makefile with automake:
- in the top source directory type:
- automake utils/wxMMedia2/Makefile
- in the top build directory type:
- mkdir -p utils/wxMMedia2
- CONFIG_FILES="utils/wxMMedia2/Makefile utils/wxMMedia2/lib/Makefile utils/wxMMedia2/sample/Makefile" CONFIG_HEADERS= ./config.status
-
-and then you can run make in utils/wxMMedia2.
{
}
+bool wxSoundAiff::CanRead()
+{
+ wxUint32 signature1, signature2, len;
+
+ if (m_input->Read(&signature1, 4).LastRead() != 4)
+ return FALSE;
+
+ if (wxUINT32_SWAP_ON_BE(signature1) != FORM_SIGNATURE) {
+ m_input->Ungetch(&signature1, 4);
+ return FALSE;
+ }
+
+ m_input->Read(&len, 4);
+ if (m_input->LastRead() != 4) {
+ m_input->Ungetch(&len, m_input->LastRead());
+ m_input->Ungetch(&signature1, 4);
+ return FALSE;
+ }
+
+ if (m_input->Read(&signature2, 4).LastRead() != 4) {
+ m_input->Ungetch(&signature2, m_input->LastRead());
+ m_input->Ungetch(&len, 4);
+ m_input->Ungetch(&signature1, 4);
+ return FALSE;
+ }
+
+ m_input->Ungetch(&signature2, 4);
+ m_input->Ungetch(&len, 4);
+ m_input->Ungetch(&signature1, 4);
+
+ if (
+ wxUINT32_SWAP_ON_BE(signature2) != AIFF_SIGNATURE &&
+ wxUINT32_SWAP_ON_BE(signature2) != AIFC_SIGNATURE)
+ return FALSE;
+
+ return TRUE;
+}
+
#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
bool wxSoundAiff::PrepareToPlay()
wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound);
~wxSoundAiff();
+ bool CanRead();
+
protected:
bool PrepareToPlay();
bool PrepareToRecord(unsigned long time);
char *m_cdata[2];
protected:
- // Do the async stuff.
- void DoAsyncStuff(int evt);
-
// Handles event
virtual void OnSoundEvent(int evt);
};
{
m_sndio->SetDuplexMode(duplex);
}
+
+wxUint32 wxSoundStreamCodec::GetBestSize() const
+{
+ return m_sndio->GetBestSize();
+}
bool StopProduction();
void SetDuplexMode(bool duplex);
+ wxUint32 GetBestSize() const;
protected:
wxSoundStream *m_sndio;
Convert_U2S_8,
Convert_U2S_8,
NULL
+/*,
+ Convert_U2S_S2M_8,
+ Convert_U2S_S2M_8,
+ Convert_U2S_S2M_8,
+ Convert_U2S_S2M_8,
+ Convert_S2M_8 */
};
wxSoundStreamPcm::ConverterType s_convert_in_8_to_16[] = {
#define CONVERTER_SWAP_SIGN_SWAP 3
#define CONVERTER_SWAP_SIGN 4
#define CONVERTER_SWAP 5
+#define CONVERTER_SIGN_STEREO_MONO 6
+#define CONVERTER_SIGN_SWAP_STEREO_MONO 7
+#define CONVERTER_SWAP_SIGN_SWAP_STEREO_MONO 8
+#define CONVERTER_SWAP_SIGN_STEREO_MONO 9
+#define CONVERTER_SWAP_STEREO_MONO 10
+#define CONVERTER_STEREO_MONO 11
+
+//
+// TODO: Read() and Write() aren't really safe. If you give it a buffer which
+// is not aligned on 8, you may crash (See converter.def).
+//
wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len)
{
{
wxSoundFormatPcm pcm_default;
- m_fd = esd_monitor_stream(ESD_MONO | ESD_BITS8 | ESD_RECORD, 22050,
- hostname.mb_str(), MY_ESD_NAME);
+ m_fd = esd_play_stream(ESD_PLAY | ESD_STREAM | ESD_MONO | ESD_BITS8, 22050,
+// hostname.mb_str(), MY_ESD_NAME);
+ NULL, MY_ESD_NAME);
if (m_fd == -1) {
m_snderror = wxSOUND_INVDEV;
m_snderror = wxSOUND_NOERR;
m_esd_stop = TRUE;
+ m_q_filled = TRUE;
}
wxSoundStreamESD::~wxSoundStreamESD()
else
m_snderror = wxSOUND_NOERR;
+ m_q_filled = TRUE;
+
return *this;
}
void wxSoundStreamESD::WakeUpEvt(int evt)
{
+ m_q_filled = FALSE;
OnSoundEvent(evt);
}
if (evt == wxSOUND_OUTPUT) {
flag |= ESD_PLAY | ESD_STREAM;
- m_fd = esd_play_stream(flag, pcm->GetSampleRate(), m_hostname.mb_str(),
+ m_fd = esd_play_stream(flag, pcm->GetSampleRate(), NULL,
MY_ESD_NAME);
} else {
flag |= ESD_RECORD | ESD_STREAM;
- m_fd = esd_record_stream(flag, pcm->GetSampleRate(), m_hostname.mb_str(),
+ m_fd = esd_record_stream(flag, pcm->GetSampleRate(), NULL,
MY_ESD_NAME);
}
#endif
m_esd_stop = FALSE;
+ m_q_filled = FALSE;
return TRUE;
}
gdk_input_remove(m_tag);
esd_close(m_fd);
m_esd_stop = TRUE;
+ m_q_filled = TRUE;
return TRUE;
}
// You should not call this.
void WakeUpEvt(int evt);
+
+ bool QueueFilled() const { return m_q_filled; }
protected:
int m_fd;
int m_tag;
bool m_esd_stop;
wxString m_hostname;
+ bool m_q_filled;
private:
void DetectBest(wxSoundFormatPcm *pcm);
return TRUE;
}
+wxUint32 wxSoundRouterStream::GetBestSize() const
+{
+ if (m_router)
+ return m_router->GetBestSize();
+ else
+ return m_sndio->GetBestSize();
+}
+
bool wxSoundRouterStream::StartProduction(int evt)
{
if (!m_router) {
void wxSoundFileStream::OnSoundEvent(int evt)
{
- wxUint32 len = m_sndio->GetBestSize();
+ wxUint32 len = m_codec.GetBestSize();
char *buffer;
buffer = new char[len];
m_len -= len;
if (m_len == 0) {
Stop();
+ delete[] buffer;
return;
}
break;
len = GetData(buffer, len);
if (len == 0) {
Stop();
+ delete[] buffer;
return;
}
m_codec.Write(buffer, len);
bool StartProduction(int evt);
bool StopProduction();
+ wxUint32 GetBestSize() const;
+
protected:
wxSoundStream *m_router;
};
bool SetSoundFormat(const wxSoundFormatBase& format);
- virtual bool CanRead() { return TRUE; }
+ virtual bool CanRead() { return FALSE; }
protected:
wxSoundRouterStream m_codec;
wxSoundStream& wxSoundStreamG72X::Read(void *buffer, wxUint32 len)
{
+ wxUint16 *old_linear;
+ register wxUint16 *linear_buffer;
+ register wxUint32 real_len;
+ register wxUint32 countdown = len;
+
+ real_len = (len * 8 / m_n_bits);
+
+ old_linear = linear_buffer = new wxUint16[real_len];
+
+ m_router->Read(linear_buffer, real_len);
+
+ real_len = (wxUint32)(m_router->GetLastAccess() * ((float)m_n_bits / 8));
+ if (!real_len)
+ return *m_router;
+
+ m_io_buffer = (wxUint8 *)buffer;
+ m_current_b_pos = 0;
+
+ while (countdown != 0) {
+ PutBits(m_coder(*linear_buffer++, AUDIO_ENCODING_LINEAR, m_state));
+ countdown--;
+ }
+ m_lastcount = real_len;
+ m_snderror = m_router->GetError();
+
+ delete[] old_linear;
+
return *this;
}
register wxUint32 countdown = len;
register wxUint32 real_len;
- real_len = (wxUint32)(len * ((float)m_n_bits / 8));
+ // Compute the real length (PCM format) to sendt to the sound card
+ real_len = (len * m_n_bits / 8);
+ // Allocate a temporary buffer
old_linear = linear_buffer = new wxUint16[real_len];
// Bad, we override the const
m_io_buffer = (wxUint8 *)buffer;
m_current_b_pos = 0;
+ // Decode the datas
while (countdown != 0) {
*linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state);
countdown--;
}
m_lastcount = len;
+ // Send them to the sound card
m_router->Write(old_linear, real_len);
+ // Destroy the temporary buffer
delete[] old_linear;
return *m_router;
g72x = (wxSoundFormatG72X *)m_sndformat;
+ // Set PCM as the output format of the codec
pcm.SetSampleRate(g72x->GetSampleRate());
pcm.SetBPS(16);
pcm.SetChannels(1);
pcm.Signed(TRUE);
pcm.SetOrder(wxBYTE_ORDER);
+ // Look for the correct codec to use and set its bit width
switch (g72x->GetG72XType()) {
case wxSOUND_G721:
m_n_bits = 4;
break;
}
+ // Let the router finish the work
m_router->SetSoundFormat(pcm);
return TRUE;
return *m_router;
}
+wxUint32 wxSoundStreamUlaw::GetBestSize() const
+{
+ return m_sndio->GetBestSize() / 2;
+}
+
bool wxSoundStreamUlaw::SetSoundFormat(const wxSoundFormatBase& format)
{
if (format.GetType() != wxSOUND_ULAW) {
bool SetSoundFormat(const wxSoundFormatBase& format);
+ wxUint32 GetBestSize() const;
+
protected:
wxSoundRouterStream *m_router;
};
#include <wx/stream.h>
#include <wx/datstrm.h>
#include <wx/filefn.h>
+#include <wx/mstream.h>
#include "sndbase.h"
#include "sndcodec.h"
bool wxSoundWave::CanRead()
{
- wxUint32 len, signature;
+ wxUint32 len, signature1, signature2;
m_snderror = wxSOUND_NOERR;
- FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
+ FAIL_WITH(m_input->Read(&signature1, 4).LastRead() != 4, wxSOUND_INVSTRM);
- if (wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE) {
- m_input->Ungetch(&signature, 4);
+ if (wxUINT32_SWAP_ON_BE(signature1) != RIFF_SIGNATURE) {
+ m_input->Ungetch(&signature1, 4);
return FALSE;
}
m_input->Read(&len, 4);
FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
- FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
- if (wxUINT32_SWAP_ON_BE(signature) != WAVE_SIGNATURE) {
- m_input->Ungetch(&signature, 4);
- return FALSE;
- }
-
- m_input->Ungetch("RIFF", 4);
+ FAIL_WITH(m_input->Read(&signature2, 4).LastRead() != 4, wxSOUND_INVSTRM);
+ m_input->Ungetch(&signature2, 4);
m_input->Ungetch(&len, 4);
- m_input->Ungetch("WAVE", 4);
+ m_input->Ungetch(&signature1, 4);
+
+ if (wxUINT32_SWAP_ON_BE(signature2) != WAVE_SIGNATURE)
+ return FALSE;
return TRUE;
}
bool wxSoundWave::PrepareToRecord(unsigned long time)
{
-#define WRITE_SIGNATURE(sig) \
+#define WRITE_SIGNATURE(s,sig) \
signature = sig; \
signature = wxUINT32_SWAP_ON_BE(signature); \
-FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
+FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
- wxUint32 signature, len;
+ wxUint32 signature;
+ wxMemoryOutputStream fmt_data;
if (!m_output) {
m_snderror = wxSOUND_INVSTRM;
}
wxDataOutputStream data(*m_output);
- data.BigEndianOrdered(FALSE);
+ wxDataOutputStream fmt_d_data(fmt_data);
- len = m_sndformat->GetBytesFromTime(time);
-
- len += HEADER_SIZE;
+ data.BigEndianOrdered(FALSE);
+ fmt_d_data.BigEndianOrdered(FALSE);
- WRITE_SIGNATURE(RIFF_SIGNATURE);
+ WRITE_SIGNATURE(m_output, RIFF_SIGNATURE);
- data << len;
FAIL_WITH(m_output->LastWrite() != 4, wxSOUND_INVSTRM);
- WRITE_SIGNATURE(WAVE_SIGNATURE);
+ WRITE_SIGNATURE((&fmt_data), WAVE_SIGNATURE);
{
wxSoundFormatBase *frmt;
- WRITE_SIGNATURE(FMT_SIGNATURE);
+ WRITE_SIGNATURE((&fmt_data), FMT_SIGNATURE);
switch (m_sndformat->GetType()) {
case wxSOUND_PCM:
- frmt = HandleInputPCM(data);
+ frmt = HandleInputPCM(fmt_d_data);
break;
case wxSOUND_G72X:
- frmt = HandleInputG72X(data);
+ frmt = HandleInputG72X(fmt_d_data);
break;
default:
m_snderror = wxSOUND_NOCODEC;
delete frmt;
}
- WRITE_SIGNATURE(DATA_SIGNATURE);
+ data << (fmt_data.GetSize() + 8 + m_sndformat->GetBytesFromTime(time));
+
+ {
+ char *out_buf;
+ out_buf = new char[fmt_data.GetSize()];
+
+ fmt_data.CopyTo(out_buf, fmt_data.GetSize());
+ m_output->Write(out_buf, fmt_data.GetSize());
+
+ delete[] out_buf;
+ }
+
+ WRITE_SIGNATURE(m_output, DATA_SIGNATURE);
data.Write32(m_sndformat->GetBytesFromTime(time));
return TRUE;
}
wxSoundStreamWin *m_driver;
};
-#define WXSOUND_MAX_QUEUE 128
+#define WXSOUND_MAX_QUEUE 10
wxSoundStreamWin::wxSoundStreamWin()
{
WPARAM wParam, LPARAM lParam)
{
switch (message) {
- case MM_WOM_DONE: {
- wxFindSoundFromHandle((WXHWND)hWnd)->NotifyDoneBuffer(wParam);
+ case MM_WOM_DONE:
+ wxFindSoundFromHandle((WXHWND)hWnd)->NotifyDoneBuffer(wParam, wxSOUND_OUTPUT);
+ break;
+ case MM_WIM_DATA:
+ wxFindSoundFromHandle((WXHWND)hWnd)->NotifyDoneBuffer(wParam, wxSOUND_INPUT);
break;
- }
default:
break;
}
wformat.wFormatTag = WAVE_FORMAT_PCM;
wformat.nChannels = pcm->GetChannels();
- wformat.nBlockAlign = pcm->GetBPS() / 8 * wformat.nChannels;
- wformat.nAvgBytesPerSec = pcm->GetBytesFromTime(1);
+ wformat.nBlockAlign = wformat.nChannels * pcm->GetBPS() / 8;
wformat.nSamplesPerSec = pcm->GetSampleRate();
+ wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign;
wformat.wBitsPerSample = pcm->GetBPS();
wformat.cbSize = 0;
return FALSE;
}
- m_input_frag_in = WXSOUND_MAX_QUEUE-1;
- m_current_frag_in = 0;
+ m_current_frag_in = WXSOUND_MAX_QUEUE-1;
+ m_input_frag_in = 0;
m_internal->m_input_enabled = TRUE;
}
- if (!AllocHeaders(mode)) {
- CloseDevice();
- return FALSE;
+ if (mode & wxSOUND_OUTPUT) {
+ if (!AllocHeaders(wxSOUND_OUTPUT)) {
+ CloseDevice();
+ return FALSE;
+ }
}
+ if (mode & wxSOUND_INPUT) {
+ if (!AllocHeaders(wxSOUND_INPUT)) {
+ CloseDevice();
+ return FALSE;
+ }
+ }
+
return TRUE;
}
// -------------------------------------------------------------------------
void wxSoundStreamWin::CloseDevice()
{
+ m_internal->m_output_enabled = FALSE;
+ m_internal->m_input_enabled = FALSE;
+
if (m_internal->m_output_enabled) {
- FreeHeaders(wxSOUND_OUTPUT);
waveOutReset(m_internal->m_devout);
+ FreeHeaders(wxSOUND_OUTPUT);
waveOutClose(m_internal->m_devout);
}
if (m_internal->m_input_enabled) {
- FreeHeaders(wxSOUND_INPUT);
waveInReset(m_internal->m_devin);
+ FreeHeaders(wxSOUND_INPUT);
waveInClose(m_internal->m_devin);
}
-
- m_internal->m_output_enabled = FALSE;
- m_internal->m_input_enabled = FALSE;
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void wxSoundStreamWin::WaitFor(wxSoundInfoHeader *info)
{
- // We begun filling it: we must send it to the Windows queue
- if (info->m_position != 0) {
- memset(info->m_data + info->m_position, 0, info->m_size-info->m_position);
- AddToQueue(info);
- }
-
// If the buffer is finished, we return immediately
- if (!info->m_playing && !info->m_recording)
+ if (!info->m_playing) {
+
+ // We begun filling it: we must send it to the Windows queue
+ if (info->m_position != 0) {
+ memset(info->m_data + info->m_position, 0, info->m_size);
+ AddToQueue(info);
+ }
+
return;
+ }
// Else, we wait for its termination
while (info->m_playing || info->m_recording)
if (info->m_mode == wxSOUND_INPUT) {
// Increment the input fragment pointer
- m_current_frag_in = (m_current_frag_in + 1) % WXSOUND_MAX_QUEUE;
result = waveInAddBuffer(m_internal->m_devin,
info->m_header, sizeof(WAVEHDR));
if (result == MMSYSERR_NOERROR)
{
wxSoundInfoHeader *header;
- // TODO //
header = m_headers_rec[m_current_frag_in];
- WaitFor(header);
+ if (header->m_recording)
+ WaitFor(header);
+
+ m_current_frag_in = (m_current_frag_in + 1) % WXSOUND_MAX_QUEUE;
if (m_current_frag_in == m_input_frag_in)
m_queue_filled = TRUE;
// fragment finished. It reinitializes the parameters of the fragment and
// sends an event to the clients.
// -------------------------------------------------------------------------
-void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 dev_handle)
+void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 dev_handle, int flag)
{
wxSoundInfoHeader *info;
- if (dev_handle == (wxUint32)m_internal->m_devout) {
+ if (flag == wxSOUND_OUTPUT) {
+ if (!m_internal->m_output_enabled)
+ return;
+
m_output_frag_out = (m_output_frag_out + 1) % WXSOUND_MAX_QUEUE;
info = m_headers_play[m_output_frag_out];
ClearHeader(info);
m_queue_filled = FALSE;
OnSoundEvent(wxSOUND_OUTPUT);
} else {
+ if (!m_internal->m_input_enabled)
+ return;
+
m_input_frag_in = (m_input_frag_in + 1) % WXSOUND_MAX_QUEUE;
+ m_headers_rec[m_input_frag_in]->m_recording = FALSE;
OnSoundEvent(wxSOUND_INPUT);
m_queue_filled = FALSE;
}
int i;
for (i=0;i<WXSOUND_MAX_QUEUE;i++)
AddToQueue(m_headers_rec[i]);
+
+ waveInStart(m_internal->m_devin);
}
return TRUE;
// -------------------------------------------------------------------------
bool wxSoundStreamWin::StopProduction()
{
+ if (m_internal->m_input_enabled)
+ waveInStop(m_internal->m_devin);
+
m_production_started = FALSE;
CloseDevice();
return TRUE;
bool QueueFilled() const;
// Internal but defined as public
- void NotifyDoneBuffer(wxUint32 dev_handle);
+ void NotifyDoneBuffer(wxUint32 dev_handle, int flag);
protected:
wxSoundInternal *m_internal;
#include <wx/wfstream.h>
#include <wx/frame.h>
#include "../lib/sndoss.h"
+#include "../lib/sndesd.h"
#include "../lib/sndwav.h"
#include "../lib/sndaiff.h"
class MyApp: public wxApp {
bool OnInit() {
- wxSoundStreamOSS *oss_dev = new wxSoundStreamOSS();
+// wxSoundStreamOSS *oss_dev = new wxSoundStreamOSS();
+ wxSoundStreamESD *oss_dev = new wxSoundStreamESD();
wxFileInputStream *f_input = new wxFileInputStream(argv[1]);
- wxSoundFileStream *wav_file = new wxSoundAiff(*f_input, *oss_dev);
+ wxSoundFileStream *wav_file;
wxFrame *frame = new wxFrame(NULL, -1, "My Frame");
wxSoundFormatPcm pcm;
return FALSE;
}
+ wav_file = new wxSoundWave(*f_input, *oss_dev);
+ if (!wav_file->CanRead()) {
+ wav_file = new wxSoundAiff(*f_input, *oss_dev);
+ if (!wav_file->CanRead())
+ return FALSE;
+ }
+
wav_file->Play();
frame->Show(TRUE);
return TRUE;