1998-11-09 13:37:38 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: sndfile.cpp
|
|
|
|
// Purpose: wxMMedia
|
|
|
|
// Author: Guilhem Lavaux
|
|
|
|
// Created: 1997
|
|
|
|
// Updated: 1998
|
|
|
|
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
|
|
|
// License: wxWindows license
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
|
|
#pragma implementation "sndfile.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "mmedia.h"
|
|
|
|
#include "sndfile.h"
|
|
|
|
#ifdef WX_PRECOMP
|
|
|
|
#include <wx/wxprec.h>
|
|
|
|
#else
|
|
|
|
#include <wx/wx.h>
|
|
|
|
#endif
|
|
|
|
#include <wx/module.h>
|
|
|
|
#include "sndfrmt.h"
|
|
|
|
|
|
|
|
#ifdef __BORLANDC__
|
|
|
|
#pragma hdrstop
|
|
|
|
#endif
|
|
|
|
|
|
|
|
wxSndFileCodec::wxSndFileCodec()
|
|
|
|
: wxMMediaFile(), wxSndBuffer(),
|
|
|
|
m_fstate(wxSFILE_STOPPED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
wxSndFileCodec::wxSndFileCodec(wxOutputStream& s, bool seekable)
|
|
|
|
: wxMMediaFile(s, seekable),
|
|
|
|
wxSndBuffer(),
|
|
|
|
m_fstate(wxSFILE_STOPPED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
wxSndFileCodec::wxSndFileCodec(wxInputStream& s, bool preload, bool seekable)
|
|
|
|
: wxMMediaFile(s, preload, seekable),
|
|
|
|
wxSndBuffer(),
|
|
|
|
m_fstate(wxSFILE_STOPPED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
wxSndFileCodec::wxSndFileCodec(const wxString& fname)
|
|
|
|
: wxMMediaFile(fname), wxSndBuffer(),
|
|
|
|
m_fstate(wxSFILE_STOPPED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
wxSndFileCodec::~wxSndFileCodec()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxSndFileCodec::Play(wxSound& snd)
|
|
|
|
{
|
|
|
|
if (m_fstate != wxSFILE_STOPPED || IsSet(wxSND_BUFLOCKED))
|
|
|
|
return;
|
|
|
|
|
1999-02-18 13:18:06 -05:00
|
|
|
if (m_fstate != wxSFILE_PREPARED_TO_PLAY)
|
|
|
|
if (!(m_fsize = PrepareToPlay()))
|
|
|
|
return;
|
1998-11-09 13:37:38 -05:00
|
|
|
|
|
|
|
m_fpos = 0;
|
|
|
|
m_fstate = wxSFILE_PLAYING;
|
|
|
|
|
|
|
|
Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
|
|
|
|
snd.QueueBuffer(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxSndFileCodec::Stop(wxSound& snd)
|
|
|
|
{
|
|
|
|
if (m_fstate == wxSFILE_STOPPED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
snd.UnqueueBuffer(*this);
|
|
|
|
Clear(wxSND_BUFREADY | wxSND_KEEPQUEUED);
|
|
|
|
m_fstate = wxSFILE_STOPPED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxSndFileCodec::Record(wxSound& snd,
|
|
|
|
const wxSoundDataFormat& format,
|
|
|
|
wxUint32 seconds)
|
|
|
|
{
|
|
|
|
wxUint32 byterate;
|
|
|
|
|
|
|
|
if (m_fstate != wxSFILE_STOPPED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_sndformat = format;
|
|
|
|
byterate = m_sndformat.GetCodec()->GetByteRate();
|
|
|
|
|
|
|
|
m_fsize = seconds*byterate;
|
|
|
|
if (!PrepareToRecord(m_fsize))
|
|
|
|
return;
|
|
|
|
if (IsSet(wxSND_BUFLOCKED))
|
|
|
|
return;
|
|
|
|
|
|
|
|
wxUint32 sec1 = m_fsize / byterate,
|
|
|
|
sec2 = sec1 % 3600;
|
|
|
|
|
|
|
|
m_sndtime.hours = sec1 / 3600;
|
|
|
|
m_sndtime.minutes = sec2 / 60;
|
|
|
|
m_sndtime.seconds = sec2 % 60;
|
|
|
|
|
|
|
|
m_fdone = m_fpos = 0;
|
|
|
|
m_fstate = wxSFILE_RECORDING;
|
|
|
|
|
|
|
|
m_sndmode = wxSND_INPUT;
|
|
|
|
|
|
|
|
Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
|
|
|
|
snd.QueueBuffer(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxSndFileCodec::OnNeedOutputData(char *data, wxUint32& size)
|
|
|
|
{
|
|
|
|
wxUint32 datas_left = m_fsize-m_fpos;
|
|
|
|
|
|
|
|
if (m_fstate != wxSFILE_PLAYING) {
|
|
|
|
size = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!datas_left) {
|
|
|
|
size = 0;
|
|
|
|
m_fpos = 0;
|
|
|
|
m_fstate = wxSFILE_STOPPED;
|
|
|
|
Clear(wxSND_KEEPQUEUED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size > datas_left)
|
|
|
|
size = datas_left;
|
|
|
|
|
|
|
|
if (!OnNeedData(data, size)) {
|
|
|
|
size = 0;
|
|
|
|
m_fpos = 0;
|
|
|
|
m_fstate = wxSFILE_STOPPED;
|
|
|
|
Clear(wxSND_KEEPQUEUED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fpos += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxSndFileCodec::OnBufferInFinished(char *iobuf, wxUint32& size)
|
|
|
|
{
|
|
|
|
wxUint32 datas_left = m_fsize-m_fdone;
|
|
|
|
|
|
|
|
if (m_fstate != wxSFILE_RECORDING) {
|
|
|
|
size = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!datas_left) {
|
|
|
|
size = 0;
|
|
|
|
Clear(wxSND_KEEPQUEUED); // To be sure.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size > datas_left)
|
|
|
|
size = datas_left;
|
|
|
|
|
|
|
|
OnWriteData(iobuf, size);
|
|
|
|
m_fdone += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxMMtime wxSndFileCodec::GetPosition()
|
|
|
|
{
|
|
|
|
wxMMtime mm_time;
|
|
|
|
wxUint32 sec1, sec2;
|
|
|
|
wxUint32 byterate;
|
|
|
|
|
|
|
|
byterate = m_sndformat.GetCodec()->GetByteRate();
|
|
|
|
|
|
|
|
if (m_fpos && byterate) {
|
|
|
|
sec1 = m_fpos / byterate;
|
|
|
|
sec2 = sec1 % 3600;
|
|
|
|
mm_time.hours = sec1 / 3600;
|
|
|
|
mm_time.minutes = sec2 / 60;
|
|
|
|
mm_time.seconds = sec2 % 60;
|
|
|
|
} else {
|
|
|
|
mm_time.hours = 0;
|
|
|
|
mm_time.minutes = 0;
|
|
|
|
mm_time.seconds = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mm_time;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxMMtime wxSndFileCodec::GetLength()
|
|
|
|
{
|
|
|
|
if (m_sndtime.hours == -1 && m_istream)
|
1999-02-18 13:18:06 -05:00
|
|
|
m_fsize = PrepareToPlay();
|
1998-11-09 13:37:38 -05:00
|
|
|
|
|
|
|
return m_sndtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wxSndFileCodec::TranslateBuffer(wxSndBuffer& buf)
|
|
|
|
{
|
|
|
|
#define TMP_BUFSIZE 10240
|
|
|
|
|
|
|
|
wxStreamBuffer *tmp_buf;
|
|
|
|
wxSoundCodec *codec_in, *codec_out;
|
|
|
|
wxSoundDataFormat std_format;
|
|
|
|
|
|
|
|
if (!m_ostream || !buf.RestartBuffer(wxSND_OUTPUT))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
m_sndformat = buf.GetFormat();
|
|
|
|
codec_in = buf.GetCurrentCodec();
|
|
|
|
|
|
|
|
m_fdone = 0;
|
|
|
|
|
|
|
|
if (!PrepareToRecord(m_fsize))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
codec_out = GetCurrentCodec();
|
|
|
|
m_fsize = (int)(((float)buf.GetSize() / codec_in->GetByteRate()) *
|
|
|
|
codec_out->GetByteRate());
|
|
|
|
|
|
|
|
if (!PrepareToRecord(m_fsize))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
codec_out = GetCurrentCodec();
|
|
|
|
codec_in->InitIO(m_sndformat);
|
|
|
|
codec_out->InitIO(m_sndformat);
|
|
|
|
|
|
|
|
tmp_buf = new wxStreamBuffer(wxStreamBuffer::read_write);
|
|
|
|
tmp_buf->Fixed(TRUE);
|
|
|
|
tmp_buf->Flushable(FALSE);
|
|
|
|
tmp_buf->SetBufferIO(TMP_BUFSIZE);
|
|
|
|
|
|
|
|
m_fstate = wxSFILE_RECORDING;
|
|
|
|
|
|
|
|
while (m_fdone < m_fsize) {
|
|
|
|
tmp_buf->ResetBuffer();
|
|
|
|
codec_in->SetOutStream(tmp_buf);
|
|
|
|
codec_in->Decode();
|
|
|
|
|
|
|
|
tmp_buf->ResetBuffer();
|
|
|
|
codec_out->SetInStream(tmp_buf);
|
|
|
|
codec_out->Encode();
|
|
|
|
|
|
|
|
buf.OnBufferOutFinished();
|
|
|
|
}
|
|
|
|
delete tmp_buf;
|
|
|
|
|
|
|
|
m_fstate = wxSFILE_STOPPED;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wxSndFileCodec::RestartBuffer(wxSndMode mode)
|
|
|
|
{
|
|
|
|
if (IsSet(wxSND_BUFLOCKED))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
m_fdone = 0;
|
|
|
|
m_fpos = 0;
|
|
|
|
|
|
|
|
if (mode == wxSND_OUTPUT && m_istream) {
|
|
|
|
m_fsize = PrepareToPlay();
|
|
|
|
m_fstate = wxSFILE_PLAYING;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if (mode == wxSND_INPUT && m_ostream) {
|
|
|
|
m_fsize = 0;
|
|
|
|
m_fstate = wxSFILE_RECORDING;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxUint32 wxSndFileCodec::GetSize() const
|
|
|
|
{
|
|
|
|
return m_fsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxUint32 wxSndFileCodec::Available() const
|
|
|
|
{
|
1998-12-25 06:02:39 -05:00
|
|
|
if (m_fstate == wxSFILE_STOPPED)
|
|
|
|
return 0;
|
1998-11-09 13:37:38 -05:00
|
|
|
return m_fsize-m_fpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Simple API
|
|
|
|
//
|
|
|
|
static wxSoundDevice *dev_snd = NULL;
|
|
|
|
|
|
|
|
bool wxSndFileCodec::StartPlay()
|
|
|
|
{
|
|
|
|
if (!dev_snd)
|
|
|
|
dev_snd = new wxSoundDevice;
|
|
|
|
|
|
|
|
Play(*dev_snd);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxSndFileCodec::StopPlay()
|
|
|
|
{
|
|
|
|
if (!dev_snd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Stop(*dev_snd);
|
|
|
|
m_fpos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
class wxSoundModule : public wxModule {
|
|
|
|
DECLARE_DYNAMIC_CLASS(wxSoundModule)
|
|
|
|
public:
|
|
|
|
virtual bool OnInit() { return TRUE; }
|
|
|
|
virtual void OnExit() {
|
|
|
|
if (dev_snd)
|
|
|
|
delete dev_snd;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxSoundModule, wxModule)
|