git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1722 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			326 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
////////////////////////////////////////////////////////////////////////////////
 | 
						|
// 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;
 | 
						|
 | 
						|
  if (m_fstate != wxSFILE_PREPARED_TO_PLAY)
 | 
						|
    if (!(m_fsize = PrepareToPlay()))
 | 
						|
      return;
 | 
						|
 | 
						|
  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)
 | 
						|
    m_fsize = PrepareToPlay();
 | 
						|
 | 
						|
  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
 | 
						|
{
 | 
						|
  if (m_fstate == wxSFILE_STOPPED)
 | 
						|
    return 0;
 | 
						|
  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)
 |