@@ -449,9 +449,7 @@ class GeneratedSoundStream : public AudioStream {
449
449
AudioInfo audioInfo () override { return generator_ptr->audioInfo (); }
450
450
451
451
// / This is unbounded so we just return the buffer size
452
- virtual int available () override {
453
- return active ? buffer_size : 0 ;
454
- }
452
+ virtual int available () override { return active ? buffer_size : 0 ; }
455
453
456
454
// / privide the data as byte stream
457
455
size_t readBytes (uint8_t *data, size_t len) override {
@@ -472,7 +470,8 @@ class GeneratedSoundStream : public AudioStream {
472
470
protected:
473
471
bool active = true ; // support for legacy sketches
474
472
SoundGenerator<T> *generator_ptr;
475
- int buffer_size = DEFAULT_BUFFER_SIZE * 100 ; // there is no reason to limit this
473
+ int buffer_size =
474
+ DEFAULT_BUFFER_SIZE * 100 ; // there is no reason to limit this
476
475
const char *source_not_defined_error = " Source not defined" ;
477
476
};
478
477
@@ -579,15 +578,15 @@ class BufferedStream : public ModifyingStream {
579
578
}
580
579
}
581
580
582
- // / Provides data w/o consuming
581
+ // / Provides data w/o consuming
583
582
size_t peekBytes (uint8_t *data, size_t len) {
584
583
if (buffer.isEmpty ()) {
585
584
refill ();
586
- }
585
+ }
587
586
return buffer.peekArray (data, len);
588
587
}
589
588
590
- // / Returns the available bytes
589
+ // / Returns the available bytes
591
590
int available () override {
592
591
if (p_in == nullptr ) return 0 ;
593
592
return buffer.available () + p_in->available ();
@@ -599,10 +598,9 @@ class BufferedStream : public ModifyingStream {
599
598
// / Resize the buffer
600
599
void resize (int size) { buffer.resize (size); }
601
600
602
- // / Defines the minimum direct unbuffered read size to the original source (default is 1024)
603
- void setMinUnbufferedReadSize (size_t size) {
604
- minReadBufferSize = size;
605
- }
601
+ // / Defines the minimum direct unbuffered read size to the original source
602
+ // / (default is 1024)
603
+ void setMinUnbufferedReadSize (size_t size) { minReadBufferSize = size; }
606
604
607
605
protected:
608
606
SingleBuffer<uint8_t > buffer{0 };
@@ -1258,7 +1256,7 @@ class InputMixer : public AudioStream {
1258
1256
void setRetryCount (int retry) { retry_count = retry; }
1259
1257
1260
1258
// / Removes a stream by index position
1261
- bool remove (int idx){
1259
+ bool remove (int idx) {
1262
1260
if (idx < 0 || idx >= size ()) {
1263
1261
return false ;
1264
1262
}
@@ -1313,11 +1311,11 @@ class InputMixer : public AudioStream {
1313
1311
1314
1312
// / Recalculate the weights
1315
1313
void recalculateWeights () {
1316
- int total = 0 ;
1317
- for (int j = 0 ; j < weights.size (); j++) {
1318
- total += weights[j];
1319
- }
1320
- total_weights = total;
1314
+ int total = 0 ;
1315
+ for (int j = 0 ; j < weights.size (); j++) {
1316
+ total += weights[j];
1317
+ }
1318
+ total_weights = total;
1321
1319
}
1322
1320
1323
1321
// / mixing using a vector of samples
@@ -1753,14 +1751,8 @@ class FilteredStream : public ModifyingStream {
1753
1751
class VolumeMeter : public ModifyingStream {
1754
1752
public:
1755
1753
VolumeMeter () = default ;
1756
- VolumeMeter (AudioStream &as) {
1757
- addNotifyAudioChange (as);
1758
- setStream (as);
1759
- }
1760
- VolumeMeter (AudioOutput &ao) {
1761
- addNotifyAudioChange (ao);
1762
- setOutput (ao);
1763
- }
1754
+ VolumeMeter (AudioStream &as) { setStream (as); }
1755
+ VolumeMeter (AudioOutput &ao) { setOutput (ao); }
1764
1756
VolumeMeter (Print &print) { setOutput (print); }
1765
1757
VolumeMeter (Stream &stream) { setStream (stream); }
1766
1758
@@ -1875,6 +1867,14 @@ class VolumeMeter : public ModifyingStream {
1875
1867
}
1876
1868
}
1877
1869
1870
+ void setOutput (AudioOutput &out) {
1871
+ addNotifyAudioChange (out);
1872
+ setOutput ((Print &)out);
1873
+ }
1874
+ void setStream (AudioStream &io) {
1875
+ addNotifyAudioChange (io);
1876
+ setStream ((Stream &)io);
1877
+ }
1878
1878
void setOutput (Print &out) override { p_out = &out; }
1879
1879
void setStream (Stream &io) override {
1880
1880
p_out = &io;
@@ -1953,10 +1953,178 @@ class VolumeMeter : public ModifyingStream {
1953
1953
// / @ingroup io
1954
1954
using VolumePrint = VolumeMeter;
1955
1955
1956
- // / @brief Legacy alias for VolumeMeter
1956
+ // / @brief Legacy alias for VolumeMeter
1957
1957
// / @ingroup io
1958
1958
using VolumeOutput = VolumeMeter;
1959
1959
1960
+ /* *
1961
+ * @brief Monitors audio input and reports if the volume exceeds a specified
1962
+ * limit within a given period.
1963
+ *
1964
+ * This class uses a VolumeMeter internally and tracks if the input volume has
1965
+ * exceeded the specified limit during the last period. It can be used in an
1966
+ * audio processing chain as a ModifyingStream.
1967
+ * @ingroup io
1968
+ * @ingroup volume
1969
+ * @author Phil Schatzmann
1970
+ * @copyright GPLv3
1971
+ */
1972
+ class AudioInputMonitor : public ModifyingStream {
1973
+ public:
1974
+ /* *
1975
+ * @brief Construct a new AudioInputMonitor with a volume limit in percent
1976
+ * @param limitPercent The volume threshold as percent (default: 20)
1977
+ */
1978
+ AudioInputMonitor (uint8_t limitPercent = 20 ) {
1979
+ setLimitPercent (limitPercent);
1980
+ volume_meter.addNotifyAudioChange (*this );
1981
+ }
1982
+ /* *
1983
+ * @brief Construct a new AudioInputMonitor with an input stream
1984
+ * @param as Reference to an AudioStream
1985
+ * @param limitPercent The volume threshold as percent (default: 20)
1986
+ */
1987
+ AudioInputMonitor (AudioStream &as, uint8_t limitPercent = 20 )
1988
+ : AudioInputMonitor(limitPercent) {
1989
+ setStream (as);
1990
+ }
1991
+ /* *
1992
+ * @brief Construct a new AudioInputMonitor with an output
1993
+ * @param ao Reference to an AudioOutput
1994
+ * @param limitPercent The volume threshold as percent (default: 20)
1995
+ */
1996
+ AudioInputMonitor (AudioOutput &ao, uint8_t limitPercent = 20 )
1997
+ : AudioInputMonitor(limitPercent) {
1998
+ setOutput (ao);
1999
+ }
2000
+ /* *
2001
+ * @brief Construct a new AudioInputMonitor with a Print output
2002
+ * @param print Reference to a Print object
2003
+ * @param limitPercent The volume threshold as percent (default: 20)
2004
+ */
2005
+ AudioInputMonitor (Print &print, uint8_t limitPercent = 20 )
2006
+ : AudioInputMonitor(limitPercent) {
2007
+ setOutput (print);
2008
+ }
2009
+ /* *
2010
+ * @brief Construct a new AudioInputMonitor with a Stream input
2011
+ * @param stream Reference to a Stream object
2012
+ * @param limitPercent The volume threshold as percent (default: 20)
2013
+ */
2014
+ AudioInputMonitor (Stream &stream, uint8_t limitPercent = 20 )
2015
+ : AudioInputMonitor(limitPercent) {
2016
+ setStream (stream);
2017
+ }
2018
+ /* *
2019
+ * @brief Set the volume threshold as percent
2020
+ * @param percent The new volume threshold (0-100)
2021
+ */
2022
+ void setLimitPercent (uint8_t percent) { limit_percent = percent; }
2023
+
2024
+ /* *
2025
+ * @brief Get the current volume threshold as percent
2026
+ * @return The current volume threshold (0-100)
2027
+ */
2028
+ uint8_t limitPercent () const { return limit_percent; }
2029
+
2030
+ /* *
2031
+ * @brief Begin processing with the given audio information
2032
+ * @param info AudioInfo structure
2033
+ * @return true if successful
2034
+ */
2035
+ bool begin (AudioInfo info) {
2036
+ setAudioInfo (info);
2037
+ return begin ();
2038
+ }
2039
+
2040
+ /* *
2041
+ * @brief Begin processing with the current audio information
2042
+ * @return true if successful
2043
+ */
2044
+ bool begin () override {
2045
+ volume_meter.begin (audioInfo ());
2046
+ return true ;
2047
+ }
2048
+
2049
+ /* *
2050
+ * @brief Set the audio information
2051
+ * @param info AudioInfo structure
2052
+ */
2053
+ void setAudioInfo (AudioInfo info) override {
2054
+ ModifyingStream::setAudioInfo (info);
2055
+ volume_meter.setAudioInfo (info);
2056
+ }
2057
+
2058
+ /* *
2059
+ * @brief Write audio data to the monitor (same as VolumeMeter)
2060
+ * @param data Pointer to audio data
2061
+ * @param len Number of bytes
2062
+ * @return Number of bytes written
2063
+ */
2064
+ size_t write (const uint8_t *data, size_t len) override {
2065
+ size_t result = volume_meter.write (data, len);
2066
+ if (result > 0 && volume_meter.volumePercent () > limit_percent) {
2067
+ time_over_last_volume_limit = millis ();
2068
+ }
2069
+ return result;
2070
+ }
2071
+
2072
+ /* *
2073
+ * @brief Read audio data from the monitor (same as VolumeMeter)
2074
+ * @param data Pointer to buffer to fill
2075
+ * @param len Number of bytes to read
2076
+ * @return Number of bytes read
2077
+ */
2078
+ size_t readBytes (uint8_t *data, size_t len) override {
2079
+ size_t result = volume_meter.readBytes (data, len);
2080
+ if (result > 0 && volume_meter.volumePercent () > limit_percent) {
2081
+ time_over_last_volume_limit = millis ();
2082
+ }
2083
+ return result;
2084
+ }
2085
+
2086
+ /* *
2087
+ * @brief Set the output target
2088
+ * @param out Reference to a Print object
2089
+ */
2090
+ void setOutput (Print &out) override { volume_meter.setOutput (out); }
2091
+ /* *
2092
+ * @brief Set the output target
2093
+ * @param out Reference to a Print object
2094
+ */
2095
+ void setOutput (AudioOutput &out) { volume_meter.setOutput (out); }
2096
+ /* *
2097
+ * @brief Set the input stream
2098
+ * @param io Reference to a Stream object
2099
+ */
2100
+ void setStream (Stream &io) override { volume_meter.setStream (io); }
2101
+ /* *
2102
+ * @brief Set the input stream
2103
+ * @param io Reference to a Stream object
2104
+ */
2105
+ void setStream (AudioStream &io) { volume_meter.setStream (io); }
2106
+
2107
+ /* *
2108
+ * @brief Access the underlying VolumeMeter
2109
+ * @return Reference to the internal VolumeMeter
2110
+ */
2111
+ VolumeMeter &getVolumeMeter () { return volume_meter; }
2112
+
2113
+ /* *
2114
+ * @brief Returns true if the volume exceeded the limit during the last period
2115
+ * @param time_ms The period in milliseconds to check (default: 1000)
2116
+ * @return true if the volume exceeded the limit during the period
2117
+ */
2118
+ bool isActive (uint16_t time_ms = 1000 ) {
2119
+ return (millis () - time_over_last_volume_limit) < time_ms;
2120
+ }
2121
+
2122
+ protected:
2123
+ VolumeMeter volume_meter; // /< Volume calculation
2124
+ uint8_t limit_percent = 20 ; // /< Threshold percent
2125
+ uint64_t time_over_last_volume_limit = 0 ; // /< Last over-limit time (ms)
2126
+ };
2127
+
1960
2128
#ifdef USE_TIMER
1961
2129
/* *
1962
2130
* @brief TimerCallbackAudioStream Configuration
0 commit comments