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