FastLED 3.9.15
Loading...
Searching...
No Matches
audio.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/fft.h"
4#include "fl/math.h"
5#include "fl/memory.h"
6#include "fl/span.h"
7#include "fl/vector.h"
8#include "fl/int.h"
9#include <math.h>
10#include "fl/stdint.h"
11#include "fl/span.h"
12
13namespace fl {
14
15class AudioSampleImpl;
16
18
19// AudioSample is a wrapper around AudioSampleImpl, hiding the reference
20// counting so that the api object can be simple and have standard object
21// semantics.
23 public:
27 AudioSample(const AudioSample &other) : mImpl(other.mImpl) {}
28 AudioSample(AudioSampleImplPtr impl) : mImpl(impl) {}
30
31 // Constructor that takes raw audio data and handles pooling internally
33
34
35 AudioSample &operator=(const AudioSample &other);
36 bool isValid() const { return mImpl != nullptr; }
37
38 fl::size size() const;
39 // Raw pcm levels.
40 const VectorPCM &pcm() const;
41 // Zero crossing factor between 0.0f -> 1.0f, detects "hiss"
42 // and sounds like cloths rubbing. Useful for sound analysis.
43 float zcf() const;
44 float rms() const;
45 fl::u32 timestamp() const; // Timestamp when sample became valid (millis)
46
47 void fft(FFTBins *out) const;
48
49 const_iterator begin() const { return pcm().begin(); }
50 const_iterator end() const { return pcm().end(); }
51 const fl::i16 &at(fl::size i) const;
52 const fl::i16 &operator[](fl::size i) const;
53 operator bool() const { return isValid(); }
54 bool operator==(const AudioSample &other) const;
55 bool operator!=(const AudioSample &other) const;
56
57 private:
58 static const VectorPCM &empty();
59 AudioSampleImplPtr mImpl;
60};
61
62// Sound level meter is a persistant measuring class that will auto-tune the
63// microphone to real world SPL levels. It will adapt to the noise floor of the
64// environment. Note that the microphone only ever outputs DBFS (dB Full Scale)
65// values, which are collected over a stream of samples. The sound level meter
66// will convert this to SPL (Sound Pressure Level) values, which are the real
67// world values.
69 public:
73 SoundLevelMeter(double spl_floor = 33.0, double smoothing_alpha = 0.0);
74
76 void processBlock(const fl::i16 *samples, fl::size count);
78 processBlock(samples.data(), samples.size());
79 }
80
82 double getDBFS() const { return current_dbfs_; }
83
85 double getSPL() const { return current_spl_; }
86
88 void setFloorSPL(double spl_floor) {
89 spl_floor_ = spl_floor;
91 }
92
94 void resetFloor() {
95 dbfs_floor_global_ = INFINITY_DOUBLE; // infinity<double>
96 offset_ = 0.0;
97 }
98
99 private:
100 double spl_floor_; // e.g. 33.0 dB SPL
101 double smoothing_alpha_; // 0 = pure min, >0 = slow adapt
102 double dbfs_floor_global_; // lowest dBFS seen so far
103 double offset_; // spl_floor_ − dbfs_floor_global_
104 double current_dbfs_; // last block’s dBFS
105 double current_spl_; // last block’s estimated SPL
106};
107
108// Implementation details.
110 public:
113 // template <typename It> void assign(It begin, It end) {
114 // assign(begin, end, 0); // Default timestamp to 0
115 // }
116 template <typename It> void assign(It begin, It end, fl::u32 timestamp) {
117 mSignedPcm.assign(begin, end);
119 // calculate zero crossings
121 }
122 const VectorPCM &pcm() const { return mSignedPcm; }
123 fl::u32 timestamp() const { return mTimestamp; }
124
125 // For object pool - reset internal state for reuse
126 void reset() {
127 mSignedPcm.clear();
128 mZeroCrossings = 0;
129 mTimestamp = 0;
130 }
131
132 // "Zero crossing factor". High values > .4 indicate hissing
133 // sounds. For example a microphone rubbing against a clothing.
134 // These types of signals indicate the audio should be ignored.
135 // Low zero crossing factors (with loud sound) indicate that there
136 // is organized sound like that coming from music. This is so cheap
137 // to calculate it's done automatically. It should be one of the first
138 // signals to reject or accept a sound signal.
139 //
140 // Returns: a value -> [0.0f, 1.0f)
141 float zcf() const {
142 const fl::size n = pcm().size();
143 if (n < 2) {
144 return 0.f;
145 }
146 return float(mZeroCrossings) / static_cast<float>(n - 1);
147 }
148
149 private:
151 mZeroCrossings = 0;
152 if (mSignedPcm.size() > 1) {
153 for (fl::size i = 1; i < mSignedPcm.size(); ++i) {
154 const bool crossed =
155 (mSignedPcm[i - 1] < 0 && mSignedPcm[i] >= 0) ||
156 (mSignedPcm[i - 1] >= 0 && mSignedPcm[i] < 0);
157 if (crossed) {
159 }
160 }
161 }
162 }
163
165 fl::i16 mZeroCrossings = 0;
166 fl::u32 mTimestamp = 0;
167};
168
169} // namespace fl
AudioAnalyzeFFT1024 fft
const VectorPCM & pcm() const
Definition audio.cpp:62
AudioSampleImplPtr mImpl
Definition audio.h:59
VectorPCM::const_iterator const_iterator
Definition audio.h:25
fl::vector< fl::i16 > VectorPCM
Definition audio.h:24
float zcf() const
Definition audio.cpp:119
fl::size size() const
Definition audio.cpp:75
AudioSample(const AudioSample &other)
Definition audio.h:27
bool operator!=(const AudioSample &other) const
Definition audio.cpp:109
bool isValid() const
Definition audio.h:36
AudioSample(AudioSampleImplPtr impl)
Definition audio.h:28
bool operator==(const AudioSample &other) const
Definition audio.cpp:91
const fl::i16 & operator[](fl::size i) const
Definition audio.cpp:89
float rms() const
Definition audio.cpp:128
const fl::i16 & at(fl::size i) const
Definition audio.cpp:82
fl::u32 timestamp() const
Definition audio.cpp:121
const_iterator begin() const
Definition audio.h:49
const_iterator end() const
Definition audio.h:50
AudioSample & operator=(const AudioSample &other)
Definition audio.cpp:70
static const VectorPCM & empty()
Definition audio.cpp:113
float zcf() const
Definition audio.h:141
fl::u32 mTimestamp
Definition audio.h:166
fl::u32 timestamp() const
Definition audio.h:123
fl::vector< fl::i16 > VectorPCM
Definition audio.h:111
void initZeroCrossings()
Definition audio.h:150
fl::i16 mZeroCrossings
Definition audio.h:165
void assign(It begin, It end, fl::u32 timestamp)
Definition audio.h:116
VectorPCM mSignedPcm
Definition audio.h:164
const VectorPCM & pcm() const
Definition audio.h:122
fl::size size() const
Definition vector.h:545
iterator begin()
Definition vector.h:584
iterator end()
Definition vector.h:590
const T * data() const
Definition slice.h:138
fl::size size() const
Definition slice.h:142
SoundLevelMeter(double spl_floor=33.0, double smoothing_alpha=0.0)
Definition audio.cpp:142
double getDBFS() const
Definition audio.h:82
double dbfs_floor_global_
Definition audio.h:102
double current_dbfs_
Definition audio.h:104
void processBlock(fl::span< const fl::i16 > samples)
Definition audio.h:77
void setFloorSPL(double spl_floor)
change your known noise-floor SPL at runtime
Definition audio.h:88
double getSPL() const
Definition audio.h:85
double smoothing_alpha_
Definition audio.h:101
void processBlock(const fl::i16 *samples, fl::size count)
Process a block of int16 PCM samples.
Definition audio.cpp:147
double spl_floor_
Definition audio.h:100
double current_spl_
Definition audio.h:105
void resetFloor()
reset so the next quiet block will re-initialize your floor
Definition audio.h:94
#define INFINITY_DOUBLE
Definition math_macros.h:85
Slice< T > span
Definition span.h:8
constexpr T * begin(T(&array)[N]) noexcept
Definition range_access.h:9
constexpr T * end(T(&array)[N]) noexcept
HeapVector< T, Allocator > vector
Definition vector.h:1214
IMPORTANT!
Definition crgb.h:20
#define FASTLED_SMART_PTR(type)
Definition ptr.h:33