File size: 4,455 Bytes
5288edb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import pretty_midi
import jsonpickle
def vocal_midi2note(midi):
    """
    """
    
    notes=[]
    for note in midi:
        pretty_note =pretty_midi.Note(velocity=100, start=note[0], end=note[1], pitch=note[2])
        notes.append(pretty_note)
    return notes


def quantize(notes, beat_times, downbeat_start, chord_time_gap):
    """
    ์–ด๋–ค Note๊ฐ€ ๋ช‡๋ฒˆ์งธ Bar์˜ ๋ช‡๋ฒˆ์งธ timing๋ถ€ํ„ฐ ๋ช‡๋ฒˆ์งธ timing๊นŒ์ง€ ๋‚˜ํƒ€๋‚˜๋Š”์ง€๋ฅผ returnํ•ด์„œ ์ค€๋‹ค.

    Pianoroll์˜ Index๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค? ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ ๋‹นํžˆ ๋งž๋‹ค.

    ex) 1๋งˆ๋””๊ฐ€ 1์ดˆ์ธ ๊ณก์—์„œ ์—ฐ์ฃผ ์‹œ๊ฐ„์ด 4.25~4.75์ธ ์Œ์ด ์žˆ๊ณ , 1๋งˆ๋””๋ฅผ 48๋ถ„ ์Œํ‘œ๊นŒ์ง€ ๊ณ ๋ คํ•œ๋‹ค๋ฉด
    5๋ฒˆ์งธ ๋งˆ๋””์— 12~35๊นŒ์ง€ ์—ฐ์ฃผํ•จ.. ์ด๋ผ๋Š” ์ •๋ณด๋ฅผ ๊ฑด๋„ค์คŒ
    
    """
    first_beat = downbeat_start
    one_beat_time = beat_times[1]-beat_times[0] #๊ทธ๋ƒฅ 1๋น„ํŠธ
    quantize_48th_time = one_beat_time/12 
    beat_num = chord_time_gap//one_beat_time * 12 # 4๋ฐ•์ž ๊ณก์ด๋ฉด 48, 3๋ฐ•์ž ๊ณก์ด๋ฉด 36 -> ์ด๊ฑฐ 24๋‚˜์˜ค๋ฉด.. ์‹œ๊ฐํ™” ๋ง๊ฐ€์ง€๊ฒ ๋„ค? 
    max_idx=0
    for note in notes:
        start_idx = round((note.start-downbeat_start)/quantize_48th_time)
        end_idx = round((note.end-downbeat_start)/quantize_48th_time)
        if max_idx <int(start_idx // beat_num):
            max_idx = int(start_idx// beat_num)

    note_info={str(key) : [] for key in range(max_idx)}

    for note in notes:
        if note.start>downbeat_start: # ๊ทน์ดˆ๋ฐ˜์˜ ์ผ๋ถ€ ์Œํ‘œ๊ฐ€ ์ƒ๋žต๋  ์ˆ˜๋„ ์žˆ๊ธดํ•ฉ๋‹ˆ๋‹ค.
            start_idx = round((note.start-downbeat_start)/quantize_48th_time)
            end_idx = round((note.end-downbeat_start)/quantize_48th_time)
            if end_idx == start_idx:
                end_idx+=1

            note_start = start_idx * quantize_48th_time + first_beat
            note_end  = end_idx * quantize_48th_time + first_beat
            note_pitch = note.pitch
            note_velocity = note.velocity

            bar_idx = int(start_idx // beat_num)
            bar_pos = start_idx % beat_num 
            bar_pos_end = end_idx % beat_num # ์ด๊ฑฐ ๋•Œ๋ฌธ์—, ์Œ ๊ธธ์ด๊ฐ€ ํ•œ ๋งˆ๋””๋ฅผ ๋ชป๋„˜์–ด ๊ฐ *** ์˜ˆ๋ฅผ๋“ค์–ด beatnum์ด 48์ด๊ณ  35~67์ด๋ผ ํ•˜๋ฉด 35 ~ 19 ๋˜์—ˆ๋‹ค๊ฐ€ if๋ฌธ ํƒ€๋ฉด์„œ 35~47๋จ. 
            if bar_pos_end<bar_pos and int(end_idx//beat_num) > bar_idx:
                bar_pos_end = (int(end_idx//beat_num) - bar_idx) * beat_num # ์ด์ œ๋Š” ๊ตฌํ˜„ ํ•จ. ๋‚˜์ค‘์— index์—๋Ÿฌ ๋ฐ˜๋“œ์‹œ ๋‚ ๊ฑฐ์ž„

            if bar_pos_end<bar_pos:
                bar_pos_end = beat_num-1

            note = [float(note_start), float(note_end), int(note_pitch), int(note_velocity), int(bar_pos), int(bar_pos_end)]
            #note = {'start':note_start, 'end':note_end, 'pitch':note_pitch, 'velocity':note_velocity, 'start_idx':bar_pos, 'end_idx':bar_pos_end}
            if str(bar_idx) not in note_info:
                note_info[str(bar_idx)]=[note]
            else:
                note_info[str(bar_idx)].append(note)

    return note_info





def chord_quantize(chord_info, beat_times):
    """
    returns Quantized Chord info, First chord starting point and chord time(3๋ฐ•์ด๋ƒ 4๋ฐ•์ด๋ƒ์— ๋”ฐ๋ผ chord time์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ์ฝ”๋“œ ๋ณ€ํ™”๊ฐ€ ํ•œ ๋งˆ๋”” ๋‚ด์—์„œ ์—ฌ๋Ÿฌ๋ฒˆ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๊ธด ํ•˜์ง€๋งŒ ์ „๋ฐ˜์ ์œผ๋กœ ๋งˆ๋”” ๊ฐ€์žฅ ์ฒ˜์Œ 1๋ฒˆ ์ด๋ฃจ์–ด์ง„๋‹ค๋Š” ๊ฐ€์ •์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.)
    first chord๋Š” ์ฒซ Downbeat์˜ ์‹œ์ž‘์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๊ณ ์ณ์•ผํ•  ๊ฒƒ ๊ฐ™๋„ค์š”..
    """
    first_beat = beat_times[0]
    one_beat_time = beat_times[1]-beat_times[0]
    q_chord_info = []

    for chord in chord_info:
        chord_dict={}
        chord_dict['chord'] = chord['chord']
        chord_dict['start'] = float(round((chord['start']-first_beat)/one_beat_time) * one_beat_time + first_beat) # 0.2, 0.6, 1.0, 1.4 .... ๊ฐ€ ์žˆ๊ณ  chord timing์ด 1.9๋ผ๋ฉด 1.8์„ returnํ•˜๋Š” ์ฝ”๋“œ
        end_time = round((chord['end']-first_beat)/one_beat_time) * one_beat_time + first_beat
        if end_time==chord_dict['start']:
            end_time += one_beat_time
        chord_dict['end'] = float(end_time)
        q_chord_info.append(chord_dict)
    
    return q_chord_info


def save_to_json(data, filename):
    """๋ฐ์ดํ„ฐ๋ฅผ JSON ํŒŒ์ผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค."""
    with open(filename, 'w', encoding='utf-8') as file:
        # JSON ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
        json_data = jsonpickle.encode(data, unpicklable=False)
        # ํŒŒ์ผ์— ์“ฐ๊ธฐ
        file.write(json_data)