X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/526ddb13e289be62ee1926c265138c0dea36fa56..7d533797a0cca03359b6a23e7e54fb1c648eb998:/utils/wxMMedia2/lib/sndwav.cpp diff --git a/utils/wxMMedia2/lib/sndwav.cpp b/utils/wxMMedia2/lib/sndwav.cpp index be6f1b3777..509a004009 100644 --- a/utils/wxMMedia2/lib/sndwav.cpp +++ b/utils/wxMMedia2/lib/sndwav.cpp @@ -9,14 +9,18 @@ #pragma implementation "sndwav.cpp" #endif -#include +#include + #include #include #include +#include + #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->GetByteFromTime(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->GetByteFromTime(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); - data.Write32(m_sndformat->GetByteFromTime(time)); + 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(); }