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
37 static void *sndfile_handle;
38 #define MAKE_FUNC(x) static typeof(x)* p##x
40 MAKE_FUNC(sf_open_virtual);
41 MAKE_FUNC(sf_readf_short);
45 #define sf_close psf_close
46 #define sf_open_virtual psf_open_virtual
47 #define sf_readf_short psf_readf_short
48 #define sf_seek psf_seek
50 #define sndfile_handle 1
54 struct sndStream : public alureStream {
65 #define SNDFILE_LIB "libsndfile-1.dll"
66 #elif defined(__APPLE__)
67 #define SNDFILE_LIB "libsndfile.1.dylib"
69 #define SNDFILE_LIB "libsndfile.so.1"
71 sndfile_handle = OpenLib(SNDFILE_LIB);
72 if(!sndfile_handle) return;
74 LOAD_FUNC(sndfile_handle, sf_close);
75 LOAD_FUNC(sndfile_handle, sf_open_virtual);
76 LOAD_FUNC(sndfile_handle, sf_readf_short);
77 LOAD_FUNC(sndfile_handle, sf_seek);
82 CloseLib(sndfile_handle);
83 sndfile_handle = NULL;
86 static void Init() { }
87 static void Deinit() { }
90 virtual bool IsValid()
91 { return sndFile != NULL; }
93 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
96 format = GetSampleFormat(sndInfo.channels, 16, false);
98 *frequency = sndInfo.samplerate;
99 *blockalign = sndInfo.channels*2;
103 virtual ALuint GetData(ALubyte *data, ALuint bytes)
105 const ALuint frameSize = 2*sndInfo.channels;
106 return sf_readf_short(sndFile, (short*)data, bytes/frameSize) * frameSize;
109 virtual bool Rewind()
111 if(sf_seek(sndFile, 0, SEEK_SET) != -1)
114 SetError("Seek failed");
118 virtual alureInt64 GetLength()
120 if(sndInfo.frames == -1)
122 return sndInfo.frames;
125 sndStream(std::istream *_fstream)
126 : alureStream(_fstream), sndFile(NULL), format(AL_NONE)
128 memset(&sndInfo, 0, sizeof(sndInfo));
130 if(!sndfile_handle) return;
132 static SF_VIRTUAL_IO streamIO = {
136 sndFile = sf_open_virtual(&streamIO, SFM_READ, &sndInfo, this);
147 // libSndFile iostream callbacks
148 static sf_count_t get_filelen(void *user_data)
150 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
153 std::streampos len = -1;
154 std::streampos pos = stream->tellg();
155 if(stream->seekg(0, std::ios_base::end))
157 len = stream->tellg();
164 static sf_count_t seek(sf_count_t offset, int whence, void *user_data)
166 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
169 if((whence == SEEK_CUR && stream->seekg(offset, std::ios_base::cur)) ||
170 (whence == SEEK_SET && stream->seekg(offset, std::ios_base::beg)) ||
171 (whence == SEEK_END && stream->seekg(offset, std::ios_base::end)))
172 return stream->tellg();
177 static sf_count_t read(void *ptr, sf_count_t count, void *user_data)
179 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
181 stream->read(static_cast<char*>(ptr), count);
182 return stream->gcount();
185 static sf_count_t write(const void*, sf_count_t, void*)
188 static sf_count_t tell(void *user_data)
190 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
192 return stream->tellg();
195 static DecoderDecl<sndStream,0> sndStream_decoder;
196 Decoder &alure_init_sndfile(void)
197 { return sndStream_decoder; }