comparison foosdk/sdk/foobar2000/helpers/duration_counter.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #pragma once
2
3 #include <SDK/dsp.h>
4 #include <pfc/map.h>
5
6 //! Duration counter class - accumulates duration using sample values, without any kind of rounding error accumulation.
7 class duration_counter {
8 public:
9 duration_counter() {}
10 void set(double v) {
11 m_sampleCounts.remove_all();
12 m_offset = v;
13 }
14 void reset() {
15 set(0);
16 }
17
18 void add(double v) { m_offset += v; }
19 void subtract(double v) { m_offset -= v; }
20
21 double query() const {
22 double acc = m_offset;
23 for (auto& walk : m_sampleCounts) {
24 acc += audio_math::samples_to_time(walk.m_value, walk.m_key);
25 }
26 return acc;
27 }
28
29 uint64_t queryAsAnySampleCount() const {
30 if (m_sampleCounts.get_count() == 1) {
31 return m_sampleCounts.first()->m_value;
32 }
33 return 0;
34 }
35
36 uint64_t queryAsSampleCount(uint32_t rate) const {
37 uint64_t samples = 0;
38 double acc = m_offset;
39 for (auto& walk : m_sampleCounts) {
40 if (walk.m_key == rate) samples += walk.m_value;
41 else acc += audio_math::samples_to_time(walk.m_value, walk.m_key);
42 }
43 return samples + audio_math::time_to_samples(acc, rate);
44 }
45
46 void add(const audio_chunk & c) {
47 add(c.get_sample_count(), c.get_sample_rate());
48 }
49 #ifdef FOOBAR2000_HAVE_DSP
50 void add(dsp_chunk_list const & c) {
51 const size_t num = c.get_count();
52 for (size_t walk = 0; walk < num; ++walk) {
53 add(*c.get_item(walk));
54 }
55 }
56 #endif
57 void add(t_uint64 sampleCount, t_uint32 sampleRate) {
58 PFC_ASSERT(sampleRate > 0);
59 if (sampleRate > 0 && sampleCount > 0) {
60 m_sampleCounts.find_or_add(sampleRate) += sampleCount;
61 }
62 }
63 void add(const duration_counter & other) {
64 add(other.m_offset);
65 for (auto& walk : other.m_sampleCounts) add(walk.m_value, walk.m_key);
66 }
67 void subtract(const duration_counter & other) {
68 subtract(other.m_offset);
69 for (auto& walk : other.m_sampleCounts) subtract(walk.m_value, walk.m_key);
70 }
71 void subtract(t_uint64 sampleCount, t_uint32 sampleRate) {
72 PFC_ASSERT(sampleRate > 0);
73 if (sampleRate > 0 && sampleCount > 0) {
74 t_uint64 * val = m_sampleCounts.query_ptr(sampleRate);
75 if (val == NULL) throw pfc::exception_invalid_params();
76 if (*val < sampleCount) throw pfc::exception_invalid_params();
77 else if (*val == sampleCount) {
78 m_sampleCounts.remove(sampleRate);
79 } else {
80 *val -= sampleCount;
81 }
82
83 }
84 }
85 void subtract(const audio_chunk & c) {
86 subtract(c.get_sample_count(), c.get_sample_rate());
87 }
88 template<typename t_source> duration_counter & operator+=(const t_source & source) { add(source); return *this; }
89 template<typename t_source> duration_counter & operator-=(const t_source & source) { subtract(source); return *this; }
90 template<typename t_source> duration_counter & operator=(const t_source & source) { reset(); add(source); return *this; }
91 private:
92 double m_offset = 0;
93 typedef pfc::map_t<t_uint32, t_uint64> t_map;
94 t_map m_sampleCounts;
95 };
96