23#define __WIZARD_ENGINE_INTERNAL__
31std::vector<wze::speaker*> wze::speaker::_instances = {};
33void wze::speaker::set_angle([[maybe_unused]]
float _) {}
35float wze::speaker::angle_offset()
const {
39bool wze::speaker::attach_angle()
const {
43std::vector<wze::speaker*>
const& wze::speaker::instances() {
47std::shared_ptr<wze::sound>
const& wze::speaker::sound()
const {
51void wze::speaker::set_sound(std::shared_ptr<wze::sound>
const& sound) {
55int8_t wze::speaker::volume()
const {
56 return (int8_t)Mix_Volume(_channel, -1);
60void wze::speaker::set_volume(int8_t volume) {
61 Mix_Volume(_channel, volume);
64float wze::speaker::range()
const {
68void wze::speaker::set_range(
float range) {
72bool wze::speaker::auto_panning()
const {
76void wze::speaker::set_auto_panning(
bool auto_panning) {
77 _auto_panning = auto_panning;
80float wze::speaker::x()
const {
84void wze::speaker::set_x(
float x) {
88float wze::speaker::y()
const {
92void wze::speaker::set_y(
float y) {
96float wze::speaker::z()
const {
100void wze::speaker::set_z(
float z) {
104bool wze::speaker::spatial()
const {
108void wze::speaker::set_spatial(
bool spatial) {
112float wze::speaker::x_offset()
const {
116void wze::speaker::set_x_offset(
float x_offset) {
117 _x_offset = x_offset;
120float wze::speaker::y_offset()
const {
124void wze::speaker::set_y_offset(
float y_offset) {
125 _y_offset = y_offset;
128bool wze::speaker::attach_x()
const {
132void wze::speaker::set_attach_x(
bool attach_x) {
133 _attach_x = attach_x;
136bool wze::speaker::attach_y()
const {
140void wze::speaker::set_attach_y(
bool attach_y) {
141 _attach_y = attach_y;
144bool wze::speaker::x_angle_lock()
const {
145 return _x_angle_lock;
148void wze::speaker::set_x_angle_lock(
bool x_angle_lock) {
149 _x_angle_lock = x_angle_lock;
152bool wze::speaker::y_angle_lock()
const {
153 return _y_angle_lock;
156void wze::speaker::set_y_angle_lock(
bool y_angle_lock) {
157 _y_angle_lock = y_angle_lock;
160bool wze::speaker::playing()
const {
161 return (
bool)Mix_Playing(_channel);
164bool wze::speaker::paused()
const {
165 return (
bool)Mix_Paused(_channel);
168wze::speaker::speaker(std::shared_ptr<wze::sound>
const& sound, int8_t volume,
169 float range,
bool auto_panning,
float x,
float y,
float z,
170 bool spatial,
float x_offset,
float y_offset,
171 bool attach_x,
bool attach_y,
bool x_angle_lock,
173 _channel = audio::request_channel();
177 set_auto_panning(auto_panning);
181 set_spatial(spatial);
182 set_x_offset(x_offset);
183 set_y_offset(y_offset);
184 set_attach_x(attach_x);
185 set_attach_y(attach_y);
186 set_x_angle_lock(x_angle_lock);
187 set_y_angle_lock(y_angle_lock);
188 _instances.push_back(
this);
191wze::speaker::speaker(speaker
const& other) {
192 _channel = audio::request_channel();
194 _instances.push_back(
this);
197wze::speaker::speaker(speaker&& other)
noexcept(
false) {
198 _channel = audio::request_channel();
199 *
this = std::move(other);
200 _instances.push_back(
this);
203wze::speaker::~speaker() {
204 _instances.erase(std::find(instances().begin(), instances().end(),
this));
205 audio::drop_channel(_channel);
208wze::speaker& wze::speaker::operator=(speaker
const& other) {
209 if (&other !=
this) {
210 set_sound(other.sound());
211 set_volume(other.volume());
212 set_range(other.range());
213 set_auto_panning(other.auto_panning());
217 set_spatial(other.spatial());
218 set_x_offset(other.x_offset());
219 set_y_offset(other.y_offset());
220 set_attach_x(other.attach_x());
221 set_attach_y(other.attach_y());
222 set_x_angle_lock(other.x_angle_lock());
223 set_y_angle_lock(other.y_angle_lock());
229wze::speaker& wze::speaker::operator=(speaker&& other)
noexcept(
false) {
230 if (&other !=
this) {
232 std::swap(_channel, other._channel);
239void wze::speaker::play(uint16_t fade_in, uint16_t loops) {
240 if (Mix_FadeInChannel(_channel, sound().get(), loops, fade_in) == -1) {
241 throw exception(Mix_GetError());
246void wze::speaker::pause() {
251void wze::speaker::resume() {
252 Mix_Resume(_channel);
256void wze::speaker::stop(uint16_t fade_out) {
257 Mix_FadeOutChannel(_channel, fade_out);
261void wze::speaker::align_panning() {
262 constexpr uint16_t circle = 360;
263 constexpr uint16_t top = 270;
264 constexpr uint16_t bottom = 90;
274 x_distance = x() - camera::x();
275 y_distance = y() - camera::y();
276 z_ratio = spatial() ? 1 - abs(z() - camera::z()) / range() : 1;
279 math::angle(x_distance, y_distance) - camera::angle())) %
285 if (range() <= distance || z_ratio <= 0) {
288 }
else if (bottom < angle && angle < top) {
289 left = 1 - distance / range();
290 right = powf(left, 2);
295 }
else if (top < angle || angle < bottom) {
296 right = 1 - distance / range();
297 left = powf(right, 2);
307 if (!(
bool)Mix_SetPanning(
309 (uint8_t)roundf(std::numeric_limits<uint8_t>::max() * left),
310 (uint8_t)roundf(std::numeric_limits<uint8_t>::max() * right))) {
311 throw exception(Mix_GetError());
Subsystem to handle global audio.
Subsystem to handle transformations and spatial projections.
static float angle(float x, float y)
Returns the angle of a vector.
static constexpr float to_degrees(float radians)
Converts radians to degrees.
static float length(float x, float y)
Returns the length of a vector.