asigalov61 commited on
Commit
0ed666d
·
verified ·
1 Parent(s): 3dead54

Upload TMIDIX.py

Browse files
Files changed (1) hide show
  1. TMIDIX.py +199 -1
TMIDIX.py CHANGED
@@ -51,7 +51,7 @@ r'''############################################################################
51
 
52
  ###################################################################################
53
 
54
- __version__ = "26.4.13"
55
 
56
  print('=' * 70)
57
  print('TMIDIX Python module')
@@ -18321,6 +18321,204 @@ def rle_toks_to_binary_matrix(rle_toks,
18321
 
18322
  ###################################################################################
18323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18324
  print('Module loaded!')
18325
  print('=' * 70)
18326
  print('Enjoy! :)')
 
51
 
52
  ###################################################################################
53
 
54
+ __version__ = "26.4.15"
55
 
56
  print('=' * 70)
57
  print('TMIDIX Python module')
 
18321
 
18322
  ###################################################################################
18323
 
18324
+ class SAM:
18325
+ def __init__(self):
18326
+ self.len = [0]
18327
+ self.link = [-1]
18328
+ self.next = [dict()]
18329
+ self.last = 0
18330
+
18331
+ def add(self, c):
18332
+ cur = len(self.len)
18333
+ self.len.append(self.len[self.last] + 1)
18334
+ self.link.append(0)
18335
+ self.next.append(dict())
18336
+ p = self.last
18337
+ while p != -1 and c not in self.next[p]:
18338
+ self.next[p][c] = cur
18339
+ p = self.link[p]
18340
+ if p == -1:
18341
+ self.link[cur] = 0
18342
+ else:
18343
+ q = self.next[p][c]
18344
+ if self.len[p] + 1 == self.len[q]:
18345
+ self.link[cur] = q
18346
+ else:
18347
+ clone = len(self.len)
18348
+ self.len.append(self.len[p] + 1)
18349
+ self.link.append(self.link[q])
18350
+ self.next.append(self.next[q].copy())
18351
+ while p != -1 and self.next[p].get(c) == q:
18352
+ self.next[p][c] = clone
18353
+ p = self.link[p]
18354
+ self.link[q] = self.link[cur] = clone
18355
+ self.last = cur
18356
+
18357
+ ###################################################################################
18358
+
18359
+ def common_subpatterns(lists):
18360
+ if not lists:
18361
+ return []
18362
+ # Build SAM from first list
18363
+ sam = SAM()
18364
+ for x in lists[0]:
18365
+ sam.add(x)
18366
+
18367
+ m = len(sam.len)
18368
+ # For each state, store minimal matched length across all other lists
18369
+ min_match = [sam.len[i] for i in range(m)]
18370
+
18371
+ # For each other list, compute for every state the longest match ending at that state
18372
+ for arr in lists[1:]:
18373
+ cur = 0
18374
+ l = 0
18375
+ best = [0]*m
18376
+ for x in arr:
18377
+ if x in sam.next[cur]:
18378
+ cur = sam.next[cur][x]
18379
+ l += 1
18380
+ else:
18381
+ while cur != -1 and x not in sam.next[cur]:
18382
+ cur = sam.link[cur]
18383
+ if cur == -1:
18384
+ cur = 0
18385
+ l = 0
18386
+ else:
18387
+ l = sam.len[cur] + 1
18388
+ cur = sam.next[cur][x]
18389
+ best[cur] = max(best[cur], l)
18390
+ # propagate best values along suffix links in decreasing len order
18391
+ order = sorted(range(m), key=lambda i: sam.len[i], reverse=True)
18392
+ for v in order:
18393
+ p = sam.link[v]
18394
+ if p != -1:
18395
+ best[p] = max(best[p], min(best[v], sam.len[p]))
18396
+ for i in range(m):
18397
+ min_match[i] = min(min_match[i], best[i])
18398
+
18399
+ # collect all distinct substrings: each state contributes lengths (link.len+1 .. min_match[state])
18400
+ res = set()
18401
+ for v in range(1, m):
18402
+ low = sam.len[sam.link[v]] + 1
18403
+ high = min_match[v]
18404
+ for L in range(low, high+1):
18405
+ # recover one substring of length L ending at this state by walking back from a position:
18406
+ # To avoid expensive reconstruction for every L, we reconstruct by scanning the first list.
18407
+ pass
18408
+
18409
+ # Efficient reconstruction: collect all end positions for each state by walking the first list
18410
+ # Build transitions to find substrings by scanning first list and recording (state, length) pairs
18411
+ cur = 0; l = 0
18412
+ pos_states = []
18413
+ for x in lists[0]:
18414
+ if x in sam.next[cur]:
18415
+ cur = sam.next[cur][x]; l += 1
18416
+ else:
18417
+ while cur != -1 and x not in sam.next[cur]:
18418
+ cur = sam.link[cur]
18419
+ if cur == -1:
18420
+ cur = 0; l = 0
18421
+ else:
18422
+ l = sam.len[cur] + 1
18423
+ cur = sam.next[cur][x]
18424
+ pos_states.append((cur, l))
18425
+
18426
+ # For each position, enumerate valid substring lengths and add actual slices
18427
+ n0 = len(lists[0])
18428
+ for i,(state, length) in enumerate(pos_states):
18429
+ maxlen = min(length, min_match[state])
18430
+ minlen = sam.len[sam.link[state]] + 1
18431
+ for L in range(minlen, maxlen+1):
18432
+ start = i - L + 1
18433
+ res.add(tuple(lists[0][start:start+L]))
18434
+
18435
+ return [list(t) for t in sorted(res, key=lambda x:(len(x), x))]
18436
+
18437
+ ###################################################################################
18438
+
18439
+ def extract_non_overlapping_chords(escore_notes, max_dur=-1):
18440
+
18441
+ cscore = chordify_score([1000, escore_notes])
18442
+
18443
+ no_chords = []
18444
+
18445
+ for i, c in enumerate(cscore[:-1]):
18446
+ ntime = cscore[i+1][0][1]
18447
+
18448
+ if max_dur > 0:
18449
+ cval = max_dur
18450
+
18451
+ else:
18452
+ cval = closest_avg_val([e[2] for e in c])
18453
+
18454
+ if c[0][1]+cval <= ntime:
18455
+ no_chords.append(c)
18456
+
18457
+ no_chords.append(cscore[-1])
18458
+
18459
+ return no_chords
18460
+
18461
+ ###################################################################################
18462
+
18463
+ def escore_chord_to_chord_token(escore_chord,
18464
+ use_full_chords=False,
18465
+ shift_chords=False
18466
+ ):
18467
+
18468
+ if use_full_chords:
18469
+ CHORDS = ALL_CHORDS_FULL
18470
+
18471
+ else:
18472
+ CHORDS = ALL_CHORDS_SORTED
18473
+
18474
+ pitches = sorted(set([e[4] for e in escore_chord if e[3] != 9]))
18475
+
18476
+ if len(pitches) > 1:
18477
+ tones_chord = sorted(set([p % 12 for p in pitches]))
18478
+
18479
+ if tones_chord not in CHORDS:
18480
+ tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=use_full_chords)
18481
+
18482
+ if shift_chords:
18483
+ return CHORDS.index(tones_chord)+12
18484
+
18485
+ else:
18486
+ return CHORDS.index(tones_chord)
18487
+
18488
+ elif len(pitches) == 1:
18489
+ if shift_chords:
18490
+ return pitches[0] % 12
18491
+
18492
+ else:
18493
+ return CHORDS.index([pitches[0] % 12])
18494
+
18495
+ else:
18496
+ return -1
18497
+
18498
+ ###################################################################################
18499
+
18500
+ def transpose_chord_token(chord_token, transpose_value, use_full_chords=False):
18501
+
18502
+ if use_full_chords:
18503
+ CHORDS = ALL_CHORDS_FULL
18504
+
18505
+ else:
18506
+ CHORDS = ALL_CHORDS_SORTED
18507
+
18508
+ if 0 <= chord_token < len(CHORDS):
18509
+ tchord = CHORDS[chord_token]
18510
+
18511
+ t_tchord = transpose_tones_chord(tchord, transpose_value)
18512
+
18513
+ if t_tchord in CHORDS:
18514
+ return CHORDS.index(t_tchord)
18515
+
18516
+ return chord_token
18517
+
18518
+ return chord_token
18519
+
18520
+ ###################################################################################
18521
+
18522
  print('Module loaded!')
18523
  print('=' * 70)
18524
  print('Enjoy! :)')