开发者

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]

This question already has answers here: Closed 11 years ago.

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜