You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Analyzer reads sample blocks of size Config.SampleBlockSize * ISamples.Channels from the input sample data and feeds each sample block to its IDetector every time AnalyzeNextBlock() is called. An internal state machine is used to skip redundant reports of the same DTMF tone detected in consecutive sample blocks. Instead only the starting and stop position of each DMTF tone will be reported. When no more samples are available the property MoreSamplesAvailable will be set to false and the analysis is considered finished (i.e. subsequent calls to AnalyzeNextBlock() should be avoided as they might fail or result in undefined behavior, depending on the ISamples implementation.
Properties
Name
Type
Summary
MoreSamplesAvailable
bool
Indicates whether there is more data to analyze. AnalyzeNextBlock() should not be called when this is false. Is true initially and turns false as soon as ISamples.Read() returned a number less than Config.SampleBlockSize.
Tries to read Config.SampleBlockSize * ISamples.Channels samples from the input data and runs DTMF detection on that sample block. Should only be called when MoreSamplesAvailable is true.
Creates a new Analyzer using a self-created instance of Detector to feed the given sample data to it.
AudioData Class
Namespace: DtmfDetection
Convenience implementation of ISamples for PCM audio data. PCM data is usually represented as an array of floats. The Analyzer uses ISamples to read the input data in blocks and feed them to the Detector.
Properties
Name
Type
Summary
Channels
int
Returns the number of channels this AudioData has been created with.
SampleRate
int
Returns the sample rate this AudioData has been created with.
Position
TimeSpan
Calculates and returns the current position in the PCM data.
Constructors
Name
Summary
AudioData(float[] samples, int channels, int sampleRate)
Creates a new AudioData from the given array of float values which were sampled with the given sample rate and for the given number of channels.
Methods
Name
Returns
Summary
Read(float[] buffer, int count)
int
Reads count samples from the input and writes them into buffer. Because the input PCM data already has the expected format, this boils down to a simple call to Array.Copy().
Config Struct
Namespace: DtmfDetection
The detector configuration.
Constructors
Name
Summary
Config(double threshold, int sampleBlockSize, int sampleRate, bool normalizeResponse)
Creates a cloned Config instance from this instance, but with a new Threshold setting.
Fields
Name
Type
Summary
Threshold
double
The detection threshold. Typical values are 30-35 (when NormalizeResponse is true) and 100-115 (when NormalizeResponse is false).
SampleBlockSize
int
The number of samples to analyze before the Goertzel response should be calulated. It is recommened to leave it at the default value 205 (tuned to minimize error of the target frequency bin).
SampleRate
int
The sample rate (in Hz) the Goertzel algorithm expects. Sources with higher samples rates must resampled to this sample rate. It is recommended to leave it at the default value 8000.
NormalizeResponse
bool
Toggles normalization of the Goertzel response with the total signal energy of the sample block. Recommended setting is true as this provides invariance to loudness changes of the signal.
The default detection threshold (tuned to normalized responses).
DefaultSampleBlockSize
int
The default number of samples to analyze before the Goertzel response should be calulated (tuned to minimize error of the target frequency bin).
DefaultSampleRate
int
Default rate (in Hz) at which the analyzed samples are expected to have been measured.
Detector Class
Namespace: DtmfDetection
Creates a Goertzel accumulator for each of the DTMF tone low (697, 770, 852, and 941 Hz) and high frequencies (1209, 1336, 1477, and 1633 Hz) and repeats that for each audio channel in the input data. When Detect() is called, each sample of the input sample block is added to each Goertzel accumulator and afterwards the Goertzel response of each frequency is retrieved. Reports a detected DTMF tone when exactly one of the four low frequency responses crosses the detection threshold, and exactly one of the four high frequency responses crosses the detection threshold.
Properties
Name
Type
Summary
Channels
int
The number of channels this detector has been created for. Used by the Analyzer to validate that this detector supports the number of channels present int the source data (ISamples.Channels).
Runs the Goertzel algorithm on all samples in sampleBlock and returns the DTMF key detected in each channel. PhoneKey.None is used in case no DTMF key has been detected in a channel.
DtmfChange Struct
Namespace: DtmfDetection
Represents the start or a stop of a DTMF tone in audio data.
Properties
Name
Type
Summary
IsStop
bool
Indicates whether a DMTF tone started or stopped at the current position.
Constructors
Name
Summary
DtmfChange(PhoneKey key, TimeSpan position, int channel, bool isStart)
Creates a new DtmfChange with the given identification and location.
The actual implementation of the Goertzel algorithm (https://en.wikipedia.org/wiki/Goertzel_algorithm) that estimates the strength of a frequency in a signal. It works similar to a Fourier transform except that it doesn't analyze the whole spectrum, but only a single frequency.
Properties
Name
Type
Summary
Response
double
Calculates and returns the estimated strength of the frequency in the samples given so far.
NormResponse
double
Calculates Response, but normalized with the total signal energy, which achieves loudness invariance.
Creates a new Goertzel from this one's coefficient C, but resets the state (S1, S2) and the total signal energy (E) to 0. Useful to save the computation of C when the parameters of Init() were to stay the same.
ToString()
string
Prints the value of NormResponse to a string and returns it.
Fields
Name
Type
Summary
C
double
Stores a pre-computed coefficient calculated from the parameters of Init().
S1
double
Stores the state of the Goertzel. Used to determine the strength of the target frequency in the signal.
S2
double
Stores the state of the Goertzel. Used to determine the strength of the target frequency in the signal.
E
double
Accumulates the total signal energy of the signal. Used for normalization.
PhoneKey Enum
Namespace: DtmfDetection
An enumeration of all possible DTMF keys.
Values
Name
Summary
Zero
Key '0'
One
Key '1'
Two
Key '2'
Three
Key '3'
Four
Key '4'
Five
Key '5'
Six
Key '6'
Seven
Key '7'
Eight
Key '8'
Nine
Key '9'
Star
Key '*'
Hash
Key '#'
A
Key 'A'
B
Key 'B'
C
Key 'C'
D
Key 'D'
None
Used to represent the absence of any DTMF tones.
ToDtmfTonesExt Class
Namespace: DtmfDetection
Provides helpers to generate a sequence of DtmfTones from a list of DtmfChanges.
Finds the stop of a DTMF tone matching the given start of a DTMF tone in a list of DtmfChanges. A DtmfChange x matches start when: x.IsStop == true, x.Channel == start.Channel,x.Key == start.Key, and x.Position >= start.Position.
Converts a list of DtmfChanges to a sequence of DtmfTones by finding the matching stop of a DTMF tones to each start of a DTMF tone and merging both into a single DtmfTone struct.
Utils Class
Namespace: DtmfDetection
Provides helpers to convert between PhoneKeys and their corresponding frequency encodings.
Interface to decouple the BackgroundAnalyzer from the Analyzer it is using by default. Use this if you want to inject your own analyzer into the BackgroundAnalyzer. Feel free to start by copying the original Analyzer and adjust it to your needs.
Properties
Name
Type
Summary
MoreSamplesAvailable
bool
Indicates whether there is more data to analyze. Should always be true initially and once it turned false, it should never turn back to true again.
Analyzes the next block of samples. The size of the analyzed block should match Config.SampleBlockSize multiplied by the number of channels in the sample data. This might throw when called while MoreSamplesAvailable is false.
IDetector Class
Namespace: DtmfDetection.Interfaces
Interface to decouple the Analyzer from the Detector it is using by default. Use this if you want to inject your own detector into the Analyzer. Feel free to start by copying the original Detector and adjust it to your needs.
Properties
Name
Type
Summary
Channels
int
The number of channels this detector has been created for. Used by the Analyzer to validate that this detector supports the number of channels present int the source data (ISamples.Channels).
Runs the Goertzel algorithm on all samples in sampleBlock and returns the DTMF key detected in each channel. PhoneKey.None is used in case no DTMF key has been detected in a channel.
ISamples Class
Namespace: DtmfDetection.Interfaces
Interface used by the Analyzer to access a variety of audio sources in a uniform way. Implement this interface if your data source does not fit any of the pre-built implementations: AudioData for float arrays of PCM data, AudioFile for audio files (mp3, wav, aiff and Windows Media Foundation formats), or AudioStream for infinite audio streams.
Properties
Name
Type
Summary
Channels
int
The number of audio channels. This should match the value of Config.Channels the Analyzer is using.
SampleRate
int
The rate at which the values have been sampled in Hz. This should match the value of Config.SampleRate the Analyzer is using.
Position
TimeSpan
The position of the "read cursor" in the sample stream. This should increase with every call to Read() that returns a value greater than 0.
Methods
Name
Returns
Summary
Read(float[] buffer, int count)
int
Reads count samples from the input and writes them into buffer. This method should either block until count samples have been succesfully read, or return a number less than count to indicate that the end of the stream has been reached. Once the end of stream has been reached, subsequent calls to Read() are allowed to fail with exceptions.