顯示具有 wav 標籤的文章。 顯示所有文章
顯示具有 wav 標籤的文章。 顯示所有文章

2013年12月4日 星期三

java wav 過濾頻率

這邊主要是將原wav過濾頻率, 只保留部分的音頻...
相信在google上也有很多的實作~

不過有找到一個方便的lib...
只要一個jar, 下個cmd就OK了~

使用dsp-collection.jar
出處:
http://www.source-code.biz/dsp/java/

用法很簡單~ 只要下cmd就好了
雖然偶不懂用那個演算法比較好XD..個人指導最高原則就是...能動就好了
ex:
java -cp dsp-collection.jar WavFilterFisher sample.wav bandpass chebyshev 4 -0.5 1000 5000 out.wav

來個檔案做圖解~ 雖然沒辦法濾得很乾淨, 但是看起來還是有差的+_+
原始檔頻譜


過濾後頻譜

java wav 轉 mp3

wav檔處理是OK的~ 不過因為檔案很大~ 不太適合做資訊發布...
所以最後發布就轉成mp3壓縮~

我這邊採用jave的lib...
http://www.sauronsoftware.it/projects/jave/

原因最主要也是輕量(只要一個jar)
win/centos通吃
可java呼叫
可以成功使用(重點)

呼叫的java sample code如下:

            File source = new File(fin);
            File target = new File(fout);
            AudioAttributes audio = new AudioAttributes();
            audio.setCodec("libmp3lame");
            audio.setBitRate(new Integer(128000));
            audio.setChannels(new Integer(2));
            audio.setSamplingRate(new Integer(44100));
            EncodingAttributes attrs = new EncodingAttributes();
            attrs.setFormat("mp3");
            attrs.setAudioAttributes(audio);
            Encoder encoder = new Encoder();
            encoder.encode(source, target, attrs);

java wav 計算db值

承上篇...
有計算音量的部分(算db值, 只是一個強度相對的大小值)

我忘了是從那邊copy出來的~
不過用google查該method name應該可以找到不少...

反正就把從WaveFile裡面讀到的raw data丟進去就有一個值生出來了XD"

主要計算db的method
/** Computes the RMS volume of a group of signal sizes ranging from -1 to 1. */
    public double volumeRMS(double[] raw) {
        double sum = 0d;
        if (raw.length==0) {
            return sum;
        } else {
            for (int ii=0; ii<raw.length; ii++) {
                sum += raw[ii];
            }
        }
        double average = sum/raw.length;

        double sumMeanSquare = 0d;
        for (int ii=0; ii<raw.length; ii++) {
            sumMeanSquare += Math.pow(raw[ii]-average,2d);
        }
        double averageMeanSquare = sumMeanSquare/raw.length;
        double rootMeanSquare = Math.pow(averageMeanSquare,0.5d);

        return rootMeanSquare;
    }

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) {}
            }
        }

    }

2013年10月29日 星期二

wav spectrum 頻譜圖 + python audiolab

因為這次要處理wav檔案資料...
其實py audiolab能處理上不止算頻譜,
只是其他的項目用Java解決掉~
就只有頻譜圖是用python...
(一來不會算頻譜, 二來Java繪圖的套件過於艱澀, py找來的資源就已經相當漂亮了Q_Q)

環境安裝貼在上一篇文...



先貼一張結果圖~













程式沒幾行, 過程是挺心酸的...Q_Q...
整個重點大概在於:
python 與相關應用module安裝...
找一段可以用的程式碼來打底...
(google audiolab+spectrum 應該就會有~我也是google來的)
調好圖表版面, 對齊(因有上下圖需要對齊的需求), 間隔, 顏色
(sample是2分鐘的wav, 但因實務上只使用大約30s, 所以才用5s做單位x軸)
解決中文字的問題....
(python原生沒中文, 最後採用指定TTF解決, 跨平台機器安裝才方便Q_Q)

原始碼

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import sys
from pylab import *
import wave
import matplotlib.pyplot as plt

myfont = matplotlib.font_manager.FontProperties(fname='/etc/xxxx/MSJH.TTF')
infile = None
outfile = None
secInterval = 5    #x-axis interval

def show_wave_n_spec():
   
    if(len(sys.argv) < 2) :
        print('err input, plz input argv[1] and argv[2]')
        return
   
    infile = sys.argv[1]
    outfile = sys.argv[2]
   
    spf = wave.open(infile,'r')
    f = spf.getframerate()
   
    sound_info = spf.readframes(-1)
    sound_info = fromstring(sound_info, 'Int16')
    spflength = round(spf.getnframes()/f)
    #print(spflength)
    #print(sound_info)
   
    #---------------pic1   
    ax = subplot(211)
    title(u'Waveform(波形圖)',fontproperties=myfont)
   
    plot(sound_info, '#5755FF')
    xlim(0, len(sound_info))
    plt.axis([0, len(sound_info), -15000, 15000])
    grid(True)
   
    #change axis-x position/text
    xlabel2 = range(0, int(spflength+1), secInterval)
    xposition2 = []
    for x in xlabel2:
        xposition2.append(x*f)
   
    #print(xposition2)
    ax.set_xticks(xposition2)
    ax.set_xticklabels(xlabel2)
   
    #change axis-y
    ylabel2 = []
    for x in ax.get_yticks() :
        ylabel2.append(str(x/1000)+'k')
    ax.set_yticklabels(ylabel2)
   
    #---------------pic2   
    ax2 = subplot(212)
    title(u'Spectrogram(頻譜圖)',fontproperties=myfont)
    spectrogram = specgram(sound_info, Fs = f, scale_by_freq=True,sides='default')   
    plt.axis([0, spflength, 0, 20000])
    ax2.set_xticks(xlabel2)
    ax2.set_xticklabels(xlabel2)
    grid(True)
    ylabel2 = []
    for x in ax2.get_yticks() :
        ylabel2.append(str(x/1000)+'k')
    ax2.set_yticklabels(ylabel2)   
       
    #show()
    savefig(outfile);
    spf.close()


show_wave_n_spec()