(view source code of detectsound.cs as plain text)
using NAudio.CoreAudioApi;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
namespace RobvanderWoude{internal class DetectSound
{static readonly string progver = "2.00";
static bool debugmode = false;
static bool micaccess = true;
static bool timedout = false;
static Recorder recorder;
[STAThread]
static int Main( string[] args )
{ #region Declare Variables#if DEBUGdebugmode = true;
#endifbool exitatonce = false;
bool quietmode = false;
bool thresholdexceeded = false;
bool thresholdset = false;
bool timeoutset = false;
bool useaverage = false;
int threshold = 50;
int timeout = 1000;
int interval = 100;
int peakmax = 0;
int peakmin = 0;
int peakavg = 0;
int peakcnt = 0;
#endregion Declare Variables #region Parse Command Lineforeach ( string arg in args )
{switch ( arg.ToUpper( ) )
{case "/?":
return ShowHelp( );
case "/A":
if ( useaverage )
{return ShowHelp( "Duplicate command line switch /A" );
}useaverage = true;
break;
case "/D":
#if DEBUG#elseif ( debugmode )
{return ShowHelp( "Duplicate command line switch /D" );
}#endifdebugmode = true;
break;
case "/Q":
if ( useaverage )
{return ShowHelp( "Duplicate command line switch /Q" );
}useaverage = true;
break;
case "/X":
if ( exitatonce )
{return ShowHelp( "Duplicate command line switch /X" );
}exitatonce = true;
break;
default:
if ( int.TryParse( arg, out int test ) )
{if ( thresholdset && timeoutset )
{return ShowHelp( "Invalid numeric argument {0}", arg );
}if ( !thresholdset )
{if ( test > 0 && test < 100 )
{threshold = test;
thresholdset = true;
} else {return ShowHelp( "Invalid threshold value {0}", arg );
} } else {if ( !timeoutset )
{if ( test > 99 )
{timeout = test;
timeoutset = true;
} else {return ShowHelp( "Invalid threshold value {0}", arg );
} } }break;
} else {return ShowHelp( "Invalid command line argument {0}", arg );
} } }if ( exitatonce && useaverage )
{return ShowHelp( "Command line switches /A and /X are mutually exclusive" );
} #endregion Parse Command Line // start timeout timerTimer timer = new Timer( TimerExpired, null, timeout, Timeout.Infinite );
if ( debugmode )
{Console.WriteLine( DateTime.Now.ToString( ) );
} // Start listeningwhile ( !timedout )
{Dictionary<int, AudioEndPoint> allaudioendpoints = GetMicrophones( );
if ( allaudioendpoints.Count == 0 )
{if ( debugmode || !quietmode )
{Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( "No microphone detected" );
Console.ResetColor( );
}return -1;
} else {Thread waverecorder = new Thread( new ThreadStart( WaveRecorder ) );
if ( !micaccess )
{if ( debugmode || !quietmode )
{Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( "Access to microphone denied" );
Console.ResetColor( );
}return -1;
}waverecorder.Start( );
foreach ( AudioEndPoint endpoint in allaudioendpoints.Values )
{if ( endpoint.InOut == DataFlow.Capture )
{if ( endpoint.State == DeviceState.Active )
{ peakcnt++;string devicename = endpoint.Name;
int peak = (int) ( 100 * endpoint.MasterPeakValue );
peakavg += peak;
peakmax = Math.Max( peak, peakmax );
peakmin = Math.Min( peak, peakmin );
if ( debugmode )
{Console.WriteLine( "{0}\t{1}\t{2}", DateTime.Now.TimeOfDay.ToString( ), devicename, endpoint.GetPeakLevel( ) );
}if ( peak >= threshold )
{thresholdexceeded = true;
if ( exitatonce && !quietmode )
{Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine( "Sound detected" );
Console.ResetColor( );
waverecorder.Abort( );
timer.Dispose( );
return 1;
} }Thread.Sleep( interval );
} } }waverecorder.Abort( );
} } // Cleanup timeout timertimer.Dispose( );
#region Show Resultsif ( peakcnt == 0 )
{if ( debugmode || !quietmode )
{Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( "No microphone or access denied" );
Console.ResetColor( );
}return -1;
}peakavg = (int) ( peakavg / peakcnt );
if ( useaverage )
{thresholdexceeded = ( peakavg > threshold );
}if ( debugmode )
{Console.WriteLine( "{0}\tmin {1}%, max {2}%, average {3}%", DateTime.Now.ToString( ), peakmin, peakmax, peakavg );
}if ( useaverage )
{if ( !quietmode )
{Console.WriteLine( "Sound level {0}%", peakavg );
} }if ( !quietmode )
{if ( thresholdexceeded )
{Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine( "Sound detected" );
Console.ResetColor( );
} else {Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( "No sound exceeding the threshold" );
Console.ResetColor( );
} }if ( useaverage )
{return peakavg;
}return ( thresholdexceeded ? 1 : 0 );
#endregion Show Results }private static Dictionary<int, AudioEndPoint> GetMicrophones( )
{Dictionary<int, AudioEndPoint> audioendpoints = new Dictionary<int, AudioEndPoint>( );
MMDeviceEnumerator enumerator = new MMDeviceEnumerator( );
int index = 0;
foreach ( MMDevice endpoint in enumerator.EnumerateAudioEndPoints( DataFlow.Capture, DeviceState.Active ) )
{AudioEndPoint audioendpoint = new AudioEndPoint
{ Index = index,InOut = endpoint.DataFlow,
Name = endpoint.FriendlyName,
State = endpoint.State,
ID = endpoint.ID,
};
audioendpoint.MasterVolumeLevelScalar = endpoint.AudioEndpointVolume.MasterVolumeLevelScalar;
audioendpoint.MasterPeakValue = endpoint.AudioMeterInformation.MasterPeakValue;
audioendpoint.PeakValues = endpoint.AudioMeterInformation.PeakValues;
audioendpoints[index] = audioendpoint;
index++; }return audioendpoints;
} #region Error handlingstatic int ShowHelp( params string[] errmsg )
{ #region Error Messageif ( errmsg.Length > 0 )
{List<string> errargs = new List<string>( errmsg );
errargs.RemoveAt( 0 );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR:\t" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
Console.ResetColor( );
} #endregion Error Message #region Help Text /* DetectSound.exe, Version 2.00 Detect sound input on default microphone before detection period expires? Usage: DetectSound.exe [ threshold ] [ timeout ] [ /A | /X ] [ /D ] [ /Q ]? Where: threshold the minimum peak level to detect (1..99; default 50) timeout detection period in milliseconds (100 or up; default: 1000) /A Average peak value is returned as errorlevel /D Debug mode: display value for each sample /Q Quiet mode: no messages, only errorlevel to check result /X eXit immediately if threshold is exceeded before timeout expires (default: wait till timeout expires) Notes: This program uses Mark Heath's NAudio, available at https://github.com/naudio/NAudio to detect sound. Return code 1 or average peak level if sound is detected within the timeout period, 0 if not, or -1 in case of errors.? Written by Rob van der Woude https://www.robvanderwoude.com */ #endregion Help Text #region Display Help TextConsole.Error.WriteLine( );
Console.Error.WriteLine( "DetectSound.exe, Version {0}", progver );
Console.Error.WriteLine( "Detect sound input on default microphone before detection period expires" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "DetectSound.exe [ threshold ] [ timeout ] [ /A | /X ] [ /D ] [ /Q ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Where: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "threshold" );
Console.ResetColor( );
Console.Error.WriteLine( " the minimum peak level to detect (1..99; default 50)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " timeout" );
Console.ResetColor( );
Console.Error.WriteLine( " detection period in milliseconds (100 or up; default: 1000)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /A A" );
Console.ResetColor( );
Console.Error.WriteLine( "verage peak value is returned as errorlevel" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /D D" );
Console.ResetColor( );
Console.Error.WriteLine( "ebug mode: display value for each sample" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /Q Q" );
Console.ResetColor( );
Console.Error.WriteLine( "uiet mode: no messages, only errorlevel to check result" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /X" );
Console.ResetColor( );
Console.Error.Write( " e" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "X" );
Console.ResetColor( );
Console.Error.WriteLine( "it immediately if threshold is exceeded before timeout" );
Console.Error.WriteLine( " expires (default: wait till timeout expires)" );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Notes: This program uses Mark Heath's NAudio, available at" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.Write( " https://github.com/naudio/NAudio" );
Console.ResetColor( );
Console.Error.WriteLine( " to detect sound." );
Console.Error.WriteLine( " Return code 1 or average peak level if sound is detected within the" );
Console.Error.WriteLine( " timeout period, 0 if not, or -1 in case of errors." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.WriteLine( "https://www.robvanderwoude.com" );
#endregion Display Help Textreturn -1;
} #endregion Error handlingprivate static void TimerExpired( object state )
{if ( debugmode )
{Console.WriteLine( "{0}\tTime's Up", DateTime.Now.ToString( ) );
}timedout = true;
}public static void WaveRecorder( )
{ try {recorder = new Recorder( );
recorder.StartRecording( );
micaccess = true;
}catch ( Exception )
{micaccess = false;
} } }public class AudioEndPoint
{public int Index
{get; set;
} public DataFlow InOut {get; set;
}public string Name
{get; set;
} public DeviceState State {get; set;
}public string ID
{get; set;
}public float MasterVolumeLevelScalar
{get; set;
}public float MasterPeakValue
{get; set;
} public AudioMeterInformationChannels PeakValues {get; set;
}public string GetVolume( )
{if ( State == DeviceState.Active )
{return string.Format( "{0} %", (int) ( MasterVolumeLevelScalar * 100 ) );
} else {return string.Empty;
} }public string GetPeakLevel( int channel = -1 )
{if ( State == DeviceState.Active )
{switch ( channel )
{case 0:
if ( PeakValues.Count > 0 )
{return string.Format( "{0} %", (int) ( 100 * float.Parse( PeakValues[0].ToString( ) ) ) );
} else {return string.Empty;
}case 1:
if ( PeakValues.Count > 1 )
{return string.Format( "{0} %", (int) ( 100 * float.Parse( PeakValues[1].ToString( ) ) ) );
} else {return string.Empty;
}default:
return string.Format( "{0} %", (int) ( 100 * MasterPeakValue ) );
} } else {return string.Empty;
} } }public class Recorder
{public WaveInEvent wavein = new WaveInEvent( );
public void StartRecording( )
{wavein.StartRecording( );
} }}page last modified: 2025-10-11; loaded in 0.0117 seconds