asigalov61 commited on
Commit
81a0ada
·
verified ·
1 Parent(s): c0864d1

Upload TMIDIX.py

Browse files
Files changed (1) hide show
  1. TMIDIX.py +266 -12
TMIDIX.py CHANGED
@@ -14,14 +14,14 @@ r'''############################################################################
14
  #
15
  # Project Los Angeles
16
  #
17
- # Tegridy Code 2021
18
  #
19
  # https://github.com/Tegridy-Code/Project-Los-Angeles
20
  #
21
  #
22
  ###################################################################################
23
  ###################################################################################
24
- # Copyright 2021 Project Los Angeles / Tegridy Code
25
  #
26
  # Licensed under the Apache License, Version 2.0 (the "License");
27
  # you may not use this file except in compliance with the License.
@@ -9552,15 +9552,20 @@ MOOD_SCALES = ['Major', 'Minor', 'Major Minor']
9552
  ###################################################################################
9553
 
9554
  def alpha_str(string):
9555
- return re.sub(r'[^a-zA-Z ()]', '', string).strip()
 
9556
 
9557
  ###################################################################################
9558
 
9559
- def escore_notes_to_text_description(escore_notes, song_name='', artist_name=''):
 
 
 
 
9560
 
9561
  #==============================================================================
9562
 
9563
- song_time_min = (escore_notes[-1][1] * 16) / 1000 / 60
9564
 
9565
  if song_time_min < 1.5:
9566
  song_length = 'short'
@@ -9592,10 +9597,16 @@ def escore_notes_to_text_description(escore_notes, song_name='', artist_name='')
9592
 
9593
  #==============================================================================
9594
 
9595
- patches = sorted(set([e[6] for e in escore_notes]))
 
 
9596
 
9597
  instruments = [alpha_str(Number2patch[p]) for p in patches if p < 128]
9598
 
 
 
 
 
9599
  if 128 in patches:
9600
  drums_present = True
9601
 
@@ -9641,22 +9652,22 @@ def escore_notes_to_text_description(escore_notes, song_name='', artist_name='')
9641
 
9642
  escore_averages = escore_notes_averages(escore_notes, return_ptcs_and_vels=True)
9643
 
9644
- if escore_averages[0] < 8:
9645
  rythm = 'fast'
9646
 
9647
- elif 8 <= escore_averages[0] <= 12:
9648
  rythm = 'average'
9649
 
9650
- elif escore_averages[0] > 12:
9651
  rythm = 'slow'
9652
 
9653
- if escore_averages[1] < 16:
9654
  tempo = 'fast'
9655
 
9656
- elif 16 <= escore_averages[1] <= 24:
9657
  tempo = 'average'
9658
 
9659
- elif escore_averages[1] > 24:
9660
  tempo = 'slow'
9661
 
9662
  if escore_averages[2] < 50:
@@ -9740,10 +9751,20 @@ def escore_notes_to_text_description(escore_notes, song_name='', artist_name='')
9740
 
9741
  description += '\n'
9742
 
 
 
 
 
 
 
 
 
9743
  if drums_present and most_common_drums:
9744
  description += 'The drum track has predominant '
9745
  description += ', '.join(most_common_drums[:-1]) + ' and ' + most_common_drums[-1] + '.'
9746
 
 
 
9747
  #==============================================================================
9748
 
9749
  return description
@@ -10065,6 +10086,239 @@ CONTROL_CHANGES = {
10065
  127: "Poly Mode On", # + mono off, +all notes off
10066
  }
10067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10068
  ###################################################################################
10069
  #
10070
  # This is the end of the TMIDI X Python module
 
14
  #
15
  # Project Los Angeles
16
  #
17
+ # Tegridy Code 2024
18
  #
19
  # https://github.com/Tegridy-Code/Project-Los-Angeles
20
  #
21
  #
22
  ###################################################################################
23
  ###################################################################################
24
+ # Copyright 2024 Project Los Angeles / Tegridy Code
25
  #
26
  # Licensed under the Apache License, Version 2.0 (the "License");
27
  # you may not use this file except in compliance with the License.
 
9552
  ###################################################################################
9553
 
9554
  def alpha_str(string):
9555
+ astr = re.sub(r'[^a-zA-Z ()]', '', string).strip()
9556
+ return re.sub(r'\s+', ' ', astr).strip()
9557
 
9558
  ###################################################################################
9559
 
9560
+ def escore_notes_to_text_description(escore_notes,
9561
+ song_name='',
9562
+ artist_name='',
9563
+ timings_divider=16,
9564
+ ):
9565
 
9566
  #==============================================================================
9567
 
9568
+ song_time_min = (escore_notes[-1][1] * timings_divider) / 1000 / 60
9569
 
9570
  if song_time_min < 1.5:
9571
  song_length = 'short'
 
9597
 
9598
  #==============================================================================
9599
 
9600
+ all_patches = [e[6] for e in escore_notes]
9601
+
9602
+ patches = ordered_set(all_patches)
9603
 
9604
  instruments = [alpha_str(Number2patch[p]) for p in patches if p < 128]
9605
 
9606
+ nd_patches_counts = Counter([p for p in all_patches if p < 128]).most_common()
9607
+
9608
+ dominant_instrument = alpha_str(Number2patch[nd_patches_counts[0][0]])
9609
+
9610
  if 128 in patches:
9611
  drums_present = True
9612
 
 
9652
 
9653
  escore_averages = escore_notes_averages(escore_notes, return_ptcs_and_vels=True)
9654
 
9655
+ if escore_averages[0] < (128 / timings_divider):
9656
  rythm = 'fast'
9657
 
9658
+ elif (128 / timings_divider) <= escore_averages[0] <= (192 / timings_divider):
9659
  rythm = 'average'
9660
 
9661
+ elif escore_averages[0] > (192 / timings_divider):
9662
  rythm = 'slow'
9663
 
9664
+ if escore_averages[1] < (256 / timings_divider):
9665
  tempo = 'fast'
9666
 
9667
+ elif (256 / timings_divider) <= escore_averages[1] <= (384 / timings_divider):
9668
  tempo = 'average'
9669
 
9670
+ elif escore_averages[1] > (384 / timings_divider):
9671
  tempo = 'slow'
9672
 
9673
  if escore_averages[2] < 50:
 
9751
 
9752
  description += '\n'
9753
 
9754
+ description += 'The song starts with ' + instruments[0] + '.'
9755
+
9756
+ description += '\n'
9757
+
9758
+ description += 'The song main instrument is ' + dominant_instrument + '.'
9759
+
9760
+ description += '\n'
9761
+
9762
  if drums_present and most_common_drums:
9763
  description += 'The drum track has predominant '
9764
  description += ', '.join(most_common_drums[:-1]) + ' and ' + most_common_drums[-1] + '.'
9765
 
9766
+ description += '\n'
9767
+
9768
  #==============================================================================
9769
 
9770
  return description
 
10086
  127: "Poly Mode On", # + mono off, +all notes off
10087
  }
10088
 
10089
+ ###################################################################################
10090
+
10091
+ def patches_onset_times(escore_notes, times_idx=1, patches_idx=6):
10092
+
10093
+ patches = [e[patches_idx] for e in escore_notes]
10094
+
10095
+ patches_oset = ordered_set(patches)
10096
+
10097
+ patches_onset_times = []
10098
+
10099
+ for p in patches_oset:
10100
+ for e in escore_notes:
10101
+ if e[patches_idx] == p:
10102
+ patches_onset_times.append([p, e[times_idx]])
10103
+ break
10104
+
10105
+ return patches_onset_times
10106
+
10107
+ ###################################################################################
10108
+
10109
+ def count_escore_notes_patches(escore_notes, patches_idx=6):
10110
+
10111
+ patches = [e[patches_idx] for e in escore_notes]
10112
+
10113
+ return Counter(patches).most_common()
10114
+
10115
+ ###################################################################################
10116
+
10117
+ def escore_notes_monoponic_melodies(escore_notes,
10118
+ bad_notes_ratio=0.0,
10119
+ times_idx=1,
10120
+ patches_idx=6
10121
+ ):
10122
+
10123
+ patches = escore_notes_patches(escore_notes, patches_index=patches_idx)
10124
+
10125
+ monophonic_melodies = []
10126
+
10127
+ for p in patches:
10128
+ patch_score = [e for e in escore_notes if e[patches_idx] == p]
10129
+
10130
+ ps_times = [e[times_idx] for e in patch_score]
10131
+
10132
+ if len(ps_times) <= len(set(ps_times)) * (1+bad_notes_ratio):
10133
+ monophonic_melodies.append([p, len(patch_score)])
10134
+
10135
+ return monophonic_melodies
10136
+
10137
+ ###################################################################################
10138
+
10139
+ from itertools import groupby
10140
+ from operator import itemgetter
10141
+
10142
+ def group_by_threshold(data, threshold, groupby_idx):
10143
+
10144
+ data.sort(key=itemgetter(groupby_idx))
10145
+
10146
+ grouped_data = []
10147
+ cluster = []
10148
+
10149
+ for i, item in enumerate(data):
10150
+ if not cluster:
10151
+ cluster.append(item)
10152
+ elif abs(item[groupby_idx] - cluster[-1][groupby_idx]) <= threshold:
10153
+ cluster.append(item)
10154
+ else:
10155
+ grouped_data.append(cluster)
10156
+ cluster = [item]
10157
+
10158
+ if cluster:
10159
+ grouped_data.append(cluster)
10160
+
10161
+ return grouped_data
10162
+
10163
+ ###################################################################################
10164
+
10165
+ def split_escore_notes_by_time(escore_notes, time_threshold=256):
10166
+
10167
+ dscore = delta_score_notes(escore_notes, timings_clip_value=time_threshold-1)
10168
+
10169
+ score_chunks = []
10170
+
10171
+ ctime = 0
10172
+ pchunk_idx = 0
10173
+
10174
+ for i, e in enumerate(dscore):
10175
+
10176
+ ctime += e[1]
10177
+
10178
+ if ctime >= time_threshold:
10179
+ score_chunks.append(escore_notes[pchunk_idx:i])
10180
+ pchunk_idx = i
10181
+ ctime = 0
10182
+
10183
+ return score_chunks
10184
+
10185
+ ###################################################################################
10186
+
10187
+ def escore_notes_grouped_patches(escore_notes, time_threshold=256):
10188
+
10189
+ split_score_chunks = split_escore_notes_by_time(escore_notes,
10190
+ time_threshold=time_threshold
10191
+ )
10192
+
10193
+ chunks_patches = []
10194
+
10195
+ for s in split_score_chunks:
10196
+ chunks_patches.append(escore_notes_patches(s))
10197
+
10198
+ return chunks_patches
10199
+
10200
+ ###################################################################################
10201
+
10202
+ def computeLPSArray(pattern, M, lps):
10203
+ length = 0
10204
+ i = 1
10205
+
10206
+ lps[0] = 0
10207
+
10208
+ while i < M:
10209
+ if pattern[i] == pattern[length]:
10210
+ length += 1
10211
+ lps[i] = length
10212
+ i += 1
10213
+ else:
10214
+ if length != 0:
10215
+ length = lps[length-1]
10216
+ else:
10217
+ lps[i] = 0
10218
+ i += 1
10219
+
10220
+ ###################################################################################
10221
+
10222
+ def find_pattern_idxs(sub_pattern, pattern):
10223
+
10224
+ lst = pattern
10225
+ pattern = sub_pattern
10226
+
10227
+ M = len(pattern)
10228
+ N = len(lst)
10229
+
10230
+ lps = [0] * M
10231
+ j = 0 # index for pattern[]
10232
+
10233
+ computeLPSArray(pattern, M, lps)
10234
+
10235
+ i = 0 # index for lst[]
10236
+ indexes = []
10237
+
10238
+ while i < N:
10239
+ if pattern[j] == lst[i]:
10240
+ i += 1
10241
+ j += 1
10242
+
10243
+ if j == M:
10244
+ end_index = i - 1
10245
+ start_index = end_index - M + 1
10246
+ indexes.append((start_index, end_index))
10247
+ j = lps[j-1]
10248
+ elif i < N and pattern[j] != lst[i]:
10249
+ if j != 0:
10250
+ j = lps[j-1]
10251
+ else:
10252
+ i += 1
10253
+
10254
+ return indexes
10255
+
10256
+ ###################################################################################
10257
+
10258
+ def escore_notes_patch_lrno_patterns(escore_notes,
10259
+ patch=0,
10260
+ zero_score_timings=False,
10261
+ pitches_idx=4,
10262
+ patches_idx=6
10263
+ ):
10264
+
10265
+ patch_escore = [e for e in escore_notes if e[patches_idx] == patch]
10266
+
10267
+ if patch_escore:
10268
+
10269
+ patch_cscore = chordify_score([1000, patch_escore])
10270
+
10271
+ patch_tscore = []
10272
+
10273
+ for c in patch_cscore:
10274
+
10275
+ tones_chord = sorted(set([p[pitches_idx] % 12 for p in c]))
10276
+
10277
+ if tones_chord not in ALL_CHORDS_SORTED:
10278
+ tnoes_chord = check_and_fix_tones_chord(tones_chord)
10279
+
10280
+ patch_tscore.append(ALL_CHORDS_SORTED.index(tones_chord))
10281
+
10282
+ pattern = find_lrno_pattern_fast(patch_tscore)
10283
+
10284
+ patterns_idxs = find_pattern_idxs(pattern, patch_tscore)
10285
+
10286
+ patch_lrno_scores = []
10287
+
10288
+ for idxs in patterns_idxs:
10289
+
10290
+ score = patch_escore[idxs[0]:idxs[1]]
10291
+
10292
+ if zero_score_timings:
10293
+ score = recalculate_score_timings(score)
10294
+
10295
+ patch_lrno_scores.append(score)
10296
+
10297
+ return patch_lrno_scores
10298
+
10299
+ else:
10300
+ return []
10301
+
10302
+ ###################################################################################
10303
+
10304
+ ALL_BASE_CHORDS_SORTED = [[0], [0, 2], [0, 2, 4], [0, 2, 4, 6], [0, 2, 4, 6, 8], [0, 2, 4, 6, 8, 10],
10305
+ [0, 2, 4, 6, 9], [0, 2, 4, 6, 10], [0, 2, 4, 7], [0, 2, 4, 7, 9],
10306
+ [0, 2, 4, 7, 10], [0, 2, 4, 8], [0, 2, 4, 8, 10], [0, 2, 4, 9], [0, 2, 4, 10],
10307
+ [0, 2, 5], [0, 2, 5, 7], [0, 2, 5, 7, 9], [0, 2, 5, 7, 10], [0, 2, 5, 8],
10308
+ [0, 2, 5, 8, 10], [0, 2, 5, 9], [0, 2, 5, 10], [0, 2, 6], [0, 2, 6, 8],
10309
+ [0, 2, 6, 8, 10], [0, 2, 6, 9], [0, 2, 6, 10], [0, 2, 7], [0, 2, 7, 9],
10310
+ [0, 2, 7, 10], [0, 2, 8], [0, 2, 8, 10], [0, 2, 9], [0, 2, 10], [0, 3],
10311
+ [0, 3, 5], [0, 3, 5, 7], [0, 3, 5, 7, 9], [0, 3, 5, 7, 10], [0, 3, 5, 8],
10312
+ [0, 3, 5, 8, 10], [0, 3, 5, 9], [0, 3, 5, 10], [0, 3, 6], [0, 3, 6, 8],
10313
+ [0, 3, 6, 8, 10], [0, 3, 6, 9], [0, 3, 6, 10], [0, 3, 7], [0, 3, 7, 9],
10314
+ [0, 3, 7, 10], [0, 3, 8], [0, 3, 8, 10], [0, 3, 9], [0, 3, 10], [0, 4],
10315
+ [0, 4, 6], [0, 4, 6, 8], [0, 4, 6, 8, 10], [0, 4, 6, 9], [0, 4, 6, 10],
10316
+ [0, 4, 7], [0, 4, 7, 9], [0, 4, 7, 10], [0, 4, 8], [0, 4, 8, 10], [0, 4, 9],
10317
+ [0, 4, 10], [0, 5], [0, 5, 7], [0, 5, 7, 9], [0, 5, 7, 10], [0, 5, 8],
10318
+ [0, 5, 8, 10], [0, 5, 9], [0, 5, 10], [0, 6], [0, 6, 8], [0, 6, 8, 10],
10319
+ [0, 6, 9], [0, 6, 10], [0, 7], [0, 7, 9], [0, 7, 10], [0, 8], [0, 8, 10],
10320
+ [0, 9], [0, 10]]
10321
+
10322
  ###################################################################################
10323
  #
10324
  # This is the end of the TMIDI X Python module