-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaudio_sample.cpp
More file actions
73 lines (62 loc) · 2.61 KB
/
Copy pathaudio_sample.cpp
File metadata and controls
73 lines (62 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Signed fixed-point audio samples in [-1, 1] with mixing.
// A 1/16384 notch gives ~Q1.14 precision and fits uint16 storage.
// Mixing two waveforms can exceed [-1, 1] at peaks; `with_clamp()` saturates
// to the boundary instead of wrapping or throwing.
//
// No `<cmath>` in the example body — the sine waveforms come from
// `bnd::math::sin` on a radians-valued bound. The 2π scaling is one
// bound × bound multiply via inline `just<math::two_pi>`.
#include <iostream>
#include <vector>
#include "bound/bound.hpp"
#include "bound/io.hpp"
#include "bound/cmath.hpp"
using namespace bnd;
int main()
{
// Signed fractional grid: 32769 steps in [-1, 1] -> uint16 storage
using sample = bound<{{-1, 1}, notch<1, 16384>}, round_nearest>;
static_assert(sizeof(sample) == 2);
// Two sine waves; combined peaks exceed unity to exercise clamping.
// wave_b is phase-shifted by -π/6 (= 30° behind wave_a).
constexpr std::size_t N = 8;
using time_t = bound<{{ 0, 1}, notch<1, N>}, round_nearest>;
using offset_t = bound<{{-2, 2}, notch<1, 16384>}, round_nearest>;
using angle_t = bound<{{-4, 10}, notch<1, 16384>}, round_nearest | real>;
using gainfac_t = bound<{{ 0, 1}, notch<1, 1024>}, round_nearest>;
constexpr offset_t off_a{0};
constexpr offset_t off_b{-math::pi / just<6>};
constexpr gainfac_t gain_a{0.8_b};
constexpr gainfac_t gain_b{0.6_b};
std::vector<sample> wave_a(N), wave_b(N);
for (auto i : bound_range<{0, N-1}>{})
{
time_t t{i / just<N>}; // bound / bound — give the divisor N a grid
angle_t base{t * math::two_pi}; // bound × bound, snap
angle_t a_a{base + off_a}; // bound + bound
angle_t a_b{base + off_b}; // bound + bound
wave_a[i] = sample{gain_a * math::sin(a_a)}; // bound × bound
wave_b[i] = sample{gain_b * math::sin(a_b)};
}
std::cout << "i a b a+b (clamped)\n";
for (std::size_t i = 0; i < N; ++i)
{
sample mixed{0};
mixed.with_clamp() = wave_a[i] + wave_b[i];
std::cout << i << " "
<< wave_a[i] << " "
<< wave_b[i] << " "
<< mixed << "\n";
}
// Peak detection over the buffer (max magnitude). `math::abs` keeps us in
// the bound world; the result is signed-stripped via |x| <= max.
using abs_t = bound<{{0, 1}, notch<1, 16384>}, round_nearest>;
abs_t peak{0};
for (auto s : wave_a)
{
abs_t mag{math::abs(s)};
if (mag > peak) peak = mag;
}
std::cout << "\npeak |a| = " << peak << " (expected ~0.8)\n";
return 0;
}