1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
7 // --------------------------------------------------------------------------
9 #pragma implementation "sndwav.cpp"
13 #include <wx/stream.h>
14 #include <wx/datstrm.h>
15 #include <wx/filefn.h>
22 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
24 #define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
25 #define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
26 #define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
27 #define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
29 #define HEADER_SIZE 4+4 + 4+4+16 + 4+4
33 wxSoundWave::wxSoundWave(wxInputStream
& stream
, wxSoundStream
& io_sound
)
34 : wxSoundFileStream(stream
, io_sound
)
38 wxSoundWave::wxSoundWave(wxOutputStream
& stream
, wxSoundStream
& io_sound
)
39 : wxSoundFileStream(stream
, io_sound
)
43 wxSoundWave::~wxSoundWave()
47 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
49 bool wxSoundWave::CanRead()
51 wxUint32 len
, signature
;
52 m_snderror
= wxSOUND_NOERR
;
54 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
56 if (wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
) {
57 m_input
->Ungetch(&signature
, 4);
61 m_input
->Read(&len
, 4);
62 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
64 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
65 if (wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
) {
66 m_input
->Ungetch(&signature
, 4);
70 m_input
->Ungetch("RIFF", 4);
71 m_input
->Ungetch(&len
, 4);
72 m_input
->Ungetch("WAVE", 4);
77 bool wxSoundWave::PrepareToPlay()
79 wxUint32 signature
, len
;
83 m_snderror
= wxSOUND_INVSTRM
;
87 wxDataInputStream
data(*m_input
);
88 data
.BigEndianOrdered(FALSE
);
90 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
91 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
, wxSOUND_INVSTRM
);
95 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
98 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
99 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
, wxSOUND_INVSTRM
);
103 while (!end_headers
) {
104 FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
);
107 FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
);
109 switch (wxUINT32_SWAP_ON_BE(signature
)) {
110 case FMT_SIGNATURE
: { // "fmt "
111 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
112 wxUint32 sample_fq
, byte_p_sec
;
113 wxSoundFormatPcm sndformat
;
115 data
>> format
>> channels
>> sample_fq
116 >> byte_p_sec
>> byte_p_spl
>> bits_p_spl
;
117 FAIL_WITH(format
!= 1, wxSOUND_NOCODEC
);
119 sndformat
.SetSampleRate(sample_fq
);
120 sndformat
.SetBPS(bits_p_spl
);
121 sndformat
.SetChannels(channels
);
122 sndformat
.Signed(TRUE
);
123 sndformat
.SetOrder(wxLITTLE_ENDIAN
);
125 if (!SetSoundFormat(sndformat
))
127 m_input
->SeekI(len
-16, wxFromCurrent
);
130 case DATA_SIGNATURE
: // "data"
134 m_input
->SeekI(len
, wxFromCurrent
);
141 bool wxSoundWave::PrepareToRecord(unsigned long time
)
143 #define WRITE_SIGNATURE(sig) \
145 signature = wxUINT32_SWAP_ON_BE(signature); \
146 FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
148 wxUint32 signature
, len
;
151 m_snderror
= wxSOUND_INVSTRM
;
155 wxDataOutputStream
data(*m_output
);
156 data
.BigEndianOrdered(FALSE
);
158 len
= m_sndformat
->GetBytesFromTime(time
);
162 WRITE_SIGNATURE(RIFF_SIGNATURE
);
165 FAIL_WITH(m_output
->LastWrite() != 4, wxSOUND_INVSTRM
);
167 WRITE_SIGNATURE(WAVE_SIGNATURE
);
170 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
;
171 wxUint32 sample_fq
, byte_p_sec
;
172 wxSoundFormatPcm
*pcm
;
174 if (m_sndformat
->GetType() != wxSOUND_PCM
) {
175 m_snderror
= wxSOUND_NOCODEC
;
179 pcm
= (wxSoundFormatPcm
*)(m_sndformat
->Clone());
181 WRITE_SIGNATURE(FMT_SIGNATURE
);
184 sample_fq
= pcm
->GetSampleRate();
185 bits_p_spl
= pcm
->GetBPS();
186 channels
= pcm
->GetChannels();
187 byte_p_spl
= pcm
->GetBPS() / 8;
188 byte_p_sec
= pcm
->GetBytesFromTime(1);
190 data
<< format
<< channels
<< sample_fq
191 << byte_p_sec
<< byte_p_spl
<< bits_p_spl
;
194 pcm
->SetOrder(wxLITTLE_ENDIAN
);
196 if (!SetSoundFormat(*pcm
))
202 WRITE_SIGNATURE(DATA_SIGNATURE
);
203 data
.Write32(m_sndformat
->GetBytesFromTime(time
));
207 bool wxSoundWave::FinishRecording()
209 // TODO: Update headers when we stop before the specified time (if possible)
213 size_t wxSoundWave::GetData(void *buffer
, size_t len
)
215 return m_input
->Read(buffer
, len
).LastRead();
218 size_t wxSoundWave::PutData(const void *buffer
, size_t len
)
220 return m_output
->Write(buffer
, len
).LastWrite();