1/**************************************************************************/
2/* audio_frame.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef AUDIO_FRAME_H
32#define AUDIO_FRAME_H
33
34#include "core/math/vector2.h"
35#include "core/typedefs.h"
36
37static inline float undenormalize(volatile float f) {
38 union {
39 uint32_t i;
40 float f;
41 } v;
42
43 v.f = f;
44
45 // original: return (v.i & 0x7f800000) == 0 ? 0.0f : f;
46 // version from Tim Blechmann:
47 return (v.i & 0x7f800000) < 0x08000000 ? 0.0f : f;
48}
49
50static const float AUDIO_PEAK_OFFSET = 0.0000000001f;
51static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear_to_db(AUDIO_PEAK_OFFSET)
52
53struct AudioFrame {
54 //left and right samples
55 float l = 0.f, r = 0.f;
56
57 _ALWAYS_INLINE_ const float &operator[](int idx) const { return idx == 0 ? l : r; }
58 _ALWAYS_INLINE_ float &operator[](int idx) { return idx == 0 ? l : r; }
59
60 _ALWAYS_INLINE_ AudioFrame operator+(const AudioFrame &p_frame) const { return AudioFrame(l + p_frame.l, r + p_frame.r); }
61 _ALWAYS_INLINE_ AudioFrame operator-(const AudioFrame &p_frame) const { return AudioFrame(l - p_frame.l, r - p_frame.r); }
62 _ALWAYS_INLINE_ AudioFrame operator*(const AudioFrame &p_frame) const { return AudioFrame(l * p_frame.l, r * p_frame.r); }
63 _ALWAYS_INLINE_ AudioFrame operator/(const AudioFrame &p_frame) const { return AudioFrame(l / p_frame.l, r / p_frame.r); }
64
65 _ALWAYS_INLINE_ AudioFrame operator+(float p_sample) const { return AudioFrame(l + p_sample, r + p_sample); }
66 _ALWAYS_INLINE_ AudioFrame operator-(float p_sample) const { return AudioFrame(l - p_sample, r - p_sample); }
67 _ALWAYS_INLINE_ AudioFrame operator*(float p_sample) const { return AudioFrame(l * p_sample, r * p_sample); }
68 _ALWAYS_INLINE_ AudioFrame operator/(float p_sample) const { return AudioFrame(l / p_sample, r / p_sample); }
69
70 _ALWAYS_INLINE_ void operator+=(const AudioFrame &p_frame) {
71 l += p_frame.l;
72 r += p_frame.r;
73 }
74 _ALWAYS_INLINE_ void operator-=(const AudioFrame &p_frame) {
75 l -= p_frame.l;
76 r -= p_frame.r;
77 }
78 _ALWAYS_INLINE_ void operator*=(const AudioFrame &p_frame) {
79 l *= p_frame.l;
80 r *= p_frame.r;
81 }
82 _ALWAYS_INLINE_ void operator/=(const AudioFrame &p_frame) {
83 l /= p_frame.l;
84 r /= p_frame.r;
85 }
86
87 _ALWAYS_INLINE_ void operator+=(float p_sample) {
88 l += p_sample;
89 r += p_sample;
90 }
91 _ALWAYS_INLINE_ void operator-=(float p_sample) {
92 l -= p_sample;
93 r -= p_sample;
94 }
95 _ALWAYS_INLINE_ void operator*=(float p_sample) {
96 l *= p_sample;
97 r *= p_sample;
98 }
99 _ALWAYS_INLINE_ void operator/=(float p_sample) {
100 l /= p_sample;
101 r /= p_sample;
102 }
103
104 _ALWAYS_INLINE_ void undenormalize() {
105 l = ::undenormalize(l);
106 r = ::undenormalize(r);
107 }
108
109 _FORCE_INLINE_ AudioFrame lerp(const AudioFrame &p_b, float p_t) const {
110 AudioFrame res = *this;
111
112 res.l += (p_t * (p_b.l - l));
113 res.r += (p_t * (p_b.r - r));
114
115 return res;
116 }
117
118 _ALWAYS_INLINE_ AudioFrame(float p_l, float p_r) {
119 l = p_l;
120 r = p_r;
121 }
122 _ALWAYS_INLINE_ AudioFrame(const AudioFrame &p_frame) {
123 l = p_frame.l;
124 r = p_frame.r;
125 }
126
127 _ALWAYS_INLINE_ void operator=(const AudioFrame &p_frame) {
128 l = p_frame.l;
129 r = p_frame.r;
130 }
131
132 _ALWAYS_INLINE_ operator Vector2() const {
133 return Vector2(l, r);
134 }
135
136 _ALWAYS_INLINE_ AudioFrame(const Vector2 &p_v2) {
137 l = p_v2.x;
138 r = p_v2.y;
139 }
140 _ALWAYS_INLINE_ AudioFrame() {}
141};
142
143_ALWAYS_INLINE_ AudioFrame operator*(float p_scalar, const AudioFrame &p_frame) {
144 return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
145}
146
147_ALWAYS_INLINE_ AudioFrame operator*(int32_t p_scalar, const AudioFrame &p_frame) {
148 return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
149}
150
151_ALWAYS_INLINE_ AudioFrame operator*(int64_t p_scalar, const AudioFrame &p_frame) {
152 return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
153}
154
155#endif // AUDIO_FRAME_H
156