HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
dither.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "xorshift128p.hpp"
8#include "../required.hpp"
9
10namespace tt {
11
23class dither {
24public:
25 dither(dither const &) = default;
26 dither(dither &&) = default;
27 dither &operator=(dither const &) = default;
28 dither &operator=(dither &&) = default;
29
35 dither(int num_bits) noexcept : _state(), _multiplier()
36 {
37 tt_axiom(num_bits > 0);
38 auto maximum_value = static_cast<float>((1_uz << num_bits) - 1);
39
40 // The maximum value from the rectangular probability density function.
41 maximum_value *= 127.0f;
42
43 // Triangular probability density function is has twice the range.
44 maximum_value *= 2.0f;
45
46 _multiplier = f32x4::broadcast(1.0f / maximum_value);
47 }
48
52 f32x4 next() noexcept
53 {
54 if (static_cast<bool>(++_counter & 1)) {
55 auto rand = _state.next<u64x2>();
56 auto spdf1 = i16x8{bit_cast<i8x16>(rand)};
57 rand = rand.yx();
58 auto spdf2 = i16x8{bit_cast<i8x16>(rand)};
59
60 _tpdf = spdf1 + spdf2;
61 return f32x4{i32x4{_tpdf}} * _multiplier;
62 } else {
63 auto second_tpdf = bit_cast<i16x8>(bit_cast<u64x2>(_tpdf).yx());
64 return f32x4{i32x4{second_tpdf}} * _multiplier;
65 }
66 }
67
73 [[nodiscard]] f32x4 next(f32x4 samples) noexcept
74 {
75 return samples + next();
76 }
77
83 [[nodiscard]] float next(float sample) noexcept
84 {
85 return get<0>(f32x4::broadcast(sample) + next());
86 }
87
88private:
89 f32x4 _multiplier;
90 i16x8 _tpdf;
91 xorshift128p _state;
92 unsigned char _counter = 0;
93};
94
95} // namespace tt
An object that create dither values to add to samples before rounding.
Definition dither.hpp:23
f32x4 next(f32x4 samples) noexcept
Add dither to the given samples.
Definition dither.hpp:73
float next(float sample) noexcept
Add dither to the given samples.
Definition dither.hpp:83
f32x4 next() noexcept
Get 8 floating point number to add to a samples.
Definition dither.hpp:52
dither(int num_bits) noexcept
Create a dither object.
Definition dither.hpp:35
xorshift128+
Definition xorshift128p.hpp:16