CoolFace
Apppublic

avans06/Audio-To-MIDI-And-Advanced-Renderer

sourceHugging Facecc-by-nc-4.0updated 1y agoView on Hugging Face
37likes
TMIDIX.py11604 linesDownload Raw Back to src
1#! /usr/bin/python32 3import os4import re5import json6import math7import tqdm8import copy9import psutil10import shutil11import random12import hashlib13import secrets14import statistics15import multiprocessing16from src import MIDI17 18from array import array19from pathlib import Path20from fnmatch import fnmatch21from collections import Counter22from collections import defaultdict23from collections import OrderedDict24from difflib import SequenceMatcher as SM25from operator import itemgetter26from itertools import product, combinations, groupby27 28###################################################################################29 30# TMIDI X Code is below31 32###################################################################################33 34def Optimus_MIDI_TXT_Processor(MIDI_file, 35                              line_by_line_output=True, 36                              chordify_TXT=False,37                              dataset_MIDI_events_time_denominator=1,38                              output_velocity=True,39                              output_MIDI_channels = False, 40                              MIDI_channel=0, 41                              MIDI_patch=[0, 1], 42                              char_offset = 30000,43                              transpose_by = 0,44                              flip=False, 45                              melody_conditioned_encoding=False,46                              melody_pitch_baseline = 0,47                              number_of_notes_to_sample = -1,48                              sampling_offset_from_start = 0,49                              karaoke=False,50                              karaoke_language_encoding='utf-8',51                              song_name='Song',52                              perfect_timings=False,53                              musenet_encoding=False,54                              transform=0,55                              zero_token=False,56                              reset_timings=False):57 58    '''Project Los Angeles59       Tegridy Code 2021'''60  61###########62 63    debug = False64 65    ev = 066 67    chords_list_final = []68    chords_list = []69    events_matrix = []70    melody = []71    melody1 = []72 73    itrack = 174 75    min_note = 076    max_note = 077    ev = 078    patch = 079 80    score = []81    rec_event = []82 83    txt = ''84    txtc = ''85    chords = []86    melody_chords = []87 88    karaoke_events_matrix = []89    karaokez = []90 91    sample = 092    start_sample = 093 94    bass_melody = []95 96    INTS = []97    bints = 098 99###########    100 101    def list_average(num):102      sum_num = 0103      for t in num:104          sum_num = sum_num + t           105 106      avg = sum_num / len(num)107      return avg108 109###########110 111    #print('Loading MIDI file...')112    midi_file = open(MIDI_file, 'rb')113    if debug: print('Processing File:', MIDI_file)114    115    try:116      opus = MIDI.midi2opus(midi_file.read())117    118    except:119      print('Problematic MIDI. Skipping...')120      print('File name:', MIDI_file)121      midi_file.close()122      return txt, melody, chords123         124    midi_file.close()125 126    score1 = MIDI.to_millisecs(opus)127    score2 = MIDI.opus2score(score1)128 129    # score2 = MIDI.opus2score(opus) # TODO Improve score timings when it will be possible.130    131    if MIDI_channel == 16: # Process all MIDI channels132      score = score2133    134    if MIDI_channel >= 0 and MIDI_channel <= 15: # Process only a selected single MIDI channel135      score = MIDI.grep(score2, [MIDI_channel])136    137    if MIDI_channel == -1: # Process all channels except drums (except channel 9)138      score = MIDI.grep(score2, [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15])   139    140    #print('Reading all MIDI events from the MIDI file...')141    while itrack < len(score):142      for event in score[itrack]:143        144        if perfect_timings:145          if event[0] == 'note':146            event[1] = round(event[1], -1)147            event[2] = round(event[2], -1)148 149        if event[0] == 'text_event' or event[0] == 'lyric' or event[0] == 'note':150          if perfect_timings:151            event[1] = round(event[1], -1)152          karaokez.append(event)153        154        if event[0] == 'text_event' or event[0] == 'lyric':155          if perfect_timings:156            event[1] = round(event[1], -1)157          try:158            event[2] = str(event[2].decode(karaoke_language_encoding, 'replace')).replace('/', '').replace(' ', '').replace('\\', '')159          except:160            event[2] = str(event[2]).replace('/', '').replace(' ', '').replace('\\', '')161            continue162          karaoke_events_matrix.append(event)163 164        if event[0] == 'patch_change':165          patch = event[3]166 167        if event[0] == 'note' and patch in MIDI_patch:168          if len(event) == 6: # Checking for bad notes...169              eve = copy.deepcopy(event)170              171              eve[1] = int(event[1] / dataset_MIDI_events_time_denominator)172              eve[2] = int(event[2] / dataset_MIDI_events_time_denominator)173              174              eve[4] = int(event[4] + transpose_by)175              176              if flip == True:177                eve[4] = int(127 - (event[4] + transpose_by)) 178              179              if number_of_notes_to_sample > -1:180                if sample <= number_of_notes_to_sample:181                  if start_sample >= sampling_offset_from_start:182                    events_matrix.append(eve)183                    sample += 1184                    ev += 1185                  else:186                    start_sample += 1187 188              else:189                events_matrix.append(eve)190                ev += 1191                start_sample += 1192                193      itrack +=1 # Going to next track...194 195    #print('Doing some heavy pythonic sorting...Please stand by...')196 197    fn = os.path.basename(MIDI_file)198    song_name = song_name.replace(' ', '_').replace('=', '_').replace('\'', '-')199    if song_name == 'Song':200      sng_name = fn.split('.')[0].replace(' ', '_').replace('=', '_').replace('\'', '-')201      song_name = sng_name202 203    # Zero token204    if zero_token:205      txt += chr(char_offset) + chr(char_offset)206      if output_MIDI_channels:207        txt += chr(char_offset)208      if output_velocity:209        txt += chr(char_offset) + chr(char_offset)     210      else:211        txt += chr(char_offset)212 213      txtc += chr(char_offset) + chr(char_offset)214      if output_MIDI_channels:215        txtc += chr(char_offset)216      if output_velocity:217        txtc += chr(char_offset) + chr(char_offset)      218      else:219        txtc += chr(char_offset)220      221      txt += '=' + song_name + '_with_' + str(len(events_matrix)-1) + '_notes'222      txtc += '=' + song_name + '_with_' + str(len(events_matrix)-1) + '_notes'223    224    else:225      # Song stamp226      txt += 'SONG=' + song_name + '_with_' + str(len(events_matrix)-1) + '_notes'227      txtc += 'SONG=' + song_name + '_with_' + str(len(events_matrix)-1) + '_notes'228 229    if line_by_line_output:230      txt += chr(10)231      txtc += chr(10)232    else:233      txt += chr(32)234      txtc += chr(32)235 236    #print('Sorting input by start time...')237    events_matrix.sort(key=lambda x: x[1]) # Sorting input by start time    238    239    #print('Timings converter')240    if reset_timings:241      ev_matrix = Tegridy_Timings_Converter(events_matrix)[0]242    else:243      ev_matrix = events_matrix244    245    chords.extend(ev_matrix)246    #print(chords)247 248    #print('Extracting melody...')249    melody_list = []250 251    #print('Grouping by start time. This will take a while...')252    values = set(map(lambda x:x[1], ev_matrix)) # Non-multithreaded function version just in case253 254    groups = [[y for y in ev_matrix if y[1]==x and len(y) == 6] for x in values] # Grouping notes into chords while discarting bad notes...255  256    #print('Sorting events...')257    for items in groups:258        259        items.sort(reverse=True, key=lambda x: x[4]) # Sorting events by pitch260        261        if melody_conditioned_encoding: items[0][3] = 0 # Melody should always bear MIDI Channel 0 for code to work262        263        melody_list.append(items[0]) # Creating final melody list264        melody_chords.append(items) # Creating final chords list265        bass_melody.append(items[-1]) # Creating final bass melody list266    267    # [WIP] Melody-conditioned chords list268    if melody_conditioned_encoding == True:269      if not karaoke:270   271        previous_event = copy.deepcopy(melody_chords[0][0])272 273        for ev in melody_chords:274          hp = True275          ev.sort(reverse=False, key=lambda x: x[4]) # Sorting chord events by pitch276          for event in ev:277          278            # Computing events details279            start_time = int(abs(event[1] - previous_event[1]))280            281            duration = int(previous_event[2])282 283            if hp == True:284              if int(previous_event[4]) >= melody_pitch_baseline:285                channel = int(0)286                hp = False287              else:288                channel = int(previous_event[3]+1)289                hp = False  290            else:291              channel = int(previous_event[3]+1)292              hp = False293 294            pitch = int(previous_event[4])295 296            velocity = int(previous_event[5])297 298            # Writing INTergerS...299            try:300              INTS.append([(start_time)+char_offset, (duration)+char_offset, channel+char_offset, pitch+char_offset, velocity+char_offset])301            except:302              bints += 1303 304            # Converting to TXT if possible...305            try:306              txtc += str(chr(start_time + char_offset))307              txtc += str(chr(duration + char_offset))308              txtc += str(chr(pitch + char_offset))309              if output_velocity:310                txtc += str(chr(velocity + char_offset))311              if output_MIDI_channels:312                txtc += str(chr(channel + char_offset))313 314              if line_by_line_output:315              316 317                txtc += chr(10)318              else:319 320                txtc += chr(32)321 322              previous_event = copy.deepcopy(event)323            324            except:325              # print('Problematic MIDI event! Skipping...')326              continue327 328        if not line_by_line_output:329          txtc += chr(10)330 331        txt = txtc332        chords = melody_chords333    334    # Default stuff (not melody-conditioned/not-karaoke)335    else:      336      if not karaoke:337        melody_chords.sort(reverse=False, key=lambda x: x[0][1])338        mel_chords = []339        for mc in melody_chords:340          mel_chords.extend(mc)341 342        if transform != 0: 343          chords = Tegridy_Transform(mel_chords, transform)344        else:345          chords = mel_chords346 347        # TXT Stuff348        previous_event = copy.deepcopy(chords[0])349        for event in chords:350 351          # Computing events details352          start_time = int(abs(event[1] - previous_event[1]))353          354          duration = int(previous_event[2])355 356          channel = int(previous_event[3])357 358          pitch = int(previous_event[4] + transpose_by)359          if flip == True:360            pitch = 127 - int(previous_event[4] + transpose_by)361 362          velocity = int(previous_event[5])363 364          # Writing INTergerS...365          try:366            INTS.append([(start_time)+char_offset, (duration)+char_offset, channel+char_offset, pitch+char_offset, velocity+char_offset])367          except:368            bints += 1369 370          # Converting to TXT if possible...371          try:372            txt += str(chr(start_time + char_offset))373            txt += str(chr(duration + char_offset))374            txt += str(chr(pitch + char_offset))375            if output_velocity:376              txt += str(chr(velocity + char_offset))377            if output_MIDI_channels:378              txt += str(chr(channel + char_offset))379 380 381            if chordify_TXT == True and int(event[1] - previous_event[1]) == 0:382              txt += ''      383            else:     384              if line_by_line_output:385                txt += chr(10)386              else:387                txt += chr(32) 388            389            previous_event = copy.deepcopy(event)390          391          except:392            # print('Problematic MIDI event. Skipping...')393            continue394 395        if not line_by_line_output:396          txt += chr(10)      397 398    # Karaoke stuff399    if karaoke:400 401      melody_chords.sort(reverse=False, key=lambda x: x[0][1])402      mel_chords = []403      for mc in melody_chords:404        mel_chords.extend(mc)405 406      if transform != 0: 407        chords = Tegridy_Transform(mel_chords, transform)408      else:409        chords = mel_chords410 411      previous_event = copy.deepcopy(chords[0])412      for event in chords:413 414        # Computing events details415        start_time = int(abs(event[1] - previous_event[1]))416        417        duration = int(previous_event[2])418 419        channel = int(previous_event[3])420 421        pitch = int(previous_event[4] + transpose_by)422 423        velocity = int(previous_event[5])424 425        # Converting to TXT426        txt += str(chr(start_time + char_offset))427        txt += str(chr(duration + char_offset))428        txt += str(chr(pitch + char_offset))429 430        txt += str(chr(velocity + char_offset))431        txt += str(chr(channel + char_offset))     432 433        if start_time > 0:434          for k in karaoke_events_matrix:435            if event[1] == k[1]:436              txt += str('=')437              txt += str(k[2])          438              break439 440        if line_by_line_output:441          txt += chr(10)442        else:443          txt += chr(32) 444        445        previous_event = copy.deepcopy(event)446      447      if not line_by_line_output:448        txt += chr(10)449 450    # Final processing code...451    # =======================================================================452 453    # Helper aux/backup function for Karaoke454    karaokez.sort(reverse=False, key=lambda x: x[1])  455 456    # MuseNet sorting457    if musenet_encoding and not melody_conditioned_encoding and not karaoke:458      chords.sort(key=lambda x: (x[1], x[3]))459    460    # Final melody sort461    melody_list.sort()462 463    # auxs for future use464    aux1 = [None]465    aux2 = [None]466 467    return txt, melody_list, chords, bass_melody, karaokez, INTS, aux1, aux2 # aux1 and aux2 are not used atm468 469###################################################################################470 471def Optimus_TXT_to_Notes_Converter(Optimus_TXT_String,472                                    line_by_line_dataset = True,473                                    has_velocities = True,474                                    has_MIDI_channels = True,475                                    dataset_MIDI_events_time_denominator = 1,476                                    char_encoding_offset = 30000,477                                    save_only_first_composition = True,478                                    simulate_velocity=True,479                                    karaoke=False,480                                    zero_token=False):481 482    '''Project Los Angeles483       Tegridy Code 2020'''484 485    print('Tegridy Optimus TXT to Notes Converter')486    print('Converting TXT to Notes list...Please wait...')487 488    song_name = ''489 490    if line_by_line_dataset:491      input_string = Optimus_TXT_String.split('\n')492    else:493      input_string = Optimus_TXT_String.split(' ')494 495    if line_by_line_dataset:496      name_string = Optimus_TXT_String.split('\n')[0].split('=')497    else:498      name_string = Optimus_TXT_String.split(' ')[0].split('=')499 500    # Zero token501    zt = ''502 503    zt += chr(char_encoding_offset) + chr(char_encoding_offset)504    505    if has_MIDI_channels:506      zt += chr(char_encoding_offset)507    508    if has_velocities:509      zt += chr(char_encoding_offset) + chr(char_encoding_offset)     510    511    else:512      zt += chr(char_encoding_offset)513 514    if zero_token:515      if name_string[0] == zt:516        song_name = name_string[1]517    518    else:519      if name_string[0] == 'SONG':520        song_name = name_string[1]521 522    output_list = []523    st = 0524 525    for i in range(2, len(input_string)-1):526 527      if save_only_first_composition:528        if zero_token:529          if input_string[i].split('=')[0] == zt:530 531            song_name = name_string[1]532            break533        534        else:535          if input_string[i].split('=')[0] == 'SONG':536 537            song_name = name_string[1]538            break539      try:540        istring = input_string[i]541 542        if has_MIDI_channels == False:543          step = 4          544 545        if has_MIDI_channels == True:546          step = 5547 548        if has_velocities == False:549          step -= 1550 551        st += int(ord(istring[0]) - char_encoding_offset) * dataset_MIDI_events_time_denominator552 553        if not karaoke:554          for s in range(0, len(istring), step):555              if has_MIDI_channels==True:556                if step > 3 and len(istring) > 2:557                      out = []       558                      out.append('note')559 560                      out.append(st) # Start time561 562                      out.append(int(ord(istring[s+1]) - char_encoding_offset) * dataset_MIDI_events_time_denominator) # Duration563 564                      if has_velocities:565                        out.append(int(ord(istring[s+4]) - char_encoding_offset)) # Channel566                      else:567                        out.append(int(ord(istring[s+3]) - char_encoding_offset)) # Channel  568 569                      out.append(int(ord(istring[s+2]) - char_encoding_offset)) # Pitch570 571                      if simulate_velocity:572                        if s == 0:573                          sim_vel = int(ord(istring[s+2]) - char_encoding_offset)574                        out.append(sim_vel) # Simulated Velocity (= highest note's pitch)575                      else:                      576                        out.append(int(ord(istring[s+3]) - char_encoding_offset)) # Velocity577 578              if has_MIDI_channels==False:579                if step > 3 and len(istring) > 2:580                      out = []       581                      out.append('note')582 583                      out.append(st) # Start time584                      out.append(int(ord(istring[s+1]) - char_encoding_offset) * dataset_MIDI_events_time_denominator) # Duration585                      out.append(0) # Channel586                      out.append(int(ord(istring[s+2]) - char_encoding_offset)) # Pitch587 588                      if simulate_velocity:589                        if s == 0:590                          sim_vel = int(ord(istring[s+2]) - char_encoding_offset)591                        out.append(sim_vel) # Simulated Velocity (= highest note's pitch)592                      else:                      593                        out.append(int(ord(istring[s+3]) - char_encoding_offset)) # Velocity594 595              if step == 3 and len(istring) > 2:596                      out = []       597                      out.append('note')598 599                      out.append(st) # Start time600                      out.append(int(ord(istring[s+1]) - char_encoding_offset) * dataset_MIDI_events_time_denominator) # Duration601                      out.append(0) # Channel602                      out.append(int(ord(istring[s+2]) - char_encoding_offset)) # Pitch603 604                      out.append(int(ord(istring[s+2]) - char_encoding_offset)) # Velocity = Pitch605 606              output_list.append(out)607 608        if karaoke:609          try:610              out = []       611              out.append('note')612 613              out.append(st) # Start time614              out.append(int(ord(istring[1]) - char_encoding_offset) * dataset_MIDI_events_time_denominator) # Duration615              out.append(int(ord(istring[4]) - char_encoding_offset)) # Channel616              out.append(int(ord(istring[2]) - char_encoding_offset)) # Pitch617 618              if simulate_velocity:619                if s == 0:620                  sim_vel = int(ord(istring[2]) - char_encoding_offset)621                out.append(sim_vel) # Simulated Velocity (= highest note's pitch)622              else:                      623                out.append(int(ord(istring[3]) - char_encoding_offset)) # Velocity624              output_list.append(out)625              out = []626              if istring.split('=')[1] != '':627                out.append('lyric')628                out.append(st)629                out.append(istring.split('=')[1])630                output_list.append(out)631          except:632            continue633 634 635      except:636        print('Bad note string:', istring)637        continue638 639    # Simple error control just in case640    S = []641    for x in output_list:642      if len(x) == 6 or len(x) == 3:643        S.append(x)644 645    output_list.clear()    646    output_list = copy.deepcopy(S)647 648 649    print('Task complete! Enjoy! :)')650 651    return output_list, song_name652 653###################################################################################654 655def Optimus_Data2TXT_Converter(data,656                              dataset_time_denominator=1,657                              transpose_by = 0,658                              char_offset = 33,659                              line_by_line_output = True,660                              output_velocity = False,661                              output_MIDI_channels = False):662 663 664  '''Input: data as a flat chords list of flat chords lists665 666  Output: TXT string667          INTs668 669  Project Los Angeles670  Tegridy Code 2021'''671 672  txt = ''673  TXT = ''674 675  quit = False676  counter = 0677 678  INTs = []679  INTs_f = []680 681  for d in tqdm.tqdm(sorted(data)):682 683    if quit == True:684      break685 686    txt = 'SONG=' + str(counter)687    counter += 1688 689    if line_by_line_output:690      txt += chr(10)691    else:692      txt += chr(32)693      694    INTs = []695 696    # TXT Stuff697    previous_event = copy.deepcopy(d[0])698    for event in sorted(d):699 700      # Computing events details701      start_time = int(abs(event[1] - previous_event[1]) / dataset_time_denominator)702      703      duration = int(previous_event[2] / dataset_time_denominator)704 705      channel = int(previous_event[3])706 707      pitch = int(previous_event[4] + transpose_by)708 709      velocity = int(previous_event[5])710 711      INTs.append([start_time, duration, pitch])712 713      # Converting to TXT if possible...714      try:715        txt += str(chr(start_time + char_offset))716        txt += str(chr(duration + char_offset))717        txt += str(chr(pitch + char_offset))718        if output_velocity:719          txt += str(chr(velocity + char_offset))720        if output_MIDI_channels:721          txt += str(chr(channel + char_offset))722    723        if line_by_line_output:724          txt += chr(10)725        else:726          txt += chr(32) 727        728        previous_event = copy.deepcopy(event)729      except KeyboardInterrupt:730        quit = True731        break732      except:733        print('Problematic MIDI data. Skipping...')734        continue735 736    if not line_by_line_output:737      txt += chr(10)738    739    TXT += txt740    INTs_f.extend(INTs)741 742  return TXT, INTs_f743 744###################################################################################745 746def Optimus_Squash(chords_list, simulate_velocity=True, mono_compression=False):747 748  '''Input: Flat chords list749            Simulate velocity or not750            Mono-compression enabled or disabled751            752            Default is almost lossless 25% compression, otherwise, lossy 50% compression (mono-compression)753 754     Output: Squashed chords list755             Resulting compression level756 757             Please note that if drums are passed through as is758 759     Project Los Angeles760     Tegridy Code 2021'''761 762  output = []763  ptime = 0764  vel = 0765  boost = 15766  stptc = []767  ocount = 0768  rcount = 0769 770  for c in chords_list:771    772    cc = copy.deepcopy(c)773    ocount += 1774    775    if [cc[1], cc[3], (cc[4] % 12) + 60] not in stptc:776      stptc.append([cc[1], cc[3], (cc[4] % 12) + 60])777 778      if cc[3] != 9:779        cc[4] = (c[4] % 12) + 60780 781      if simulate_velocity and c[1] != ptime:782        vel = c[4] + boost783      784      if cc[3] != 9:785        cc[5] = vel786 787      if mono_compression:788        if c[1] != ptime:789          output.append(cc)790          rcount += 1  791      else:792        output.append(cc)793        rcount += 1794      795      ptime = c[1]796 797  output.sort(key=lambda x: (x[1], x[4]))798 799  comp_level = 100 - int((rcount * 100) / ocount)800 801  return output, comp_level802 803###################################################################################804 805def Optimus_Signature(chords_list, calculate_full_signature=False):806 807    '''Optimus Signature808 809    ---In the name of the search for a perfect score slice signature---810     811    Input: Flat chords list to evaluate812 813    Output: Full Optimus Signature as a list814            Best/recommended Optimus Signature as a list815 816    Project Los Angeles817    Tegridy Code 2021'''818    819    # Pitches820 821    ## StDev822    if calculate_full_signature:823      psd = statistics.stdev([int(y[4]) for y in chords_list])824    else:825      psd = 0826 827    ## Median828    pmh = statistics.median_high([int(y[4]) for y in chords_list])829    pm = statistics.median([int(y[4]) for y in chords_list])830    pml = statistics.median_low([int(y[4]) for y in chords_list])831    832    ## Mean833    if calculate_full_signature:834      phm = statistics.harmonic_mean([int(y[4]) for y in chords_list])835    else:836      phm = 0837 838    # Durations839    dur = statistics.median([int(y[2]) for y in chords_list])840 841    # Velocities842 843    vel = statistics.median([int(y[5]) for y in chords_list])844 845    # Beats846    mtds = statistics.median([int(abs(chords_list[i-1][1]-chords_list[i][1])) for i in range(1, len(chords_list))])847    if calculate_full_signature:848      hmtds = statistics.harmonic_mean([int(abs(chords_list[i-1][1]-chords_list[i][1])) for i in range(1, len(chords_list))])849    else:850      hmtds = 0851 852    # Final Optimus signatures853    full_Optimus_signature = [round(psd), round(pmh), round(pm), round(pml), round(phm), round(dur), round(vel), round(mtds), round(hmtds)]854    ########################    PStDev     PMedianH    PMedian    PMedianL    PHarmoMe    Duration    Velocity      Beat       HarmoBeat855 856    best_Optimus_signature = [round(pmh), round(pm), round(pml), round(dur, -1), round(vel, -1), round(mtds, -1)]857    ########################   PMedianH    PMedian    PMedianL      Duration        Velocity          Beat858    859    # Return...860    return full_Optimus_signature, best_Optimus_signature861    862 863###################################################################################864#865# TMIDI 2.0 Helper functions866#867###################################################################################868 869def Tegridy_FastSearch(needle, haystack, randomize = False):870 871  '''872 873  Input: Needle iterable874         Haystack iterable875         Randomize search range (this prevents determinism)876 877  Output: Start index of the needle iterable in a haystack iterable878          If nothing found, -1 is returned879 880  Project Los Angeles881  Tegridy Code 2021'''882 883  need = copy.deepcopy(needle)884 885  try:886    if randomize:887      idx = haystack.index(need, secrets.randbelow(len(haystack)-len(need)))888    else:889      idx = haystack.index(need)890 891  except KeyboardInterrupt:892    return -1893 894  except:895    return -1896    897  return idx898 899###################################################################################900 901def Tegridy_Chord_Match(chord1, chord2, match_type=2):902 903    '''Tegridy Chord Match904     905    Input: Two chords to evaluate906           Match type: 2 = duration, channel, pitch, velocity907                       3 = channel, pitch, velocity908                       4 = pitch, velocity909                       5 = velocity910 911    Output: Match rating (0-100)912            NOTE: Match rating == -1 means identical source chords913            NOTE: Match rating == 100 means mutual shortest chord914 915    Project Los Angeles916    Tegridy Code 2021'''917 918    match_rating = 0919 920    if chord1 == []:921      return 0922    if chord2 == []:923      return 0924 925    if chord1 == chord2:926      return -1927 928    else:929      zipped_pairs = list(zip(chord1, chord2))930      zipped_diff = abs(len(chord1) - len(chord2))931 932      short_match = [False]933      for pair in zipped_pairs:934        cho1 = ' '.join([str(y) for y in pair[0][match_type:]])935        cho2 = ' '.join([str(y) for y in pair[1][match_type:]])936        if cho1 == cho2:937          short_match.append(True)938        else:939          short_match.append(False)940      941      if True in short_match:942        return 100943 944      pairs_ratings = []945 946      for pair in zipped_pairs:947        cho1 = ' '.join([str(y) for y in pair[0][match_type:]])948        cho2 = ' '.join([str(y) for y in pair[1][match_type:]])949        pairs_ratings.append(SM(None, cho1, cho2).ratio())950 951      match_rating = sum(pairs_ratings) / len(pairs_ratings) * 100952 953      return match_rating954 955###################################################################################956 957def Tegridy_Last_Chord_Finder(chords_list):958 959    '''Tegridy Last Chord Finder960     961    Input: Flat chords list962 963    Output: Last detected chord of the chords list964            Last chord start index in the original chords list965            First chord end index in the original chords list966 967    Project Los Angeles968    Tegridy Code 2021'''969 970    chords = []971    cho = []972 973    ptime = 0974 975    i = 0976 977    pc_idx = 0978    fc_idx = 0979 980    chords_list.sort(reverse=False, key=lambda x: x[1])981    982    for cc in chords_list:983 984      if cc[1] == ptime:985        986        cho.append(cc)987 988        ptime = cc[1]989 990      else:991        if pc_idx == 0: 992          fc_idx = chords_list.index(cc)993        pc_idx = chords_list.index(cc)994        995        chords.append(cho)996        997        cho = []998      999        cho.append(cc)1000        1001        ptime = cc[1]1002        1003        i += 11004      1005    if cho != []: 1006      chords.append(cho)1007      i += 11008     1009    return chords_list[pc_idx:], pc_idx, fc_idx1010 1011###################################################################################1012 1013def Tegridy_Chords_Generator(chords_list, shuffle_pairs = True, remove_single_notes=False):1014 1015    '''Tegridy Score Chords Pairs Generator1016     1017    Input: Flat chords list1018           Shuffle pairs (recommended)1019 1020    Output: List of chords1021            1022            Average time(ms) per chord1023            Average time(ms) per pitch1024            Average chords delta time1025 1026            Average duration1027            Average channel1028            Average pitch1029            Average velocity1030 1031    Project Los Angeles1032    Tegridy Code 2021'''1033 1034    chords = []1035    cho = []1036 1037    i = 01038 1039    # Sort by start time1040    chords_list.sort(reverse=False, key=lambda x: x[1])1041 1042    # Main loop1043    pcho = chords_list[0]1044    for cc in chords_list:1045      if cc[1] == pcho[1]:1046        1047        cho.append(cc)1048        pcho = copy.deepcopy(cc)1049 1050      else:1051        if not remove_single_notes:1052          chords.append(cho)1053          cho = []1054          cho.append(cc)1055          pcho = copy.deepcopy(cc)1056          1057          i += 11058        else:1059          if len(cho) > 1:1060            chords.append(cho)1061          cho = []1062          cho.append(cc)1063          pcho = copy.deepcopy(cc)1064            1065          i += 1  1066    1067    # Averages1068    t0 = chords[0][0][1]1069    t1 = chords[-1][-1][1]1070    tdel = abs(t1 - t0)1071    avg_ms_per_chord = int(tdel / i)1072    avg_ms_per_pitch = int(tdel / len(chords_list))1073 1074    # Delta time1075    tds = [int(abs(chords_list[i-1][1]-chords_list[i][1]) / 1) for i in range(1, len(chords_list))]1076    if len(tds) != 0: avg_delta_time = int(sum(tds) / len(tds))1077 1078    # Chords list attributes1079    p = int(sum([int(y[4]) for y in chords_list]) / len(chords_list))1080    d = int(sum([int(y[2]) for y in chords_list]) / len(chords_list))1081    c = int(sum([int(y[3]) for y in chords_list]) / len(chords_list))1082    v = int(sum([int(y[5]) for y in chords_list]) / len(chords_list))1083 1084    # Final shuffle1085    if shuffle_pairs:1086      random.shuffle(chords)1087 1088    return chords, [avg_ms_per_chord, avg_ms_per_pitch, avg_delta_time], [d, c, p, v]1089 1090###################################################################################1091 1092def Tegridy_Chords_List_Music_Features(chords_list, st_dur_div = 1, pitch_div = 1, vel_div = 1):1093 1094    '''Tegridy Chords List Music Features1095     1096    Input: Flat chords list1097 1098    Output: A list of the extracted chords list's music features1099 1100    Project Los Angeles1101    Tegridy Code 2021'''1102 1103    chords_list1 = [x for x in chords_list if x]1104    chords_list1.sort(reverse=False, key=lambda x: x[1])1105    1106    # Features extraction code1107 1108    melody_list = []1109    bass_melody = []1110    melody_chords = []1111    mel_avg_tds = []1112    mel_chrd_avg_tds = []1113    bass_melody_avg_tds = []1114 1115    #print('Grouping by start time. This will take a while...')1116    values = set(map(lambda x:x[1], chords_list1)) # Non-multithreaded function version just in case1117 1118    groups = [[y for y in chords_list1 if y[1]==x and len(y) == 6] for x in values] # Grouping notes into chords while discarting bad notes...1119 1120    #print('Sorting events...')1121    for items in groups:1122        items.sort(reverse=True, key=lambda x: x[4]) # Sorting events by pitch1123        melody_list.append(items[0]) # Creating final melody list1124        melody_chords.append(items) # Creating final chords list1125        bass_melody.append(items[-1]) # Creating final bass melody list1126 1127    #print('Final sorting by start time...')      1128    melody_list.sort(reverse=False, key=lambda x: x[1]) # Sorting events by start time1129    melody_chords.sort(reverse=False, key=lambda x: x[0][1]) # Sorting events by start time1130    bass_melody.sort(reverse=False, key=lambda x: x[1]) # Sorting events by start time1131 1132    # Extracting music features from the chords list1133    1134    # Melody features1135    mel_avg_pitch = int(sum([y[4] for y in melody_list]) / len(melody_list) / pitch_div)1136    mel_avg_dur = int(sum([int(y[2] / st_dur_div) for y in melody_list]) / len(melody_list))1137    mel_avg_vel = int(sum([int(y[5] / vel_div) for y in melody_list]) / len(melody_list))1138    mel_avg_chan = int(sum([int(y[3]) for y in melody_list]) / len(melody_list))1139    1140    mel_tds = [int(abs(melody_list[i-1][1]-melody_list[i][1])) for i in range(1, len(melody_list))]1141    if len(mel_tds) != 0: mel_avg_tds = int(sum(mel_tds) / len(mel_tds) / st_dur_div)1142    1143    melody_features = [mel_avg_tds, mel_avg_dur, mel_avg_chan, mel_avg_pitch, mel_avg_vel]1144 1145    # Chords list features1146    mel_chrd_avg_pitch = int(sum([y[4] for y in chords_list1]) / len(chords_list1) / pitch_div)1147    mel_chrd_avg_dur = int(sum([int(y[2] / st_dur_div) for y in chords_list1]) / len(chords_list1))1148    mel_chrd_avg_vel = int(sum([int(y[5] / vel_div) for y in chords_list1]) / len(chords_list1))1149    mel_chrd_avg_chan = int(sum([int(y[3]) for y in chords_list1]) / len(chords_list1))1150    1151    mel_chrd_tds = [int(abs(chords_list1[i-1][1]-chords_list1[i][1])) for i in range(1, len(chords_list1))]1152    if len(mel_tds) != 0: mel_chrd_avg_tds = int(sum(mel_chrd_tds) / len(mel_chrd_tds) / st_dur_div)1153    1154    chords_list_features = [mel_chrd_avg_tds, mel_chrd_avg_dur, mel_chrd_avg_chan, mel_chrd_avg_pitch, mel_chrd_avg_vel]1155 1156    # Bass melody features1157    bass_melody_avg_pitch = int(sum([y[4] for y in bass_melody]) / len(bass_melody) / pitch_div)1158    bass_melody_avg_dur = int(sum([int(y[2] / st_dur_div) for y in bass_melody]) / len(bass_melody))1159    bass_melody_avg_vel = int(sum([int(y[5] / vel_div) for y in bass_melody]) / len(bass_melody))1160    bass_melody_avg_chan = int(sum([int(y[3]) for y in bass_melody]) / len(bass_melody))1161    1162    bass_melody_tds = [int(abs(bass_melody[i-1][1]-bass_melody[i][1])) for i in range(1, len(bass_melody))]1163    if len(bass_melody_tds) != 0: bass_melody_avg_tds = int(sum(bass_melody_tds) / len(bass_melody_tds) / st_dur_div)1164    1165    bass_melody_features = [bass_melody_avg_tds, bass_melody_avg_dur, bass_melody_avg_chan, bass_melody_avg_pitch, bass_melody_avg_vel]1166    1167    # A list to return all features1168    music_features = []1169 1170    music_features.extend([len(chords_list1)]) # Count of the original chords list notes1171    1172    music_features.extend(melody_features) # Extracted melody features1173    music_features.extend(chords_list_features) # Extracted chords list features1174    music_features.extend(bass_melody_features) # Extracted bass melody features1175    music_features.extend([sum([y[4] for y in chords_list1])]) # Sum of all pitches in the original chords list1176 1177    return music_features1178 1179###################################################################################1180 1181def Tegridy_Transform(chords_list, to_pitch=60, to_velocity=-1):1182 1183    '''Tegridy Transform1184     1185    Input: Flat chords list1186           Desired average pitch (-1 == no change)1187           Desired average velocity (-1 == no change)1188 1189    Output: Transformed flat chords list1190 1191    Project Los Angeles1192    Tegridy Code 2021'''1193 1194    transformed_chords_list = []1195 1196    chords_list.sort(reverse=False, key=lambda x: x[1])1197 1198    chords_list_features = Optimus_Signature(chords_list)[1]1199 1200    pitch_diff = int((chords_list_features[0] + chords_list_features[1] + chords_list_features[2]) / 3) - to_pitch

Showing the first 1,200 of 11604 lines. Download the file for the rest.