为了绘制它,我使用的是JavaFX created this repository(ps的代码可能会有所不同,因为我现在有几天没有提交)。

因此:

/**
 * Get Wav Amplitudes
 *
 * @param file
 * @return
 * @throws UnsupportedAudioFileException
 * @throws IOException
 */
private int[] getWavAmplitudes(File file) throws UnsupportedAudioFileException , IOException {
    System.out.println("Calculting WAV amplitudes");
    int[] amplitudes = null;

    //Get Audio input stream
    try (AudioInputStream input = AudioSystem.getAudioInputStream(file)) {
        AudioFormat baseFormat = input.getFormat();

        Encoding encoding = AudioFormat.Encoding.PCM_UNSIGNED;
        float sampleRate = baseFormat.getSampleRate();
        int numChannels = baseFormat.getChannels();

        AudioFormat decodedFormat = new AudioFormat(encoding, sampleRate, 16, numChannels, numChannels * 2, sampleRate, false);
        int available = input.available();
        amplitudes = new int[available];

        //Get the PCM Decoded Audio Input Stream
        try (AudioInputStream pcmDecodedInput = AudioSystem.getAudioInputStream(decodedFormat, input)) {
            final int BUFFER_SIZE = 4096; //this is actually bytes
            System.out.println(available);

            //Create a buffer
            byte[] buffer = new byte[BUFFER_SIZE];

            //Read all the available data on chunks
            int counter = 0;
            while (pcmDecodedInput.readNBytes(buffer, 0, BUFFER_SIZE) > 0)
                for (int i = 0; i < buffer.length - 1; i += 2, counter += 2) {
                    if (counter == available)
                        break;
                    amplitudes[counter] = ( ( buffer[i + 1] << 8 ) | buffer[i] & 0xff ) << 16;
                    amplitudes[counter] /= 32767;
                    amplitudes[counter] *= WAVEFORM_HEIGHT_COEFFICIENT;
                }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    //System.out.println("Finished Calculting amplitudes");
    return amplitudes;
}

然后我像这样处理振幅:
/**
 * Process the amplitudes
 *
 * @param sourcePcmData
 * @return An array with amplitudes
 */
private float[] processAmplitudes(int[] sourcePcmData) {
    System.out.println("Processing WAV amplitudes");

    //The width of the resulting waveform panel
    int width = waveVisualization.width;
    System.out.println("P Width :" + width);
    float[] waveData = new float[width];
    int samplesPerPixel = sourcePcmData.length / width;

    //Calculate
    float nValue;
    for (int w = 0; w < width; w++) {
        //if (isCancelled())
        //  break;

        //For performance keep it here
        int c = w * samplesPerPixel;
        nValue = 0.0f;

        //Keep going
        for (int s = 0; s < samplesPerPixel; s++) {
            //if (isCancelled())
            //  break;
            nValue += ( Math.abs(sourcePcmData[c + s]) / 65536.0f );
        }

        //Set WaveData
        waveData[w] = nValue / samplesPerPixel;
    }

    System.out.println("Finished Processing amplitudes");
    return waveData;
}

输出是这样的:

java - 如何减少Java中振幅数组的大小?-LMLPHP

最佳答案

找到了一个很好的解决方案,尽管我不确定最终数组的最大大小应该是多少,经过一些实验之后100.000似乎是一个不错的数字。

所有代码都在this github存储库中。

因此,方法 getWavAmplitudes 变为:

/**
 * Get Wav Amplitudes
 *
 * @param file
 * @return
 * @throws UnsupportedAudioFileException
 * @throws IOException
 */
private int[] getWavAmplitudes(File file) throws UnsupportedAudioFileException , IOException {

    //Get Audio input stream
    try (AudioInputStream input = AudioSystem.getAudioInputStream(file)) {
        AudioFormat baseFormat = input.getFormat();

        //Encoding
        Encoding encoding = AudioFormat.Encoding.PCM_UNSIGNED;
        float sampleRate = baseFormat.getSampleRate();
        int numChannels = baseFormat.getChannels();

        AudioFormat decodedFormat = new AudioFormat(encoding, sampleRate, 16, numChannels, numChannels * 2, sampleRate, false);
        int available = input.available();

        //Get the PCM Decoded Audio Input Stream
        try (AudioInputStream pcmDecodedInput = AudioSystem.getAudioInputStream(decodedFormat, input)) {
            final int BUFFER_SIZE = 4096; //this is actually bytes

            //Create a buffer
            byte[] buffer = new byte[BUFFER_SIZE];

            //Now get the average to a smaller array
            int maximumArrayLength = 100000;
            int[] finalAmplitudes = new int[maximumArrayLength];
            int samplesPerPixel = available / maximumArrayLength;

            //Variables to calculate finalAmplitudes array
            int currentSampleCounter = 0;
            int arrayCellPosition = 0;
            float currentCellValue = 0.0f;

            //Variables for the loop
            int arrayCellValue = 0;

            //Read all the available data on chunks
            while (pcmDecodedInput.readNBytes(buffer, 0, BUFFER_SIZE) > 0)
                for (int i = 0; i < buffer.length - 1; i += 2) {

                    //Calculate the value
                    arrayCellValue = (int) ( ( ( ( ( buffer[i + 1] << 8 ) | buffer[i] & 0xff ) << 16 ) / 32767 ) * WAVEFORM_HEIGHT_COEFFICIENT );

                    //Every time you him [currentSampleCounter=samplesPerPixel]
                    if (currentSampleCounter != samplesPerPixel) {
                        ++currentSampleCounter;
                        currentCellValue += Math.abs(arrayCellValue);
                    } else {
                        //Avoid ArrayIndexOutOfBoundsException
                        if (arrayCellPosition != maximumArrayLength)
                            finalAmplitudes[arrayCellPosition] = finalAmplitudes[arrayCellPosition + 1] = (int) currentCellValue / samplesPerPixel;

                        //Fix the variables
                        currentSampleCounter = 0;
                        currentCellValue = 0;
                        arrayCellPosition += 2;
                    }
                }

            return finalAmplitudes;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    } catch (Exception ex) {
        ex.printStackTrace();

    }

    //You don't want this to reach here...
    return new int[1];
}

任何建议和改进都非常欢迎。

09-15 17:11