1

我想修改 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 请帮忙

谢谢

4

0 回答 0