be.tarsos.dsp.onsets.PercussionOnsetDetector Maven / Gradle / Ivy
/*
* _______ _____ _____ _____
* |__ __| | __ \ / ____| __ \
* | | __ _ _ __ ___ ___ ___| | | | (___ | |__) |
* | |/ _` | '__/ __|/ _ \/ __| | | |\___ \| ___/
* | | (_| | | \__ \ (_) \__ \ |__| |____) | |
* |_|\__,_|_| |___/\___/|___/_____/|_____/|_|
*
* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*
* -------------------------------------------------------------
*
* Info: http://0110.be/tag/TarsosDSP
* Github: https://github.com/JorenSix/TarsosDSP
* Releases: http://0110.be/releases/TarsosDSP/
*
* TarsosDSP includes modified source code by various authors,
* for credits and info, see README.
*
*/
package be.tarsos.dsp.onsets;
import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;
import be.tarsos.dsp.util.fft.FFT;
/**
*
* Estimates the locations of percussive onsets using a simple method described
* in "Drum Source Separation using Percussive Feature Detection and Spectral
* Modulation" by Dan Barry, Derry Fitzgerald, Eugene Coyle and Bob Lawlor,
* ISSC 2005.
*
*
* Implementation based on a VAMP plugin example by Chris Cannam at Queen Mary, London:
*
*
* Centre for Digital Music, Queen Mary, University of London.
* Copyright 2006 Chris Cannam.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the names of the Centre for
* Digital Music; Queen Mary, University of London; and Chris Cannam
* shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written
* authorization.
*
*
*
*
* @author Joren Six
* @author Chris Cannam
*/
public class PercussionOnsetDetector implements AudioProcessor, OnsetDetector {
public static final double DEFAULT_THRESHOLD = 8;
public static final double DEFAULT_SENSITIVITY = 20;
private final FFT fft;
private final float[] priorMagnitudes;
private final float[] currentMagnitudes;
private float dfMinus1, dfMinus2;
private OnsetHandler handler;
private final float sampleRate;//samples per second (Hz)
private long processedSamples;//in samples
/**
* Sensitivity of peak detector applied to broadband detection function (%).
* In [0-100].
*/
private final double sensitivity;
/**
* Energy rise within a frequency bin necessary to count toward broadband
* total (dB). In [0-20].
*
*/
private final double threshold;
/**
* Create a new percussion onset detector. With a default sensitivity and threshold.
*
* @param sampleRate
* The sample rate in Hz (used to calculate timestamps)
* @param bufferSize
* The size of the buffer in samples.
* @param bufferOverlap
* The overlap of buffers in samples.
* @param handler
* An interface implementor to handle percussion onset events.
*/
public PercussionOnsetDetector(float sampleRate, int bufferSize,
int bufferOverlap, OnsetHandler handler) {
this(sampleRate, bufferSize, handler,
DEFAULT_SENSITIVITY, DEFAULT_THRESHOLD);
}
/**
* Create a new percussion onset detector.
*
* @param sampleRate
* The sample rate in Hz (used to calculate timestamps)
* @param bufferSize
* The size of the buffer in samples.
* @param handler
* An interface implementor to handle percussion onset events.
* @param sensitivity
* Sensitivity of the peak detector applied to broadband
* detection function (%). In [0-100].
* @param threshold
* Energy rise within a frequency bin necessary to count toward
* broadband total (dB). In [0-20].
*/
public PercussionOnsetDetector(float sampleRate, int bufferSize, OnsetHandler handler, double sensitivity, double threshold) {
fft = new FFT(bufferSize / 2);
this.threshold = threshold;
this.sensitivity = sensitivity;
priorMagnitudes = new float[bufferSize / 2];
currentMagnitudes = new float[bufferSize / 2];
this.handler = handler;
this.sampleRate = sampleRate;
}
@Override
public boolean process(AudioEvent audioEvent) {
float[] audioFloatBuffer = audioEvent.getFloatBuffer();
this.processedSamples += audioFloatBuffer.length;
this.processedSamples -= audioEvent.getOverlap();
fft.forwardTransform(audioFloatBuffer);
fft.modulus(audioFloatBuffer, currentMagnitudes);
int binsOverThreshold = 0;
for (int i = 0; i < currentMagnitudes.length; i++) {
if (priorMagnitudes[i] > 0.f) {
double diff = 10 * Math.log10(currentMagnitudes[i]
/ priorMagnitudes[i]);
if (diff >= threshold) {
binsOverThreshold++;
}
}
priorMagnitudes[i] = currentMagnitudes[i];
}
if (dfMinus2 < dfMinus1
&& dfMinus1 >= binsOverThreshold
&& dfMinus1 > ((100 - sensitivity) * audioFloatBuffer.length) / 200) {
float timeStamp = processedSamples / sampleRate;
handler.handleOnset(timeStamp,-1);
}
dfMinus2 = dfMinus1;
dfMinus1 = binsOverThreshold;
return true;
}
@Override
public void processingFinished() {
}
@Override
public void setHandler(OnsetHandler handler) {
this.handler = handler;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy