#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))
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;
}
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);
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;
}
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();
}