見出し画像

ガバキックはキックなのか?AIに聞いてみた

こんにちは、Quarkです。

音楽で「キック」といえばどんな音を想像しますか?

人それぞれあると思いますが、「トッ」とか「タン」とか短い余韻の音を想像する人が多いと思います。


次に、「ガバキック」といえばどんな音を想像しますか?

ドゥバー」とか「ブォォォォ」とかじゃないですか?めっちゃうるさくて長い余韻ですよね多分。あと絶対濁音付きますよね。


ガバキックは、名前に「キック」と入ってますが、本当にキックと言って良いのか気になる時、あると思います。

意見が欲しいのですが、ボッチで友達がいないので、AI作ってAIに聞いてみました


データを用意する

まずはデータが必要です。サンプルパックや、音源を自作して学習用データを用意します。

それぞれサンプリングレート44100Hz,16bit深度のモノラルで書き出し、1ch  x 75600列のデータとして用意します。


分類のラベルとしてはベース、キック、スネア、ノイズの4種類、合計892サンプル用意しました。

【ベース】
SerumのClassic Synths 01_RESO1 ~ 15_ORGANまでの波形をC#0 ~ B0の各音階で書き出したものを用いました。WT POSを若干上げています。

画像1

【キック】
キックは、TR-909のキックサンプル,VEC5 Clubby Kicks,GHOSTHACK Drum Hero Kicksを用いました。

【スネア】
スネアも、上記同様、VEC5 Snares,GHOSTHACK Drum Hero Snaresを用いました。

【ノイズ】
SerumのNOISEオシレータ Analog,Attacks_Kickを、Pitch44,47,49,50,51,53,56に設定したものを用いました。

画像2


それぞれのサンプルの出力周波数はこんな感じです。

画像3


学習させる

用意したデータを深層学習ライブラリ Keras を用いて畳み込みニューラルネットワークを構築し、音源に対してどのクラスなのかを学習させます。

分類クラスは
・ベース = 0
・キック = 1
・スネア = 2
・ノイズ = 3

とします。
BPM175で5泊分の長さをとり、前述のとおり1つの音源につき75600列のデータがあります。(下記画像は学習データの音源をランダムに取得してプロットしたものです)

学習データ

16bit深度のデータを0~1の範囲へと変換し、学習用の次元へと変換、畳み込みニューラルネットワークを構築します。
詳しくはGistにコードをアップしています。気になる方は見てみてください。

#音声の数値データ範囲を0~1へ
#16bit深度の為、32768で割る
test_waves_norm = test_waves / 32768

#学習用の次元に変換
twnr = test_waves_norm.reshape(test_waves_norm.shape[0], 1, 75600, 1)

#クラスを学習用に変換
from keras.utils import to_categorical
y = to_categorical(np.array(df['class']), 4 )

#CV
from sklearn.model_selection import train_test_split
from collections import Counter
X_train, X_valid, Y_train, Y_valid = train_test_split(twnr, y, test_size=0.2, random_state=42)


import keras
from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPool2D, Flatten, Dropout
from keras.layers.normalization import BatchNormalization
from sklearn.metrics import confusion_matrix

#分類クラス数
num_classes = 4
#学習回数
epochs = 200
#入力次元
input_shape = (1, 75600, 1)

#層の定義
model = Sequential()
model.add(Conv2D(16, kernel_size=(1, 3), activation='relu', kernel_initializer='glorot_normal', input_shape=input_shape, padding='same', strides=(1, 1)))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(1, 2), strides=(1, 2), padding='valid'))
model.add(Dropout(0.2))

model.add(Conv2D(16, kernel_size=(1, 3), activation='relu', kernel_initializer='glorot_normal', padding='same', strides=(1, 1)))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(1, 2), strides=(1, 2), padding='valid'))
model.add(Dropout(0.2))

#以降下記を11回繰り返します。
#model.add(Conv2D(16, kernel_size=(1, 3), activation='relu', kernel_initializer='glorot_normal', padding='same', strides=(1, 1)))
#model.add(BatchNormalization())
#model.add(MaxPool2D(pool_size=(1, 2), strides=(1, 2), padding='valid'))
#model.add(Dropout(0.2))


model.add(Flatten())
model.add(Dense(4, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
            optimizer=keras.optimizers.Adam(learning_rate=0.0001),
            metrics=['accuracy'])
model.summary()

#学習
result = model.fit(X_train, Y_train, batch_size=32, epochs=epochs, validation_data = (X_valid, Y_valid),
                 verbose=1)


学習結果としては、分類精度93.8%。予測結果としては以下となりました。

学習データのバリデーション混合行列

横軸が実際の分類、縦軸が予測した分類です。

ノイズをスネアと間違ってしまうことが若干あるようです。
個人的には、ベースとノイズはサステインが続いているので、ベースとノイズの過誤が多いかなと思ったのですが、予想外でした。

バリデーションデータだけでは、物足りないので、VEC4のキックとスネアも100個ずつ、正しく分類できるか試してみましたが、精度は100%でした。

画像6



ガバキックを分類する

ということで本題です。ガバキックは「キック」と分類されるのでしょうか。

日本のアーティストと海外のクロスブリードを中心に、曲を選んで分類させてみました。

【用意した曲】
1. 6th - Jormungand
2. Brainpain & YMB - Get UP
3. COLON - For You (イントロキック)
4. COLON - For You (メインキック)
5. DJ Myosuke - Phantom Killer
6. Fragz & Sinister Souls - Something Sinister
7. Holly - Spare
8. Lowroller - Deadly Intent
9. Micromakine & Sinister Souls - Invaders (イントロキック)
10. Micromakine & Sinister Souls - Invaders (メインキック)
11. Pemcy - Brain Waves
12. Quark - Kill Everybody
13. Right as Rain - Abandon
14. RoughSketch feat. Aikapin - Alice In Voodooland
15. Stellabee - Enemy
16. Switch Technique - Roll Hard
17. Takeru - Eodem Rave
18. The Outside Agency & Deathmachine - My Design
19. The Outside Agency - Headphone Wisdom
(50音順)

それぞれ、極力ガバキックのみが取れそうな部分を一拍書き出し、使用しました。一部イントロキックも使っているのは、「キック」ときちんと分類されるのかも見たかった為です。

音そのものが気になる方は、上記曲名に見つかるものはリンクをはっていますので、聴いてみてください。

使用したガバキックの波形は以下になります。

使用したガバキック

#予測するために0~1へ変換、次元変換
gabbakick_waves_norm = gabbakick_waves / 32768
gabbakick_waves_1 = gabbakick_waves.reshape(gabbakick_waves_norm.shape[0], 1, 75600, 1)

#予測
gabbakick_predict = model.predict(gabbakick_waves_1)

#結果を見やすいようにDataFrameへ
gabbakick_test.loc[gabbakick_test.index, 'class'] = np.argmax(gabbakick_predict, axis=1)
gabbakick_test['audio_data'] = gabbakick_test['audio_data'].str[15:]
gabbakick_test['sound'] = gabbakick_test['class'].apply(lambda x: 'kick' if x == 1 else 'bass' if x == 0 else 'snare' if x == 2 else 'noise')


分類結果

画像8

ベース : 8
キック : 10
スネア : 1

だいたいベースとキックで半々くらいに分けられるみたいですね。
「キック」と分類してほしいイントロ2曲はきちんと「キック」になってるようです。
Brainpain & YMB - Get UPも普通のキック枠で入れましたが「キック」ですね。

キックとベースが一つ続きになってない系ガバキックは「ベース」になっちゃうんですかね?どういう判断がされたかは自分は想像つかないです。低音の出方が肝なのかな。

1曲、スネアと判定されていますが、どうやら高周波帯域に影響しているっぽいです。ほかの曲もクラッシュと一緒に鳴るガバキック部分を分類させてみたら「スネア」と出ました。


結果

ガバキックは半分くらいキックで残りはベース
たまにスネア
でした。

自分の曲はベースと分類されてました。今後はAIにとっても良いガバキックが作れるように頑張ろうと思います。



※今回使用した著作物に関しては個人的な使用の範疇で使用していますので、問題無いと判断しています。問題がある方はご連絡いただければと思います。

この記事が気に入ったらサポートをしてみませんか?