15 using ALuintPair
= std::pair
<ALuint
,ALuint
>;
18 void BufferImpl::cleanup()
21 throw std::runtime_error("Buffer is in use");
24 alDeleteBuffers(1, &mId
);
25 if(alGetError() != AL_NO_ERROR
)
26 throw std::runtime_error("Buffer failed to delete");
31 void BufferImpl::load(ALuint frames
, ALenum format
, SharedPtr
<Decoder
> decoder
, ContextImpl
*ctx
)
33 Vector
<ALbyte
> data(FramesToBytes(frames
, mChannelConfig
, mSampleType
));
35 ALuint got
= decoder
->read(data
.data(), frames
);
39 data
.resize(FramesToBytes(frames
, mChannelConfig
, mSampleType
));
44 if(mSampleType
== SampleType::UInt8
) silence
= 0x80;
45 else if(mSampleType
== SampleType::Mulaw
) silence
= 0x7f;
46 std::fill(data
.begin(), data
.end(), silence
);
49 std::pair
<uint64_t,uint64_t> loop_pts
= decoder
->getLoopPoints();
50 if(loop_pts
.first
>= loop_pts
.second
)
51 loop_pts
= std::make_pair(0, frames
);
54 loop_pts
.second
= std::min
<uint64_t>(loop_pts
.second
, frames
);
55 loop_pts
.first
= std::min
<uint64_t>(loop_pts
.first
, loop_pts
.second
-1);
58 ctx
->send(&MessageHandler::bufferLoading
,
59 mName
, mChannelConfig
, mSampleType
, mFrequency
, data
62 alBufferData(mId
, format
, data
.data(), data
.size(), mFrequency
);
63 if(ctx
->hasExtension(AL::SOFT_loop_points
))
65 ALint pts
[2]{(ALint
)loop_pts
.first
, (ALint
)loop_pts
.second
};
66 alBufferiv(mId
, AL_LOOP_POINTS_SOFT
, pts
);
71 DECL_THUNK0(ALuint
, Buffer
, getLength
, const)
72 ALuint
BufferImpl::getLength() const
74 CheckContext(mContext
);
76 ALint size
=-1, bits
=-1, chans
=-1;
77 alGetBufferi(mId
, AL_SIZE
, &size
);
78 alGetBufferi(mId
, AL_BITS
, &bits
);
79 alGetBufferi(mId
, AL_CHANNELS
, &chans
);
80 if(size
< 0 || bits
< 0 || chans
< 0)
81 throw std::runtime_error("Buffer format error");
82 return size
/ chans
* 8 / bits
;
85 DECL_THUNK0(ALuint
, Buffer
, getSize
, const)
86 ALuint
BufferImpl::getSize() const
88 CheckContext(mContext
);
91 alGetBufferi(mId
, AL_SIZE
, &size
);
93 throw std::runtime_error("Buffer size error");
97 DECL_THUNK2(void, Buffer
, setLoopPoints
,, ALuint
, ALuint
)
98 void BufferImpl::setLoopPoints(ALuint start
, ALuint end
)
100 ALuint length
= getLength();
103 throw std::runtime_error("Buffer is in use");
105 if(!mContext
->hasExtension(AL::SOFT_loop_points
))
107 if(start
!= 0 || end
!= length
)
108 throw std::runtime_error("Loop points not supported");
112 if(start
>= end
|| end
> length
)
113 throw std::out_of_range("Loop points out of range");
115 ALint pts
[2]{(ALint
)start
, (ALint
)end
};
117 alBufferiv(mId
, AL_LOOP_POINTS_SOFT
, pts
);
118 if(alGetError() != AL_NO_ERROR
)
119 throw std::runtime_error("Failed to set loop points");
122 DECL_THUNK0(ALuintPair
, Buffer
, getLoopPoints
, const)
123 std::pair
<ALuint
,ALuint
> BufferImpl::getLoopPoints() const
125 CheckContext(mContext
);
127 if(!mContext
->hasExtension(AL::SOFT_loop_points
))
128 return std::make_pair(0, getLength());
131 alGetBufferiv(mId
, AL_LOOP_POINTS_SOFT
, pts
);
132 if(pts
[0] == -1 || pts
[1] == -1)
133 throw std::runtime_error("Failed to get loop points");
135 return std::make_pair(pts
[0], pts
[1]);
138 DECL_THUNK0(ALuint
, Buffer
, getFrequency
, const)
139 DECL_THUNK0(ChannelConfig
, Buffer
, getChannelConfig
, const)
140 DECL_THUNK0(SampleType
, Buffer
, getSampleType
, const)
141 DECL_THUNK0(Vector
<Source
>, Buffer
, getSources
, const)
142 DECL_THUNK0(StringView
, Buffer
, getName
, const)
143 DECL_THUNK0(bool, Buffer
, isInUse
, const)
146 ALURE_API
const char *GetSampleTypeName(SampleType type
)
150 case SampleType::UInt8
: return "Unsigned 8-bit";
151 case SampleType::Int16
: return "Signed 16-bit";
152 case SampleType::Float32
: return "32-bit float";
153 case SampleType::Mulaw
: return "Mulaw";
155 throw std::invalid_argument("Invalid type");
158 ALURE_API
const char *GetChannelConfigName(ChannelConfig cfg
)
162 case ChannelConfig::Mono
: return "Mono";
163 case ChannelConfig::Stereo
: return "Stereo";
164 case ChannelConfig::Rear
: return "Rear";
165 case ChannelConfig::Quad
: return "Quadrophonic";
166 case ChannelConfig::X51
: return "5.1 Surround";
167 case ChannelConfig::X61
: return "6.1 Surround";
168 case ChannelConfig::X71
: return "7.1 Surround";
169 case ChannelConfig::BFormat2D
: return "B-Format 2D";
170 case ChannelConfig::BFormat3D
: return "B-Format 3D";
172 throw std::invalid_argument("Invalid config");
175 ALURE_API ALuint
FramesToBytes(ALuint frames
, ChannelConfig chans
, SampleType type
)
177 ALuint size
= frames
;
180 case ChannelConfig::Mono
: size
*= 1; break;
181 case ChannelConfig::Stereo
: size
*= 2; break;
182 case ChannelConfig::Rear
: size
*= 2; break;
183 case ChannelConfig::Quad
: size
*= 4; break;
184 case ChannelConfig::X51
: size
*= 6; break;
185 case ChannelConfig::X61
: size
*= 7; break;
186 case ChannelConfig::X71
: size
*= 8; break;
187 case ChannelConfig::BFormat2D
: size
*= 3; break;
188 case ChannelConfig::BFormat3D
: size
*= 4; break;
192 case SampleType::UInt8
: size
*= 1; break;
193 case SampleType::Int16
: size
*= 2; break;
194 case SampleType::Float32
: size
*= 4; break;
195 case SampleType::Mulaw
: size
*= 1; break;
201 ALURE_API ALuint
BytesToFrames(ALuint bytes
, ChannelConfig chans
, SampleType type
)
203 return bytes
/ FramesToBytes(1, chans
, type
);
207 ALenum
GetFormat(ChannelConfig chans
, SampleType type
)
209 #define RETURN_FMT(x) do { \
210 ALenum fmt = alGetEnumValue(x); \
211 if(fmt != AL_NONE && fmt != -1) \
214 if(type
== SampleType::UInt8
)
216 if(chans
== ChannelConfig::Mono
) return AL_FORMAT_MONO8
;
217 if(chans
== ChannelConfig::Stereo
) return AL_FORMAT_STEREO8
;
218 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_MCFORMATS
))
220 if(chans
== ChannelConfig::Rear
) RETURN_FMT("AL_FORMAT_REAR8");
221 if(chans
== ChannelConfig::Quad
) RETURN_FMT("AL_FORMAT_QUAD8");
222 if(chans
== ChannelConfig::X51
) RETURN_FMT("AL_FORMAT_51CHN8");
223 if(chans
== ChannelConfig::X61
) RETURN_FMT("AL_FORMAT_61CHN8");
224 if(chans
== ChannelConfig::X71
) RETURN_FMT("AL_FORMAT_71CHN8");
226 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_BFORMAT
))
228 if(chans
== ChannelConfig::BFormat2D
) RETURN_FMT("AL_FORMAT_BFORMAT2D_8");
229 if(chans
== ChannelConfig::BFormat3D
) RETURN_FMT("AL_FORMAT_BFORMAT3D_8");
232 else if(type
== SampleType::Int16
)
234 if(chans
== ChannelConfig::Mono
) return AL_FORMAT_MONO16
;
235 if(chans
== ChannelConfig::Stereo
) return AL_FORMAT_STEREO16
;
236 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_MCFORMATS
))
238 if(chans
== ChannelConfig::Rear
) RETURN_FMT("AL_FORMAT_REAR16");
239 if(chans
== ChannelConfig::Quad
) RETURN_FMT("AL_FORMAT_QUAD16");
240 if(chans
== ChannelConfig::X51
) RETURN_FMT("AL_FORMAT_51CHN16");
241 if(chans
== ChannelConfig::X61
) RETURN_FMT("AL_FORMAT_61CHN16");
242 if(chans
== ChannelConfig::X71
) RETURN_FMT("AL_FORMAT_71CHN16");
244 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_BFORMAT
))
246 if(chans
== ChannelConfig::BFormat2D
) RETURN_FMT("AL_FORMAT_BFORMAT2D_16");
247 if(chans
== ChannelConfig::BFormat3D
) RETURN_FMT("AL_FORMAT_BFORMAT3D_16");
250 else if(type
== SampleType::Float32
&& ContextImpl::GetCurrent()->hasExtension(AL::EXT_FLOAT32
))
252 if(chans
== ChannelConfig::Mono
) return AL_FORMAT_MONO_FLOAT32
;
253 if(chans
== ChannelConfig::Stereo
) return AL_FORMAT_STEREO_FLOAT32
;
254 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_MCFORMATS
))
256 if(chans
== ChannelConfig::Rear
) RETURN_FMT("AL_FORMAT_REAR32");
257 if(chans
== ChannelConfig::Quad
) RETURN_FMT("AL_FORMAT_QUAD32");
258 if(chans
== ChannelConfig::X51
) RETURN_FMT("AL_FORMAT_51CHN32");
259 if(chans
== ChannelConfig::X61
) RETURN_FMT("AL_FORMAT_61CHN32");
260 if(chans
== ChannelConfig::X71
) RETURN_FMT("AL_FORMAT_71CHN32");
262 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_BFORMAT
))
264 if(chans
== ChannelConfig::BFormat2D
) RETURN_FMT("AL_FORMAT_BFORMAT2D_FLOAT32");
265 if(chans
== ChannelConfig::BFormat3D
) RETURN_FMT("AL_FORMAT_BFORMAT3D_FLOAT32");
268 else if(type
== SampleType::Mulaw
&& ContextImpl::GetCurrent()->hasExtension(AL::EXT_MULAW
))
270 if(chans
== ChannelConfig::Mono
) return AL_FORMAT_MONO_MULAW
;
271 if(chans
== ChannelConfig::Stereo
) return AL_FORMAT_STEREO_MULAW
;
272 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_MULAW_MCFORMATS
))
274 if(chans
== ChannelConfig::Rear
) RETURN_FMT("AL_FORMAT_REAR_MULAW");
275 if(chans
== ChannelConfig::Quad
) RETURN_FMT("AL_FORMAT_QUAD_MULAW");
276 if(chans
== ChannelConfig::X51
) RETURN_FMT("AL_FORMAT_51CHN_MULAW");
277 if(chans
== ChannelConfig::X61
) RETURN_FMT("AL_FORMAT_61CHN_MULAW");
278 if(chans
== ChannelConfig::X71
) RETURN_FMT("AL_FORMAT_71CHN_MULAW");
280 if(ContextImpl::GetCurrent()->hasExtension(AL::EXT_MULAW_BFORMAT
))
282 if(chans
== ChannelConfig::BFormat2D
) RETURN_FMT("AL_FORMAT_BFORMAT2D_MULAW");
283 if(chans
== ChannelConfig::BFormat3D
) RETURN_FMT("AL_FORMAT_BFORMAT3D_MULAW");