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>
25 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
27 #define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
28 #define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
29 #define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
30 #define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
32 #define HEADER_SIZE 4+4 + 4+4+16 + 4+4
36 wxSoundWave::wxSoundWave(wxInputStream
& stream
, wxSoundStream
& io_sound
)
37 : wxSoundFileStream(stream
, io_sound
)
41 wxSoundWave::wxSoundWave(wxOutputStream
& stream
, wxSoundStream
& io_sound
)
42 : wxSoundFileStream(stream
, io_sound
)
46 wxSoundWave::~wxSoundWave()
50 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
52 bool wxSoundWave::CanRead()
54 wxUint32 len
, signature
;
55 m_snderror
= wxSOUND_NOERR
;
57 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
59 if (wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
) {
60 m_input
->Ungetch(&signature
, 4);
64 m_input
->Read(&len
, 4);
65 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
67 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
68 if (wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
) {
69 m_input
->Ungetch(&signature
, 4);
73 m_input
->Ungetch("RIFF", 4);
74 m_input
->Ungetch(&len
, 4);
75 m_input
->Ungetch("WAVE", 4);
80 bool wxSoundWave::HandleOutputPCM(wxDataInputStream
& data
, wxUint16 channels
,
81 wxUint32 sample_fq
, wxUint32 byte_p_sec
,
82 wxUint16 byte_p_spl
, wxUint16 bits_p_spl
)
84 wxSoundFormatPcm sndformat
;
86 sndformat
.SetSampleRate(sample_fq
);
87 sndformat
.SetBPS(bits_p_spl
);
88 sndformat
.SetChannels(channels
);
89 sndformat
.Signed(TRUE
);
90 sndformat
.SetOrder(wxLITTLE_ENDIAN
);
92 if (!SetSoundFormat(sndformat
))
98 bool wxSoundWave::HandleOutputG721(wxDataInputStream
& data
, wxUint16 channels
,
99 wxUint32 sample_fq
, wxUint32 byte_p_sec
,
100 wxUint16 byte_p_spl
, wxUint16 bits_p_spl
)
102 wxSoundFormatG72X sndformat
;
104 sndformat
.SetSampleRate(sample_fq
);
105 sndformat
.SetG72XType(wxSOUND_G721
);
107 if (!SetSoundFormat(sndformat
))
113 bool wxSoundWave::PrepareToPlay()
115 wxUint32 signature
, len
;
119 m_snderror
= wxSOUND_INVSTRM
;
123 wxDataInputStream
data(*m_input
);
124 data
.BigEndianOrdered(FALSE
);
126 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
127 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
, wxSOUND_INVSTRM
);
131 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
134 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
135 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
, wxSOUND_INVSTRM
);
139 while (!end_headers
) {
140 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
143 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
145 switch (wxUINT32_SWAP_ON_BE(signature
)) {
146 case FMT_SIGNATURE
: { // "fmt "
147 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
148 wxUint32 sample_fq
, byte_p_sec
;
150 data
>> format
>> channels
>> sample_fq
151 >> byte_p_sec
>> byte_p_spl
>> bits_p_spl
;
155 if (!HandleOutputPCM(data
, channels
, sample_fq
,
156 byte_p_sec
, byte_p_spl
, bits_p_spl
))
160 if (!HandleOutputG721(data
, channels
, sample_fq
,
161 byte_p_sec
, byte_p_spl
, bits_p_spl
))
165 m_snderror
= wxSOUND_NOCODEC
;
170 case DATA_SIGNATURE
: // "data"
174 m_input
->SeekI(len
, wxFromCurrent
);
181 wxSoundFormatBase
*wxSoundWave::HandleInputPCM(wxDataOutputStream
& data
)
183 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
184 wxUint32 sample_fq
, byte_p_sec
;
185 wxSoundFormatPcm
*pcm
;
187 pcm
= (wxSoundFormatPcm
*)(m_sndformat
->Clone());
189 // Write block length
192 sample_fq
= pcm
->GetSampleRate();
193 bits_p_spl
= pcm
->GetBPS();
194 channels
= pcm
->GetChannels();
195 byte_p_spl
= pcm
->GetBPS() / 8;
196 byte_p_sec
= pcm
->GetBytesFromTime(1);
200 pcm
->SetOrder(wxLITTLE_ENDIAN
);
202 data
<< format
<< channels
<< sample_fq
203 << byte_p_sec
<< byte_p_spl
<< bits_p_spl
;
208 wxSoundFormatBase
*wxSoundWave::HandleInputG72X(wxDataOutputStream
& data
)
210 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
211 wxUint32 sample_fq
, byte_p_sec
;
212 wxSoundFormatG72X
*g72x
;
214 // Write block length
217 g72x
= (wxSoundFormatG72X
*)(m_sndformat
->Clone());
218 if (g72x
->GetG72XType() != wxSOUND_G721
) {
223 sample_fq
= g72x
->GetSampleRate();
227 byte_p_sec
= g72x
->GetBytesFromTime(1);
229 data
<< format
<< channels
<< sample_fq
230 << byte_p_sec
<< byte_p_spl
<< bits_p_spl
;
235 bool wxSoundWave::PrepareToRecord(unsigned long time
)
237 #define WRITE_SIGNATURE(sig) \
239 signature = wxUINT32_SWAP_ON_BE(signature); \
240 FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
242 wxUint32 signature
, len
;
245 m_snderror
= wxSOUND_INVSTRM
;
249 wxDataOutputStream
data(*m_output
);
250 data
.BigEndianOrdered(FALSE
);
252 len
= m_sndformat
->GetBytesFromTime(time
);
256 WRITE_SIGNATURE(RIFF_SIGNATURE
);
259 FAIL_WITH(m_output
->LastWrite() != 4, wxSOUND_INVSTRM
);
261 WRITE_SIGNATURE(WAVE_SIGNATURE
);
264 wxSoundFormatBase
*frmt
;
266 WRITE_SIGNATURE(FMT_SIGNATURE
);
268 switch (m_sndformat
->GetType()) {
270 frmt
= HandleInputPCM(data
);
273 frmt
= HandleInputG72X(data
);
276 m_snderror
= wxSOUND_NOCODEC
;
280 FAIL_WITH(!frmt
, wxSOUND_NOCODEC
);
282 if (!SetSoundFormat(*frmt
)) {
290 WRITE_SIGNATURE(DATA_SIGNATURE
);
291 data
.Write32(m_sndformat
->GetBytesFromTime(time
));
295 bool wxSoundWave::FinishRecording()
297 // TODO: Update headers when we stop before the specified time (if possible)
301 wxUint32
wxSoundWave::GetData(void *buffer
, wxUint32 len
)
303 return m_input
->Read(buffer
, len
).LastRead();
306 wxUint32
wxSoundWave::PutData(const void *buffer
, wxUint32 len
)
308 return m_output
->Write(buffer
, len
).LastWrite();