自成一派,這個做曲大師確實名副其實!

image

AWS DeepComposer 是一項教育型的 AWS 服務,能夠訓練出生成式人工智能,並利用 GAN(Generative Adversarial Network)轉換輸入的旋律,創做出完整的原創樂曲。git

以前咱們曾有篇文章詳細介紹過該服務,感興趣的童鞋能夠在這裏查看:當音樂趕上人工智能 -- 歌手們都在「雲競演」,做曲家就不想試試「雲譜曲」?github

簡單來講,藉助 AWS DeepComposer,咱們可使用預先訓練好的音樂流派模型(如爵士、搖滾、流行、交響樂等)將咱們提供的旋律轉換爲相應流派的曲子。那麼當你玩轉這個服務後,有沒有想過本身也「開宗立派」,經過必定的參數訓練出本身的流派選項?segmentfault

固然能夠!咱們只須要將音樂數據文件存儲在 NumPy 對象中,隨後結合 GitHub 上的 Lab 2—— 訓練一套自定義 GAN 模型中的訓練步驟進行操做便可。下文將介紹如何將 MIDI 文件轉換爲適用於 AWS Deepomposer 的格式,而訓練出本身的流派模型。數組

在下文中,咱們可使用本身的 MIDI 文件訓練出雷鬼音樂流派模型。雷鬼音樂誕生於牙買加島,經常使用樂器包括低音吉他、鼓以及各種打擊樂器。不過本文介紹的方法也是通用的,你們徹底能夠藉此訓練任何其餘音樂流派。app

數據處理:生成訓練數據

MIDI(.mid)文件是訓練數據的最初始狀態。MIDI 文件由軟件生成(並讀取),文件中包括關於音符及聲音回放的數據。在數據處理過程當中,咱們須要將 MIDI 文件轉換爲 NumPy 數組,並將其持久化保存成磁盤上的一個單獨的.npy 文件。下圖展現了數據的轉換過程:
imagecomposer

儘管機器學習廣泛使用.csv文件存儲數據,但.npy文件是爲加速訓練過程當中的讀取速度高度優化的。.npy文件的最終形態應爲(x, 32, 128, 4),其含義分別爲(樣本數量,每一個樣本的時間步數, 音高範圍, 樂器)。less

若將 MIDI 文件轉換爲適當的格式,咱們須要完成如下步驟:機器學習

  1. 讀取 MIDI 文件以生成一個 Multitrack 對象。
  2. 肯定要使用的四條樂器音軌。
  3. 檢索各音軌中的 Pianoroll 矩陣,並將其調整爲正確的格式。
  4. 將 Pianoroll 對象與給定的樂器相匹配,並將其存儲在.npy文件中。

讀取 MIDI 文件以生成一個 Multitrack 對象

數據處理的第一步,是解析各 MIDI 文件並生成一個 Multitrack 對象。下圖即爲 Multitrack 對象的基本結構。
image
這個過程用須要用到 Pypianoroll 庫,它以 Python 代碼實現讀取及寫入 MIDI 文件的功能。具體參見如下代碼:ide

#init with beat resolution of 4
music_tracks = pypianoroll.Multitrack(beat_resolution=4)
#Load MIDI file using parse_midi
#returns Multitrack object containing Track objects
music_tracks.parse_midi(your_midi_file_directory + your_midi_filename)

music_tracks 是一個 Mulitrack 對象,包含一個從 MIDI 文件中讀取到的 Track 對象列表。每一個 Mulitrack 對象都包含速度(Tempo)、節拍(Downbeat)、節拍分辨率(Beat resolution)以及名稱(Name),具體如如下代碼所示:函數

tracks: [FRETLSSS, ORGAN 2, CLAVINET, MUTED GTR, CLEAN GTR, VIBRAPHONE, DRUMS],
tempo: [120. 120. 120. ... 120. 120. 120.],
downbeat: [ True False False False False False False False False . . .
 False False False False False False False False False False False False],
beat_resolution: 4,
name: 「reggae1」

肯定要使用的四條樂器音軌

若是要解析的 Mulitrack 對象中剛好包含四種樂器,則能夠直接跳過此步驟。

咱們以前解析的 Mulitrack 對象共包含7條樂器音軌(Fretless 電貝司、風琴、豎笛、靜音電吉他、清音電吉他、顫音琴和鼓)。模型須要學習的樂器種類越多,訓練時間就越長,成本天然也越高。有鑑於此,這裏咱們選擇的 GAN 只支持最多4種樂器。若是 MIDI 文件中的音軌包含4種以上樂器,請直接從所選擇的音樂流派中選擇最重要的4種樂器進行模型訓練。相應的,若是樂器數量不足4種,則須要擴充 MIDI 文件。樂器數量錯誤會致使 NumPy 的形制出現錯誤。

給定音軌上的每一種樂器都擁有本身的編號。編號由通用 MIDI 規範規定,至關於樂器的惟一標識符。如下代碼示例就用相關編號提取到鋼琴、風琴、貝司以及吉他四種樂器:

instrument1_program_numbers = [1,2,3,4,5,6,7,8] #Piano
instrument2_program_numbers = [17,18,19,20,21,22,23,24] #Organ
instrument3_program_numbers = [33,34,35,36,37,38,39,40] #Bass
instrument4_program_numbers = [25,26,27,28,29,30,31,32] #Guitar
if track.program in instrument1_program_numbers:
 collection['Piano'].append(track)
elif track.program in instrument2_program_numbers:
 collection['Organ'].append(track)
elif track.program in instrument3_program_numbers:
 collection['Bass'].append(track)
elif track.program in instrument4_program_numbers:
 collection['Guitar'].append(track)

檢索每條音軌中的 Pianoroll 矩陣,並將其調整爲正確的格式

Multitrack 對象爲每種樂器提供一個 Track 對象。每一個 Track 對象中都包含一個 Pianoroll 矩陣、一個編號、人個表示音軌是否爲鼓的布爾值以及一個名稱。

如下代碼,爲單一 Track 的具體示例:

pianoroll:
[[0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]],
program: 7,
is_drum: False,
name: CLAVINET

在訓練當中,單一 Pianoroll 對象應具備32個離散的時間步長,表明一首歌曲的片斷與128個音高。所選樂器音軌的 Pianoroll 對象的起始形態爲(512,128),咱們須要將其調整爲正確的格式。每一個 Pianoroll 對象將從新調整爲2個小節(32個時間步長)、音高爲128。輸入如下代碼後,單一 Pianoroll 對象的最終形制爲 (16, 32, 128):

#loop through chosen tracks
for index, track in enumerate(chosen_tracks): 
 try:
 #reshape pianoroll to 2 bar (i.e. 32 time step) chunks 
 track.pianoroll = track.pianoroll.reshape( -1, 32, 128)
 #store reshaped pianoroll per instrument
 reshaped_piano_roll_dict = store_track(track, reshaped_piano_roll_dict) 
 except Exception as e:
 print("ERROR!!!!!----> Skipping track # ", index, " with error ", e)

爲了簡潔起見,如下代碼示例僅顯示鋼琴音軌的製做示例:

{'Piano': [Track(pianoroll=array([[[0, 0, 0, ..., 0, 0, 0],
 [0, 0, 0, ..., 0, 0, 0],
 [0, 0, 0, ..., 0, 0, 0],
 ...,
 [0, 0, 0, ..., 0, 0, 0],
 [0, 0, 0, ..., 0, 0, 0],
 [0, 0, 0, ..., 0, 0, 0]],
 ...,
 [0, 0, 0, ..., 0, 0, 0],
 [0, 0, 0, ..., 0, 0, 0],
 [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8), program=7, is_drum=False, name=CLAVINET)]

將 Pianoroll 對象與給定樂器相匹配,並將其存儲在.npy 文件中。

下一步是按樂器將全部音軌連結起來,並將其存儲在.npy 訓練文件當中。咱們能夠將這個過程理解爲各 Pianoroll 對象間的彼此堆疊。咱們須要爲4種所選樂器分別重複這個過程,具體請參見如下代碼:

def get_merged(music_tracks, filename):
...
#will hold all merged instrument tracks
merge_piano_roll_list = []
for instrument in reshaped_piano_roll_dict:
 try:
 merged_pianorolls = np.empty(shape=(0,32,128))
 #concatenate/stack all tracks for a single instrument
 if len(reshaped_piano_roll_dict[instrument]) > 0:
 if reshaped_piano_roll_dict[instrument]: 
 merged_pianorolls = np.stack([track.pianoroll for track in reshaped_piano_roll_dict[instrument]], -1)
 merged_pianorolls = merged_pianorolls[:, :, :, 0]
 merged_piano_rolls = np.any(merged_pianorolls, axis=0)
 merge_piano_roll_list.append(merged_piano_rolls)
 except Exception as e:
 print("ERROR!!!!!----> Cannot concatenate/merge track for instrument", instrument, " with error ", e)
merge_piano_roll_list = np.stack([track for track in merge_piano_roll_list], -1)
return merge_piano_roll_list.reshape(-1,32,128,4)

如今,咱們將合併後的 Pianoroll 存儲在.npy 文件當中,詳見如下代碼:

#holds final reshaped tracks that will be saved to training .npy file
track_list = np.empty(shape=(0,32,128,4))
. . .
#merge pianoroll objects by instrument
merged_tracks_to_add_to_training_file = get_merged(music_tracks, filename)
#concatenate merged pianoroll objects to final training data track list
track_list = np.concatenate((merged_tracks_to_add_to_training_file, track_list))
# binarize data
track_list[track_list == 0] = -1
track_list[track_list >= 0] = 1
#save the training data to reggae-train.npy
save(train_dir + '/reggae-train.npy', np.array(track_list))

結果

以上代碼將一組存儲在 your_midi_file_directory 中的 MIDI 文件生成 reggae-train.npy。相應 Jupyter notebook 與完整代碼可經過GitHub repo獲取。

如今,咱們已經擁有了訓練數據文件,接下來就能夠根據 AWS DeepComposer 示例 notebook 中 Lab 2—— 訓練自定義 GAN 模型提出的步驟訓練自定義音樂流派模型。

本文在 SoundCloud 上提供兩個由 AI 生成的雷鬼風格音軌:Summer BreezeMellow Vibe

技巧與祕訣

咱們可使用如下技巧與祕訣理解你的數據內容,並生成更悅耳的 AI 樂曲。

在 GarageBand 中查看及收聽 MIDI 文件

若是你使用 Mac 設備,可使用 GarageBand 收聽 MIDI 文件並查看其中使用的樂器。若是沒有 Mac 設備,則可以使用任何其餘支持 MIDI 文件的Digital Audio Workstation(DAW)。在經過 GarageBand 收聽 AI 生成的樂曲時,音質要明顯更好,甚至能夠鏈接專業級揚聲器以得到極好的聽覺效果。

使用樂器編號更改伴奏的樂器

在運行Lab 2—— 訓練自定義 GAN 模型提供的推理代碼時,你們可能會注意到,全部由 AI 生成的音軌都會在 GarageBand 中顯示爲「Steinway Grand Piano」。若是熟悉 AWS DeepComposer 控制檯,則可隨時調整樂器種類。要在訓練自定義模型時更改伴奏的樂器種類,請在調用midi_utils中的save_pianoroll_as_midi函數時使用programs參數,具體請見如下代碼:

#use programs to provide the program numbers for the instruments I care about
#17 = Drawbar Organ, 28 = Electric Guitar, 27 = Electric Guitar, 11 = Music Box
midi_utils.save_pianoroll_as_midi(fake_sample_x[:4], programs=[17, 28, 27, 11], destination_path=destination_path)

使用 GarageBand 添加其餘伴奏

在使用AI生成一首樂曲(帶伴奏)以後,咱們可使用GarageBand(或者其餘相似的工具)進一步添加更多伴奏。咱們能夠調整音軌的速度,甚至讓某些樂器靜音。咱們也能夠添加任意數量的其餘伴奏樂器以創造出獨特的聲音表現。

在 AWS DeepComposer 控制檯上建立推理旋律

在運行推理時,咱們須要一段 MIDI 格式的自定義旋律。咱們還能夠添加伴奏樂器配合該自定義旋律生成一首獨特的樂曲。在訓練自定義模型時,最簡單的旋律建立方法就是使用 AWS DeepComposer 控制檯。咱們可使用虛擬鍵盤或者 AWS DeepComposer 鍵盤記錄下旋律,然後選擇「Download」將其下載爲 MIDI 文件。
image

使用 Matplotlib 繪製 Pianoroll

你們可使用 Track 上的 Plot 函數繪製 Pianoroll 對象,這樣就能直觀查看 Pianoroll 對象了。具體請參見如下代碼:

import matplotlib.pyplot as plt
...
fig, ax = track.plot()
plt.show()

下圖所示,爲 Pianoroll 對象的基本觀感。
image

數據二值化

代碼包含了一段對數據進行二進制化的部分。這項更新很是重要,由於在處理二進制化輸入時,該模型實際處理的是-1與1(而非0與1)。Track_list 中包含最終訓練數據,在繼續使用 Reggae-train.npy 以前,應將其設置爲-1或者1。具體請參見如下代碼:

# binarize data
track_list[track_list == 0] = -1
track_list[track_list >= 0] = 1

總結

AWS DeepComposer 不僅是一款普通的鍵盤,同時也是一種有趣的互動方式,幫助咱們瞭解生成式的 AI 與 GAN 的複雜性。咱們能夠在它的幫助下學習演奏簡單的旋律,甚至可能激發出創做全新樂曲的靈感、訓練出本身的自定義音樂流派模型、最終創造出史無前例的聲音。咱們也能夠將兩種流派融合起來以創造出新的音樂類型!

image

相關文章
相關標籤/搜索