2 * ALURE OpenAL utility library
3 * Copyright (c) 2009-2010 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34 struct wavStream
: public alureStream
{
45 static void Init() { }
46 static void Deinit() { }
48 virtual bool IsValid()
49 { return (dataStart
> 0 && format
!= AL_NONE
); }
51 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
54 *frequency
= samplerate
;
55 *blockalign
= blockAlign
;
59 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
61 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
62 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
64 std::streamsize got
= fstream
->gcount();
65 got
-= got
%blockAlign
;
68 if(BigEndian
&& sampleSize
== 16)
70 for(std::streamsize i
= 0;i
< got
;i
+=2)
71 swap(data
[i
], data
[i
+1]);
73 else if(BigEndian
&& sampleSize
== 32)
75 for(std::streamsize i
= 0;i
< got
;i
+=4)
77 swap(data
[i
+0], data
[i
+3]);
78 swap(data
[i
+1], data
[i
+2]);
81 else if(BigEndian
&& sampleSize
== 64)
83 for(std::streamsize i
= 0;i
< got
;i
+=8)
85 swap(data
[i
+0], data
[i
+7]);
86 swap(data
[i
+1], data
[i
+6]);
87 swap(data
[i
+2], data
[i
+5]);
88 swap(data
[i
+3], data
[i
+4]);
98 if(fstream
->seekg(dataStart
))
104 SetError("Seek failed");
108 wavStream(std::istream
*_fstream
)
109 : alureStream(_fstream
), format(0), dataStart(0)
114 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
115 memcmp(buffer
, "RIFF", 4) != 0 || memcmp(buffer
+8, "WAVE", 4) != 0)
118 while(!dataStart
|| format
== AL_NONE
)
121 if(!fstream
->read(tag
, 4))
124 /* read chunk length */
125 length
= read_le32(fstream
);
127 if(memcmp(tag
, "fmt ", 4) == 0 && length
>= 16)
129 /* Data type (should be 1 for PCM data, 3 for float PCM data,
130 * and 17 for IMA4 data) */
131 int type
= read_le16(fstream
);
132 if(type
!= 0x0001 && type
!= 0x0003 && type
!= 0x0011)
135 /* mono or stereo data */
136 int channels
= read_le16(fstream
);
138 /* sample frequency */
139 samplerate
= read_le32(fstream
);
141 /* skip average bytes per second */
144 /* bytes per block */
145 blockAlign
= read_le16(fstream
);
149 /* bits per sample */
150 sampleSize
= read_le16(fstream
);
154 /* Look for any extra data and try to find the format */
155 ALuint extrabytes
= 0;
158 extrabytes
= read_le16(fstream
);
161 extrabytes
= std::min
<ALuint
>(extrabytes
, length
);
164 format
= GetSampleFormat(channels
, sampleSize
, false);
165 else if(type
== 0x0003)
166 format
= GetSampleFormat(channels
, sampleSize
, true);
167 else if(type
== 0x0011 && extrabytes
>= 2)
169 int samples
= read_le16(fstream
);
172 /* AL_EXT_IMA4 only supports 36 bytes-per-channel block
173 * alignment, which has 65 uncompressed sample frames */
174 if(blockAlign
== 36*channels
&& samples
== 65*channels
&&
175 alIsExtensionPresent("AL_EXT_IMA4"))
178 format
= AL_FORMAT_MONO_IMA4
;
179 else if(channels
== 2)
180 format
= AL_FORMAT_STEREO_IMA4
;
184 else if(memcmp(tag
, "data", 4) == 0)
186 dataStart
= fstream
->tellg();
187 dataLen
= remLen
= length
;
190 fstream
->seekg(length
, std::ios_base::cur
);
193 if(dataStart
> 0 && format
!= AL_NONE
)
194 fstream
->seekg(dataStart
);
200 static DecoderDecl
<wavStream
> wavStream_decoder
;