我想修改WhistleApi以用于我想要检测的另一种声音。我想知道如何定义这些属性的值以及如何检测。
public WhistleApi(int sampleRate, int bitsPerSample, int channel) {
this.numFrequencyUnit = this.fftSampleSize / 2;
this.unitFrequency = (double)this.sampleRate / 2.0D / (double)this.numFrequencyUnit;
this.passFrequency = 400.0D;
this.passIntensity = 100.0D;
this.passStandardDeviation = 0.2D;
this.highPass = 400;
this.lowPass = 4000;
this.minNumZeroCross = 60;
this.maxNumZeroCross = 90;
this.numRobust = 2;
this.sampleRate = sampleRate;
this.bitsPerSample = bitsPerSample;
if(channel != 1) {
System.out.println("Support mono channel only.");
}
}
public boolean isWhistle(byte[] audioBytes) {
int bytesPerSample = this.bitsPerSample / 8;
int numSamples = audioBytes.length / bytesPerSample;
if(Integer.bitCount(numSamples) == 1) {
this.fftSampleSize = numSamples;
short[] amplitudes = this.getAmplitudes(audioBytes, this.bitsPerSample);
double[] spectrum = this.getSpectrum(amplitudes);
double intensity = 0.0D;
int lowerBoundary;
for(lowerBoundary = 0; lowerBoundary < spectrum.length; ++lowerBoundary) {
intensity += spectrum[lowerBoundary];
}
intensity /= (double)spectrum.length;
this.normalizeSpectrum(spectrum);
lowerBoundary = (int)((double)this.highPass / this.unitFrequency);
int upperBoundary = (int)((double)this.lowPass / this.unitFrequency);
double[] temp = new double[upperBoundary - lowerBoundary + 1];
System.arraycopy(spectrum, lowerBoundary, temp, 0, temp.length);
StandardDeviation standardDeviation = new StandardDeviation();
standardDeviation.setValues(temp);
double sd = standardDeviation.evaluate();
if(sd < this.passStandardDeviation) {
ArrayRankDouble arrayRankDouble = new ArrayRankDouble();
double maxFrequency = (double)arrayRankDouble.getMaxValueIndex(temp) * this.unitFrequency;
double[] robustFrequencies = new double[this.numRobust];
double nthValue = arrayRankDouble.getNthOrderedValue(temp, this.numRobust, false);
int count = 0;
for(int pitchHandler = lowerBoundary; pitchHandler <= upperBoundary; ++pitchHandler) {
if(spectrum[pitchHandler] >= nthValue) {
robustFrequencies[count++] = (double)pitchHandler * this.unitFrequency;
if(count >= this.numRobust) {
break;
}
}
}
PitchHandler var25 = new PitchHandler();
if(maxFrequency >= this.passFrequency && intensity > this.passIntensity) {
double probability = var25.getHarmonicProbability(robustFrequencies);
if(probability < 0.5D) {
int zc = this.getNumZeroCrosses(amplitudes);
if(zc >= this.minNumZeroCross && zc <= this.maxNumZeroCross) {
return true;
}
}
}
}
} else {
System.out.print("The sample size must be a power of 2");
}
return false;
}
private short[] getAmplitudes(byte[] audioBytes, int bitsPerSample) {
int bytesPerSample = bitsPerSample / 8;
int numSamples = audioBytes.length / bytesPerSample;
short[] amplitudes = new short[numSamples];
int pointer = 0;
for(int i = 0; i < numSamples; ++i) {
short amplitude = 0;
for(int byteNumber = 0; byteNumber < bytesPerSample; ++byteNumber) {
amplitude |= (short)((audioBytes[pointer++] & 255) << byteNumber * 8);
}
amplitudes[i] = amplitude;
}
return amplitudes;
}
private double[] getSpectrum(short[] amplitudes) {
int sampleSize = amplitudes.length;
WindowFunction window = new WindowFunction();
window.setWindowType("Hamming");
double[] win = window.generate(sampleSize);
double[] signals = new double[sampleSize];
for(int fft = 0; fft < sampleSize; ++fft) {
signals[fft] = (double)amplitudes[fft] * win[fft];
}
FastFourierTransform var8 = new FastFourierTransform();
double[] spectrum = new double[sampleSize];
spectrum = var8.getMagnitudes(signals);
return spectrum;
}
private int getNumZeroCrosses(short[] amplitudes) {
int numZC = 0;
int size = amplitudes.length;
for(int i = 0; i < size - 1; ++i) {
if(amplitudes[i] >= 0 && amplitudes[i + 1] < 0 || amplitudes[i] < 0 && amplitudes[i + 1] >= 0) {
++numZC;
}
}
return numZC;
}
private void normalizeSpectrum(double[] spectrum) {
double maxAmp = 4.9E-324D;
double minAmp = 1.7976931348623157E308D;
for(int minValidAmp = 0; minValidAmp < spectrum.length; ++minValidAmp) {
if(spectrum[minValidAmp] > maxAmp) {
maxAmp = spectrum[minValidAmp];
} else if(spectrum[minValidAmp] < minAmp) {
minAmp = spectrum[minValidAmp];
}
}
double var11 = 9.999999960041972E-12D;
if(minAmp == 0.0D) {
minAmp = var11;
}
double diff = Math.log10(maxAmp / minAmp);
for(int i = 0; i < spectrum.length; ++i) {
if(spectrum[i] < var11) {
spectrum[i] = 0.0D;
} else {
spectrum[i] = Math.log10(spectrum[i] / minAmp) / diff;
}
}
}
}
来自此链接的代码 https://code.google.com/archive/p/musicg/downloads
我使用musicg-sound-api-1.2.0.1.jar 请帮忙
谢谢