Beispiel #1
0
    def __init__(self, melody_pattern_data, continuous_bar_data):

        self.input_data = []  # 输入model的数据
        self.output_data = []  # 从model输出的数据

        # 1.从数据集中读取鼓点,
        raw_drum_data = get_raw_song_data_from_dataset('drum', None)
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_drum_data[song_it] != dict():
                raw_drum_data[song_it] = flat_array(raw_drum_data[song_it])
            else:
                raw_drum_data[song_it] = []  # 对于没有鼓点的歌曲,将格式转化为list格式

        # 2.获取最常见的鼓点组合
        common_pattern_cls = CommonMusicPatterns(COMMON_DRUM_PAT_NUM)
        common_pattern_cls.train(raw_drum_data, 0.125, 2)
        common_pattern_cls.store('drum')
        self.common_drum_pats = common_pattern_cls.common_pattern_list

        # 3.生成输入输出数据
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_drum_data[song_it] and melody_pattern_data[song_it]:
                # 3.1.将一首歌的鼓点编码为常见的鼓点组合。如果该鼓点组合不常见,则记为common_drum_patterns+1
                drum_pat_data = DrumPatternEncode(self.common_drum_pats,
                                                  raw_drum_data[song_it],
                                                  0.125, 2).music_pattern_list
                # 3.2.生成训练数据 输入内容是当前时间的编码 最近两小节+一个时间步长的主旋律和前两小节的鼓点 输出内容是这个时间步长的鼓点
                self.get_model_io_data(drum_pat_data,
                                       melody_pattern_data[song_it],
                                       continuous_bar_data[song_it])

        DiaryLog.warn('Generation of drum train data has finished!')
Beispiel #2
0
 def train(self,
           raw_music_data,
           note_time_step,
           pattern_time_step,
           multipart=False):
     """
     获取最常见的number种旋律组合
     :param multipart: 一首歌的一种表现手法是否有多个part
     :param raw_music_data: 一首歌一个音轨的数据
     :param note_time_step: 音符的时间步长
     :param pattern_time_step: 旋律组合的时间步长
     :return: 最常见的旋律组合
     """
     # :param unit: 以小节为单元还是以音符步长为单元
     common_pattern_dic = {}
     time_step_ratio = round(pattern_time_step / note_time_step)
     # 1.准备:如果一首歌的这种表现手法是否有多个part,将数据降一阶
     if multipart is False:  # 一首歌的这种表现手法是否有多个part,
         music_data = copy.deepcopy(raw_music_data)
     else:
         music_data = flat_array(raw_music_data)
     # 2.将所有的歌的这种表现手法以一定的步长分组,对每一组的音符组合进行编码,并计数
     for song_it in range(
             len(music_data)):  # 注意这里不是TRAIN_FILE_NUMBERS,因为可能是multipart
         if len(music_data[song_it]) != 0:
             # if unit == 'bar':  # 将以小节为单元的数组转成以音符时间步长为单元的数组
             #     music_data[song_it] = flat_array(music_data[song_it])
             beat_num = len(music_data[song_it]) * note_time_step  # 这首歌有多少拍
             try:
                 raw_data_in_1pat = [
                     music_data[song_it][time_step_ratio *
                                         t:time_step_ratio * (t + 1)]
                     for t in range(round(beat_num / pattern_time_step))
                 ]  # 将这首歌以pattern_time_step为步长进行分割
                 for music_pattern in raw_data_in_1pat:
                     try:
                         common_pattern_dic[str(music_pattern)] += 1
                     except KeyError:
                         common_pattern_dic[str(music_pattern)] = 1
             except KeyError:
                 pass
     # 3.截取最常见的多少种组合。按照组合的出现次数由高到底排序
     common_pattern_list_temp = sorted(common_pattern_dic.items(),
                                       key=lambda asd: asd[1],
                                       reverse=True)
     self.not_empty_pat_cnt = 0
     self.common_pat_cnt = 0
     for t in common_pattern_list_temp[1:]:
         self.not_empty_pat_cnt += t[1]
     for t in common_pattern_list_temp[1:(self.pattern_number + 1)]:
         self.common_pat_cnt += t[1]
     self.common_pattern_list = []
     self.pattern_number_list = []
     for pattern_tuple in common_pattern_list_temp[:(self.pattern_number +
                                                     1)]:
         self.common_pattern_list.append(eval(pattern_tuple[0]))
         self.pattern_number_list.append(pattern_tuple[1])
Beispiel #3
0
    def __init__(self, raw_melody_data, melody_pat_data, common_melody_pats,
                 section_data, continuous_bar_data):

        self.input_data = []  # 输入model的数据
        self.output_data = []  # 从model输出的数据

        self.ShiftConfidence = IntroShiftConfidenceCheck()

        # 1.从数据集中读取intro/interlude信息,并变更为以音符步长为单位的列表
        raw_intro_data = get_raw_song_data_from_dataset('intro')
        raw_interlude_data = get_raw_song_data_from_dataset('interlude')
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_intro_data[song_it] != dict():
                raw_intro_data[song_it] = flat_array(raw_intro_data[song_it])
            else:
                raw_intro_data[song_it] = [
                ]  # 对于没有intro/interlude的歌曲,将格式转化为list格式
            if raw_interlude_data[song_it] != dict():
                raw_interlude_data[song_it] = flat_array(
                    raw_interlude_data[song_it])
            else:
                raw_interlude_data[song_it] = []

        # 2.对数据进行处理,调整前奏/间奏音符的音高 防止出现前奏/间奏和主旋律音高差异过大的问题
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_intro_data[song_it] and raw_melody_data[song_it]:
                raw_intro_data[song_it] = adjust_intro_pitch(
                    raw_melody_data[song_it], raw_intro_data[song_it])
            if raw_interlude_data[song_it] and raw_melody_data[song_it]:
                raw_interlude_data[song_it] = adjust_intro_pitch(
                    raw_melody_data[song_it], raw_interlude_data[song_it])

        # 3.生成每首歌的旋律变化累积幅度数据
        # 3.1.生成每段前奏/间奏的音高变化情况
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_intro_data[song_it]:
                self.ShiftConfidence.train_1song(
                    raw_melody_data=raw_melody_data[song_it],
                    raw_intro_data=raw_intro_data[song_it],
                    continuous_bar_data=continuous_bar_data[song_it])
            if raw_interlude_data[song_it]:
                self.ShiftConfidence.train_1song(
                    raw_melody_data=raw_melody_data[song_it],
                    raw_intro_data=raw_interlude_data[song_it],
                    continuous_bar_data=continuous_bar_data[song_it])
        # 3.2.找出旋律变化和段落内差异前90%所在位置
        self.ShiftConfidence.calc_confidence_level(0.9)
        self.ShiftConfidence.store('intro_shift')

        # 4.获取前奏模型的输入输出数据
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_intro_data[song_it] and melody_pat_data[song_it]:
                intro_pat_data = MelodyPatternEncode(common_melody_pats,
                                                     raw_intro_data[song_it],
                                                     0.125,
                                                     1).music_pattern_list
                self.get_intro_model_io_data(intro_pat_data,
                                             melody_pat_data[song_it],
                                             continuous_bar_data[song_it],
                                             section_data[song_it])

        # 5.获取间奏模型的输入输出数据
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_interlude_data[song_it] and melody_pat_data[song_it]:
                interlude_pat_data = MelodyPatternEncode(
                    common_melody_pats, raw_interlude_data[song_it], 0.125,
                    1).music_pattern_list  # 前奏和间奏的common patterns沿用主旋律的
                self.get_interlude_model_io_data(interlude_pat_data,
                                                 melody_pat_data[song_it],
                                                 continuous_bar_data[song_it])
        np.save(os.path.join(PATH_PATTERNLOG, 'IntroInputData.npy'),
                self.input_data)  # 在generate的时候要比较生成数据和训练集是否雷同,因此这个也要存储

        DiaryLog.warn(
            'Generation of intro and interlude train data has finished!')
Beispiel #4
0
    def __init__(self, tone_restrict=None):

        self.input_data = []  # 输入model的数据
        self.output_data = []  # 从model输出的数据

        self.continuous_bar_data = [[] for t in range(TRAIN_FILE_NUMBERS)
                                    ]  # 每一首歌连续的小节计数
        self.continuous_bar_data_nres = [[] for t in range(TRAIN_FILE_NUMBERS)
                                         ]  # 每一首歌无限制的小节计数

        self.keypress_pat_data = [[] for t in range(TRAIN_FILE_NUMBERS)
                                  ]  # 二维数组 第一维是歌曲列表 第二维是按键的组合(步长是2拍)
        self.all_keypress_pats = [[0 for t in range(16)]]  # 主旋律按键组合的对照表
        self.keypress_pat_count = [0]  # 各种按键组合的计数

        self.core_note_ary_nres = [[] for t in range(TRAIN_FILE_NUMBERS)
                                   ]  # 每一首歌每一拍的骨干音列表
        self.core_note_pat_nres = [[] for t in range(TRAIN_FILE_NUMBERS)
                                   ]  # 骨干音组合数据

        self.melody_pat_data = [[] for t in range(TRAIN_FILE_NUMBERS)
                                ]  # 有调式限制的旋律组合数据
        self.melody_pat_data_nres = [[] for t in range(TRAIN_FILE_NUMBERS)
                                     ]  # 无调式限制的旋律组合数据

        self.ShiftConfidence = ShiftConfidenceCheck()  # 计算训练集中所有歌曲相邻两小节的音高变化情况
        self.DiffNoteConfidence = DiffNoteConfidenceCheck(
        )  # 计算训练集中所有歌曲所有段落前半段和后半段的按键和音高上的差异

        # 1.从数据集中读取所有歌曲的主旋律数据,并变更为以音符步长为单位的列表
        self.raw_train_data = get_raw_song_data_from_dataset(
            'main', tone_restrict)
        self.raw_melody_data = get_raw_song_data_from_dataset(
            'main', None)  # 没有旋律限制的主旋律数据 用于训练其他数据
        self.section_data = get_section_data_from_dataset()
        for song_it in range(TRAIN_FILE_NUMBERS):
            if self.raw_train_data[song_it] != dict():
                self.raw_train_data[song_it] = flat_array(
                    self.raw_train_data[song_it])
            else:
                self.raw_train_data[song_it] = []  # 对于没有主旋律的歌曲,将格式转化为list格式
            if self.raw_melody_data[song_it] != dict():
                self.raw_melody_data[song_it] = flat_array(
                    self.raw_melody_data[song_it])
            else:
                self.raw_train_data[song_it] = []
        raw_melody_data_nres = copy.deepcopy(self.raw_melody_data)

        # 2.获取最常见的主旋律组合
        common_pattern_cls = CommonMusicPatterns(
            COMMON_MELODY_PAT_NUM)  # 这个类可以获取常见的主旋律组合
        common_pattern_cls.train(self.raw_train_data, 0.125, 1, False)
        common_pattern_cls.store('melody')  # 存储在sqlite文件中
        self.common_melody_pats = common_pattern_cls.common_pattern_list  # 常见的旋律组合列表
        self.melody_pats_num_list = common_pattern_cls.pattern_number_list  # 这些旋律组合出现的次数列表

        # 3.逐歌曲获取连续不为空的小节列表/按键数据/骨干音数据/
        for song_it in range(TRAIN_FILE_NUMBERS):
            # 3.1.获取没有调式限制的旋律数据
            if raw_melody_data_nres[song_it]:  # 获取相关没有调式限制的相关数据
                # 3.1.1.获取旋律的按键数据
                self.get_keypress_data(
                    song_it,
                    raw_melody_data_nres[song_it])  # 获取按键数据 当前有按键记为1 没有按键记为0
                # 3.1.3.将它的主旋律编码为常见的旋律组合。如果该旋律组合不常见,则记为COMMON_MELODY_PAT_NUM+1
                self.continuous_bar_data_nres[
                    song_it] = get_continuous_bar_cnt(
                        raw_melody_data_nres[song_it])
                # 3.1.2.获取骨干音及骨干音的常见组合列表
                self.core_note_ary_nres[song_it] = melody_core_note(
                    raw_melody_data_nres[song_it],
                    self.continuous_bar_data_nres[song_it],
                    self.section_data[song_it])
            # 3.2.获取有调式限制的旋律数据
            if self.raw_train_data[song_it]:
                # 3.2.1.获取歌曲的连续不为空的小节序号列表
                self.continuous_bar_data[song_it] = get_continuous_bar_cnt(
                    self.raw_train_data[song_it])
        # 3.3.存储按键数据的组合列表
        keyperss_pattern_cls = BaseMusicPatterns()
        keyperss_pattern_cls.common_pattern_list = self.all_keypress_pats
        keyperss_pattern_cls.pattern_number_list = self.keypress_pat_count
        keyperss_pattern_cls.store('keypress')

        # 4.获取无调式限制的常见骨干音组合列表
        core_note_pattern_cls = CommonMusicPatterns(COMMON_CORE_NOTE_PAT_NUM)
        core_note_pattern_cls.train(self.core_note_ary_nres, 0.125, 2)
        core_note_pattern_cls.store('core_note')  # 存储在sqlite文件中
        self.common_corenote_pats = core_note_pattern_cls.common_pattern_list  # 常见的旋律组合列表

        # 5.根据常见的音符组合,对原始的旋律音符和骨干音列表进行编码
        for song_it in range(TRAIN_FILE_NUMBERS):
            # 5.1.编码无调式限制的主旋律及其骨干音
            if raw_melody_data_nres[song_it]:  # 没有调式限制的相关数据
                self.melody_pat_data_nres[song_it] = MelodyPatternEncode(
                    self.common_melody_pats, raw_melody_data_nres[song_it],
                    0.125, 1).music_pattern_list
                self.core_note_pat_nres[song_it] = CoreNotePatternEncode(
                    self.common_corenote_pats,
                    self.core_note_ary_nres[song_it], 0.125,
                    2).music_pattern_list
            # 5.2.编码有调式限制的主旋律。如果该旋律组合不常见,则记为COMMON_MELODY_PAT_NUM+1
            if self.raw_train_data[song_it]:
                self.melody_pat_data[song_it] = MelodyPatternEncode(
                    self.common_melody_pats, self.raw_train_data[song_it],
                    0.125, 1).music_pattern_list

        # 6.生成每首歌的旋律变化累积幅度的数据
        # 6.1.生成每首歌的相邻两小节的音高变化情况,和每个段落的前半部分与后半部分的差异
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_melody_data_nres[song_it]:
                self.ShiftConfidence.train_1song(
                    raw_melody_data=raw_melody_data_nres[song_it],
                    section_data=self.section_data[song_it])
                self.DiffNoteConfidence.train_1song(
                    raw_melody_data=raw_melody_data_nres[song_it],
                    section_data=self.section_data[song_it])
        # 6.2.找出旋律变化和段落内差异前95%所在位置
        self.ShiftConfidence.calc_confidence_level(0.95)
        self.DiffNoteConfidence.calc_confidence_level(0.95)
        self.ShiftConfidence.store(
            'melody_shift')  # 把shift_confidence_level和diff_note保存到sqlite中
        self.DiffNoteConfidence.store('melody_diffnote')

        # 7.生成每首歌的训练数据
        for song_it in range(TRAIN_FILE_NUMBERS):
            if self.raw_train_data[song_it]:
                self.get_model_io_data(self.melody_pat_data[song_it],
                                       self.continuous_bar_data[song_it])
        np.save(os.path.join(PATH_PATTERNLOG, 'MelodyInputData.npy'),
                self.input_data)  # 在generate的时候要比较生成数据和训练集是否雷同,因此这个也要存储

        DiaryLog.warn('Generation of melody train data has finished!')
Beispiel #5
0
    def __init__(self, melody_pat_data, continuous_bar_data, corenote_pat_data, common_corenote_pats, chord_cls):
        """
        :param melody_pat_data: 主旋律组合的数据
        :param continuous_bar_data: 连续小节的计数数据
        :param corenote_pat_data: 主旋律骨干音的组合数据
        :param common_corenote_pats: 主旋律骨干音组合的对照表
        :param chord_cls: 0.95开始这个参数变成和弦的类而不只是最后的和弦数据 因为需要用到和弦类的方法
        """
        self.input_data = []  # 输入model的数据
        self.output_data = []  # 从model输出的数据

        # 1.从数据集中读取歌的string数据
        raw_string_data = []  # 四维数组 第一维是string的编号 第二维是歌曲id 第三维是小节列表(dict) 第四维是小节内容
        part_count = 1
        while True:
            string_part_data = get_raw_song_data_from_dataset('string' + str(part_count), None)  # 从sqlite文件中读取的数据。三维数组,第一维是歌的id,第二维是小节的id,第三维是小节内容
            if string_part_data == [dict() for t in range(TRAIN_FILE_NUMBERS)]:
                break
            raw_string_data.append(string_part_data)
            part_count += 1
        del part_count
        for part_it in range(len(raw_string_data)):
            for song_it in range(TRAIN_FILE_NUMBERS):
                if raw_string_data[part_it][song_it] != dict():
                    raw_string_data[part_it][song_it] = flat_array(raw_string_data[part_it][song_it])
                else:
                    raw_string_data[part_it][song_it] = []  # 对于没有和弦的歌曲,将格式转化为list格式

        # 2.获取根音组合及根音-和弦配对组合
        self.string_avr_root = get_nearest_number_multiple(STRING_AVR_NOTE, 12)
        self.root_data, self.rc_pat_data, self.all_rc_pats, rc_pat_count = chord_cls.get_root_data(self.string_avr_root)
        self.rc_pat_num = len(self.all_rc_pats)
        rc_pattern_cls = BaseMusicPatterns()
        rc_pattern_cls.common_pattern_list = self.all_rc_pats
        rc_pattern_cls.pattern_number_list = rc_pat_count
        rc_pattern_cls.store('StringRC')

        # 3.将原数据转化成相对音高形式
        rel_note_list = [[[] for t0 in range(TRAIN_FILE_NUMBERS)] for t in range(len(raw_string_data))]
        for part_it in range(len(raw_string_data)):
            for song_it in range(TRAIN_FILE_NUMBERS):
                if raw_string_data[part_it][song_it] and melody_pat_data[song_it]:
                    rel_note_list[part_it][song_it] = one_song_rel_notelist_chord(raw_string_data[part_it][song_it], self.root_data[song_it], chord_cls.chord_data[song_it])

        # 4.获取最常见的弦乐组合
        common_pattern_cls = CommonMusicPatterns(COMMON_STRING_PAT_NUM)  # 这个类可以获取常见的弦乐组合
        common_pattern_cls.train(rel_note_list, 0.25, 2, multipart=True)
        common_pattern_cls.store('String')  # 存储在sqlite文件中
        self.common_string_pats = common_pattern_cls.common_pattern_list  # 常见的旋律组合列表

        # 5.获取用于验证的数据
        # 5.1.生成每首歌的piano_guitar的前后段差异,以及piano_guitar与同时期和弦的差异
        string_confidence_config = StringConfidenceCheckConfig()
        self.StringConfidence = AccompanyConfidenceCheck(string_confidence_config)
        for part_it in range(len(raw_string_data)):
            for song_it in range(TRAIN_FILE_NUMBERS):
                if chord_cls.chord_data[song_it] and raw_string_data[part_it][song_it]:
                    self.StringConfidence.train_1song(raw_data=raw_string_data[part_it][song_it], chord_data=chord_cls.chord_data[song_it])
        # 5.2.找出前90%所在位置
        self.StringConfidence.calc_confidence_level(0.9)
        self.StringConfidence.store('string')

        # 6.将其编码为组合并获取模型的输入输出数据
        for part_it in range(len(raw_string_data)):
            for song_it in range(TRAIN_FILE_NUMBERS):
                if raw_string_data[part_it][song_it] and melody_pat_data[song_it]:
                    string_pat_data = StringPatternEncode(self.common_string_pats, rel_note_list[part_it][song_it], 0.25, 2).music_pattern_list
                    self.get_model_io_data(string_pat_data, melody_pat_data[song_it], continuous_bar_data[song_it], corenote_pat_data[song_it], self.rc_pat_data[song_it])

        DiaryLog.warn('Generation of string train data has finished!')
Beispiel #6
0
    def __init__(self, melody_pat_data, continuous_bar_data, keypress_pat_data,
                 all_keypress_pats, chord_cls):
        """
        :param melody_pat_data: 主旋律组合的数据
        :param continuous_bar_data: 连续小节的计数数据
        :param keypress_pat_data: 主旋律按键的组合数据
        :param all_keypress_pats: 主旋律组合的按键对照表
        :param chord_cls: 0.95开始这个参数变成和弦的类而不只是最后的和弦数据 因为需要用到和弦类的方法
        """
        self.input_data = []  # 输入model的数据
        self.output_data = []  # 从model输出的数据

        # 1.从数据集中读取bass信息,并变更为以音符步长为单位的列表
        raw_bass_data = get_raw_song_data_from_dataset('bass', None)
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_bass_data[song_it] != dict():
                raw_bass_data[song_it] = flat_array(raw_bass_data[song_it])
            else:
                raw_bass_data[song_it] = []  # 对于没有bass的歌曲,将格式转化为list格式

        # 2.获取和弦的根音组合 预期的根音平均值为36(即比中央C低2个八度)
        self.bass_avr_root = get_nearest_number_multiple(BASS_AVR_NOTE, 12)
        self.root_data, self.rc_pat_data, self.all_rc_pats, rc_pat_count = chord_cls.get_root_data(
            self.bass_avr_root)
        self.keypress_pat_num = len(all_keypress_pats)  # 一共有多少种按键组合数据(步长为2拍)
        self.rc_pat_num = len(self.all_rc_pats)
        rc_pattern_cls = BaseMusicPatterns()
        rc_pattern_cls.common_pattern_list = self.all_rc_pats
        rc_pattern_cls.pattern_number_list = rc_pat_count
        rc_pattern_cls.store('BassRC')

        # 3.将原bass数据转化成相对音高形式
        rel_note_list = [[] for t in range(TRAIN_FILE_NUMBERS)]
        for song_it in range(TRAIN_FILE_NUMBERS):
            if raw_bass_data[song_it]:
                rel_note_list[song_it] = one_song_rel_notelist_chord(
                    raw_bass_data[song_it],
                    self.root_data[song_it],
                    chord_cls.chord_data[song_it],
                    note_time_step=0.125)

        # 4.获取最常见的Bass组合
        common_pattern_cls = CommonMusicPatterns(
            COMMON_BASS_PAT_NUM)  # 这个类可以获取常见的bass组合
        common_pattern_cls.train(rel_note_list, 0.125, 2, multipart=False)
        common_pattern_cls.store('Bass')  # 存储在sqlite文件中
        self.common_bass_pats = common_pattern_cls.common_pattern_list  # 常见的bass组合列表

        # 5.获取用于验证的数据
        # 5.1.生成每首歌的bass的前后段差异,以及bass与同时期和弦的差异
        bass_confidence_config = BassConfidenceCheckConfig()
        self.BassConfidence = AccompanyConfidenceCheck(bass_confidence_config)
        for song_it in range(TRAIN_FILE_NUMBERS):
            if chord_cls.chord_data[song_it] and raw_bass_data[song_it]:
                self.BassConfidence.train_1song(
                    raw_data=raw_bass_data[song_it],
                    chord_data=chord_cls.chord_data[song_it])
        # 5.2.找出前90%所在位置
        self.BassConfidence.calc_confidence_level(0.9)
        self.BassConfidence.store('bass')

        # 6.获取模型的输入输出数据
        for song_it in range(TRAIN_FILE_NUMBERS):
            if rel_note_list[song_it] and melody_pat_data[song_it]:
                bass_pat_data = BassPatternEncode(self.common_bass_pats,
                                                  rel_note_list[song_it],
                                                  0.125, 2).music_pattern_list
                self.get_model_io_data(bass_pat_data, melody_pat_data[song_it],
                                       continuous_bar_data[song_it],
                                       keypress_pat_data[song_it],
                                       self.rc_pat_data[song_it])

        DiaryLog.warn('Generation of bass train data has finished!')
Beispiel #7
0
    def __init__(self, raw_melody_data, section_data, continuous_bar_data):

        # 1.从数据集中读取歌的加花数据,并变更为以音符步长为单位的列表
        raw_fill_data = [
        ]  # 四维数组 第一维是piano_guitar的编号 第二维是歌曲id 第三维是小节列表(dict) 第四维是小节内容
        part_count = 1
        song_bpm_list = get_bpm_list()  # 歌曲的调式信息
        while True:
            fill_part_data = get_raw_song_data_from_dataset(
                'fill' + str(part_count),
                None)  # 从sqlite文件中读取的数据。三维数组,第一维是歌的id,第二维是小节的id,第三维是小节内容
            if fill_part_data == [dict() for t in range(TRAIN_FILE_NUMBERS)]:
                break
            raw_fill_data.append(fill_part_data)
            part_count += 1
        del part_count
        for part_it in range(len(raw_fill_data)):
            for song_it in range(TRAIN_FILE_NUMBERS):
                if raw_fill_data[part_it][song_it] != dict():
                    raw_fill_data[part_it][song_it] = flat_array(
                        raw_fill_data[part_it][song_it])
                else:
                    raw_fill_data[part_it][song_it] = [
                    ]  # 对于没有和弦的歌曲,将格式转化为list格式

        # 2.对加花数据进行分类和组合,分成过渡型、强调型、补充型三种。组合取全部的,而不只取最常见的
        self.fill_type_pat_cls = FillClassifyAndPats(
            len(raw_fill_data))  # 记录加花数据的分类和组合
        # fill_type_data = [[[] for t1 in range(TRAIN_FILE_NUMBERS)] for t0 in range(part_count)]
        for fill_part_it, fill_part in enumerate(
                raw_fill_data):  # 将绝对音高转变为相对音高
            for song_it in range(TRAIN_FILE_NUMBERS):
                self.fill_type_pat_cls.run_1song(fill_part_it, song_it,
                                                 fill_part[song_it],
                                                 raw_melody_data[song_it],
                                                 song_bpm_list[song_it])
        self.fill_type_pat_cls.store()

        # 3.对于前一拍无加花的情况,本拍是否加花
        self.all_fill_ary = [0 for t in range(4)]
        self.keypress_fill_ary = np.zeros((4, 16),
                                          dtype=np.int32)  # 主旋律按键情况对应加花的频数
        self.timecode_fill_ary = np.zeros(
            (4, 8),
            dtype=np.int32)  # 时间编码对应加花的频数(最大值8。0-4为非过渡小节的时间编码 5-8为过渡小节的时间编码)
        self.sec_nfill_ary = np.zeros((3, 6),
                                      dtype=np.int32)  # 本段落此前的加花概率对应此拍不加花的频数
        self.sameinsec_fill_ary = np.zeros(
            (3, 6), dtype=np.int32)  # 本段落此前的加花概率对应此拍同种类型加花的频数
        for fill_part_it, fill_part in enumerate(
                raw_fill_data):  # 将绝对音高转变为相对音高
            for song_it in range(TRAIN_FILE_NUMBERS):
                self.cal_fill_freq(
                    self.fill_type_pat_cls.classify_data[fill_part_it]
                    [song_it], raw_melody_data[song_it], section_data[song_it],
                    continuous_bar_data[song_it])
        np.save(os.path.join(PATH_PATTERNLOG, 'FillTotalCount.npy'),
                self.all_fill_ary)
        np.save(os.path.join(PATH_PATTERNLOG, 'FillKeypressCount.npy'),
                self.keypress_fill_ary)
        np.save(os.path.join(PATH_PATTERNLOG, 'FillTimecodeCount.npy'),
                self.timecode_fill_ary)
        np.save(os.path.join(PATH_PATTERNLOG, 'FillSecNCount.npy'),
                self.sec_nfill_ary)
        np.save(os.path.join(PATH_PATTERNLOG, 'FillSecYCount.npy'),
                self.sameinsec_fill_ary)

        # 5.对于前一拍有加花的情况,本拍是否加花
        self.all_fill_rep_ary = [
            0 for t in range(6)
        ]  # 六个数分别是上一拍的加花内容为第一类/第二类/第三类,本拍不延续;上一拍的加花内容为第一类/第二类/第三类,本拍延续
        self.keypress_fill_rep_ary = np.zeros((6, 16),
                                              dtype=np.int32)  # 主旋律按键情况对应加花的频数
        self.timecode_fill_rep_ary = np.zeros(
            (6, 32),
            dtype=np.int32)  # 加花已延续拍数和时间编码对应加花的频数(高两位为加花已延续拍数-1,低三位为时间编码)
        for fill_part_it, fill_part in enumerate(
                raw_fill_data):  # 将绝对音高转变为相对音高
            for song_it in range(TRAIN_FILE_NUMBERS):
                self.cal_fill_freq_repeat(
                    self.fill_type_pat_cls.classify_data[fill_part_it]
                    [song_it], raw_melody_data[song_it], section_data[song_it],
                    continuous_bar_data[song_it])
        np.save(os.path.join(PATH_PATTERNLOG, 'FillRepTotalCount.npy'),
                self.all_fill_rep_ary)
        np.save(os.path.join(PATH_PATTERNLOG, 'FillRepKeypressCount.npy'),
                self.keypress_fill_rep_ary)
        np.save(os.path.join(PATH_PATTERNLOG, 'FillRepTimecodeCount.npy'),
                self.timecode_fill_rep_ary)

        DiaryLog.warn('Generation of fill train data has finished!')
Beispiel #8
0
    def __init__(self, melody_pat_data, raw_melody_data, continuous_bar_data,
                 core_note_pat_data):

        self.input_data = []  # 输入model的数据
        self.output_data = []  # 从model输出的数据

        self.transfer_count = np.zeros(
            [COMMON_CORE_NOTE_PAT_NUM * 2 + 2,
             len(CHORD_LIST) + 1],
            dtype=np.float32
        ) + np.e**(
            -3
        )  # 主旋律/调式与同时期和弦的转移矩阵 0是空主旋律 1-400是大调对应的主旋律 401-800是小调对应的主旋律 801对应的是罕见主旋律
        self.real_transfer_count = np.zeros(
            [COMMON_CORE_NOTE_PAT_NUM * 2 + 2,
             len(CHORD_LIST) + 1],
            dtype=np.float32)  # 主旋律/调式与同时期和弦的转移矩阵 与上个变量的区别是不添加e**(-3)
        self.transfer = np.zeros(
            [COMMON_CORE_NOTE_PAT_NUM * 2 + 2,
             len(CHORD_LIST) + 1],
            dtype=np.float32
        )  # 主旋律/调式与同时期和弦 概率取对数后的转移矩阵 这个转移矩阵的数字精度必须是float32的

        # 1.从数据集中读取所有歌曲的和弦数据,并变更为以音符步长为单位的列表
        self.chord_data = get_raw_song_data_from_dataset(
            'chord', None)  # 从sqlite文件中读取的数据。三维数组,第一维是歌的id,第二维是小节的id,第三维是小节内容
        for song_it in range(TRAIN_FILE_NUMBERS):
            if self.chord_data[song_it] != dict():
                self.chord_data[song_it] = flat_array(self.chord_data[song_it])
            else:
                self.chord_data[song_it] = []  # 对于没有和弦的歌曲,将格式转化为list格式

        # 2.和弦数据以1拍为单位存储,但在训练时以2拍为单位。因此逐两拍生成和弦-和弦组合
        cc_pat_data, self.all_cc_pats, cc_pat_count = get_chord_chord_pattern(
            self.chord_data)  # 和弦-和弦组合
        self.cc_pat_num = len(self.all_cc_pats)
        cc_pattern_cls = BaseMusicPatterns()
        cc_pattern_cls.common_pattern_list = self.all_cc_pats
        cc_pattern_cls.pattern_number_list = cc_pat_count
        cc_pattern_cls.store('ChordChord')

        # 3.获取并保存主旋律与同时期和弦的状态转移矩阵
        # 3.1.获取和弦的状态转移矩阵
        tone_list = get_tone_list()  # 获取训练用曲的旋律列表
        for song_it in range(TRAIN_FILE_NUMBERS):
            if self.chord_data[song_it] and melody_pat_data[song_it]:
                self.freq_count(self.chord_data[song_it],
                                core_note_pat_data[song_it],
                                tone_list[song_it])
        # 3.2.保存和弦的状态转移矩阵
        np.save(os.path.join(PATH_PATTERNLOG, 'ChordTransferCount.npy'),
                self.transfer_count)
        np.save(os.path.join(PATH_PATTERNLOG, 'ChordTransferCountReal.npy'),
                self.real_transfer_count)

        # 4.生成输入输出数据
        for song_it in range(TRAIN_FILE_NUMBERS):
            if self.chord_data[song_it] and melody_pat_data[song_it]:
                self.get_model_io_data(cc_pat_data[song_it],
                                       melody_pat_data[song_it],
                                       continuous_bar_data[song_it])

        DiaryLog.warn('Generation of chord train data has finished!')