X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/622e48cbd2b024ca6c36fdd90cc075950ccf53af..171774fcf39d89d62bccc2e035d44f2f3a6495e7:/utils/wxMMedia2/lib/sndfile.cpp diff --git a/utils/wxMMedia2/lib/sndfile.cpp b/utils/wxMMedia2/lib/sndfile.cpp index 3040943411..c92ea71d9e 100644 --- a/utils/wxMMedia2/lib/sndfile.cpp +++ b/utils/wxMMedia2/lib/sndfile.cpp @@ -2,124 +2,170 @@ // Name: sndfile.cpp // Purpose: // Date: 08/11/1999 -// Author: Guilhem Lavaux (C) 1999 +// Author: Guilhem Lavaux (C) 1999, 2000 // CVSID: $Id$ // -------------------------------------------------------------------------- +#include + +#ifndef WX_PRECOMP #include +#endif + #include "sndbase.h" #include "sndcodec.h" #include "sndfile.h" #include "sndcpcm.h" #include "sndulaw.h" +#include "sndg72x.h" // -------------------------------------------------------------------------- // Sound codec router +// A very important class: it ensures that everybody is satisfied. +// It is supposed to create as many codec as it is necessary to transform +// a signal in a specific format in an another. // -------------------------------------------------------------------------- - wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio) : wxSoundStreamCodec(sndio) { - m_router = NULL; + m_router = NULL; } wxSoundRouterStream::~wxSoundRouterStream() { - if (m_router) - delete m_router; + if (m_router) + delete m_router; } -wxSoundStream& wxSoundRouterStream::Read(void *buffer, size_t len) +// -------------------------------------------------------------------------- +// Read(void *buffer, wxUint32 len): It reads data synchronously. See sndbase.h +// for possible errors and behaviours ... +// -------------------------------------------------------------------------- +wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len) { - if (m_router) { - m_router->Read(buffer, len); - m_snderror = m_router->GetError(); - m_lastcount = m_router->GetLastAccess(); - } else { - m_sndio->Read(buffer, len); - m_snderror = m_sndio->GetError(); - m_lastcount = m_sndio->GetLastAccess(); - } - return *this; + if (m_router) { + m_router->Read(buffer, len); + m_snderror = m_router->GetError(); + m_lastcount = m_router->GetLastAccess(); + } else { + m_sndio->Read(buffer, len); + m_snderror = m_sndio->GetError(); + m_lastcount = m_sndio->GetLastAccess(); + } + return *this; } -wxSoundStream& wxSoundRouterStream::Write(const void *buffer, size_t len) +// -------------------------------------------------------------------------- +// Write(const void *buffer, wxUint32 len): It writes data synchronously +// -------------------------------------------------------------------------- +wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len) { - if (m_router) { - m_router->Write(buffer, len); - m_snderror = m_router->GetError(); - m_lastcount = m_router->GetLastAccess(); - } else { - m_sndio->Write(buffer, len); - m_snderror = m_sndio->GetError(); - m_lastcount = m_sndio->GetLastAccess(); + if (m_router) { + m_router->Write(buffer, len); + m_snderror = m_router->GetError(); + m_lastcount = m_router->GetLastAccess(); + } else { + m_sndio->Write(buffer, len); + m_snderror = m_sndio->GetError(); + m_lastcount = m_sndio->GetLastAccess(); } return *this; } +// -------------------------------------------------------------------------- +// SetSoundFormat(const wxSoundFormatBase& format) first tries to setup the +// sound driver using the specified format. If this fails, it uses personnal +// codec converters: for the moment there is a PCM converter (PCM to PCM: +// with optional resampling, ...), an ULAW converter (ULAW to PCM), a G72X +// converter (G72X to PCM). If nothing works, it returns FALSE. +// -------------------------------------------------------------------------- bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format) { - if (m_router) - delete m_router; - - if (m_sndio->SetSoundFormat(format)) { - wxSoundStream::SetSoundFormat(m_sndio->GetSoundFormat()); + if (m_router) + delete m_router; + + // First, we try to setup the sound device + if (m_sndio->SetSoundFormat(format)) { + // We are lucky, it is working. + wxSoundStream::SetSoundFormat(m_sndio->GetSoundFormat()); + return TRUE; + } + + switch(format.GetType()) { + case wxSOUND_NOFORMAT: + return FALSE; + case wxSOUND_PCM: + m_router = new wxSoundStreamPcm(*m_sndio); + m_router->SetSoundFormat(format); + break; + case wxSOUND_ULAW: + m_router = new wxSoundStreamUlaw(*m_sndio); + m_router->SetSoundFormat(format); + break; + case wxSOUND_G72X: + m_router = new wxSoundStreamG72X(*m_sndio); + m_router->SetSoundFormat(format); + break; + } + wxSoundStream::SetSoundFormat(m_router->GetSoundFormat()); return TRUE; - } +} - switch(format.GetType()) { - case wxSOUND_NOFORMAT: - return FALSE; - case wxSOUND_PCM: - m_router = new wxSoundStreamPcm(*m_sndio); - m_router->SetSoundFormat(format); - break; - case wxSOUND_ULAW: - m_router = new wxSoundStreamUlaw(*m_sndio); - m_router->SetSoundFormat(format); - break; - } - wxSoundStream::SetSoundFormat(m_router->GetSoundFormat()); - return TRUE; +// -------------------------------------------------------------------------- +// GetBestSize() returns the specific best buffer size a sound driver +// can manage. It means that it will be easier for it to manage the buffer +// and so it will be faster and in some case more accurate for real-time event. +// -------------------------------------------------------------------------- +wxUint32 wxSoundRouterStream::GetBestSize() const +{ + if (m_router) + return m_router->GetBestSize(); + else + return m_sndio->GetBestSize(); } +// -------------------------------------------------------------------------- +// StartProduction(int evt). See sndbase.h +// -------------------------------------------------------------------------- bool wxSoundRouterStream::StartProduction(int evt) { - if (!m_router) { - if (m_sndio->StartProduction(evt)) - return TRUE; - - m_snderror = m_sndio->GetError(); - m_lastcount = m_sndio->GetLastAccess(); + if (!m_router) { + if (m_sndio->StartProduction(evt)) + return TRUE; + + m_snderror = m_sndio->GetError(); + m_lastcount = m_sndio->GetLastAccess(); + return FALSE; + } + + if (m_router->StartProduction(evt)) + return TRUE; + + m_snderror = m_router->GetError(); + m_lastcount = m_router->GetLastAccess(); return FALSE; - } - - if (m_router->StartProduction(evt)) - return TRUE; - - m_snderror = m_router->GetError(); - m_lastcount = m_router->GetLastAccess(); - return FALSE; } +// -------------------------------------------------------------------------- +// StopProduction(). See sndbase.h +// -------------------------------------------------------------------------- bool wxSoundRouterStream::StopProduction() { - if (!m_router) { - if (m_sndio->StopProduction()) - return TRUE; - - m_snderror = m_sndio->GetError(); - m_lastcount = m_sndio->GetLastAccess(); + if (!m_router) { + if (m_sndio->StopProduction()) + return TRUE; + + m_snderror = m_sndio->GetError(); + m_lastcount = m_sndio->GetLastAccess(); + return FALSE; + } + + if (m_router->StopProduction()) + return TRUE; + + m_snderror = m_router->GetError(); + m_lastcount = m_router->GetLastAccess(); return FALSE; - } - - if (m_router->StopProduction()) - return TRUE; - - m_snderror = m_router->GetError(); - m_lastcount = m_router->GetLastAccess(); - return FALSE; } - // -------------------------------------------------------------------------- // wxSoundFileStream: generic reader @@ -127,9 +173,12 @@ bool wxSoundRouterStream::StopProduction() wxSoundFileStream::wxSoundFileStream(wxInputStream& stream, wxSoundStream& io_sound) - : m_codec(io_sound), m_sndio(&io_sound), - m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED) + : m_codec(io_sound), m_sndio(&io_sound), + m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED) { + m_length = 0; + m_bytes_left = 0; + m_prepared = FALSE; } wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream, @@ -137,6 +186,9 @@ wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream, : m_codec(io_sound), m_sndio(&io_sound), m_input(NULL), m_output(&stream), m_state(wxSOUND_FILE_STOPPED) { + m_length = 0; + m_bytes_left = 0; + m_prepared = FALSE; } wxSoundFileStream::~wxSoundFileStream() @@ -150,17 +202,19 @@ bool wxSoundFileStream::Play() if (m_state != wxSOUND_FILE_STOPPED) return FALSE; - if (!PrepareToPlay()) - return FALSE; + if (!m_prepared) + if (!PrepareToPlay()) + return FALSE; + + m_state = wxSOUND_FILE_PLAYING; if (!StartProduction(wxSOUND_OUTPUT)) return FALSE; - m_state = wxSOUND_FILE_PLAYING; return TRUE; } -bool wxSoundFileStream::Record(unsigned long time) +bool wxSoundFileStream::Record(wxUint32 time) { if (m_state != wxSOUND_FILE_STOPPED) return FALSE; @@ -168,12 +222,12 @@ bool wxSoundFileStream::Record(unsigned long time) if (!PrepareToRecord(time)) return FALSE; - m_len = m_sndformat->GetBytesFromTime(time); + FinishPreparation(m_sndformat->GetBytesFromTime(time)); + m_state = wxSOUND_FILE_RECORDING; if (!StartProduction(wxSOUND_INPUT)) return FALSE; - m_state = wxSOUND_FILE_RECORDING; return TRUE; } @@ -185,13 +239,20 @@ bool wxSoundFileStream::Stop() if (!StopProduction()) return FALSE; + m_prepared = FALSE; + if (m_state == wxSOUND_FILE_RECORDING) if (!FinishRecording()) { m_state = wxSOUND_FILE_STOPPED; return FALSE; } + + if (m_input) + m_input->SeekI(0, wxFromStart); + + if (m_output) + m_output->SeekO(0, wxFromStart); - // TODO reset counter m_state = wxSOUND_FILE_STOPPED; return TRUE; } @@ -224,22 +285,18 @@ bool wxSoundFileStream::Resume() return TRUE; } -wxSoundStream& wxSoundFileStream::Read(void *buffer, size_t len) +wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len) { m_lastcount = GetData(buffer, len); return *this; } -wxSoundStream& wxSoundFileStream::Write(const void *buffer, size_t len) +wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len) { m_lastcount = PutData(buffer, len); return *this; } -void wxSoundFileStream::SetDuplexMode(bool duplex) -{ -} - bool wxSoundFileStream::StartProduction(int evt) { m_sndio->SetEventHandler(this); @@ -255,35 +312,92 @@ bool wxSoundFileStream::StopProduction() return m_codec.StopProduction(); } +void wxSoundFileStream::FinishPreparation(wxUint32 len) +{ + m_bytes_left = m_length = len; + m_prepared = TRUE; +} + +wxString wxSoundFileStream::GetCodecName() const +{ + return wxString(wxT("wxSoundFileStream base codec")); +} + +wxUint32 wxSoundFileStream::GetLength() +{ + if (m_input && !m_prepared && GetError() == wxSOUND_NOERR) + return (PrepareToPlay()) ? m_length : 0; + + return m_length; +} + +wxUint32 wxSoundFileStream::GetPosition() +{ + if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR) + PrepareToPlay(); + + return m_length-m_bytes_left; +} + +wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position) +{ + if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR) + PrepareToPlay(); + + if (!m_prepared) + return 0; + + if (!RepositionStream(new_position)) + return m_length-m_bytes_left; + + if (new_position >= m_length) { + m_bytes_left = 0; + return m_length; + } + + m_bytes_left = m_length-new_position; + return new_position; +} + void wxSoundFileStream::OnSoundEvent(int evt) { - size_t len = m_sndio->GetBestSize(); - char buffer[m_sndio->GetBestSize()]; + wxUint32 len = m_codec.GetBestSize(); + char *buffer; + buffer = new char[len]; wxSoundStream::OnSoundEvent(evt); - switch(evt) { - case wxSOUND_INPUT: - if (len > m_len) - len = m_len; - - len = m_codec.Read(buffer, len).GetLastAccess(); - PutData(buffer, len); - m_len -= len; - if (m_len == 0) { - Stop(); - return; - } - break; - case wxSOUND_OUTPUT: - len = GetData(buffer, len); - if (len == 0) { - Stop(); - return; + while (!m_sndio->QueueFilled()) { + switch(evt) { + case wxSOUND_INPUT: + if (len > m_bytes_left) + len = m_bytes_left; + + len = m_codec.Read(buffer, len).GetLastAccess(); + PutData(buffer, len); + m_bytes_left -= len; + if (m_bytes_left == 0) { + Stop(); + delete[] buffer; + return; + } + break; + case wxSOUND_OUTPUT: + if (len > m_bytes_left) + len = m_bytes_left; + + len = GetData(buffer, len); + m_bytes_left -= len; + if (m_bytes_left == 0) { + Stop(); + delete[] buffer; + return; + } + m_codec.Write(buffer, len); + break; } - m_codec.Write(buffer, len); - break; } + delete[] buffer; } bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)