1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
7 // --------------------------------------------------------------------------
9 #pragma implementation "sndwav.cpp"
12 #include <wx/wxprec.h>
14 #include <wx/stream.h>
15 #include <wx/datstrm.h>
16 #include <wx/filefn.h>
24 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
26 #define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
27 #define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
28 #define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
29 #define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
31 #define HEADER_SIZE 4+4 + 4+4+16 + 4+4
35 wxSoundWave::wxSoundWave(wxInputStream
& stream
, wxSoundStream
& io_sound
)
36 : wxSoundFileStream(stream
, io_sound
)
40 wxSoundWave::wxSoundWave(wxOutputStream
& stream
, wxSoundStream
& io_sound
)
41 : wxSoundFileStream(stream
, io_sound
)
45 wxSoundWave::~wxSoundWave()
49 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
51 bool wxSoundWave::CanRead()
53 wxUint32 len
, signature
;
54 m_snderror
= wxSOUND_NOERR
;
56 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
58 if (wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
) {
59 m_input
->Ungetch(&signature
, 4);
63 m_input
->Read(&len
, 4);
64 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
66 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
67 if (wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
) {
68 m_input
->Ungetch(&signature
, 4);
72 m_input
->Ungetch("RIFF", 4);
73 m_input
->Ungetch(&len
, 4);
74 m_input
->Ungetch("WAVE", 4);
79 bool wxSoundWave::PrepareToPlay()
81 wxUint32 signature
, len
;
85 m_snderror
= wxSOUND_INVSTRM
;
89 wxDataInputStream
data(*m_input
);
90 data
.BigEndianOrdered(FALSE
);
92 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
93 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
, wxSOUND_INVSTRM
);
97 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
100 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
101 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
, wxSOUND_INVSTRM
);
105 while (!end_headers
) {
106 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
109 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
111 switch (wxUINT32_SWAP_ON_BE(signature
)) {
112 case FMT_SIGNATURE
: { // "fmt "
113 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
114 wxUint32 sample_fq
, byte_p_sec
;
115 wxSoundFormatPcm sndformat
;
117 data
>> format
>> channels
>> sample_fq
118 >> byte_p_sec
>> byte_p_spl
>> bits_p_spl
;
119 FAIL_WITH(format
!= 1, wxSOUND_NOCODEC
);
121 sndformat
.SetSampleRate(sample_fq
);
122 sndformat
.SetBPS(bits_p_spl
);
123 sndformat
.SetChannels(channels
);
124 sndformat
.Signed(TRUE
);
125 sndformat
.SetOrder(wxLITTLE_ENDIAN
);
127 if (!SetSoundFormat(sndformat
))
129 m_input
->SeekI(len
-16, wxFromCurrent
);
132 case DATA_SIGNATURE
: // "data"
136 m_input
->SeekI(len
, wxFromCurrent
);
143 bool wxSoundWave::PrepareToRecord(unsigned long time
)
145 #define WRITE_SIGNATURE(sig) \
147 signature = wxUINT32_SWAP_ON_BE(signature); \
148 FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
150 wxUint32 signature
, len
;
153 m_snderror
= wxSOUND_INVSTRM
;
157 wxDataOutputStream
data(*m_output
);
158 data
.BigEndianOrdered(FALSE
);
160 len
= m_sndformat
->GetBytesFromTime(time
);
164 WRITE_SIGNATURE(RIFF_SIGNATURE
);
167 FAIL_WITH(m_output
->LastWrite() != 4, wxSOUND_INVSTRM
);
169 WRITE_SIGNATURE(WAVE_SIGNATURE
);
172 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
173 wxUint32 sample_fq
, byte_p_sec
;
174 wxSoundFormatPcm
*pcm
;
176 if (m_sndformat
->GetType() != wxSOUND_PCM
) {
177 m_snderror
= wxSOUND_NOCODEC
;
181 pcm
= (wxSoundFormatPcm
*)(m_sndformat
->Clone());
183 WRITE_SIGNATURE(FMT_SIGNATURE
);
186 sample_fq
= pcm
->GetSampleRate();
187 bits_p_spl
= pcm
->GetBPS();
188 channels
= pcm
->GetChannels();
189 byte_p_spl
= pcm
->GetBPS() / 8;
190 byte_p_sec
= pcm
->GetBytesFromTime(1);
192 data
<< format
<< channels
<< sample_fq
193 << byte_p_sec
<< byte_p_spl
<< bits_p_spl
;
196 pcm
->SetOrder(wxLITTLE_ENDIAN
);
198 if (!SetSoundFormat(*pcm
))
204 WRITE_SIGNATURE(DATA_SIGNATURE
);
205 data
.Write32(m_sndformat
->GetBytesFromTime(time
));
209 bool wxSoundWave::FinishRecording()
211 // TODO: Update headers when we stop before the specified time (if possible)
215 size_t wxSoundWave::GetData(void *buffer
, size_t len
)
217 return m_input
->Read(buffer
, len
).LastRead();
220 size_t wxSoundWave::PutData(const void *buffer
, size_t len
)
222 return m_output
->Write(buffer
, len
).LastWrite();