]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/wxMMedia2/lib/sndwav.cpp
* ESD works in full duplex (theorically)
[wxWidgets.git] / utils / wxMMedia2 / lib / sndwav.cpp
index 9cd9fb2f84e1d159f0984737a059dcdbfaae31bf..509a004009ea504e6021e15aa59d7f0bb41dcfc0 100644 (file)
@@ -9,14 +9,18 @@
 #pragma implementation "sndwav.cpp"
 #endif
 
-#include <wx/defs.h>
+#include <wx/wxprec.h>
+
 #include <wx/stream.h>
 #include <wx/datstrm.h>
 #include <wx/filefn.h>
+#include <wx/mstream.h>
+
 #include "sndbase.h"
 #include "sndcodec.h"
 #include "sndfile.h"
 #include "sndpcm.h"
+#include "sndg72x.h"
 #include "sndwav.h"
 
 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16)  | (((wxUint32)d) << 24)) 
@@ -48,28 +52,59 @@ wxSoundWave::~wxSoundWave()
 
 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);
+  FAIL_WITH(m_input->Read(&signature2, 4).LastRead() != 4, wxSOUND_INVSTRM);
+  m_input->Ungetch(&signature2, 4);
+  m_input->Ungetch(&len, 4);
+  m_input->Ungetch(&signature1, 4);
+
+  if (wxUINT32_SWAP_ON_BE(signature2) != WAVE_SIGNATURE)
     return FALSE;
-  }
 
-  m_input->Ungetch("RIFF", 4);
-  m_input->Ungetch(&len, 4);
-  m_input->Ungetch("WAVE", 4);
+  return TRUE;
+}
+
+bool wxSoundWave::HandleOutputPCM(wxDataInputStream& data, wxUint16 channels, 
+                            wxUint32 sample_fq, wxUint32 byte_p_sec,
+                            wxUint16 byte_p_spl, wxUint16 bits_p_spl)
+{
+  wxSoundFormatPcm sndformat;
+
+  sndformat.SetSampleRate(sample_fq);
+  sndformat.SetBPS(bits_p_spl);
+  sndformat.SetChannels(channels);
+  sndformat.Signed(TRUE);
+  sndformat.SetOrder(wxLITTLE_ENDIAN);
+
+  if (!SetSoundFormat(sndformat))
+    return FALSE;
+
+  return TRUE;
+}
+
+bool wxSoundWave::HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
+                             wxUint32 sample_fq, wxUint32 byte_p_sec,
+                             wxUint16 byte_p_spl, wxUint16 bits_p_spl)
+{
+  wxSoundFormatG72X sndformat;
+
+  sndformat.SetSampleRate(sample_fq);
+  sndformat.SetG72XType(wxSOUND_G721);
+  if (!SetSoundFormat(sndformat))
+    return FALSE;
 
   return TRUE;
 }
@@ -110,25 +145,30 @@ bool wxSoundWave::PrepareToPlay()
     case FMT_SIGNATURE: {  // "fmt "
       wxUint16 format, channels, byte_p_spl, bits_p_spl;
       wxUint32 sample_fq, byte_p_sec;
-      wxSoundFormatPcm sndformat;
 
       data >> format >> channels >> sample_fq 
            >> byte_p_sec >> byte_p_spl >> bits_p_spl;
-      FAIL_WITH(format != 1, wxSOUND_NOCODEC);
-      
-      sndformat.SetSampleRate(sample_fq);
-      sndformat.SetBPS(bits_p_spl);
-      sndformat.SetChannels(channels);
-      sndformat.Signed(TRUE);
-      sndformat.SetOrder(wxLITTLE_ENDIAN);
-
-      if (!SetSoundFormat(sndformat))
+
+      switch (format) {
+      case 0x01:
+        if (!HandleOutputPCM(data, channels, sample_fq,
+                       byte_p_sec, byte_p_spl, bits_p_spl))
+          return FALSE;
+        break;
+      case 0x40:
+        if (!HandleOutputG721(data, channels, sample_fq,
+                        byte_p_sec, byte_p_spl, bits_p_spl))
+          return FALSE;
+        break;
+      default: 
+        m_snderror = wxSOUND_NOCODEC;
         return FALSE;
-      m_input->SeekI(len-16, wxFromCurrent);
+      }
       break;
     }
     case DATA_SIGNATURE: // "data"
       end_headers = TRUE;
+      FinishPreparation(len);
       break;
     default:
       m_input->SeekI(len, wxFromCurrent);
@@ -138,14 +178,69 @@ bool wxSoundWave::PrepareToPlay()
   return TRUE;
 }
 
+wxSoundFormatBase *wxSoundWave::HandleInputPCM(wxDataOutputStream& data)
+{
+  wxUint16 format, channels, byte_p_spl, bits_p_spl;
+  wxUint32 sample_fq, byte_p_sec;
+  wxSoundFormatPcm *pcm;
+
+  pcm = (wxSoundFormatPcm *)(m_sndformat->Clone());
+
+  // Write block length
+  data.Write32(16);
+
+  sample_fq  = pcm->GetSampleRate();
+  bits_p_spl = pcm->GetBPS();
+  channels   = pcm->GetChannels();
+  byte_p_spl = pcm->GetBPS() / 8;
+  byte_p_sec = pcm->GetBytesFromTime(1);
+  format     = 0x01;
+
+  pcm->Signed(TRUE);
+  pcm->SetOrder(wxLITTLE_ENDIAN);
+
+  data << format << channels << sample_fq
+       << byte_p_sec << byte_p_spl << bits_p_spl;
+
+  return pcm;
+}
+
+wxSoundFormatBase *wxSoundWave::HandleInputG72X(wxDataOutputStream& data)
+{
+  wxUint16 format, channels, byte_p_spl, bits_p_spl;
+  wxUint32 sample_fq, byte_p_sec;
+  wxSoundFormatG72X *g72x;
+
+  // Write block length
+  data.Write32(16);
+
+  g72x = (wxSoundFormatG72X *)(m_sndformat->Clone());
+  if (g72x->GetG72XType() != wxSOUND_G721) {
+    delete g72x;
+    return NULL;
+  } 
+
+  sample_fq  = g72x->GetSampleRate();
+  bits_p_spl = 4;
+  channels   = 1;
+  byte_p_spl = 0;
+  byte_p_sec = g72x->GetBytesFromTime(1);
+  format     = 0x40;
+  data << format << channels << sample_fq
+       << byte_p_sec << byte_p_spl << bits_p_spl;
+
+  return g72x;
+}
+
 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;
@@ -153,69 +248,80 @@ FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
   }
 
   wxDataOutputStream data(*m_output);
-  data.BigEndianOrdered(FALSE);
-
-  len = m_sndformat->GetBytesFromTime(time);
+  wxDataOutputStream fmt_d_data(fmt_data);
 
-  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);
 
   {
-    wxUint16 format, channels, byte_p_spl, bits_p_spl;
-    wxUint32 sample_fq, byte_p_sec;
-    wxSoundFormatPcm *pcm;
+    wxSoundFormatBase *frmt;
 
-    if (m_sndformat->GetType() != wxSOUND_PCM) {
+    WRITE_SIGNATURE((&fmt_data), FMT_SIGNATURE);
+
+    switch (m_sndformat->GetType()) {
+    case wxSOUND_PCM:
+      frmt = HandleInputPCM(fmt_d_data);
+      break;
+    case wxSOUND_G72X:
+      frmt = HandleInputG72X(fmt_d_data);
+      break;
+    default:
       m_snderror = wxSOUND_NOCODEC;
       return FALSE;
     }
 
-    pcm = (wxSoundFormatPcm *)(m_sndformat->Clone());
+    FAIL_WITH(!frmt, wxSOUND_NOCODEC);
 
-    WRITE_SIGNATURE(FMT_SIGNATURE);
-    data.Write32(16);
+    if (!SetSoundFormat(*frmt)) {
+      delete frmt;
+      return FALSE;
+    }
 
-    sample_fq  = pcm->GetSampleRate();
-    bits_p_spl = pcm->GetBPS();
-    channels   = pcm->GetChannels();
-    byte_p_spl = pcm->GetBPS() / 8;
-    byte_p_sec = pcm->GetBytesFromTime(1);
-    format     = 1;
-    data << format << channels << sample_fq
-         << byte_p_sec << byte_p_spl << bits_p_spl;
+    delete frmt;
+  }
 
-    pcm->Signed(TRUE);
-    pcm->SetOrder(wxLITTLE_ENDIAN);
-    
-    if (!SetSoundFormat(*pcm))
-      return FALSE;
+  data << (fmt_data.GetSize() + m_sndformat->GetBytesFromTime(time));
+
+  {
+    char *out_buf;
+    out_buf = new char[fmt_data.GetSize()];
 
-    delete pcm;
+    fmt_data.CopyTo(out_buf, fmt_data.GetSize());
+    m_output->Write(out_buf, fmt_data.GetSize());
+
+    delete[] out_buf;
   }
 
-  WRITE_SIGNATURE(DATA_SIGNATURE);
+  WRITE_SIGNATURE(m_output, DATA_SIGNATURE);
   data.Write32(m_sndformat->GetBytesFromTime(time));
   return TRUE;
 }
 
 bool wxSoundWave::FinishRecording()
 {
+  if (m_output->SeekO(0, wxFromStart) == wxInvalidOffset)
+    // We can't but there is no error.
+    return TRUE;
+
+  if (m_bytes_left == 0)
+    return TRUE;
+
   // TODO: Update headers when we stop before the specified time (if possible)
   return TRUE;
 }
 
-size_t wxSoundWave::GetData(void *buffer, size_t len)
+wxUint32 wxSoundWave::GetData(void *buffer, wxUint32 len)
 {
   return m_input->Read(buffer, len).LastRead();
 }
 
-size_t wxSoundWave::PutData(const void *buffer, size_t len)
+wxUint32 wxSoundWave::PutData(const void *buffer, wxUint32 len)
 {
   return m_output->Write(buffer, len).LastWrite();
 }