]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia2/lib/sndwav.cpp
Added utils/Makefile.in for utils makefiles
[wxWidgets.git] / utils / wxMMedia2 / lib / sndwav.cpp
1 // --------------------------------------------------------------------------
2 // Name: sndwav.cpp
3 // Purpose:
4 // Date: 08/11/1999
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6 // CVSID: $Id$
7 // --------------------------------------------------------------------------
8 #ifdef __GNUG__
9 #pragma implementation "sndwav.cpp"
10 #endif
11
12 #include <wx/defs.h>
13 #include <wx/stream.h>
14 #include <wx/datstrm.h>
15 #include <wx/filefn.h>
16 #include "sndbase.h"
17 #include "sndcodec.h"
18 #include "sndfile.h"
19 #include "sndpcm.h"
20 #include "sndwav.h"
21
22 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
23
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')
28
29 #define HEADER_SIZE 4+4 + 4+4+16 + 4+4
30 // 4+4 => NAME + LEN
31 // 16 => fmt size
32
33 wxSoundWave::wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound)
34 : wxSoundFileStream(stream, io_sound)
35 {
36 }
37
38 wxSoundWave::wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound)
39 : wxSoundFileStream(stream, io_sound)
40 {
41 }
42
43 wxSoundWave::~wxSoundWave()
44 {
45 }
46
47 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
48
49 bool wxSoundWave::CanRead()
50 {
51 wxUint32 len, signature;
52 m_snderror = wxSOUND_NOERR;
53
54 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
55
56 if (wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE) {
57 m_input->Ungetch(&signature, 4);
58 return FALSE;
59 }
60
61 m_input->Read(&len, 4);
62 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
63
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);
67 return FALSE;
68 }
69
70 m_input->Ungetch("RIFF", 4);
71 m_input->Ungetch(&len, 4);
72 m_input->Ungetch("WAVE", 4);
73
74 return TRUE;
75 }
76
77 bool wxSoundWave::PrepareToPlay()
78 {
79 wxUint32 signature, len;
80 bool end_headers;
81
82 if (!m_input) {
83 m_snderror = wxSOUND_INVSTRM;
84 return FALSE;
85 }
86
87 wxDataInputStream data(*m_input);
88 data.BigEndianOrdered(FALSE);
89
90 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
91 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE, wxSOUND_INVSTRM);
92 // "RIFF"
93
94 len = data.Read32();
95 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
96 // dummy len
97
98 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
99 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != WAVE_SIGNATURE, wxSOUND_INVSTRM);
100 // "WAVE"
101
102 end_headers = FALSE;
103 while (!end_headers) {
104 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
105
106 len = data.Read32();
107 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
108
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;
114
115 data >> format >> channels >> sample_fq
116 >> byte_p_sec >> byte_p_spl >> bits_p_spl;
117 FAIL_WITH(format != 1, wxSOUND_NOCODEC);
118
119 sndformat.SetSampleRate(sample_fq);
120 sndformat.SetBPS(bits_p_spl);
121 sndformat.SetChannels(channels);
122 sndformat.Signed(TRUE);
123 sndformat.SetOrder(wxLITTLE_ENDIAN);
124
125 if (!SetSoundFormat(sndformat))
126 return FALSE;
127 m_input->SeekI(len-16, wxFromCurrent);
128 break;
129 }
130 case DATA_SIGNATURE: // "data"
131 end_headers = TRUE;
132 break;
133 default:
134 m_input->SeekI(len, wxFromCurrent);
135 break;
136 }
137 }
138 return TRUE;
139 }
140
141 bool wxSoundWave::PrepareToRecord(unsigned long time)
142 {
143 #define WRITE_SIGNATURE(sig) \
144 signature = sig; \
145 signature = wxUINT32_SWAP_ON_BE(signature); \
146 FAIL_WITH(m_output->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
147
148 wxUint32 signature, len;
149
150 if (!m_output) {
151 m_snderror = wxSOUND_INVSTRM;
152 return FALSE;
153 }
154
155 wxDataOutputStream data(*m_output);
156 data.BigEndianOrdered(FALSE);
157
158 len = m_sndformat->GetBytesFromTime(time);
159
160 len += HEADER_SIZE;
161
162 WRITE_SIGNATURE(RIFF_SIGNATURE);
163
164 data << len;
165 FAIL_WITH(m_output->LastWrite() != 4, wxSOUND_INVSTRM);
166
167 WRITE_SIGNATURE(WAVE_SIGNATURE);
168
169 {
170 wxUint16 format, channels, byte_p_spl, bits_p_spl;
171 wxUint32 sample_fq, byte_p_sec;
172 wxSoundFormatPcm *pcm;
173
174 if (m_sndformat->GetType() != wxSOUND_PCM) {
175 m_snderror = wxSOUND_NOCODEC;
176 return FALSE;
177 }
178
179 pcm = (wxSoundFormatPcm *)(m_sndformat->Clone());
180
181 WRITE_SIGNATURE(FMT_SIGNATURE);
182 data.Write32(16);
183
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);
189 format = 1;
190 data << format << channels << sample_fq
191 << byte_p_sec << byte_p_spl << bits_p_spl;
192
193 pcm->Signed(TRUE);
194 pcm->SetOrder(wxLITTLE_ENDIAN);
195
196 if (!SetSoundFormat(*pcm))
197 return FALSE;
198
199 delete pcm;
200 }
201
202 WRITE_SIGNATURE(DATA_SIGNATURE);
203 data.Write32(m_sndformat->GetBytesFromTime(time));
204 return TRUE;
205 }
206
207 bool wxSoundWave::FinishRecording()
208 {
209 // TODO: Update headers when we stop before the specified time (if possible)
210 return TRUE;
211 }
212
213 size_t wxSoundWave::GetData(void *buffer, size_t len)
214 {
215 return m_input->Read(buffer, len).LastRead();
216 }
217
218 size_t wxSoundWave::PutData(const void *buffer, size_t len)
219 {
220 return m_output->Write(buffer, len).LastWrite();
221 }