首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Java中减少振幅数组的大小?

如何在Java中减少振幅数组的大小?
EN

Stack Overflow用户
提问于 2018-08-17 00:16:48
回答 1查看 204关注 0票数 0

我在网上搜索了几个星期,找到了下面的代码,用

计算给定.wav文件的振幅。现在的问题是,对于像30分钟这样的大音频文件,它根本不能很好地扩展,produces数组非常大。

为了绘制它,我使用了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;                                                
}     

输出是这样的:

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-17 19:46:14

找到了一个非常好的解决方案,虽然我不确定最终的数组最大大小应该是多少,但经过一些实验,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];                                                                                                                             
}  

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51881427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档