2009年6月9日 星期二
Cloud computing
http://mr6.cc/?p=2281
http://mmdays.com/2008/02/14/cloud-computing/
好久沒新文章,來灌一下水
大家都嚷著開發雲端運算,
什麼是雲端運算?是不是分散式運算?在第二篇文章有明顯的區分。
2009年6月2日 星期二
Partial Tracking - centcent
主要是訂正 F0 frequency的精準度。
我們所得到的trajectory主要是由 F0 candidate 所產生出來的。
從Ircam的資料,我們可以明確的得知說每個frame 的 F0 candidate 是否有包含 Estimated F0。
可是從義崧的程式,只能得到上述兩個的Frequency,所以當初這部分的判斷和維城是用討論之後是用FFT bin來判斷。
不過因為義崧程式得到的 Estimated F0 的 bin 是經過權重之後的結果,會有小數,因此將這個bin 四捨五入之後在和F0 candidate的bin 做判斷,因此會有誤差存在。所以才會造成一直線的狀況發生
因為Estimated F0 的 bin經過四捨五入之後為20,包含於F0 candidate的bin,如下圖

解決辦法,如果一個frame的F0 candidate有包含 Estimated F0,這時就將F0 candidate其中的 frequency改成有包含Estimated F0的bin frequency。

投影片
comments:
1. 原先的 pruning 是判斷有無 estimated F0來移除 trajectory。
2. 如果我們沒有estimated F0的資訊,只有F0 candidate,想方法來判斷是否為 partial,移除掉其他非partial的部分,最後再利用找出來的partial來找出F0。
------------------------------------------------------------------------------------
20081125
這星期主要做的就是看能不能從義崧的程式找出更多的 candidate 出來。
改變設定上下限的變數即可找出多一點的 candidate ,不過低頻的地方看起來有很多非真正 candidate 的點。

另外發現如果有太多的 candidate,pruning 這動作好像無法找出真正的F0出來,這部分還要再仔細去看數據才知道哪裡出問題。
投影片
comments:
1. 會造成低頻有這麼多假的node,應該是因為是取最大公因數。要濾掉這些node,除了考慮這些點的weight之外,在去看看這些node有沒有能量存在
2. 如果F0沒有能量,這種例外的狀況,再想辦法來解決
------------------------------------------------------------------------------------
20081202
發現之前用當作 F0 candidate的資料是我找錯了,我找成義崧用來投票的,所以結果就不這麼好看。這次的結果看起來比較正常了。

是否可以試著透過義崧的演算法將已經找到的 partial 的資訊移除,然後再找另一個partial?
partial是經由投票所產生的,而每個bin都有提供各自的 weight,若將每個bin提供的weight記錄下來,每找完一個partial,每個bin就減掉之前提供的weight,再用來找下一個partial
投影片
comments:
1. 增加一些參數給HMM,例如能量以及partial之間的相關性
2. inharmonicity 的狀況:或許不一定要看基頻,而可以只看前一個或二個的partial
------------------------------------------------------------------------------------
20081209
1. 上週提到「是否可以試著透過義崧的演算法將已經找到的 partial 的資訊移除,然後再找另一個partial?」這部分實做的時候移除weight後沒有重算bin的能量。
2. 找到一篇paper提到說freq 和 amp 在顫音的時候,freq 上升,amp會下降。paper中提出可以把 d^2 = [(fi - fj)(ai-aj)]^2 當成 HMM 中transition Prob的參數。
投影片
paper
comments:
1. paper 的假設是錯的,如果整個音源來看是對的,可是如果看單一partial的話,並不是絕對。
------------------------------------------------------------------------------------
20081210
1. 找鋼琴inharmonicity 的曲線,直接套用此曲線即可。
2. 斷掉的partial相連,試著找出一組公式,放進去HMM裡當參數。或者用公式來 implement
3. 由義崧的演算法,找出F0之後,再找F0的倍頻,看看倍頻附近是否有peak存在(能量大的),這個peak則為F0的partial。找出一個F0以及其partial,將這些移除,再找下一組F0和partial。若有鋼琴存在,則套用[1]的曲線公式。
---------------------------------------------------------------------------------
20081216
1. 義崧學長有針對bin下去做平滑化,當初是避免有小突起的peak,不過這樣會造成multiple f0差三根bin會找不到,所以把這部分移除掉。
2. 根據20081210,找出F0之後,再找F0的倍頻,看看倍頻附近是否有peak存在(能量大的),這個peak則為F0的partial,這邊判斷方式用12平均率,f0的倍數上下半個半音是否有能量存在,大約是上下3%。
3. 上面那個判斷方式,在高頻部分,有可能會包含許多bin進來,因此,將最接近f0*multiple的peak視為f0的partial
投影片
----------------------------------------------------------------------------------
20081223
1. 這次完成找出multiple f0了,針對小提琴和長笛下去做處理,找partial的判斷方式為
f0 * mutiple * 0.97 <= peak <= f0 * mutiple * 1.03
找出的結果如下圖

2. piano inharmonicity:根據[H. Fletcher, E. D. Blackham, and R. Stratton, 「Quality of piano tones,」 J. Acoust. Soc. Am., vol. 34, no. 6, pp. 749–761, 1962.]這篇論文,鋼琴的partial 頻率和鋼琴每根弦的直徑、長度、張力、材質有關。
投影片
comments:
1. 判斷partial的範圍:若要找第N個partial,f(N):
(△f + f(N-1)) * 0.97 <= peak <= (△f + f(N-1)) * 1.03
△f = f(N-1) - f(N-2)
------------------------------------------------------------------------------------
20081225
1. 12月23號那張圖的第一段音樂,F0有260HZ和330HZ,可是找出來的結果330HZ沒有找到,這和我們設定上下3%其實沒有關連,會造成這樣的結果是因為義崧的程式有一段是針對二胡的特性來寫的,二胡的最高能量不一定落在f0,可能落在2或3倍頻,因此用這段程式碼來找出F0。將這部分拿掉就可以找到260HZ和330HZ了。
2. 將原本找partial的判斷式改為
(△f + f(N-1)) * 0.97 <= peak <= (△f + f(N-1)) * 1.03
△f = f(N-1) - f(N-2)
結果如下圖:

這邊發現一個問題:原訊號如果兩個partial相當接近,而一個partial 能量遠大於另一個partial,能量較小的那個partial會無法找到。以這張圖為例,F0為260和330,在990和1040附近應該都要有partial,可是990的能量遠大於1040,就無法找到1040這個partial。
我想這是因為一開始要將有peak的bin考慮進來的時候,包含1040HZ的這根bin並沒有特別突出,這根bin就沒有被考慮進來了。
------------------------------------------------------------------------------------
20081230
偷懶了一下,這麼晚才更新
1. 如果兩個音只差一個半音,只能找到一個F0,而且這個F0會落在兩個音頻率的中間。例如Violin:260Hz & Flute:277Hz,找出來的結果大約是269Hz,因此這269Hz的partial都沒有能量也就沒有找到。

投影片
comments:
1. 關於12/25提到的partial能量不夠大,DNA提到可以做類似將高頻的能量平方的動作,或許可以使peak更為明顯。
2. 12/25的結果,高頻部分有些partial斷掉,在HMM中加入是否為partial的condition。
-----------------------------------------------------------------------------------
20090106
comments:
1. 關於F0s差半個音無法辨別出來,可以針對低頻部分提高解析度來做
2. 高頻部分,可以利用影像處理的前處理方式,做一個operator來處理,來辨別出我們所要的資訊
-----------------------------------------------------------------------------------
20090209
1. 之前關於低頻F0s差一個半音無法辨別出來,這段期間有做一些提高解析度(zero padding)以及一些作法來實驗。
a. 經過 lowpass filter
b. 經過 lowpass filter 再做 zero padding
c. 認為高頻有太多的candidate影響投票,所以只拿一半的 candidate 來投票
d. 只拿1.2K以下的candidate來投票
發現都無法找出兩個F0(260Hz、277Hz)。
後來發現原來是義崧學長在找candidate的時候,會根據一個peak的前後兩根 bin 找最大個一根來當作candidate,在samplerate=44100,framesize=8192時,260Hz和277Hz大概差3~4根bin,所以在這個地方就只會把其中一個拉進去當candidate。所以沒有這兩個candidate。
2. 將這地方拿掉之後就可以正確的找到260Hz和277Hz了,只是高頻部分(2.5kHz以上)有點糟糕。

3. spectrum要幾次方以及protrudeValue的threshold會影響 260Hz&277Hz 和 260Hz&330Hz 的結果,第一個結果不錯,第二個就有點糟,這地方還要多測試。
------------------------------------------------------------------------------------
20090212
1. 多設定一個noise floor,將原本的spectrum扣掉這條 noise floor再去做後面的動作。noise floor的做法為往前往後看L點,取平均
s[i] = Σ x[i-k] / (2L+1) , k = -L ~ L
x:原本spectrum
這樣做可以避免若基頻落在高頻的時候,低頻一些peak會影響結果,導致找出來的F0落在低頻。
2. 原本義崧學長程式中protrudeValue表示的是 (magnitude of a peak) / (magnitude of the higher foot),這邊我改成用斜率表示。
260 & 277Hz

260 & 330Hz

1046 & 1108Hz

-----------------------------------------------------------------------------------
20090217
1. 修正bug:原本 F0 * 0.97 < F0 < F0 * 1.03,沒有處理在這個範圍內有兩個以上的bin。新增要找最接近的bin。
2. 在找 candidate 時,新增一個threshold:比最大能量小 48db(約1 / 256)的bin 不考慮進來。針對單純沒有變音的就抓的比較漂亮了。
1046 & 1108 Hz

3. 找了巴哈無伴奏的一段音樂來跑,有六段不同基頻(小明聽出來的),分別是
a. 0 - 1 sec : 830 Hz
b. 1 - 2 sec : 260 Hz & 493 Hz
c. 2 - 2.5 sec : 440 Hz
d. 2.5 - 3 sec : 554 Hz
e. 3 - 3.5 sec : 698 Hz
f. 3.5 ~ sec : 830 Hz
原始的圖如下:
找到的F0:在應該只有單音的地方找到多個F0,應該是換音所造成的,畢竟從能量上來看,這些frequency 以及其倍頻都還有能量存在。

F0 以及 Partial:

----------------------------------------------------------------------------------
20090223
1. 老師提出的對每一根有可能是f0的bin,將五倍以內的bin都取出來投票,若有得到F0以及其
partial,則下一輪投票就不要將這些考慮進來。只是這樣結果好像沒有比較好,跟上次的比較起來,F0少了一點。

2. 用midi產生DoMeSo,結尾加上 reverb,再加上ReFaLa。
Wav:

F0:在有重疊到的地方,找的還不錯

------------------------------------------------------------------------------------
20090225
1. 20090223提到的第一點,做出來效果不好是因為我程式少寫一些判斷式,所以少找了許多F0出來。下面是更改過後的結果。
做法是每個candidate都假設可能是F0,依照這根bin往上看5倍。

是有比原本的結果比較好,可是相對的高頻也多出了許多fake的F0,這是因為每個candidate都預先認為可能是F0,高頻部分有些剛好不是先前找到F0的partial,所以再往上看5倍,也有可能會認為當下的這根bin是F0。
2. 如果要用這種辦法,好像無法避免這種狀況。因此在這邊多加了一個threshold,當一個candidate的能量大於最大能量的1/8(約18db),才認為這個candidate可能是F0,再下去投票。
結果如下:高頻部分少了許多fake的F0。

3. 拿真正鋼琴的聲音來做測試
wave:
F0:當一個新的音起來,舊的音還有餘音的時候,而新的音剛好是舊餘音的倍數時,這時候就有可能把F0找成舊的音。

-----------------------------------------------------------------------------------
20090226
上面鋼琴曲的樂譜,原來有這麼複雜, Ballade No. 1 Op. 23,應該是蕭邦的吧
-----------------------------------------------------------------------------------
20090304
1. 我們為瞭解決低頻能正確找到F0,所以FFT的size增加到8192,但是,相對的原音在Vibrato時,會碎成許多小peak(如下圖),所以會找到許多相近的F0。
2. 解決辦法:在一個半音內(94% ~ 106%)只會存在一個F0,因此試著用在這範圍內,找出能量最大的來當作F0。跟20090225的巴哈比起來,第一段有抖音的部分,已經沒有非常接近的F0了。

3. 解決完這問題之後才突然發現,這問題其實可以靠HMM來解決,因為我們HMM要多加入partial和 amplitude 這兩個參數進去。到時候將HMM建構起來之後在和上面提到的方法來做比較。
-----------------------------------------------------------------------------------
20090310
1. 原本定義下列狀況下,candidate不相連。cCandidate:current candidate,rCandidate:往前看的 candidate
(cCandidate is F0) && (rCandidate is Partial)
(cCandidate is Partial) && (rCandidate is F0)
(cCandidate's F0 和 rCandidate's F0 差超過一個半音)
(cCandidate's Freq 和 rCandidate's Freq差超過一個半音)
老師建議將 candidate 的 Frequency 和 magnitude 都放進去 HMM 的 HiddenStateProb 裡。這樣可以讓 model 更加完美,讓人信服。
2. 維城學長是利用 Gaussian function ,△f當變數來算 prob,我們可以利用2維的Gaussian function,△f 和 △magnitude來當變數。function如下



3. 在前端部分,也就是f0 detection 部分,在找partial的部分加入一些 virtual node,可以讓後面的 HMM 的加以參考。要增加 virtual node的條件先假設 F0 往上看10倍,若real node比例達80%以上,再增加 virtual node。virtual node的magnitude為0。
4. 因為有這些 virtual node,magnitude 為0,所以 HMM 那邊多一個只有 △f 的 Gaussian function 給 virtual node 用。
-----------------------------------------------------------------------------------
20090312
1. 用不同的 Gaussian function 來處理node 之間的連線,會有問題,因此還是只用一個Gaussian function,只是virtual node的magnitude,直接用FFT的能量即可。
2. 原本討論要用 α*Decay + β* HiddenProb + (1 - α - β) * PartialFunc,這邊PartialFunc是考慮 Partial 的關係。原本HMM的連線方式是node 對 node,我們可以改成 整組對整組,也就是F0以及其partial視為一組下去做HMM。
-----------------------------------------------------------------------------------
20090318
1. 現在的作法是 α*Decay + (1 - α)* HiddenProb,HiddenProb是用二維的Gaussian function,△f 和 △magnitude來當變數,整組(F0+partials)下去算的。
結果如下:
小提琴 DoMeSo+ReFaLa:

巴哈無伴奏:

2. 接下來就是建立前後兩部分(f0 detect、HMM)的LOOP以及tune HMM 的參數(σ和α)。
-----------------------------------------------------------------------------------
20090325
1. 要training Gaussian function的參數,打算利用八度音來區隔,大略分成6個區段
100 ~ 261 Hz (C4)
261 ~ 523 Hz (C5)
523 ~ 1046 Hz (C6)
1046 ~ 2093 Hz (C7)
2093 ~ 4186 Hz (C8)
4186 ~ 8000 Hz
2. 用midi產生的wav來train這些參數(σ1,σ2,Cov),儘量有Vibrato和滑音。
-----------------------------------------------------------------------------------
20090408
1. 六個區域的參數已經train出來了。
只用一組參數的Bach

六組參數

變化好像不大
2. 皆下來的工作 a.建立loop b.train出attack state的initial weight c.擬出論文大綱
----------------------------------------------------------------------------------
20090421
20090421
1. 原本Loop的動作是
- 找出f0
- Tracking
- Smooth
- interpolated
- 利用出來的結果回頭找F0
2. 不過因為smooth的動作經過多次loop之後會讓vibrato趨於平緩,因此這邊改用linear prediction的方式來校正node
- 找出f0
- Tracking
- linear presiction
- interpolated
- 利用出來的結果回頭找F0
----------------------------------------------------------------------------------
20090506
1. vibrato 部分顯示出來會像是鋸齒波,而不是sin波,如下圖。

這是因為我們找出來的F0的曲線就是類似這樣子的。

2. 如果我們看f0那張圖在vibrato的時候,有時候在同一個frame會找到兩個點,這是因為在原本的頻譜圖上就有兩個peak存在了,這應該是頻率解析度造成的問題。
3. 既然我們知道它是vibrato了,那我們可以記錄它震盪的大小,經過多次smooth之後,會趨近於sin波,這時候我們再將它放大到原本震盪的大小。
4. 也可以用分bank的方式,低頻用高解析度,高頻用低解析度。
-----------------------------------------------------------------------------------
20090512
1. 記錄vibrato震盪的幅度,最後再修正到原本的位置。我是先用古琴來測試,第一張圖是一開始找到的F0,第二張是經過多次smooth之後的,第三張是是修正到原本的位置。
原本的F0,請忽略那幾條直線,畫線出問題

多次smooth之後

修正至原本位置

2. 用在Bach上,還有些問題,正在找出問題所在,應該是條件設定要調整。
----------------------------------------------------------------------------
20090602
1. 打算加入之前20090225我們討論過的,只往上看五倍下去投票,這樣子的結果比較漂亮。
下圖是沒有加入新的方法。

下圖是加入新的方法,可以看出換音的地方原本的音延長了許多。

2009年5月29日 星期五
進度報告 - OpenMAX - 塞公
--------------------- 2009/02/25 ---------------------
投影片連結
這禮拜是先介紹一下 OpenMAX
沒有實作過,所以整個架構上還沒有說很清楚
目前是打算把 DL 後面幾個feature看完
再來看一下應該怎麼去實作
OpenMAX AL 與 OpenMAX IL 的差別?
AL : OpenMAX AL is meant for media application developers.
主要是被用來開發應用程式的
在論壇中有提到說 目前 AL 1.0版 目前還沒正式發布
所以還沒有implementation 存在 有提到說大概在今年夏天就會公布 XD
IL : to integrate and communicate with multimedia codecs implemented in hardware or software.
代表是整合下層的codecs 像是把下層codecs包起來
而被包起來的名稱在 AL 這一層被稱做為object
--------------------- 2009/03/02 ---------------------
這禮拜是繼續將上禮拜沒看完的文件看完 至於會不會用到想說留到看完再來討論。
基本上OpenMAX IL 這一層主要重點是在於各個components之間的關係與溝通,而component內容可以寫到跟硬體或底層的軟體作溝通(像是可以呼叫alsa函式庫去播音樂,或者要遵循OpenMAX DL的規範 像 arm 有提供ARM OpenMAX DL Libraries有幾個codecs的API function可以使用(ex. mp3, h264...))就看自己要怎麼寫,因為跟寫slim component沒差多少。
另外有去看一個open source 的東西叫做 "Bellagio",是一個OpenMAX IL sample implementation for Linux,它上面有不多也不少的components在上面(10~30)個吧,我只有十個,看別人文章有三十個Orz,因為我一直安裝不起來,還沒辦法放一首mp3來聽聽。這個東西比較適合在學習寫IL的components的入門範例程式。有提供簡單的applications讓你連接各個components去做測試。網址 http://omxil.sourceforge.net/
還有,就是也稍微去找了一下nvidia cuda上有沒有跟 OpenMAX上相關的東西,發現是..只有新聞文章。其它就沒有了,可能還得再找找。
--------------------- 2009/03/24 ---------------------
這次主要對bellagio的做法加以了解,看是如何去驅動每個component去做初始化,連結,執行等等,為了之後看是否能使slim的架構上能夠讓OMX components 加個adapter 就能夠與slim的component 相連。並且思考該怎麼去實作。還必須要搞懂slim中如何去操作component,之前只有個概念而已。之後多找個時間看一下。
--------------------- 2009/04/07 ---------------------
報告目前進度,之前是將Bellagio的編譯環境建起來,並粗略去trace他其中一個寫好的系統,就是撥放audio的專案,目前是想先去試著將某一部分的功能試著在slim上面寫,還在嘗試的階段,先不考慮到OpenMAX component與slim中的component作連結,先試著把Bellagio中專案拆開到slim上就好,之後,還需要研究一下如何將OpenMAX中傳遞資料的"buffer"轉換成slim中的data channel和 signal channel。
--------------------- 2009/05/19 ---------------------
這次終於算是把OMX的mp3元件兜起來了,目前也把他掛在slim上可以正常work了,想一下做這麼久的原因,是一開始對mp3 decoder順序及特性的不熟悉,以及對OMX所規定的函數參數傳進傳出的不熟悉。目前有拿過不同類型的mp3去執行。到目前是都可以正常播放的,不過有去利用slim原本提供的mp3 decoder做比較,都分別將pcm檔輸出做比較,檔案內容不太一樣,可是去看一下波形兩個的差異不大。
--------------------- 2009/05/29 ---------------------
列一下目前知道可用的codec:
ARM OpenMAX_DL Sample Code
AC(Audio Coding)
mp3
aac
VC(Video Coding)
Common
MPEG4 Part2
MPEG4 Part10
IC(Image Coding)
JPEG codec
FFmpeg那個我不知道該怎麼列,太多不懂的格式了,直接列出他程式碼的一段提到他的codec格式,覺得需要什麼在去挖看看有沒有。
/* video codecs */
REGISTER_DECODER (AASC, aasc);
REGISTER_DECODER (AMV, amv);
REGISTER_ENCDEC (ASV1, asv1);
REGISTER_ENCDEC (ASV2, asv2);
REGISTER_DECODER (AVS, avs);
REGISTER_DECODER (BETHSOFTVID, bethsoftvid);
REGISTER_DECODER (BFI, bfi);
REGISTER_ENCDEC (BMP, bmp);
REGISTER_DECODER (C93, c93);
REGISTER_DECODER (CAVS, cavs);
REGISTER_DECODER (CINEPAK, cinepak);
REGISTER_DECODER (CLJR, cljr);
REGISTER_DECODER (CSCD, cscd);
REGISTER_DECODER (CYUV, cyuv);
REGISTER_ENCDEC (DNXHD, dnxhd);
REGISTER_DECODER (DSICINVIDEO, dsicinvideo);
REGISTER_ENCDEC (DVVIDEO, dvvideo);
REGISTER_DECODER (DXA, dxa);
REGISTER_DECODER (EACMV, eacmv);
REGISTER_DECODER (EATGQ, eatgq);
REGISTER_DECODER (EATGV, eatgv);
REGISTER_DECODER (EATQI, eatqi);
REGISTER_DECODER (EIGHTBPS, eightbps);
REGISTER_DECODER (EIGHTSVX_EXP, eightsvx_exp);
REGISTER_DECODER (EIGHTSVX_FIB, eightsvx_fib);
REGISTER_DECODER (ESCAPE124, escape124);
REGISTER_ENCDEC (FFV1, ffv1);
REGISTER_ENCDEC (FFVHUFF, ffvhuff);
REGISTER_ENCDEC (FLASHSV, flashsv);
REGISTER_DECODER (FLIC, flic);
REGISTER_ENCDEC (FLV, flv);
REGISTER_DECODER (FOURXM, fourxm);
REGISTER_DECODER (FRAPS, fraps);
REGISTER_ENCDEC (GIF, gif);
REGISTER_ENCDEC (H261, h261);
REGISTER_ENCDEC (H263, h263);
REGISTER_DECODER (H263I, h263i);
REGISTER_ENCODER (H263P, h263p);
REGISTER_DECODER (H264, h264);
REGISTER_DECODER (H264_VDPAU, h264_vdpau);
REGISTER_ENCDEC (HUFFYUV, huffyuv);
REGISTER_DECODER (IDCIN, idcin);
REGISTER_DECODER (INDEO2, indeo2);
REGISTER_DECODER (INDEO3, indeo3);
REGISTER_DECODER (INTERPLAY_VIDEO, interplay_video);
REGISTER_ENCDEC (JPEGLS, jpegls);
REGISTER_DECODER (KMVC, kmvc);
REGISTER_ENCODER (LJPEG, ljpeg);
REGISTER_DECODER (LOCO, loco);
REGISTER_DECODER (MDEC, mdec);
REGISTER_DECODER (MIMIC, mimic);
REGISTER_ENCDEC (MJPEG, mjpeg);
REGISTER_DECODER (MJPEGB, mjpegb);
REGISTER_DECODER (MMVIDEO, mmvideo);
REGISTER_DECODER (MOTIONPIXELS, motionpixels);
REGISTER_DECODER (MPEG_XVMC, mpeg_xvmc);
REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video);
REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video);
REGISTER_ENCDEC (MPEG4, mpeg4);
REGISTER_DECODER (MPEGVIDEO, mpegvideo);
REGISTER_DECODER (MPEG_VDPAU, mpeg_vdpau);
REGISTER_DECODER (MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_ENCDEC (MSMPEG4V1, msmpeg4v1);
REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2);
REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3);
REGISTER_DECODER (MSRLE, msrle);
REGISTER_DECODER (MSVIDEO1, msvideo1);
REGISTER_DECODER (MSZH, mszh);
REGISTER_DECODER (NUV, nuv);
REGISTER_ENCODER (PAM, pam);
REGISTER_ENCODER (PBM, pbm);
REGISTER_DECODER (PCX, pcx);
REGISTER_ENCODER (PGM, pgm);
REGISTER_ENCODER (PGMYUV, pgmyuv);
REGISTER_ENCDEC (PNG, png);
REGISTER_ENCODER (PPM, ppm);
REGISTER_DECODER (PTX, ptx);
REGISTER_DECODER (QDRAW, qdraw);
REGISTER_DECODER (QPEG, qpeg);
REGISTER_ENCDEC (QTRLE, qtrle);
REGISTER_ENCDEC (RAWVIDEO, rawvideo);
REGISTER_DECODER (RL2, rl2);
REGISTER_ENCDEC (ROQ, roq);
REGISTER_DECODER (RPZA, rpza);
REGISTER_ENCDEC (RV10, rv10);
REGISTER_ENCDEC (RV20, rv20);
REGISTER_DECODER (RV30, rv30);
REGISTER_DECODER (RV40, rv40);
REGISTER_ENCDEC (SGI, sgi);
REGISTER_DECODER (SMACKER, smacker);
REGISTER_DECODER (SMC, smc);
REGISTER_ENCDEC (SNOW, snow);
REGISTER_DECODER (SP5X, sp5x);
REGISTER_DECODER (SUNRAST, sunrast);
REGISTER_ENCDEC (SVQ1, svq1);
REGISTER_DECODER (SVQ3, svq3);
REGISTER_ENCDEC (TARGA, targa);
REGISTER_DECODER (THEORA, theora);
REGISTER_DECODER (THP, thp);
REGISTER_DECODER (TIERTEXSEQVIDEO, tiertexseqvideo);
REGISTER_ENCDEC (TIFF, tiff);
REGISTER_DECODER (TRUEMOTION1, truemotion1);
REGISTER_DECODER (TRUEMOTION2, truemotion2);
REGISTER_DECODER (TSCC, tscc);
REGISTER_DECODER (TXD, txd);
REGISTER_DECODER (ULTI, ulti);
REGISTER_DECODER (VB, vb);
REGISTER_DECODER (VC1, vc1);
REGISTER_DECODER (VC1_VDPAU, vc1_vdpau);
REGISTER_DECODER (VCR1, vcr1);
REGISTER_DECODER (VMDVIDEO, vmdvideo);
REGISTER_DECODER (VMNC, vmnc);
REGISTER_DECODER (VP3, vp3);
REGISTER_DECODER (VP5, vp5);
REGISTER_DECODER (VP6, vp6);
REGISTER_DECODER (VP6A, vp6a);
REGISTER_DECODER (VP6F, vp6f);
REGISTER_DECODER (VQA, vqa);
REGISTER_ENCDEC (WMV1, wmv1);
REGISTER_ENCDEC (WMV2, wmv2);
REGISTER_DECODER (WMV3, wmv3);
REGISTER_DECODER (WMV3_VDPAU, wmv3_vdpau);
REGISTER_DECODER (WNV1, wnv1);
REGISTER_DECODER (XAN_WC3, xan_wc3);
REGISTER_DECODER (XL, xl);
REGISTER_ENCDEC (ZLIB, zlib);
REGISTER_ENCDEC (ZMBV, zmbv);
/* audio codecs */
REGISTER_DECODER (AAC, aac);
REGISTER_ENCDEC (AC3, ac3);
REGISTER_ENCDEC (ALAC, alac);
REGISTER_DECODER (APE, ape);
REGISTER_DECODER (ATRAC3, atrac3);
REGISTER_DECODER (COOK, cook);
REGISTER_DECODER (DCA, dca);
REGISTER_DECODER (DSICINAUDIO, dsicinaudio);
REGISTER_DECODER (EAC3, eac3);
REGISTER_ENCDEC (FLAC, flac);
REGISTER_DECODER (IMC, imc);
REGISTER_DECODER (MACE3, mace3);
REGISTER_DECODER (MACE6, mace6);
REGISTER_DECODER (MLP, mlp);
REGISTER_DECODER (MP1, mp1);
REGISTER_ENCDEC (MP2, mp2);
REGISTER_DECODER (MP3, mp3);
REGISTER_DECODER (MP3ADU, mp3adu);
REGISTER_DECODER (MP3ON4, mp3on4);
REGISTER_DECODER (MPC7, mpc7);
REGISTER_DECODER (MPC8, mpc8);
REGISTER_ENCDEC (NELLYMOSER, nellymoser);
REGISTER_DECODER (QCELP, qcelp);
REGISTER_DECODER (QDM2, qdm2);
REGISTER_DECODER (RA_144, ra_144);
REGISTER_DECODER (RA_288, ra_288);
REGISTER_DECODER (SHORTEN, shorten);
REGISTER_DECODER (SMACKAUD, smackaud);
REGISTER_ENCDEC (SONIC, sonic);
REGISTER_ENCODER (SONIC_LS, sonic_ls);
REGISTER_DECODER (TRUESPEECH, truespeech);
REGISTER_DECODER (TTA, tta);
REGISTER_DECODER (VMDAUDIO, vmdaudio);
REGISTER_ENCDEC (VORBIS, vorbis);
REGISTER_DECODER (WAVPACK, wavpack);
REGISTER_ENCDEC (WMAV1, wmav1);
REGISTER_ENCDEC (WMAV2, wmav2);
REGISTER_DECODER (WS_SND1, ws_snd1);
/* PCM codecs */
REGISTER_ENCDEC (PCM_ALAW, pcm_alaw);
REGISTER_DECODER (PCM_DVD, pcm_dvd);
REGISTER_ENCDEC (PCM_F32BE, pcm_f32be);
REGISTER_ENCDEC (PCM_F32LE, pcm_f32le);
REGISTER_ENCDEC (PCM_F64BE, pcm_f64be);
REGISTER_ENCDEC (PCM_F64LE, pcm_f64le);
REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw);
REGISTER_ENCDEC (PCM_S8, pcm_s8);
REGISTER_ENCDEC (PCM_S16BE, pcm_s16be);
REGISTER_ENCDEC (PCM_S16LE, pcm_s16le);
REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar);
REGISTER_ENCDEC (PCM_S24BE, pcm_s24be);
REGISTER_ENCDEC (PCM_S24DAUD, pcm_s24daud);
REGISTER_ENCDEC (PCM_S24LE, pcm_s24le);
REGISTER_ENCDEC (PCM_S32BE, pcm_s32be);
REGISTER_ENCDEC (PCM_S32LE, pcm_s32le);
REGISTER_ENCDEC (PCM_U8, pcm_u8);
REGISTER_ENCDEC (PCM_U16BE, pcm_u16be);
REGISTER_ENCDEC (PCM_U16LE, pcm_u16le);
REGISTER_ENCDEC (PCM_U24BE, pcm_u24be);
REGISTER_ENCDEC (PCM_U24LE, pcm_u24le);
REGISTER_ENCDEC (PCM_U32BE, pcm_u32be);
REGISTER_ENCDEC (PCM_U32LE, pcm_u32le);
REGISTER_ENCDEC (PCM_ZORK , pcm_zork);
/* DPCM codecs */
REGISTER_DECODER (INTERPLAY_DPCM, interplay_dpcm);
REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm);
REGISTER_DECODER (SOL_DPCM, sol_dpcm);
REGISTER_DECODER (XAN_DPCM, xan_dpcm);
/* ADPCM codecs */
REGISTER_DECODER (ADPCM_4XM, adpcm_4xm);
REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx);
REGISTER_DECODER (ADPCM_CT, adpcm_ct);
REGISTER_DECODER (ADPCM_EA, adpcm_ea);
REGISTER_DECODER (ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa);
REGISTER_DECODER (ADPCM_EA_R1, adpcm_ea_r1);
REGISTER_DECODER (ADPCM_EA_R2, adpcm_ea_r2);
REGISTER_DECODER (ADPCM_EA_R3, adpcm_ea_r3);
REGISTER_DECODER (ADPCM_EA_XAS, adpcm_ea_xas);
REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv);
REGISTER_DECODER (ADPCM_IMA_DK3, adpcm_ima_dk3);
REGISTER_DECODER (ADPCM_IMA_DK4, adpcm_ima_dk4);
REGISTER_DECODER (ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
REGISTER_DECODER (ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead);
REGISTER_DECODER (ADPCM_IMA_ISS, adpcm_ima_iss);
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
REGISTER_DECODER (ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
REGISTER_DECODER (ADPCM_IMA_WS, adpcm_ima_ws);
REGISTER_ENCDEC (ADPCM_MS, adpcm_ms);
REGISTER_DECODER (ADPCM_SBPRO_2, adpcm_sbpro_2);
REGISTER_DECODER (ADPCM_SBPRO_3, adpcm_sbpro_3);
REGISTER_DECODER (ADPCM_SBPRO_4, adpcm_sbpro_4);
REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf);
REGISTER_DECODER (ADPCM_THP, adpcm_thp);
REGISTER_DECODER (ADPCM_XA, adpcm_xa);
REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha);
/* subtitles */
REGISTER_ENCDEC (DVBSUB, dvbsub);
REGISTER_ENCDEC (DVDSUB, dvdsub);
REGISTER_DECODER (XSUB, xsub);
/* external libraries */
REGISTER_ENCDEC (LIBAMR_NB, libamr_nb);
REGISTER_ENCDEC (LIBAMR_WB, libamr_wb);
REGISTER_ENCDEC (LIBDIRAC, libdirac);
REGISTER_ENCODER (LIBFAAC, libfaac);
REGISTER_DECODER (LIBFAAD, libfaad);
REGISTER_ENCDEC (LIBGSM, libgsm);
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
REGISTER_ENCODER (LIBMP3LAME, libmp3lame);
REGISTER_DECODER (LIBOPENJPEG, libopenjpeg);
REGISTER_ENCDEC (LIBSCHROEDINGER, libschroedinger);
REGISTER_DECODER (LIBSPEEX, libspeex);
REGISTER_ENCODER (LIBTHEORA, libtheora);
REGISTER_ENCODER (LIBVORBIS, libvorbis);
REGISTER_ENCODER (LIBX264, libx264);
REGISTER_ENCODER (LIBXVID, libxvid);
2009年5月19日 星期二
Music Information Retrieval - 冠廷
====20081118====
這週的進度式開始實做上週所報告的Paper
依照上週所報告的Paper
Input為wav file
資料庫端為midi file
而雙方都需要轉成Chroma Vector
再以時間為index去做DTW比對
而資料庫端的midi file照paper所說
也可以先轉成wav檔再轉成Chroma Vector
所以下週就可以先跑一些結果出來了
這是一部分Chroma Vector的結果
左邊為12個Chroma Bin
顏色的深淺代表能量高低 越淺代表能量越高
====20081125====
繼上週所做的事情
就把剩下的程式給寫完了
並且做了一些實驗
PPT File
====20081202====
這週跑了多個版本的命運交響曲的實驗
以及想了一個計算Chroma Vector距離所可能會發生的問題
PPT File
備註:
1. 要開始做對樂譜和onset detection的部分
2. 也許可以用HMM從Chroma Vector找出音的多條路徑,再拿這些路徑的變化量去做DTW(用以解決key shift的問題)
====20081209====
這週我報告了一篇ISMIR2007的Paper
Paper內容是在說將掃描進電腦的樂譜(圖檔)和音樂錄音(wav,mp3)做Synchronization
也就是對譜的動作
而他使用的方法則是用我之前所報告的Chroma Feature來做比對
在此,我更正一下
我在報告Paper中有提到一點
關於一開始的音高記號如果OMR辨識錯誤的話
我當時說:"Paper說還是可以對的上"
抱歉,這一點是我在報告時講錯了
是我記錯了
Paper並沒有對於這一點有特別的說明
只有說那些local的臨時記號就算多錯幾個還是對的上
PPT File
====20081223====
這週的進度是把老師上週要我做的事情
回去想了程式流程圖
並完成了一部分的程式
以下是程式的流程圖:
MIDI:
經由MIDI parser處理之後
得到event
再經過處理
將其轉成以tick為時間單位的資料
再轉成chroma feature
WAV:
做完FFT之後
直接轉成chroma vector
接下來要將時間單位統一
由tick合併(透過MIDI的tempo可以換算成時間)
接下來分段做DTW比對
由比對的結果即可知道MIDI的onset的位置是對到WAV的哪個位置
而對到的這個位置 就是WAV的onset的位置
再經由這個位置 可以寫回MIDI File
另外老師上週有問我一個問題
褐色的部分是midi的部分 三個音時同時發聲
而紅色是真正的情況(wav) 時間點上可能會有一點點誤差
而做過DTW之後 褐色onset的位置 只會對到一個紅色的位置
而藍色的地方就是拿對到的onset的位置調整後的結果
如果需要三個音找到更正確的onset位置
則需要拿對到的onset附近的幾個frame下去做分析
目前進度:
由於程式需要midi的一些資訊以及最後又要寫回midi file
為了讓我對midi format以及順便了解舊的midi parser原本的問題在哪邊
所以我就用C#重寫了一個midi parser
也順利的找到了原本midi parser的問題所在
再順利的把event取出來之後
順利的把它拆成以tick為時間單位的資料
====20081230====
紫色字的部分是我上週的進度
紅色字的部分是我這週的進度
藍色字的部分是我未完成的進度
而這週有做了一個實驗
先去看MIDI的Chroma和MIDI合成Wav的Chroma有沒有可能對的起來
必須要先對的起來
這樣MIDI的Chroma才有可能和實際演奏的Wav對的起來
而在某些樂器中的Chroma會長的有點奇怪
有可能是FFT Size太小 則可能會被分在同一個Bin,
也有可能是FFT Size夠大,但因為泛音的頻率偏掉太多,造成離另一個音比較接近
可能的解決方法有:
1.增大FFT Size 但Hop Size不變
2.改用小波轉換
3.先經過一個Low Pass Filter 再轉Chroma
而在投影片最後 有兩張圖
分別為MIDI轉Chroma 以及 實際演奏轉Chroma 的圖
另外我有想了一個解決key shift的方法
過幾天我會整理補上
====想法====
這個想法是用來解決Key Shift的問題
想法:
去記錄音高變化的趨勢,從Chroma Feature再去做一次轉換。
首先,會有一個Base Semitone,這個Base Semitone為多少是由上一個Frame的Chroma Vector來決定,而目前Frame的Chroma Vector會依照這個Base Semitone來做位移(Shift)的動作,所以如何決定Base Semitone將會影響到呈現出來的結果。我想了很久,我覺得可以設一個Threshold,如果能量大於或等於這一個Threshold的Semitone且這個Semitone是目前Base Semitone加N個Semitone而N為最小且N>=0,就當作是新的Base Semitone。
而位移(Shift)的動作就是將Semitone – Base Semitone,值如果為負值就再加上12,看值為多少,就將其Semitone的能量移至此位置;也就是說,如果原本的Chroma Vector為[0,0,1,0,0,0,0,0,0,0,0,0],若Base Semitone為1,則轉換的結果為[0,1,0,0,0,0,0,0,0,0,0,0],而位移後的結果,可以視為目前Frame和上一個Frame的音高變化是原本的音高再提高一個半音,由此也可以推測出上一個Frame的Chroma Vector有可能是長這樣:[0,1,0,0,0,0,0,0,0,0,0,0]。
以下我將舉個例子來說明,原本的Chroma Vectors如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
11 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0.6 | 0.6 | 0.8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
3 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0.8 | 0.8 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 | 1 | 0.7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
縱軸代表12個半音,橫軸代表時間(Frame Number),而每一個值代表能量(音量),假設Threshold = 0.6,值為0的位置可以視為原本就沒有能量或者是能量小於0.6。
接下來將一步步的將每一個Chroma Vector做轉換,以下的編號可以視為處理第n個Frame的過程。
0.在一開始,因為還未決定Base Semitone,所以要先決定Base Semitone,找最接近第0個半音且能量有超過Throshold的半音當作Base Semitone,在這個例子中Base Semitone為3,而轉後過後的Chroma Vector為[1,0,0,0,0,0,0,0,0,0,0,0]。
1. 此時Base Semitone為3,原本的Chroma Vector為[0,0,0,1,0,0,0,0,0,0,0,0]經過轉換的結果為[1,0,0,0,0,0,0,0,0,0,0,0],再重新決定Base Semitone為3。
2. 此時Base Semitone為3,原本的Chroma Vector為[0,1,0,0,0,0.6,0,0,0,0,0,0]經過轉換的結果為[0,0,0.6,0,0,0,0,0,0,0,1,0],再重新決定Base Semitone為5。
3. 此時Base Semitone為5,原本的Chroma Vector為[0,1,0,0,0,0.6,0,0,0,0,0,0]經過轉換的結果為[0.6,0,0,0,0,0,0,0,1,0,0,0],再重新決定Base Semitone為5。
4. 此時Base Semitone為5,原本的Chroma Vector為[0,0.7,0,0,0,0.8,0,0,0,0,0,0]經過轉換的結果為[0.8,0,0,0,0,0,0,0,0.7,0,0,0],再重新決定Base Semitone為5。
5. 此時Base Semitone為5,原本的Chroma Vector為[1,0,0.8,0,0,0,0,0,0,0,0,0]經過轉換的結果為[0,0,0,0,0,0,0,1,0,0.8,0,0],再重新決定Base Semitone為0。
6. 此時Base Semitone為0,原本的Chroma Vector為[1,0,0.8,0,0,0,0,0,0,0,0,0]經過轉換的結果為[1,0,0.8,0,0,0,0,0,0,0,0,0],再重新決定Base Semitone為0。
7. 此時Base Semitone為0,原本的Chroma Vector為[0,0,0,0,1,0,0,1,0,0,0,0]經過轉換的結果為[0,0,0,0,1,0,0,1,0,0,0,0],再重新決定Base Semitone為4。
8. 此時Base Semitone為4,原本的Chroma Vector為[0,0,0,0,1,0,0,1,0,0,0,0]經過轉換的結果為[1,0,0,1,0,0,0,0,0,0,0,0],再重新決定Base Semitone為4。
9. 此時Base Semitone為4,原本的Chroma Vector為[0,0,0,0,0,0,0,0,0,0,0,1]經過轉換的結果為[0,0,0,0,0,0,0,1,0,0,0,0],再重新決定Base Semitone為11。
10. 此時Base Semitone為11,原本的Chroma Vector為[0,0,0,0,0,0,0,0,0,1,0,1]經過轉換的結果為[1,0,0,0,0,0,0,0,0,0,1,0],再重新決定Base Semitone為11。
11. 此時Base Semitone為11,原本的Chroma Vector為[0,0,0,0,0,0,0,0,0,1,0,0]經過轉換的結果為[0,0,0,0,0,0,0,0,0,0,1,0]。
轉換的結果如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
11 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
9 | 0 | 0 | 0 | 0 | 0 | 0.8 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 | 1 | 0.7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
2 | 0 | 0 | 0.6 | 0 | 0 | 0 | 0.8 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 0.6 | 0.8 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
接著,再依照這個結果,給予不同的Base Semitone,即能還原回原本的Chroma Feature,紅字粗體的能量所代表的Semitone為Base Semitone。
還原的過程如下所述,以下的編號可以視為還原第n個Frame的過程。
假設一開始的Base Semitone給予3,照理來說,結果會與原本的Chroma Feature一樣。
0. 此時Base Semitone為3,將[1,0,0,0,0,0,0,0,0,0,0,0]還原成[0,0,0,1,0,0,0,0,0,0,0,0],再重新決定Base Semitone為3。
1. 此時Base Semitone為3,將[1,0,0,0,0,0,0,0,0,0,0,0]還原成[0,0,0,1,0,0,0,0,0,0,0,0],再重新決定Base Semitone為3。
2. 此時Base Semitone為3,將[0,0,0.6,0,0,0,0,0,0,0,1,0]還原成[0,1,0,0,0,0.6,0,0,0,0,0,0],再重新決定Base Semitone為5。
3. 此時Base Semitone為5,將[0.6,0,0,0,0,0,0,0,1,0,0,0]還原成[0,1,0,0,0,0.6,0,0,0,0,0,0],再重新決定Base Semitone為5。
4. 此時Base Semitone為5,將[0.8,0,0,0,0,0,0,0,0.7,0,0,0]還原成[0,0.7,0,0,0,0.8,0,0,0,0,0,0],再重新決定Base Semitone為5。
5. 此時Base Semitone為5,將[0,0,0,0,0,0,0,1,0,0.8,0,0]還原成[1,0,0.8,0,0,0,0,0,0,0,0,0],再重新決定Base Semitone為0。
6. 此時Base Semitone為0,將[1,0,0.8,0,0,0,0,0,0,0,0,0]還原成[1,0,0.8,0,0,0,0,0,0,0,0,0],再重新決定Base Semitone為0。
7. 此時Base Semitone為0,將[0,0,0,0,1,0,0,1,0,0,0,0]還原成[0,0,0,0,1,0,0,1,0,0,0,0],再重新決定Base Semitone為4。
8. 此時Base Semitone為4,將[1,0,0,1,0,0,0,0,0,0,0,0]還原成[0,0,0,0,1,0,0,1,0,0,0,0],再重新決定Base Semitone為4。
9. 此時Base Semitone為4,將[0,0,0,0,0,0,0,1,0,0,0,0]還原成[0,0,0,0,0,0,0,0,0,0,0,1],再重新決定Base Semitone為11。
10. 此時Base Semitone為11,將[1,0,0,0,0,0,0,0,0,0,1,0]還原成[0,0,0,0,0,0,0,0,0,1,0,1],再重新決定Base Semitone為11。
11. 此時Base Semitone為11,將[0,0,0,0,0,0,0,0,0,0,1,0]還原成[0,0,0,0,0,0,0,0,0,1,0,0]。
還原的結果如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
11 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0.6 | 0.6 | 0.8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
3 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0.8 | 0.8 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 | 1 | 0.7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
假設一開始的Base Semitone給予4。
0. 此時Base Semitone為4,將[1,0,0,0,0,0,0,0,0,0,0,0]還原成[0,0,0,0,1,0,0,0,0,0,0,0],再重新決定Base Semitone為4。
1. 此時Base Semitone為4,將[1,0,0,0,0,0,0,0,0,0,0,0]還原成[0,0,0,0,1,0,0,0,0,0,0,0],再重新決定Base Semitone為4。
2. 此時Base Semitone為4,將[0,0,0.6,0,0,0,0,0,0,0,1,0]還原成[0,0,1,0,0,0,0.6,0,0,0,0,0],再重新決定Base Semitone為6。
3. 此時Base Semitone為6,將[0.6,0,0,0,0,0,0,0,1,0,0,0]還原成[0,0,1,0,0,0,0.6,0,0,0,0,0],再重新決定Base Semitone為6。
4. 此時Base Semitone為6,將[0.8,0,0,0,0,0,0,0,0.7,0,0,0]還原成[0,0,0.7,0,0,0,0.8,0,0,0,0,0],再重新決定Base Semitone為6。
5. 此時Base Semitone為6,將[0,0,0,0,0,0,0,1,0,0.8,0,0]還原成[0,1,0,0.8,0,0,0,0,0,0,0,0],再重新決定Base Semitone為1。
6. 此時Base Semitone為1,將[1,0,0.8,0,0,0,0,0,0,0,0,0]還原成[0,1,0,0.8,0,0,0,0,0,0,0,0],再重新決定Base Semitone為1。
7. 此時Base Semitone為1,將[0,0,0,0,1,0,0,1,0,0,0,0]還原成[0,0,0,0,0,1,0,0,1,0,0,0],再重新決定Base Semitone為5。
8. 此時Base Semitone為5,將[1,0,0,1,0,0,0,0,0,0,0,0]還原成[0,0,0,0,0,1,0,0,1,0,0,0],再重新決定Base Semitone為5。
9. 此時Base Semitone為5,將[0,0,0,0,0,0,0,1,0,0,0,0]還原成[1,0,0,0,0,0,0,0,0,0,0,0],再重新決定Base Semitone為0。
10. 此時Base Semitone為0,將[1,0,0,0,0,0,0,0,0,0,1,0]還原成[1,0,0,0,0,0,0,0,0,0,1,0],再重新決定Base Semitone為0。
11. 此時Base Semitone為0,將[0,0,0,0,0,0,0,0,0,0,1,0]還原成[0,0,0,0,0,0,0,0,0,0,1,0]。
還原的結果如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
11 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0.6 | 0.6 | 0.8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
4 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0.8 | 0.8 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 1 | 1 | 0.7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
而這個結果其實就是原本的Chroma Feature將音高移高一個Semitone的Chroma Feature,而要將其還原的原因並不是要證明這個結果是可以還原的,而是要證明說只要旋律相同,不論這個音樂是什麼調,經過轉換後的結果是一樣的。
但是這邊還有一個疑問,如果兩個來源轉換出來的Chroma Feature可能中間有一小段的不同,那經過轉換的結果又會有什麼不同呢?
經過部分變更的來源:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
11 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0.6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
3 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0.8 | 0.8 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
轉換的結果如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
11 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | 0 | 0 | 1 | 0 | 0 | 0.8 | 0 | 0 | 0 | 0 | 1 | 1 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0.6 | 0 | 0 | 0 | 0.8 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
觀察這個結果與之前的結果,其來源是由原本的來源的第3、4、7個Frame修改後而成,而比對結果,與原本結果不同的為第3、4、5、7、8,其它地方還是相同的,所以只要這種不同的Frame不要太多,還是可以利用DTW來做對譜的動作。
====20090108====
這一週的進度取得了Onset的"大概位置"
接下來可能會用傳統的方式靠energy來取得比較正確的位置
接著我也會試著修改計算distance的方法
來試試看結果會不會比較好!
投影片中有一些解決Key Shift的資料
詳細的資料已在上方
其中學長有問說:為什麼我base semitone要一直改,不用同一個就好了
其實這問題我也想過
我meeting時回答的可能不好
我再重新整理一下
如何決定base semitone是一個問題
假設只以一開始決定base semitone就不更改的話
那有個先決條件
就是"這兩首歌的頭要對齊"
所以就不能用片段去對整首歌了
接著探討一下如果中間走音的話情況會如何
如果中間部分走音是shift一大段的pitch
那只以一開始的base semitone做調整的話
那這邊對過去可能會這一整片都有很大的distance (因為一整段走音 整個對不上)
但如果是用前一個frame的base semitone的話
那會有比較大distance的部分 會是"剛"走音的那幾個frame (影響範圍有限)
(如果之後又轉換回原本的pitch,那在剛轉換的那幾個frame的distance也會變大)
而整段走音的部分
因為變化趨勢還是一樣的
所以我認為distance不會變大
此外上週有一個Chroma Feature的圖
能量是集中在最上方的Chroma Bin
這是我寫程式的疏忽
把大於某個頻率的能量都分配到那根Bin
此Bug已解決
====20090113====
這週的進度為
將由DTW比對後的結果 (概略的Onset位置)
在做一次調整
調整方法為
第i個frame的x音的能量比例 - 第i-1個frame的x音的能量比例
如果大於threshold的話 則可能為Onset所在
途中
1.老師有提到說可以參考其它同時發聲的其它音高的Onset位置
2.DNA有提到說threshold的假設可以說是
經由取斜率(微分)的結果 大部分都是0.3(假設) 所以才設為0.3
其實當時我還聽不懂取斜率(微分)是該怎麼做
後來問DNA後 才知道就是後面的frame和前面的frame做相減
哈哈 請恕我才疏學淺 沒反應過來
====20090119====
本週做了一個小小的實驗
我修改了Midi和Wav計算距離的方法
主要是Midi轉Chroma後
同一個時間點通常只會有1~3個不等的Chroma elements有值
所以我的想法是只去比對這些有值的elements
而其它elements就先忽略
這個概念源自於阿扁講過的 "頭過身就過"
我就想說就只要比對這些有值elements就好了
而那些沒有值的elements如果去和wav比的話
反而會成為拉大distance的主因 !!
做了一個小實驗
以16秒的片段歌曲當做是input
去search完整的Midi file
共有五首片段歌曲
其中第五首是現場演奏
而前四首是Midi file而成出來的Wav file
因為樣本數太少
所以成功率的話..請各位看倌打個折扣
表格中的數字代表distance
越小代表越相近
而接下來會將input的Wav file加上reverb的效果
再跑一些實驗看看
====20090224====
繼續之前做的
只針對Wav File取一段去搜尋MIDI File
方法依然為DTW配合Chroma Feature
修改距離的計算方法
由原本的
修改為
因為MIDI File可以知道哪些音高有能量
所以只針對有能量的音高做運算
所以假設只有A音高有能量
則計算過程為
若A音高和B音高有能量
則計算過程為
輸入的Wav File有原始音檔(MIDI File合成)取16秒
以及Reverberate後的Wav File
其中做Dark Hall後的音檔和原本的音檔差異不大 (耳朵要很仔細聽才聽得出來)
Large Empty Hall差異比較大 (波形差很多 耳朵馬上可以聽出來)
結果還不錯 表格中的數字為距離
越小代表越相似
但是因為樣本數有點少
真正的結果得等我跑完真正的大實驗才會知道
不過我預想效果應該不會太差 (純屬預想)
因為經過Reverberate後的音檔 每個音高的能量比例會變
依照原始的方法
如果原本是符合的 經過這個一變動 在距離的計算就會變大 (因為其它音高會跑出能量 拉大距離)
但如果只比對MIDI File有能量的音高 則照理說可以避免掉這個問題
====20090227====
我整理一下週五和老師討論的內容
如果有理解錯誤的話 請指正
由於文森部分的Partial Tracking無法知道目前的F0到底是D4還是D5
所以我的部分相當於一個前處理的機制
在對完譜之後可以知道每一段對到譜上為哪些音 Ex: D4
所以可以把這個資訊告訴Partial Tracking的部分
這樣Partial Tracking就可以知道目前的F0是D4而不是D5
====20090303====
我整理一下我之前做的結果
不然可能有點亂
依照原本的方法
不管原本資料庫端或者輸入端是MIDI或Wav都無所謂
反正都可以直接轉為Chroma Vector再計算歐幾里得距離
但是假設其中一方一定是MIDI的話
則就可以知道目前是哪幾個音高為有能量的
所以可以針對那幾個有能量的音高去計算距離即可
這個方法可以避免掉reserb的影響
而我改善Key Shift的方法
則和原本方法一樣
不限制雙方為MIDI或Wav
如果資料庫端是MIDI 輸入端為Wav的話
做完DTW後所對到的結果
可以透過MIDI所給的資訊
找到Wav的Onset位置
而這個位置 可以再透過每個音框的音高的能量
去修正 找到更精確的Onset位置
但是如果要和其它paper比較的話
大多數的paper還是資料端和輸入端都是wav為主
而我這週做的就是把我之前所講的Key Shift的方法給實做
並且跑一些數據
卡農這首歌曲效果不彰的原因是
我取的那一小段歌曲在原音裡面的後段 就有經過移調然後重覆出現
我接下來會用最原始的方法測試經過reserb之後的音檔來搜尋會有多差
以及跑一下切巴哈無伴奏的結果
====20090310====
我又要來推翻我所說的話了
果然沒做過實驗之前所講的話需要打50%的折扣
如果資料庫端和輸入端都是wav的話
資料庫端為原曲
輸入端為原曲取16秒後經過reverb處理
其中我試過的種類有
Full Reverb (Medium Concert Hall (open))
Large Empty Hall Reserb
Shower Reverb
而音檔是使用Bach裡面的The Anna Magdalena Notebooks中的四首歌曲
anna-03 anna-04 anna-07 anna-10
以及Mozart的
Violin concerto No.1 in Bb, K.207 (Allegro moderato) vck207-1
Violin concerto No.2 in D, K.211 (Allegro moderato) kv211-1
Violin concerto No.3 in G, K.216 (Allegro) kv216-1
做完實驗的結果其實並沒有想像中的差
(資料庫中如果是MIDI的話 直接與Wav做DTW結果本來就不好 再reserb的話會更亂)
雖然distance有變大
但是還是比其它歌曲小
表格中的數字為Distance
Distance越大 代表越不相似
縱軸為Input 橫軸為資料庫端
不管有沒有經過Reverb
輸入端的片段歌曲 都可以成功的找到原始歌曲
同樣的音檔把資料庫中替換為MIDI File
並且使用原本的方法來做Search
以及用改善的方法來做Search (改善的方法有po在上週)
其實總體來看 是會比較好的
但是有些結果卡在第二名的原因是
其中有一首MIDI 在某段是沒有聲音的
這會造成我在計算Distance時 給他為0
所以這首歌在計算Distance時 不管是跟哪一首歌計算
Distance的結果都是非常低
順便一提 這次我用的樣本在經過Reverb之後Search的排名都沒有變
這次的結果我有列出排名
而修改後的方法也有與修改前的方法比較排名 (上升or下降)
接下來說明一下 我和文森的部分該怎麼做整合
首先 我這部分 MIDI和Wav 經過DTW之後 會輸出一份Onset的時間點以及音高
而同樣的Wav經過Partial Tracking之後 會輸出
Partial的音高
開始時間
持續時間
能量
並且會標明是屬於哪個Group(F0)
我想的修正方法很簡單
總之Parial Tracking會先有一份答案
然後再以DTW的結果
去看Onset 時間點附近的有沒有起始時間差不多的Partial
如果有的話 則去比對音高(頻率)
若有找音高相同的Partial
則把這個Group的F0更新為找到的這個Parial (可能更新前後不會變)
若沒找到 則可能是有幾個問題
1.連音問題 (時間點附近都沒Partial,因為連音,Partial Tracking把它連起來了)
2.譜錯 或者是 彈錯了 (雖然時間點附近有Partial 可是音高卻不同)
我現在比較傾向於先把這些程式整合搞定了再來解決這兩個問題XD
而在修正之後的輸出結果 會是 F0的音高 開始時間 持續時間 能量
接著就可以做合成了!
====20090324====
這一週測了幾首歌的Onset (利用MIDI和DTW)
但是由於MIDI的問題
所以目前只有一首歌找個還算不錯
這首歌是
Bach的Sonata No.1 in G-, BWV1001 (Siciliano)
由於Onset過多 我只取了幾個而已
結果請看投影片的圖!
另外有一個正規化的問題
一種是向量除以vector norm
另一種則是把一個向量的值mapping到0-1
轉檔程式會將兩種都轉出來
並著名是n1或n2
====20090401====
開始著手研究文森的程式
取得我想要的資訊
但卻發現 一首歌要下去分析實在是太龐大了 (跑不動)
只好分段下去跑
目前的想法是
分段下去跑 假設每一段是5秒鐘
可是這分段的時間位置 不一定就是音高的起始/結束
所以分析完的結果 必須得另外做一個合併的處理
依照文森目前的程式
Partial的頻率
起始Frame Index
持續的Frame Number
能量
F0
都可以取得
但是還沒有分Group的動作
我所謂的分Group的動作是指
400Hz 600Hz 這兩條 跟200Hz這一條 會是同一個Group
而對於分段後合併的想法
我合併的想法很簡單
如果前面那一段的Group的結束時間 和 後面這一段的Group的起始時間接近
且F0相同
那就合併
====20090421====
很久沒來寫了=_=
我補一下之前的東西
對Onset這部分
我找了很久 雖然網路上有Bartok 的midi
但是沒有老師給我那片CD的曲目...
我曾經試過去找wav轉midi的轉檔軟體
但是效果很差...
我覺得似乎...花錢請專家做midi比較快 囧
再來就是之前修改學長合成程式的部分
我稍微記錄一下
一開始我先把學長程式內Filter的觀念搞懂
其實也沒什麼 就跟slim差不多
不過有差別的是
學長寫的Filter 不是 Multi Thread
這個我畫的圖
分別標明了程式執行的順序
在搞懂了Filter之後
我就去看了學長合成程式也哪些Filter
大概就是長這樣
我把Noise的部分關掉 所以有關Noise的部份我沒有理會
而我看了程式之後 真正要改的只有 標明紅色的三個Filter
fAPP負責傳送AbstractPara
AbstractPara 就是 F0 和 Amp
經過fAP2SPI長出20個partial的Amp (這樣是一個Sinusoid)
再透過fSI2RIA的addPartial()這個method處理
那些方法的細節 我就不多講了
因為都是學長寫的XD
我的修改方法只是將
fAPP傳送AbstractPara 改成 傳送AbstractPara [] <---就是一堆Fo和Amp
fAP2SPI傳送Sinusoid 改成 傳送Sinusoidp[] <---就是好幾組Sinusoid
這邊都ok 反正就是多加for迴圈下去跑
接著就是fSI2RIA
其實也沒改什麼
比較要處理的就是phase
注意不同音的phase要另外算就行了
但是!!!
其實學長的程式實在是博大精深了
所以我只好先延用他的button來跑我改的程式XD
並沒有加一個新功能在內
其實之前都是會錯意...原來f0和能量是每個frame都有...
所以又重畫了一張流程圖 應該是要長這樣!
DTW只輸出onset的frame index和音高
接著和Partial Tracking的結果做修正
但其實我覺得我修正的方法還很差...
我想這部分是可以改進的
我只是去找時間差不多近的那一條partial而已
但是其實可能會誤判
我想比較好的方法 應該是寫一個Application
最後讓使用者自己修正一下比較好
甚至也可以讓使用者任意修改F0 合成出來的結果就會不同XD
所以這邊修正完會輸出成F0和能量
當然一個Frame會有多個F0
接著再丟給合成程式
聲音就出來了XD
接著...我會邊轉CD...邊寫論文...邊養身體>"<
等口試後我會把程式重整一次...並且詳細的寫上"註解"
====20090423====
貝多芬 String Trio in C-, Op.9, No.2
我成功抓到wmv檔案 也有了MIDI FIle
我兩邊都抓取部分來對Onset 感覺還OK? (私心的自己覺得>"<)
Part1
Part2
當然合成的程式我也有跑
但是 結果似乎不太好
我用的partial tracking的程式是0309的那版 (最初版)
不過我想等文森那邊都完成的話 合成出來的結果會變很棒
原因我整理一下
1.連線中間斷掉
2.低頻的都找不到? 我用cool edit看頻譜其實很明顯一條 但是低於100hz
稍微記錄一下 我今天跟老師談的內容
論文
1.第一章 Introduction
把一堆相關paper都寫進去
也當reference
切記要寫張智星老師的paper進去XD
2.第二章 簡單介紹DTW和Chroma Feature
3.第三章 Partical Tracking + DTW + 合成 (onset要在這章?)
4.第四章
4-1 利用Partical Tracking 結果 加強Chroma Feature
4-2資訊檢索
5.第五章 實驗
====20090424====
利用Partical Tracking結果 加強Chroma Feature
讓那些音高更明顯
從Partical Tracking的結果輸出F0 List
並且轉成12個音階
利用這個結果 加強原本Chroma Feature
若Partical Tracking結果對應到Chroma Feature的音高
就加個權重 ex: 平方? 乘以2之類的
====20090428====
流程圖
我這邊Enhance的方法是把能量乘以2
以下是Enhance之後的結果
Part1
Enhance前
Enhance後
Part2
Enhance前
Enhance後
Part3
Enhance前
Enhance後
====20090501====
我在Key Shift這邊,有一段解釋,是故意製造錯誤之後,再觀察經由Base Semitone轉換的結果
原文是這樣的:
觀察這個結果與之前的結果,其來源是由原本的來源的第3、4、7個Frame修改後而成,而比對結果,與原本結果不同的為第3、4、5、7、8,其它地方還是相同的,所以只要這種不同的Frame不要太多,還是可以利用DTW來做對譜的動作。
我後來發現...打這些字好像有誤導大家的嫌疑,因為我後來看,我也覺得我自己被我自己誤導了!所以要跟大家say sorry一下!
我今天報告後,想了很久,我想得在重新整理一下。
DTW除了計算Distance,還能取得Input和Reference的對應位置,至於對應位置的正確性,則就要看兩邊的時間(Index)上的內容,而DTW本來就能夠容忍部分的錯誤,至於容忍多少,要看那錯誤的片段有多長,以及那錯誤片段與原本正常片段的差距有多少(Distance)。
而我先前解決Key Shift的方法,有提到如果片段錯誤的話,那轉換的結果影響範圍有限,其實這點也只是保留原本Chorma的特性而已。
先看原本的Chroma,假設一首歌前半部的音高是錯的,而後半部的音高是對的,那轉成Chroma之後,自然也是呈現"錯對"的樣子。
而所以希望經過Base Semitone轉換之後的結果,也是跟原本的Chroma一樣,會是"錯對"的情況出現。
之所以提到這點,是因為當初在想轉換的方法時,都會想說只靠個某個Frame的某樣屬性做轉換,例如只靠第一個Frame的最高能量音高做轉換,但如果那個Frame剛好是的錯,那就慘了。假設有兩首一樣的歌,但是其中一首歌的第一個Frame是錯的,那兩首歌經過轉換後,會完全長得不一樣。
直接把例子套上以上的說法,原曲在Chroma上是"對對"的情況,而Query(假設前半部和原曲是不同的)在Chroma上是"錯對"的情況,如果靠著第一個Frame的某樣屬性做轉換,原曲依然是"對對"(我們假設他是對的,因為是放在資料庫),而Query則會變成"錯錯"的情況(因為是依賴第一個Frame做轉換,但因為第一個Frame和原曲不同),這個"錯錯"的情況意思是說,他跟原曲轉出來的不管是前半部還是後半部,都會長得不一樣。
而解決Key Shift也還有保留另一樣Chroma的特性,那就是從原曲任一時間點上擷取片段,和原曲整首直接轉再去擷取片段,不會有太大差異。(當然不可能完全一樣,從不同的sample點做FFT會有些微能量值的差異)
Chroma很直覺,擷取其中幾秒的歌曲片段,轉Chroma,會和將整首歌轉Chroma之後時間點相同的片段長的差不多。
所以希望新的轉換方法,也能有同樣的效果,不管我是擷取哪個時間點的片段做轉換,都希望能和原曲直接做轉換,接著看同樣時間點的片段的結果差不多。
很明顯Base Semitone的轉換方法有做到這一點,因為只參考前面一個Frame。
補充一下
如果"錯"的部分是key shift的話,那轉出來的結果,不會是"錯"的
====20090505====
Partial Convert to Chroma
F0 List + Chroma => Chroma (上週弄的)
F0 List => Chroma (拿f0 detection的結果直接轉chroma)
F0 List + Partial List => 128 dimensional (將f0和partial轉成128維度的向量)
F0 List + Partial List => Chroma (將f0和partial轉成chroma)
因為時間的關係 我只跑了F0 List + Partial List => Chroma
本來也想跑F0 List + Partial List => 128 dimensional 看看
但是show圖的程式 我來不及改了XD
總之先看一下結果
FFT=>Chroma
F0 detection enhance 上一張圖
Partial Tracking=>Chroma
總覺得Partial Tracking的結果很漂亮
但跟原圖的時間點有小小的差異
應該是FFT Size取很大的緣故
再補兩張 Partial Tracking=>Chroma
有些地方有斷掉 那是因為Partial Tracking我跑的是舊版程式
所以沒有補點
還有少部分的斷掉是Partial Tracking沒有連起來
====20090505====
昨天睡覺前無意間發現一篇paper
結果因為某部分很重要的地方看不太懂 讓我輾轉難眠
我英文還是太差了 誤會了他敘述的意思
多謝了小明學長替我解惑
這篇paper某個部分和我先前講的 解決key shift的方法類似
其實了解了之後...也覺得他的想法很簡單
但是當初就是沒想到><
這一張圖是原音轉Chroma
這一張圖代表的是原圖的 第 n+1 個frame 和 第 n 個frame 位移幾個半音之後的相似度 (縱軸是位移幾個半音)
所以簡單來說 他就是去記錄 前後frame 之間 移調後的相似度
而我講的方法 則是去參考前一個frame的最大能量個半音 為何
去調整目前這一個frame 的 Chroma Vector
用上一個frame的最大能量半音 來紀錄目前這一個frame要移調幾個半音 並且記錄有多少能量
所以
兩個方法都有去參考前一個frame
在記錄一種走勢
老師問我說 那他們的方法可以還原成原本的Chroma嗎?
我想答案是不行的
因為只有C圖的話 那只記錄相似度
只能大概猜出frame的走勢
至於這個走勢是從哪幾個音高 或者是 幾個音 所造成的
那就不得而知了
不過他們的paper並不是只拿C圖當特徵而已
原本的A圖也有
比對方法不是用DTW
詳細部分我沒有看
我只看Chroma Feature而已
補充:
我講的方法其實不是看最大能量的音高
而是有設一個Threshold
講最大能量只是為了方便說明和想像
不取最大能量的原因是
因為音檔是多音的
從單一首歌同樂器同調來看的話
並不能確定不同演奏家都會演奏時 某個音高一定會能量最大
從單一首歌同演奏家不同樂器同調來看的話
並不能確定不同樂器演奏時 某個音高一定會能量最大
從單一首歌同演奏家同樂器不同調來看的話
能量多寡也不會單單是往上移幾個半音這麼簡單
其實有點亂XD 我也不知道我的想法對不對
有待實驗證明...
====20090512====
我把上面那篇paper講的feature實做出來
並且和我的方法做比較
====20090519====
MIDI輸出的格式
目前我覺得可以用最流行的xml來紀錄
不然用一般的寫檔也是可以
輸出格式 以Track為單位
這邊的Track跟MIDI定義的Track不同
一個Track代表一條音
而時間的問題
我們討論的結果 決定弄一個統一的絕對時間
但是最小的單位時間 需要討論一下
另外頻率和音量 我們決定用陣列來存
因為希望這個格式 是一個統一個格式
而這個格式也能吃從文森程式output的結果
class Track
{
int 樂器id;
float[] 頻率;
float[] 能量;
int 起始單位時間;
int 持續單位時間;
Control[] control;
}
class Control
{
int type; //紀錄 control種類, ex: vibrato 就填1
int subType; //紀錄 是哪一個子類, ex: vibrato有三種,如果要第二種,就填2
string tablePath; //如果type是user define, 會由使用者指定這個路徑
int 起始單位時間; //在這個Track的單位時間多少時發生
int 持續單位時間;
}
====20080609====
我覺得我之前search MIDI Database的公式有點不太合理
所以我做了一些修改
原本是MIDI 轉 Chroma 後 看有幾個音高有發音 就去計算那幾個音高的distance
所以如果MIDI 轉 Chroma 後的音高越多的話 那distance會越大
所以我將公式改為 在開根號之前 先除以n
n就是轉Chroma後有幾個音高