@@ -449,9 +449,7 @@ class GeneratedSoundStream : public AudioStream {
449449 AudioInfo audioInfo () override { return generator_ptr->audioInfo (); }
450450
451451 // / 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 ; }
455453
456454 // / privide the data as byte stream
457455 size_t readBytes (uint8_t *data, size_t len) override {
@@ -472,7 +470,8 @@ class GeneratedSoundStream : public AudioStream {
472470 protected:
473471 bool active = true ; // support for legacy sketches
474472 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
476475 const char *source_not_defined_error = " Source not defined" ;
477476};
478477
@@ -579,15 +578,15 @@ class BufferedStream : public ModifyingStream {
579578 }
580579 }
581580
582- // / Provides data w/o consuming
581+ // / Provides data w/o consuming
583582 size_t peekBytes (uint8_t *data, size_t len) {
584583 if (buffer.isEmpty ()) {
585584 refill ();
586- }
585+ }
587586 return buffer.peekArray (data, len);
588587 }
589588
590- // / Returns the available bytes
589+ // / Returns the available bytes
591590 int available () override {
592591 if (p_in == nullptr ) return 0 ;
593592 return buffer.available () + p_in->available ();
@@ -599,10 +598,9 @@ class BufferedStream : public ModifyingStream {
599598 // / Resize the buffer
600599 void resize (int size) { buffer.resize (size); }
601600
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; }
606604
607605 protected:
608606 SingleBuffer<uint8_t > buffer{0 };
@@ -1258,7 +1256,7 @@ class InputMixer : public AudioStream {
12581256 void setRetryCount (int retry) { retry_count = retry; }
12591257
12601258 // / Removes a stream by index position
1261- bool remove (int idx){
1259+ bool remove (int idx) {
12621260 if (idx < 0 || idx >= size ()) {
12631261 return false ;
12641262 }
@@ -1313,11 +1311,11 @@ class InputMixer : public AudioStream {
13131311
13141312 // / Recalculate the weights
13151313 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;
13211319 }
13221320
13231321 // / mixing using a vector of samples
@@ -1753,14 +1751,8 @@ class FilteredStream : public ModifyingStream {
17531751class VolumeMeter : public ModifyingStream {
17541752 public:
17551753 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); }
17641756 VolumeMeter (Print &print) { setOutput (print); }
17651757 VolumeMeter (Stream &stream) { setStream (stream); }
17661758
@@ -1875,6 +1867,14 @@ class VolumeMeter : public ModifyingStream {
18751867 }
18761868 }
18771869
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+ }
18781878 void setOutput (Print &out) override { p_out = &out; }
18791879 void setStream (Stream &io) override {
18801880 p_out = &io;
@@ -1953,10 +1953,178 @@ class VolumeMeter : public ModifyingStream {
19531953// / @ingroup io
19541954using VolumePrint = VolumeMeter;
19551955
1956- // / @brief Legacy alias for VolumeMeter
1956+ // / @brief Legacy alias for VolumeMeter
19571957// / @ingroup io
19581958using VolumeOutput = VolumeMeter;
19591959
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+
19602128#ifdef USE_TIMER
19612129/* *
19622130 * @brief TimerCallbackAudioStream Configuration
0 commit comments