2013年12月4日 星期三

java WavFile 切檔案

處理wav檔資訊, 問google其實有不少的解決方案~

這次對於聲音採取lib的選擇順序重點是...
1. 要能動, 可以包成api呼叫
2. win/linex(centos) 都要相容
3. 以java原生/相關優先
4. 輕量/相依性較低

因為其實也不是只做一兩項處理而已~ ...每個人都說很簡單~
喵的~ 最好整四五個以上功能很簡單啦....

所以有很多有名的都不行T_T...
有名的大多都包成有UI了~ 很難從裡面拆method出來用@@...

我最後是採用一個有source檔的拿來回自己改...這個只能處理純wav...
有些運算可能不太正確~ 其原因為我並不了解wav本身的正確格式與內容~
不過就我需要的部分~ 能做到就好^^0....
選他是因為lib最單純(純java code, 不用lib/jar)~
然後有是有少數看懂source code用法|||Orz...
(某些lib/open source是看懂一半~ 硬改source code後就GG...因為套件流程綁太多~ 沒辦法一一找對地方改QQ)


先說明該source code的出處
http://www.labbookpages.co.uk/audio/javaWavFiles.html

至於應用上是拿來做兩件事
1. 處理切檔(ex: 2分鐘切出1分鐘)
2. 找音量相對大的位置(音量就等於內容資料強度...反正就是值越大, 音量越大)

合起來就變成~ 找出音量相對大的地方開始切N秒~ 成為新的wav檔案

這篇先放切檔案的method
基本上就是先建一個空的{secs}秒, wav, 然後從原本的wav檔, 某個位置開始讀寫...
有處理若是該位置是在原始檔的後面(會有可能造成只寫一部分的資料~ 但是新檔尾巴就空空的)
在原始檔長度小於新檔長度時就會丟excption出去了...(在偶低case裡, 原始檔長度不夠本來就不應該做處理)

/**cut wav file, start with buffersize * start, cut secs seconds
     * @param wavFile source
     * @param buffersize sample buffersize
     * @param start idx of the sample
     * @param secs cut how long seconds
     * @param target output file path*/
    public void process(WavFile wavFile, int buffersize, int start, double secs, String target) throws Exception {

        WavFile newFile = null;
        try  {
            long sampleRate = wavFile.getSampleRate();        // Samples per second
            double totalsecs = wavFile.getNumFrames()/buffersize;
            if(start+secs > totalsecs)  {
                start = (int)(totalsecs - secs);
            }
            if(start < 0)  {
                start = 0;
            }

            double duration = secs;        // Seconds
            // Calculate the number of frames required for specified duration
            long numFrames = (long)(duration * sampleRate);
            newFile = WavFile.newWavFile(new File(target),
                                             wavFile.getNumChannels(),
                                             numFrames,
                                             wavFile.getValidBits(),
                                             sampleRate);

              // Display information about the wav file
            //wavFile.display();
            //System.out.println("-----------");
            //newFile.display();

            // Get the number of audio channels in the wav file
            int numChannels = wavFile.getNumChannels();
            int frames = buffersize;

            // Create a buffer of 100 frames
            double[][] buffer = new double[numChannels][frames];

            int framesRead;

            int loop = 0;
            // Read frames into buffer
            do {
                framesRead = wavFile.readFrames(buffer, frames);

                if(loop >= start)  {

                    long remaining = newFile.getFramesRemaining();
                      int toWrite = (remaining > frames) ? frames : (int) remaining;

                    // Write the buffer
                       //newFile.writeFrames(buffer, toWrite);
                    newFile.writeFrames(buffer, toWrite);

                    if(toWrite < frames)  {
                        break;
                    }
                }

                loop++;
            }  while (framesRead != 0) ;

        }  catch(Exception e)  {
            throw e;
        }  finally  {
            if(newFile != null)  {
                try  { newFile.close(); }  catch(Exception eee) {}
            }
        }

    }

沒有留言: