Can you tell me how to detect an event from a sound whether a part of its wave or spectrum exceeds a specific amount of threshold? [duplicate]
Possible Duplicate:
How to catch the event when spectrum of an audio reached a specific height, like triggered event made by a loud sound?
I want to detect for a example, a beat or a loud sound from an audio file. All the modules are working except that I don't know how to code the detection. Some says, I'll iterate the data from the spectrum and record the parts where there is a load sound or a beat.
I'll show you the code of my FFT, I got this from NAudio. Can you show me if I can detect an event here.
For example:
if (waveLeft[] > amplitudeThreshold || waveleft[] < -amplitudeThreshold)
listbox.items.add(ActiveStream.CurrentTime)
That's the idea.
So here's the code.
public SampleAggregator(int bufferSize)
{
channelData = new Complex[bufferSize];
}
public void Clear()
{
volumeLeftMaxValue = float.MinValue;
volumeRightMaxValue = float.MinValue;
volumeLeftMinValue = float.MaxValue;
volumeRightMinValue = float.MaxValue;
channelDataPosition = 0;
}
/// <summary>
/// Add a sample value to the aggregator.
/// </summary>
/// <param name="value">The value of the sample.</param>
public void Add(float leftValue, float rightValue)
{
if (channelDataPosition == 0)
{
volumeLeftMaxValue = float.MinValue;
volumeRightMaxValue = float.MinValue;
volumeLeftMinValue = float.MaxValue;
volumeRightMinValue = float.MaxValue;
}
// Make stored channel data stereo by averaging left and right values.
channelData[channelDataPosition].X = (leftValue + rightValue) / 2.0f;
channelData[channelDataPosition].Y = 0;
channelDataPosition++;
volumeLeftMaxValue = Math.Max(volumeLeftMaxValue, leftValue);
volumeLeftMinValue = Math.Min(volumeLeftMinValue, leftValue);
volumeRightMaxValue = Math.Max(volumeRightMaxValue, rightValue);
volumeRightMinValue = Math.Min(volumeRightMinValue, rightValue);
if (channelDataPosition >= channelData.Length)
{
channelDataPosition = 0;
}
}
/// <summary>
/// Performs an FFT calculation on the channel data upon request.
/// </summary>
/// <param name="fftBuffer">A buffer where the FFT data will be stored.</param>
public void GetFFTResults(float[] fftBuffer)
{
Complex[] channelDataClone = new Complex[4096];
channelData.CopyTo(channelDataClone, 0);
// 4096 = 2^12
FastFourierTransform.FFT(true, 12, channelDataClone);
for (int i = 0; i < channelDataClone.Length / 2; i++)
{
// Calculate actual intensities for the FFT results.
fftB开发者_StackOverflowuffer[i] = (float)Math.Sqrt(channelDataClone[i].X * channelDataClone[i].X + channelDataClone[i].Y * channelDataClone[i].Y);
}
}
Thank you for the help. :)
The basic idea:
You segment your stream of wave-form samples into timeslices and convert each slice to the F-domain with your FFT.
Then you have a stream of FFT frames in which you check each channel (bin) for peaks. You'll need a lastValue and maybe even a little state-machine per bin.
FFT width and peaklevel to be configured.
精彩评论