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

顏色的深淺代表能量高低 越淺代表能量越高

PPT File

 

====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====

這週的進度是把老師上週要我做的事情

回去想了程式流程圖

並完成了一部分的程式

以下是程式的流程圖:

20081223-2

MIDI:

經由MIDI parser處理之後

得到event

再經過處理

將其轉成以tick為時間單位的資料

再轉成chroma feature

WAV:

做完FFT之後

直接轉成chroma vector

接下來要將時間單位統一

由tick合併(透過MIDI的tempo可以換算成時間)

接下來分段做DTW比對

由比對的結果即可知道MIDI的onset的位置是對到WAV的哪個位置

而對到的這個位置 就是WAV的onset的位置

再經由這個位置 可以寫回MIDI File

另外老師上週有問我一個問題

20081223-1

褐色的部分是midi的部分 三個音時同時發聲

而紅色是真正的情況(wav) 時間點上可能會有一點點誤差

而做過DTW之後 褐色onset的位置 只會對到一個紅色的位置

而藍色的地方就是拿對到的onset的位置調整後的結果

如果需要三個音找到更正確的onset位置

則需要拿對到的onset附近的幾個frame下去做分析

目前進度:

由於程式需要midi的一些資訊以及最後又要寫回midi file

為了讓我對midi format以及順便了解舊的midi parser原本的問題在哪邊

所以我就用C#重寫了一個midi parser

也順利的找到了原本midi parser的問題所在

再順利的把event取出來之後

順利的把它拆成以tick為時間單位的資料

PPTX File

PPT File

====20081230====

20081230-1

紫色字的部分是我上週的進度

紅色字的部分是我這週的進度

藍色字的部分是我未完成的進度

而這週有做了一個實驗

先去看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的方法

過幾天我會整理補上

PPT File

PPTX File

====想法====

這個想法是用來解決Key Shift的問題

DOC File

DOCX File

想法:

去記錄音高變化的趨勢,從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已解決

PTT File

PPTX File

 

====20090113====

這週的進度為

將由DTW比對後的結果 (概略的Onset位置)

在做一次調整

 

調整方法為

第i個frame的x音的能量比例 -  第i-1個frame的x音的能量比例

如果大於threshold的話 則可能為Onset所在

 

途中

1.老師有提到說可以參考其它同時發聲的其它音高的Onset位置

2.DNA有提到說threshold的假設可以說是

經由取斜率(微分)的結果 大部分都是0.3(假設) 所以才設為0.3

 

其實當時我還聽不懂取斜率(微分)是該怎麼做

後來問DNA後 才知道就是後面的frame和前面的frame做相減

哈哈 請恕我才疏學淺 沒反應過來

PTT File

PPTX File

====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的效果

再跑一些實驗看看

PTT File

PPTX File

 

====20090224====

繼續之前做的

只針對Wav File取一段去搜尋MIDI File

方法依然為DTW配合Chroma Feature

修改距離的計算方法

由原本的

MWSnap141 2009-02-25, 17_16_16

修改為

因為MIDI File可以知道哪些音高有能量

所以只針對有能量的音高做運算

所以假設只有A音高有能量

則計算過程為

MWSnap142 2009-02-25, 18_03_11

若A音高和B音高有能量

則計算過程為

MWSnap073

輸入的Wav File有原始音檔(MIDI File合成)取16秒

以及Reverberate後的Wav File

其中做Dark Hall後的音檔和原本的音檔差異不大 (耳朵要很仔細聽才聽得出來)

Large Empty Hall差異比較大 (波形差很多 耳朵馬上可以聽出來)

 

結果還不錯 表格中的數字為距離

越小代表越相似

但是因為樣本數有點少

真正的結果得等我跑完真正的大實驗才會知道

不過我預想效果應該不會太差 (純屬預想)

因為經過Reverberate後的音檔  每個音高的能量比例會變

依照原始的方法

如果原本是符合的 經過這個一變動  在距離的計算就會變大  (因為其它音高會跑出能量 拉大距離)

但如果只比對MIDI File有能量的音高 則照理說可以避免掉這個問題

 

PTT File

PPTX 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之後的音檔來搜尋會有多差

以及跑一下切巴哈無伴奏的結果

 

PTT File

PPTX File

 

====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

輸入端的片段歌曲 都可以成功的找到原始歌曲

MWSnap074

MWSnap075

 

同樣的音檔把資料庫中替換為MIDI File

並且使用原本的方法來做Search

以及用改善的方法來做Search (改善的方法有po在上週)

其實總體來看 是會比較好的

但是有些結果卡在第二名的原因是

其中有一首MIDI 在某段是沒有聲音的

這會造成我在計算Distance時 給他為0

所以這首歌在計算Distance時 不管是跟哪一首歌計算

Distance的結果都是非常低

順便一提 這次我用的樣本在經過Reverb之後Search的排名都沒有變

 

這次的結果我有列出排名

而修改後的方法也有與修改前的方法比較排名 (上升or下降)

MWSnap076

MWSnap077

MWSnap078

 MWSnap079

 

接下來說明一下 我和文森的部分該怎麼做整合

圖片1

首先 我這部分 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的音高 開始時間 持續時間 能量

接著就可以做合成了!

 

PPT File

PPTX File

 

====20090324====

這一週測了幾首歌的Onset (利用MIDI和DTW)

但是由於MIDI的問題

所以目前只有一首歌找個還算不錯

這首歌是

Bach的Sonata No.1 in G-, BWV1001 (Siciliano)

由於Onset過多 我只取了幾個而已

結果請看投影片的圖!

PPT File

PPTX File

 

另外有一個正規化的問題

一種是向量除以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

這個我畫的圖

分別標明了程式執行的順序

圖片2

 

在搞懂了Filter之後

我就去看了學長合成程式也哪些Filter

大概就是長這樣

我把Noise的部分關掉 所以有關Noise的部份我沒有理會

而我看了程式之後 真正要改的只有 標明紅色的三個Filter

圖片3

 

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都有...

所以又重畫了一張流程圖 應該是要長這樣!

圖片4

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

MWSnap128

MWSnap129

MWSnap130 

Part2

MWSnap131

MWSnap132

 

當然合成的程式我也有跑

但是 結果似乎不太好

我用的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====

流程圖

圖片5

我這邊Enhance的方法是把能量乘以2

以下是Enhance之後的結果

Part1

Enhance前

MWSnap134

Enhance後

MWSnap133

Part2

Enhance前

MWSnap136

Enhance後

MWSnap135

Part3

Enhance前

MWSnap138

Enhance後

MWSnap137

PPT File

PPTX File

====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

MWSnap134

F0 detection enhance 上一張圖

MWSnap133

Partial Tracking=>Chroma

MWSnap142

 

總覺得Partial Tracking的結果很漂亮

但跟原圖的時間點有小小的差異

應該是FFT Size取很大的緣故

 

再補兩張 Partial Tracking=>Chroma

MWSnap145

MWSnap146

有些地方有斷掉 那是因為Partial Tracking我跑的是舊版程式

所以沒有補點

還有少部分的斷掉是Partial Tracking沒有連起來

PPT File

PPTX File

 

====20090505====

paper pdf file

昨天睡覺前無意間發現一篇paper

結果因為某部分很重要的地方看不太懂 讓我輾轉難眠

我英文還是太差了 誤會了他敘述的意思

多謝了小明學長替我解惑

 

這篇paper某個部分和我先前講的 解決key shift的方法類似

其實了解了之後...也覺得他的想法很簡單

但是當初就是沒想到><

 

這一張圖是原音轉Chroma

MWSnap147 2009-05-05, 11_43_09

這一張圖代表的是原圖的 第 n+1 個frame 和 第 n 個frame 位移幾個半音之後的相似度 (縱軸是位移幾個半音)

MWSnap148 2009-05-05, 11_43_21

 

所以簡單來說 他就是去記錄 前後frame 之間 移調後的相似度

 

而我講的方法 則是去參考前一個frame的最大能量個半音 為何

去調整目前這一個frame 的 Chroma Vector

用上一個frame的最大能量半音 來紀錄目前這一個frame要移調幾個半音 並且記錄有多少能量

 

所以

兩個方法都有去參考前一個frame

在記錄一種走勢

 

老師問我說 那他們的方法可以還原成原本的Chroma嗎?

我想答案是不行的

因為只有C圖的話 那只記錄相似度

只能大概猜出frame的走勢

至於這個走勢是從哪幾個音高 或者是 幾個音 所造成的

那就不得而知了

 

不過他們的paper並不是只拿C圖當特徵而已

原本的A圖也有

比對方法不是用DTW

詳細部分我沒有看

我只看Chroma Feature而已

 

補充:

我講的方法其實不是看最大能量的音高

而是有設一個Threshold

講最大能量只是為了方便說明和想像

不取最大能量的原因是

因為音檔是多音的

從單一首歌同樂器同調來看的話

並不能確定不同演奏家都會演奏時 某個音高一定會能量最大

從單一首歌同演奏家不同樂器同調來看的話

並不能確定不同樂器演奏時 某個音高一定會能量最大

從單一首歌同演奏家同樂器不同調來看的話

能量多寡也不會單單是往上移幾個半音這麼簡單

 

其實有點亂XD 我也不知道我的想法對不對

有待實驗證明...

 

====20090512====

我把上面那篇paper講的feature實做出來

並且和我的方法做比較

PPT File

PPTX File

 

====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後有幾個音高

30 則留言:

SCREAMLab 提到...

冠廷:

MUSIC應該也在你這個的分類中.

不錯, 我下星期看你的結果.

匿名 提到...

更新一下這串就好.

想一下這方法的缺點, 我們應該要來想論文題目要做什麼了.

匿名 提到...

你可以先就這部分做一下實驗嗎?

取一首violin sonata的wave檔. 再找一首對應的midi. 看看他準確的程度到哪裡.

冠廷 提到...

好的

匿名 提到...

這問題事實上有點麻煩, 可是又不是那麼麻煩.

癥結在: 我怎麼知道那個區域有幾個音? 假如事先知道樂譜, 那麼問題簡單多了, 應該很快就可以完成. 不過要是不知道呢? 那就要求助於multiple pitches detection的結果了.

問題是: 要是multiple pitches detection的結果不正確呢? 所以最後可能一堆方法要拿來做交叉驗證與比對了, 這個我們要再深入研究.

所幸是我們現在是知道樂譜的, 了不起譜與演出有一點小差別要修正.

我期待你的結果.

另外就是我們要研究的新的比對方式了. 也就是用不同的feature vector.

SCREAMLab 提到...

你昨天講的不錯應該是一種Chroma Feature的再處理. 可以post出來嗎? 或者下次meeting來說.

另外就是我說的要改變FFT size, 有想過要換一下transform嗎? 我們可以先用一堆filter bank (照著tone frequency來排)先處理, 然後不同band再用不同size的FFT, 再加一點zero padding來增加FFT的resolution. 這很容易做的.

Onset下星期可已做好嗎?

冠廷 提到...

1.過幾天我會把我昨天跟您講的補上
2.我覺得老師說的主意不錯,我會再想一下的
3.應該可以,我會努力寫程式的

SCREAMLab 提到...

我們是否找一下時間來統整一下你目前做的成果以及狀況, 並解檢討一下呢?

還有就是定一個論文題目.

冠廷 提到...


我目前有在寫文件
整理之前報告的東西

關於剛剛老師跟我提到的我和文森的事情
我想我會和文森再去找您一次
把情況搞清楚XD

另外就是硬碟的事情
老師的黑膠唱片的資料我很早之前就備份好囉
拿去修的這顆是另外一顆Nas Server

匿名 提到...

用cent的成果那部份, 你可以上來說一下做法嗎? 我怕過幾天, 我會忘了.

匿名 提到...

另一台NAS好了嗎? 我想開始備分server上的資料了. 也請你跟keiko說, 黑膠的資料好了, 是否可以開始之前的計劃, 另外把資料架到師大那邊的情況如何了.

冠廷 提到...

喔@@
那我會整理一下

另一nas我明天會測試
測試結果我在打上來

冠廷 提到...

Nas Server我測試完了
重新format之後沒有出現任何異狀
應該是OK了

SCREAMLab 提到...

你其它的結果怎麼沒列? 我要看一下都看不到.

冠廷 提到...

老師是說投影片裡的結果嗎?
如果是的話我已經列上去了!

SCREAMLab 提到...

我是說要有說明.

centcent 提到...

頻率範圍我是設定 100~8000 Hz
因此100以下的我就略過了
所以會有你說的那個情形
100以下找不到

冠廷 提到...

了解=_=

難怪會這麼乾淨

一個點都沒有 囧

SCREAMLab 提到...

謝謝你的解說, 這是一個不錯的研究人該有的態度.

我想了解一下DTW對於錯音可以有一定程度的效果, 那麼對付多幾個音出來呢? 或者兩個接近的音的前後對調了呢?

為什麼我會提這問題呢? 因為在對譜的時候, 幾種狀況都會出現, 可是人卻可以輕易地聽出來這是兩個一樣的曲子, 但是你的對譜工具沒辦法.

我們可以再討論一下嗎?

冠廷 提到...

我想了解一下DTW對於錯音可以有一定程度的效果, 那麼對付多幾個音出來呢? 或者兩個接近的音的前後對調了呢?

=================================

這就是看distance了
其實怎麼容忍完全取決於distance的算法

1.對付多幾個音出來
2.兩個接近的音的前後對調

其實這兩點 我很早一直就有在想
distance到底要怎麼改才比較好

第一點 我覺得就是降低某些音高的權重,類似的方法就像是我對付MIDI時的做法,其實對付wav應該也可以做到(設一個Threshold)

第二點 這我覺得就要去參考前後frame了,也許可以去跟前後frame的音高借能量來用,看哪一個frame的距離最小,就取那個距離,不過這樣似乎會多出不少排列組合...詳細的方法還得再思考

SCREAMLab 提到...

針對假如有譜的情況 , 是否可以有一個distance可以比較容易對出時間點呢? 也就是對錯音, 多音, 與對調因有大一點的容忍度.

chroma 是否可以weighting後再來比對, 類似用midi來做chroma一樣?

冠廷 提到...

Q:針對假如有譜的情況 , 是否可以有一個distance可以比較容易對出時間點呢? 也就是對錯音, 多音, 與對調因有大一點的容忍度.

A:
目前是有一些想法,但是不周全
不過大致的想法是

針對MIDI同位置出現的音,但在wav中不同時間出現
我突然有一個異想天開的想法
在假設 譜和音檔沒有差異太多的話
代表時間不會差異太多
那對完之後 其實也是能找到差不多的時間
這時候,我覺得可以使用局部的音檔以及局部的音高做DTW
(現在仔細想想 搞不好找onset時用這樣做會更準? 等於就是取代之前能量的做法,或者是可以加以配合,先用這個,再去看能量)

在增加容忍度方面
在計算distance時,假設midi在音高A有一個音
wav彈錯了跑到A#
在計算distance時,是12個音高向量計算歐幾里得距離
本來是 每個音高能量相減平方開根號
我覺得 除了計算每個音高能量相減外
也可以順便去計算與wav中 差距N個半音的音高的能量相減
N要多少 也許可以給使用者選擇
N越大的話 計算出來的結果 應該可以給他乘以一個越大的數值
出來的結果要是比 原本的能量相減平方較小
那就用這個數值取代原本的數值
也就是說 本來是 ((A1-A2)^2 + ... (G1-G2)^2)^(1/2)
這時候透過midi知道A音高有能量
假設只看上下一個半音 也不考慮權重的事情
(A1-A2)^2這一項
就可以經由 (A1-A2)^2, (A1-A#2)^2, (A1-G#2)^2 這幾項
看哪項比較小
就可以取代原本(A1-A2)^2這一項

Q:chroma 是否可以weighting後再來比對, 類似用midi來做chroma一樣?

A:就跟老師上次講的主意差不多,不過我忘了打上來,像是將每個音高的能量取N次方,能量大於某個值的音高再去計算那個音高的distance

87showmin 提到...

我本來以為一條Track是一把樂器,這樣在Cuda那邊的設計,或許可以減少CPU跟GPU資料交換的次數。只是這樣起始tick跟持續tick就要改成陣列,以紀錄這把樂器在整首歌中的音符。

Control Class 是否要多一個ID? 用來紀錄user是用某type的某一預設Control model。例如預設有三種vibrato可以給user選,如果user要自訂就填 -1 。

我記得我們討論說 Control.tablePath 所指定的檔案會是個table,這些tables的格式也需要紀錄一下。例如,vibrato table的欄位有:
1. freq (決定vibrate速度)
2. amp (vibrate能量)
如果想要隨著時間有不同的vibrato手法,我建議是另外再開個table,而非加入
3. time
這樣設計起來就太複雜了 orz

冠廷 提到...

1.要記錄樂器id...我忘了.

2.我本來的想法是type就是有包含多個子類,像是vibrato有三種,第一種就是1,第二種就是2,第三種就是3,接著其他種control就從4開始.
不然可以多加一個int來辨別子類.

3.我不太清楚table會長什麼樣子,依照control的不同,table的內容會是一樣的嗎?
我想table的class可能要再討論一下.

87showmin 提到...

1. 假如vibrato有三種,user-defined table會從 4 開始填,那如果table不只一個,Control.tablePath是不是也要不只一個呢?

2. 一條Track的音高或音量可能會隨著時間的改變而改變,但目前訂的Track.StartTick 或 Track.Duration 都只是一個變數而已,要如何紀錄這樣的改變?是否可參考ADSR-type?

冠廷 提到...

1. 假如vibrato有三種,user-defined table會從 4 開始填,那如果table不只一個,Control.tablePath是不是也要不只一個呢?

一個control會有多個table嗎?

2. 一條Track的音高或音量可能會隨著時間的改變而改變,但目前訂的Track.StartTick 或 Track.Duration 都只是一個變數而已,要如何紀錄這樣的改變?是否可參考ADSR-type?

現在的格式不是只紀錄MIDI的輸出嗎?
所以一個Track的音高和能量是固定的

arwen 提到...

我們考慮的不只是從midi轉出來的, 還包含如vincent的程是分析完的結果. 所以同一個track, pitch and volume當然隨時在變.

87showmin 提到...

我在想,既然「絕對時間」的單位會影響陣列大小的話,有沒有辦法設計成在header那邊才定義單位大小就好?一來比較彈性,二來,Cuda一秒內到底能吃多少比資料也還需要測試。

冠廷 提到...

就在檔案的一開始定義一下
基本的時間單位是多少?

87showmin 提到...

就1ms吧,可讀性較高。