]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/mmedia/sndaiff.cpp
fix evaluation order bug (patch 1158099)
[wxWidgets.git] / contrib / src / mmedia / sndaiff.cpp
1 // --------------------------------------------------------------------------
2 // Name: sndaiff.cpp
3 // Purpose:
4 // Date: 08/11/1999
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6 // CVSID: $Id$
7 // wxWindows licence
8 // --------------------------------------------------------------------------
9 #ifdef __GNUG__
10 #pragma implementation "sndaiff.cpp"
11 #endif
12
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/defs.h"
17 #endif
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #include "wx/stream.h"
24 #include "wx/datstrm.h"
25 #include "wx/filefn.h"
26
27 #include "wx/mmedia/sndbase.h"
28 #include "wx/mmedia/sndcodec.h"
29 #include "wx/mmedia/sndfile.h"
30 #include "wx/mmedia/sndpcm.h"
31 #include "wx/mmedia/sndaiff.h"
32
33 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
34
35 #define FORM_SIGNATURE BUILD_SIGNATURE('F','O','R','M')
36 #define AIFF_SIGNATURE BUILD_SIGNATURE('A','I','F','F')
37 #define AIFC_SIGNATURE BUILD_SIGNATURE('A','I','F','C')
38 #define COMM_SIGNATURE BUILD_SIGNATURE('C','O','M','M')
39 #define SSND_SIGNATURE BUILD_SIGNATURE('S','S','N','D')
40
41 wxSoundAiff::wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound)
42 : wxSoundFileStream(stream, io_sound)
43 {
44 m_base_offset = wxInvalidOffset;
45 }
46
47 wxSoundAiff::wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound)
48 : wxSoundFileStream(stream, io_sound)
49 {
50 m_base_offset = wxInvalidOffset;
51 }
52
53 wxSoundAiff::~wxSoundAiff()
54 {
55 }
56
57 wxString wxSoundAiff::GetCodecName() const
58 {
59 return wxT("wxSoundAiff codec");
60 }
61
62 bool wxSoundAiff::CanRead()
63 {
64 wxUint32 signature1, signature2, len;
65
66 if (m_input->Read(&signature1, 4).LastRead() != 4)
67 return false;
68
69 if (wxUINT32_SWAP_ON_BE(signature1) != FORM_SIGNATURE) {
70 m_input->Ungetch(&signature1, 4);
71 return false;
72 }
73
74 m_input->Read(&len, 4);
75 if (m_input->LastRead() != 4) {
76 m_input->Ungetch(&len, m_input->LastRead());
77 m_input->Ungetch(&signature1, 4);
78 return false;
79 }
80
81 if (m_input->Read(&signature2, 4).LastRead() != 4) {
82 m_input->Ungetch(&signature2, m_input->LastRead());
83 m_input->Ungetch(&len, 4);
84 m_input->Ungetch(&signature1, 4);
85 return false;
86 }
87
88 m_input->Ungetch(&signature2, 4);
89 m_input->Ungetch(&len, 4);
90 m_input->Ungetch(&signature1, 4);
91
92 if (
93 wxUINT32_SWAP_ON_BE(signature2) != AIFF_SIGNATURE &&
94 wxUINT32_SWAP_ON_BE(signature2) != AIFC_SIGNATURE)
95 return false;
96
97 return true;
98 }
99
100 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return false; }
101
102 bool wxSoundAiff::PrepareToPlay()
103 {
104 wxDataInputStream data(*m_input);
105 wxUint32 signature, len, ssnd;
106 bool end_headers;
107
108 if (!m_input) {
109 m_snderror = wxSOUND_INVSTRM;
110 return false;
111 }
112 m_snderror = wxSOUND_NOERROR;
113
114 data.BigEndianOrdered(true);
115
116 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
117 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != FORM_SIGNATURE, wxSOUND_INVSTRM);
118 // "FORM"
119
120 len = data.Read32();
121 wxUnusedVar(len);
122 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
123 // dummy len
124
125 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
126 FAIL_WITH(
127 wxUINT32_SWAP_ON_BE(signature) != AIFF_SIGNATURE &&
128 wxUINT32_SWAP_ON_BE(signature) != AIFC_SIGNATURE, wxSOUND_INVSTRM);
129 // "AIFF" / "AIFC"
130
131 end_headers = false;
132 while (!end_headers) {
133 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
134
135 len = data.Read32();
136 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
137
138 switch (wxUINT32_SWAP_ON_BE(signature)) {
139 case COMM_SIGNATURE: { // "COMM"
140 wxUint16 channels, bps;
141 wxUint32 num_samples;
142 double srate;
143 wxSoundFormatPcm sndformat;
144
145 // Get sound data informations
146 data >> channels >> num_samples >> bps >> srate;
147
148 // Convert them in a wxSoundFormat object
149 sndformat.SetSampleRate((wxUint32) srate);
150 sndformat.SetBPS(bps);
151 sndformat.SetChannels(channels);
152 sndformat.Signed(false);
153 sndformat.SetOrder(wxBIG_ENDIAN);
154
155 if (!SetSoundFormat(sndformat))
156 return false;
157 // We pass all data left
158 m_input->SeekI(len-18, wxFromCurrent);
159 break;
160 }
161 case SSND_SIGNATURE: { // "SSND"
162 data >> ssnd;
163 // m_input->SeekI(4, wxFromCurrent); // Pass an INT32
164 // m_input->SeekI(len-4, wxFromCurrent); // Pass the rest
165 m_input->SeekI(ssnd + 4, wxFromCurrent);
166 m_base_offset = m_input->TellI();
167 // len-8 bytes of samples
168 FinishPreparation(len - 8);
169 end_headers = true;
170 break;
171 }
172 default:
173 m_input->SeekI(len, wxFromCurrent);
174 break;
175 }
176 }
177 return true;
178 }
179
180 bool wxSoundAiff::PrepareToRecord(wxUint32 WXUNUSED(time))
181 {
182 // TODO
183 return false;
184 }
185
186 bool wxSoundAiff::FinishRecording()
187 {
188 // TODO
189 return false;
190 }
191
192 bool wxSoundAiff::RepositionStream(wxUint32 WXUNUSED(position))
193 {
194 // If the stream is not seekable "TellI() returns wxInvalidOffset" we cannot reposition stream
195 if (m_base_offset == wxInvalidOffset)
196 return false;
197 m_input->SeekI(m_base_offset, wxFromStart);
198 return true;
199 }
200
201 wxUint32 wxSoundAiff::GetData(void *buffer, wxUint32 len)
202 {
203 return m_input->Read(buffer, len).LastRead();
204 }
205
206 wxUint32 wxSoundAiff::PutData(const void *buffer, wxUint32 len)
207 {
208 return m_output->Write(buffer, len).LastWrite();
209 }