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>
17 #include <wx/mstream.h>
26 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
28 #define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
29 #define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
30 #define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
31 #define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
33 #define HEADER_SIZE 4+4 + 4+4+16 + 4+4
37 wxSoundWave::wxSoundWave(wxInputStream
& stream
, wxSoundStream
& io_sound
)
38 : wxSoundFileStream(stream
, io_sound
)
42 wxSoundWave::wxSoundWave(wxOutputStream
& stream
, wxSoundStream
& io_sound
)
43 : wxSoundFileStream(stream
, io_sound
)
47 wxSoundWave::~wxSoundWave()
51 wxString
wxSoundWave::GetCodecName() const
53 return wxString(wxT("wxSoundWave codec"));
56 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
58 bool wxSoundWave::CanRead()
60 wxUint32 len
, signature1
, signature2
;
61 m_snderror
= wxSOUND_NOERR
;
63 FAIL_WITH(m_input
->Read(&signature1
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
65 if (wxUINT32_SWAP_ON_BE(signature1
) != RIFF_SIGNATURE
) {
66 m_input
->Ungetch(&signature1
, 4);
70 m_input
->Read(&len
, 4);
71 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
73 FAIL_WITH(m_input
->Read(&signature2
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
74 m_input
->Ungetch(&signature2
, 4);
75 m_input
->Ungetch(&len
, 4);
76 m_input
->Ungetch(&signature1
, 4);
78 if (wxUINT32_SWAP_ON_BE(signature2
) != WAVE_SIGNATURE
)
84 bool wxSoundWave::HandleOutputPCM(wxDataInputStream
& data
, wxUint16 channels
,
85 wxUint32 sample_fq
, wxUint32 byte_p_sec
,
86 wxUint16 byte_p_spl
, wxUint16 bits_p_spl
)
88 wxSoundFormatPcm sndformat
;
90 sndformat
.SetSampleRate(sample_fq
);
91 sndformat
.SetBPS(bits_p_spl
);
92 sndformat
.SetChannels(channels
);
93 sndformat
.Signed(TRUE
);
94 sndformat
.SetOrder(wxLITTLE_ENDIAN
);
96 if (!SetSoundFormat(sndformat
))
102 bool wxSoundWave::HandleOutputG721(wxDataInputStream
& data
, wxUint16 channels
,
103 wxUint32 sample_fq
, wxUint32 byte_p_sec
,
104 wxUint16 byte_p_spl
, wxUint16 bits_p_spl
)
106 wxSoundFormatG72X sndformat
;
108 sndformat
.SetSampleRate(sample_fq
);
109 sndformat
.SetG72XType(wxSOUND_G721
);
111 if (!SetSoundFormat(sndformat
))
117 bool wxSoundWave::PrepareToPlay()
119 wxUint32 signature
, len
;
123 m_snderror
= wxSOUND_INVSTRM
;
127 wxDataInputStream
data(*m_input
);
128 data
.BigEndianOrdered(FALSE
);
130 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
131 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
, wxSOUND_INVSTRM
);
135 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
138 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
139 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
, wxSOUND_INVSTRM
);
143 while (!end_headers
) {
144 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
147 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
149 switch (wxUINT32_SWAP_ON_BE(signature
)) {
150 case FMT_SIGNATURE
: { // "fmt "
151 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
152 wxUint32 sample_fq
, byte_p_sec
;
154 data
>> format
>> channels
>> sample_fq
155 >> byte_p_sec
>> byte_p_spl
>> bits_p_spl
;
159 if (!HandleOutputPCM(data
, channels
, sample_fq
,
160 byte_p_sec
, byte_p_spl
, bits_p_spl
))
164 if (!HandleOutputG721(data
, channels
, sample_fq
,
165 byte_p_sec
, byte_p_spl
, bits_p_spl
))
169 m_snderror
= wxSOUND_NOCODEC
;
174 case DATA_SIGNATURE
: // "data"
176 FinishPreparation(len
);
179 m_input
->SeekI(len
, wxFromCurrent
);
186 wxSoundFormatBase
*wxSoundWave::HandleInputPCM(wxDataOutputStream
& data
)
188 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
189 wxUint32 sample_fq
, byte_p_sec
;
190 wxSoundFormatPcm
*pcm
;
192 pcm
= (wxSoundFormatPcm
*)(m_sndformat
->Clone());
194 // Write block length
197 sample_fq
= pcm
->GetSampleRate();
198 bits_p_spl
= pcm
->GetBPS();
199 channels
= pcm
->GetChannels();
200 byte_p_spl
= pcm
->GetBPS() / 8;
201 byte_p_sec
= pcm
->GetBytesFromTime(1);
205 pcm
->SetOrder(wxLITTLE_ENDIAN
);
207 data
<< format
<< channels
<< sample_fq
208 << byte_p_sec
<< byte_p_spl
<< bits_p_spl
;
213 wxSoundFormatBase
*wxSoundWave::HandleInputG72X(wxDataOutputStream
& data
)
215 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
216 wxUint32 sample_fq
, byte_p_sec
;
217 wxSoundFormatG72X
*g72x
;
219 // Write block length
222 g72x
= (wxSoundFormatG72X
*)(m_sndformat
->Clone());
223 if (g72x
->GetG72XType() != wxSOUND_G721
) {
228 sample_fq
= g72x
->GetSampleRate();
232 byte_p_sec
= g72x
->GetBytesFromTime(1);
234 data
<< format
<< channels
<< sample_fq
235 << byte_p_sec
<< byte_p_spl
<< bits_p_spl
;
240 bool wxSoundWave::PrepareToRecord(unsigned long time
)
242 #define WRITE_SIGNATURE(s,sig) \
244 signature = wxUINT32_SWAP_ON_BE(signature); \
245 FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
248 wxMemoryOutputStream fmt_data
;
251 m_snderror
= wxSOUND_INVSTRM
;
255 wxDataOutputStream
data(*m_output
);
256 wxDataOutputStream
fmt_d_data(fmt_data
);
258 data
.BigEndianOrdered(FALSE
);
259 fmt_d_data
.BigEndianOrdered(FALSE
);
261 WRITE_SIGNATURE(m_output
, RIFF_SIGNATURE
);
263 FAIL_WITH(m_output
->LastWrite() != 4, wxSOUND_INVSTRM
);
265 WRITE_SIGNATURE((&fmt_data
), WAVE_SIGNATURE
);
268 wxSoundFormatBase
*frmt
;
270 WRITE_SIGNATURE((&fmt_data
), FMT_SIGNATURE
);
272 switch (m_sndformat
->GetType()) {
274 frmt
= HandleInputPCM(fmt_d_data
);
277 frmt
= HandleInputG72X(fmt_d_data
);
280 m_snderror
= wxSOUND_NOCODEC
;
284 FAIL_WITH(!frmt
, wxSOUND_NOCODEC
);
286 if (!SetSoundFormat(*frmt
)) {
294 data
<< (fmt_data
.GetSize() + m_sndformat
->GetBytesFromTime(time
));
298 out_buf
= new char[fmt_data
.GetSize()];
300 fmt_data
.CopyTo(out_buf
, fmt_data
.GetSize());
301 m_output
->Write(out_buf
, fmt_data
.GetSize());
306 WRITE_SIGNATURE(m_output
, DATA_SIGNATURE
);
307 data
.Write32(m_sndformat
->GetBytesFromTime(time
));
311 bool wxSoundWave::FinishRecording()
313 if (m_output
->SeekO(0, wxFromStart
) == wxInvalidOffset
)
314 // We can't but there is no error.
317 if (m_bytes_left
== 0)
320 // TODO: Update headers when we stop before the specified time (if possible)
324 wxUint32
wxSoundWave::GetData(void *buffer
, wxUint32 len
)
326 return m_input
->Read(buffer
, len
).LastRead();
329 wxUint32
wxSoundWave::PutData(const void *buffer
, wxUint32 len
)
331 return m_output
->Write(buffer
, len
).LastWrite();