12 static sf_count_t
get_filelen(void *user_data
)
14 std::istream
*file
= reinterpret_cast<std::istream
*>(user_data
);
18 std::streampos pos
= file
->tellg();
19 if(pos
!= -1 && file
->seekg(0, std::ios::end
))
27 static sf_count_t
seek(sf_count_t offset
, int whence
, void *user_data
)
29 std::istream
*file
= reinterpret_cast<std::istream
*>(user_data
);
32 if(!file
->seekg(offset
, std::ios::seekdir(whence
)))
37 static sf_count_t
read(void *ptr
, sf_count_t count
, void *user_data
)
39 std::istream
*file
= reinterpret_cast<std::istream
*>(user_data
);
42 file
->read(reinterpret_cast<char*>(ptr
), count
);
43 return file
->gcount();
46 static sf_count_t
write(const void*, sf_count_t
, void*)
51 static sf_count_t
tell(void *user_data
)
53 std::istream
*file
= reinterpret_cast<std::istream
*>(user_data
);
60 class SndFileDecoder
: public Decoder
{
61 UniquePtr
<std::istream
> mFile
;
66 ChannelConfig mChannelConfig
;
67 SampleType mSampleType
;
70 SndFileDecoder(UniquePtr
<std::istream
> file
, SNDFILE
*sndfile
, const SF_INFO sndinfo
, ChannelConfig sconfig
, SampleType stype
)
71 : mFile(std::move(file
)), mSndFile(sndfile
), mSndInfo(sndinfo
)
72 , mChannelConfig(sconfig
), mSampleType(stype
)
74 ~SndFileDecoder() override final
;
76 ALuint
getFrequency() const override final
;
77 ChannelConfig
getChannelConfig() const override final
;
78 SampleType
getSampleType() const override final
;
80 uint64_t getLength() const override final
;
81 uint64_t getPosition() const override final
;
82 bool seek(uint64_t pos
) override final
;
84 std::pair
<uint64_t,uint64_t> getLoopPoints() const override final
;
86 ALuint
read(ALvoid
*ptr
, ALuint count
) override final
;
89 SndFileDecoder::~SndFileDecoder()
96 ALuint
SndFileDecoder::getFrequency() const
98 return mSndInfo
.samplerate
;
101 ChannelConfig
SndFileDecoder::getChannelConfig() const
103 return mChannelConfig
;
106 SampleType
SndFileDecoder::getSampleType() const
112 uint64_t SndFileDecoder::getLength() const
114 return std::max
<sf_count_t
>(mSndInfo
.frames
, 0);
117 uint64_t SndFileDecoder::getPosition() const
119 sf_count_t pos
= sf_seek(mSndFile
, 0, SEEK_CUR
);
120 return std::max
<sf_count_t
>(pos
, 0);
123 bool SndFileDecoder::seek(uint64_t pos
)
125 sf_count_t newpos
= sf_seek(mSndFile
, pos
, SEEK_SET
);
126 if(newpos
< 0) return false;
130 std::pair
<uint64_t,uint64_t> SndFileDecoder::getLoopPoints() const
132 return std::make_pair(0, 0);
135 ALuint
SndFileDecoder::read(ALvoid
*ptr
, ALuint count
)
138 if(mSampleType
== SampleType::Int16
)
139 got
= sf_readf_short(mSndFile
, static_cast<short*>(ptr
), count
);
140 else if(mSampleType
== SampleType::Float32
)
141 got
= sf_readf_float(mSndFile
, static_cast<float*>(ptr
), count
);
142 return (ALuint
)std::max
<sf_count_t
>(got
, 0);
146 SharedPtr
<Decoder
> SndFileDecoderFactory::createDecoder(UniquePtr
<std::istream
> &file
)
148 SF_VIRTUAL_IO vio
= {
153 SNDFILE
*sndfile
= sf_open_virtual(&vio
, SFM_READ
, &sndinfo
, file
.get());
154 if(!sndfile
) return nullptr;
156 ChannelConfig sconfig
;
157 Vector
<int> chanmap(sndinfo
.channels
);
158 if(sf_command(sndfile
, SFC_GET_CHANNEL_MAP_INFO
, &chanmap
[0], chanmap
.size()*sizeof(int)) == SF_TRUE
)
160 auto matches
= [](const Vector
<int> &first
, std::initializer_list
<int> second
) -> bool
162 if(first
.size() != second
.size())
164 return std::mismatch(first
.begin(), first
.end(), second
.begin()).first
== first
.end();
167 if(matches(chanmap
, {SF_CHANNEL_MAP_MONO
}))
168 sconfig
= ChannelConfig::Mono
;
169 else if(matches(chanmap
, {SF_CHANNEL_MAP_LEFT
, SF_CHANNEL_MAP_RIGHT
}))
170 sconfig
= ChannelConfig::Stereo
;
171 else if(matches(chanmap
, {SF_CHANNEL_MAP_REAR_LEFT
, SF_CHANNEL_MAP_REAR_RIGHT
}))
172 sconfig
= ChannelConfig::Rear
;
173 else if(matches(chanmap
, {SF_CHANNEL_MAP_LEFT
, SF_CHANNEL_MAP_RIGHT
,
174 SF_CHANNEL_MAP_REAR_LEFT
, SF_CHANNEL_MAP_REAR_RIGHT
}))
175 sconfig
= ChannelConfig::Quad
;
176 else if(matches(chanmap
, {SF_CHANNEL_MAP_LEFT
, SF_CHANNEL_MAP_RIGHT
,
177 SF_CHANNEL_MAP_CENTER
, SF_CHANNEL_MAP_LFE
,
178 SF_CHANNEL_MAP_REAR_LEFT
, SF_CHANNEL_MAP_REAR_RIGHT
}) ||
179 matches(chanmap
, {SF_CHANNEL_MAP_LEFT
, SF_CHANNEL_MAP_RIGHT
,
180 SF_CHANNEL_MAP_CENTER
, SF_CHANNEL_MAP_LFE
,
181 SF_CHANNEL_MAP_SIDE_LEFT
, SF_CHANNEL_MAP_SIDE_RIGHT
}))
182 sconfig
= ChannelConfig::X51
;
183 else if(matches(chanmap
, {SF_CHANNEL_MAP_LEFT
, SF_CHANNEL_MAP_RIGHT
,
184 SF_CHANNEL_MAP_CENTER
, SF_CHANNEL_MAP_LFE
,
185 SF_CHANNEL_MAP_REAR_CENTER
, SF_CHANNEL_MAP_SIDE_LEFT
,
186 SF_CHANNEL_MAP_SIDE_RIGHT
}))
187 sconfig
= ChannelConfig::X61
;
188 else if(matches(chanmap
, {SF_CHANNEL_MAP_LEFT
, SF_CHANNEL_MAP_RIGHT
,
189 SF_CHANNEL_MAP_CENTER
, SF_CHANNEL_MAP_LFE
,
190 SF_CHANNEL_MAP_REAR_LEFT
, SF_CHANNEL_MAP_REAR_RIGHT
,
191 SF_CHANNEL_MAP_SIDE_LEFT
, SF_CHANNEL_MAP_SIDE_RIGHT
}))
192 sconfig
= ChannelConfig::X71
;
193 else if(matches(chanmap
, {SF_CHANNEL_MAP_AMBISONIC_B_W
, SF_CHANNEL_MAP_AMBISONIC_B_X
,
194 SF_CHANNEL_MAP_AMBISONIC_B_Y
}))
195 sconfig
= ChannelConfig::BFormat2D
;
196 else if(matches(chanmap
, {SF_CHANNEL_MAP_AMBISONIC_B_W
, SF_CHANNEL_MAP_AMBISONIC_B_X
,
197 SF_CHANNEL_MAP_AMBISONIC_B_Y
, SF_CHANNEL_MAP_AMBISONIC_B_Z
}))
198 sconfig
= ChannelConfig::BFormat3D
;
205 else if(sf_command(sndfile
, SFC_WAVEX_GET_AMBISONIC
, 0, 0) == SF_AMBISONIC_B_FORMAT
)
207 if(sndinfo
.channels
== 3)
208 sconfig
= ChannelConfig::BFormat2D
;
209 else if(sndinfo
.channels
== 4)
210 sconfig
= ChannelConfig::BFormat3D
;
217 else if(sndinfo
.channels
== 1)
218 sconfig
= ChannelConfig::Mono
;
219 else if(sndinfo
.channels
== 2)
220 sconfig
= ChannelConfig::Stereo
;
227 SampleType stype
= SampleType::Int16
;
228 switch(sndinfo
.format
&SF_FORMAT_SUBMASK
)
230 case SF_FORMAT_FLOAT
:
231 case SF_FORMAT_DOUBLE
:
232 case SF_FORMAT_VORBIS
:
233 if(Context::GetCurrent().isSupported(sconfig
, SampleType::Float32
))
235 stype
= SampleType::Float32
;
240 stype
= SampleType::Int16
;
244 return MakeShared
<SndFileDecoder
>(std::move(file
), sndfile
, sndinfo
, sconfig
, stype
);