diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/StatsServer.cpp | 12 | ||||
| -rw-r--r-- | src/StatsServer.h | 47 | 
2 files changed, 56 insertions, 3 deletions
| diff --git a/src/StatsServer.cpp b/src/StatsServer.cpp index eb30ebd..38c4607 100644 --- a/src/StatsServer.cpp +++ b/src/StatsServer.cpp @@ -360,6 +360,9 @@ std::string InputStat::encodeStateJSON()          case Unstable:              ss << "\"Unstable\"";              break; +        case Silence: +            ss << "\"Silent\""; +            break;          case Streaming:              ss << "\"Streaming\"";              break; @@ -400,7 +403,14 @@ input_state_t InputStat::determineState(void)          state = Unstable;      }      else { -        state = Streaming; +        /* The input is streaming, check if the audio level is too low */ + +        if (m_silence_counter > INPUT_AUDIO_LEVEL_SILENCE_COUNT) { +            state = Silence; +        } +        else { +            state = Streaming; +        }      }      return state; diff --git a/src/StatsServer.h b/src/StatsServer.h index 1a2993a..731d8ca 100644 --- a/src/StatsServer.h +++ b/src/StatsServer.h @@ -55,6 +55,7 @@  #include <map>  #include <boost/thread.hpp>  #include <ctime> +#include <math.h>  #define MIN_FILL_BUFFER_UNDEF (-1) @@ -66,9 +67,14 @@ enum input_state_t      /* The input is waiting for data, all buffers are empty */      NoData, -    /* The input is running, but has seen many underruns or overruns */ +    /* The input is running, but has seen many underruns or overruns recently */      Unstable, +    /* The input is running, but the audio level is too low, or has +     * been too low recently +     */ +    Silence, +      /* The input is running stable */      Streaming  }; @@ -88,6 +94,21 @@ enum input_state_t   */  #define INPUT_NODATA_TIMEOUT 30 // seconds +/* For silence detection, we count the number of occurrences the audio level + * falls below a threshold. + * + * The counter is decreased for each frame that has good audio level. + * + * The counter saturates, and this value defines for how long the + * input will be considered silent after a cut. + * + * If the count reaches a certain value, the input changes state + * to Silence. + */ +#define INPUT_AUDIO_LEVEL_THRESHOLD       -50  // dB +#define INPUT_AUDIO_LEVEL_SILENCE_COUNT    100 // superframes (120ms) +#define INPUT_AUDIO_LEVEL_COUNT_SATURATION 500 // superframes (120ms) +  /* An example of how the state changes work.   * The timeout is set to expire in 30 minutes   * at each under-/overrun. @@ -136,6 +157,7 @@ class InputStat              m_time_last_buffer_nonempty = 0;              m_buffer_empty = true;              m_glitch_counter = 0; +            m_silence_counter = 0;              reset();          } @@ -186,7 +208,27 @@ class InputStat              }              // State -            // TODO add silence detection + +            // using the smallest of the two channels +            // allows us to detect if only one channel +            // is silent. +            int minpeak = peak_left < peak_right ? peak_left : peak_right; + +            const int16_t int16_max = std::numeric_limits<int16_t>::max(); +            int peak_dB = minpeak ? +                round(20*log10((double)minpeak / int16_max)) : +                -90; + +            if (peak_dB < INPUT_AUDIO_LEVEL_THRESHOLD) { +                if (m_silence_counter < INPUT_AUDIO_LEVEL_COUNT_SATURATION) { +                    m_silence_counter++; +                } +            } +            else { +                if (m_silence_counter > 0) { +                    m_silence_counter--; +                } +            }          }          void notifyUnderrun(void) @@ -236,6 +278,7 @@ class InputStat          /************* STATE ***************/          /* Variables used for determining the input state */          int m_glitch_counter; // saturating counter +        int m_silence_counter; // saturating counter          time_t m_time_last_event;          time_t m_time_last_buffer_nonempty;          bool m_buffer_empty; | 
