Python編曲實踐(四):向MIDI文件中添加鼓組音軌

前言

在前面三篇文章中,我介紹瞭如何通過Python的Mido庫添加旋律、和絃和模擬滑音、顫音。然而,鼓的作用也是不可忽視的,它就像骨骼一樣支撐起整個音樂,而編輯鼓點的樣式也爲想象力的發揮提供了無限空間,是十分愉悅的事情,本篇文章我就介紹如何向MIDI文件中添加鼓的音軌。

專屬頻道

同其他樂器不同,MIDI格式爲鼓組提供了專屬的頻道,默認在10號頻道,並在這個頻道的40多個音符對應處替換上了不同種類的鼓點樣式,爲了更方便調用,我做成了一個函數,以供參考:

def get_drum_dict():
    drum_dict = {
        'acoustic_bass': 35,
        'bass1': 36,
        'side_stick': 37,
        'acoustic_snare': 38,
        'hand_clap': 39,
        'electric_snare': 40,
        'low_floor_tom': 41,
        'closed_hi-hat': 42,
        'high_floor_tom': 43,
        'pedal_hi-hat': 44,
        'low_tom': 45,
        'open_hi-hat': 46,
        'low-mid_tom': 47,
        'hi-mid_tom': 48,
        'crash_cymbal1': 49,
        'high_tom': 50,
        'ride_cymbal1': 51,
        'chinese_cymbal': 52,
        'ride_bell': 53,
        'tambourine': 54,
        'splash_cymbal': 55,
        'cowbell': 56,
        'crash_cymbal2': 57,
        'vibraslap': 58,
        'ride_cymbal2': 59,
        'hi_bongo': 60,
        'low_bongo': 61,
        'mute_hi_bongo': 62,
        'open_hi_bongo': 63,
        'low_conga': 64,
        'high_timbale': 65,
        'low_timbale': 66,
        'high_agogo': 67,
        'low_agogo': 68,
        'cabasa': 69,
        'maracas': 70,
        'short_whistle': 71,
        'long_whistle': 72,
        'short_guiro': 73,
        'long_guiro': 74,
        'claves': 75,
        'hi_wood_block': 76,
        'low_wood_block': 77,
        'mute_cuica': 78,
        'open_cuica': 79,
        'mute_triangle': 80,
        'open_triangle': 81
    }
    return drum_dict

可見從35到81全是對應的鼓的樣式,對普通編曲而言肯定是夠了。

編程實現

有了專屬的頻道,那麼我們就能夠很輕鬆地來創作自己的鼓組音軌了,爲了方便我寫了一個添加鼓點的函數,供大家參考:

def add_drum(name, time, track, delay=0, velocity=1):
    bpm = get_bpm(track)
    meta_time = 60 * 60 * 10 / bpm
    drum_dict = get_drum_dict()
    try:
        note = drum_dict[name]
    except:
        print(traceback.format_exc())
        return
    track.append(Message('note_on', note=note, velocity=round(64 * velocity), time=delay, channel=9))
    track.append(
        Message('note_off', note=note, velocity=round(64 * velocity), time=round(meta_time * time), channel=9))

爲了讓自己的鼓點更加豐富一點,我添加了兩個鼓的音軌,一個用於踩鑔(Hi-Hat),主要是用於基本節奏的把握,另一個是軍鼓(Snare)、嗵鼓(Tom)和強音鈸(Crash Cymbal),用於使節奏更加Funky和Groovy,並在其他樂器空白間隙加入過門,使得音樂更加豐滿。

  • 首先是鑔軌,我編寫得十分簡單:
def hi_hat(track):
    for i in range(8):
        add_drum('open_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.5, track, velocity=0.6)
        add_drum('open_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.5, track, velocity=0.6)
    for i in range(16):
        add_drum('open_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.25, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.25, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.25, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.25, track, velocity=0.6)
        add_drum('open_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.5, track, velocity=0.6)
        add_drum('closed_hi-hat', 0.5, track, velocity=0.6)
  • 然後是玩花兒的軌,我用了兩個函數來實現:
def tom_and_snare_pt1(track):
    for i in range(7):
        add_drum('acoustic_snare', 0.5, track, velocity=0.8)
        add_drum('low_tom', 0.5, track, velocity=0.6)
        add_drum('low-mid_tom', 0.5, track, velocity=0.6)
        add_drum('acoustic_snare', 0.5, track, velocity=0.6)
        add_drum('low_tom', 0.25, track, velocity=0.8)
        add_drum('acoustic_snare', 0.5, track, velocity=0.8)
        add_drum('low-mid_tom', 0.25, track, velocity=0.6)
    add_drum('acoustic_snare', 0.5, track, velocity=0.8)
    add_drum('low_tom', 0.25, track, velocity=0.6)
    add_drum('low-mid_tom', 0.25, track, velocity=0.6)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('acoustic_snare', 0.125, track, velocity=0.8)
    add_drum('acoustic_snare', 0.125, track, velocity=0.8)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('crash_cymbal1', 0.25, track, velocity=1.2)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('crash_cymbal2', 0.25, track, velocity=1.2)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)


def tom_and_snare_pt2(track, num):
    for i in range(3): #6
        add_drum('acoustic_snare', 0.25, track, velocity=0.8)
        add_drum('acoustic_snare', 0.25, track, velocity=0.8)
        add_drum('low_tom', 0.5, track, velocity=0.6)
        add_drum('high_tom', 0.25, track, velocity=0.6)
        add_drum('low-mid_tom', 0.25, track, velocity=0.6)

        add_drum('acoustic_snare', 0.5, track, velocity=0.6)
        add_drum('low_tom', 0.25, track, velocity=0.8)
        add_drum('acoustic_snare', 0.5, track, velocity=0.9)
        add_drum('low-mid_tom', 0.125, track, velocity=0.6)
        add_drum('hi-mid_tom', 0.125, track, velocity=0.6)

        add_drum('acoustic_snare', 0.5, track, velocity=0.8)
        add_drum('low_tom', 0.25, track, velocity=0.6)
        add_drum('low-mid_tom', 0.25, track, velocity=0.6)
        add_drum('high_tom', 0.25, track, velocity=0.6)
        add_drum('low-mid_tom', 0.25, track, velocity=0.6)

        add_drum('acoustic_snare', 0.125, track, velocity=0.8)
        add_drum('acoustic_snare', 0.125, track, velocity=0.8)
        add_drum('acoustic_snare', 0.125, track, velocity=0.8)
        add_drum('acoustic_snare', 0.125, track, velocity=0.8)
        add_drum('crash_cymbal1', 0.25, track, velocity=1.2)
        add_drum('high_tom', 0.25, track, velocity=0.6)
        add_drum('crash_cymbal2', 0.25, track, velocity=1.2)
        add_drum('low-mid_tom', 0.25, track, velocity=0.6)

    add_drum('acoustic_snare', 0.5, track, velocity=0.8)
    add_drum('low_tom', 0.25, track, velocity=0.6)
    add_drum('low-mid_tom', 0.25, track, velocity=0.6)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('acoustic_snare', 0.125, track, velocity=0.8)
    add_drum('acoustic_snare', 0.125, track, velocity=0.8)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('crash_cymbal1', 0.25, track, velocity=1.2)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)
    add_drum('crash_cymbal2', 0.25, track, velocity=1.2)
    add_drum('acoustic_snare', 0.25, track, velocity=0.8)

    add_drum('high_tom', 0.125, track, velocity=0.9)
    add_drum('high_tom', 0.125, track, velocity=0.9)
    add_drum('hi-mid_tom', 0.125, track, velocity=0.9)
    add_drum('hi-mid_tom', 0.125, track, velocity=0.9)
    add_drum('low-mid_tom', 0.125, track, velocity=0.9)
    add_drum('low-mid_tom', 0.125, track, velocity=0.9)
    add_drum('low_tom', 0.125, track, velocity=0.9)
    add_drum('low_tom', 0.125, track, velocity=0.9)

    add_drum('high_floor_tom', 0.25, track, velocity=1.1)
    add_drum('high_floor_tom', 0.25, track, velocity=1.1)
    add_drum('low_floor_tom', 0.25, track, velocity=1.2)
    add_drum('low_floor_tom', 0.25, track, velocity=1.2)

    if num == 1:
        add_drum('crash_cymbal1', 0.25, track, velocity=1.2)
        add_drum('crash_cymbal2', 0.25, track, velocity=1.2)
        add_drum('crash_cymbal1', 0.25, track, velocity=1.2)
        add_drum('crash_cymbal2', 0.25, track, velocity=1.2)
    if num == 2:
        add_drum('low_floor_tom', 0.25, track, velocity=1.3)
        add_drum('low_floor_tom', 0.25, track, velocity=1.3)
        add_drum('chinese_cymbal', 1, track, velocity=1.9)

鼓組音軌的MIDI文件可參考 drum.mid
完整項目可參考 Github - Truedick23/MusicCritique

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章