Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Combining Modern Tech with Traditional Music: E...

Combining Modern Tech with Traditional Music: Enhancing Angklung Performances with Python

Angklung is a traditional musical instrument from Indonesia. This instrument has a lot of variety in how it is performed; a common format is the orchestral format in which 15-30 players gather to form a team. Playing angklung in this way is fun but also presents some challenges that are hard to solve manually.

This presentation shows you how Python-based algorithms can be used to improve the quality of life of angklung players and managers, by reading Angklung sheet music and calculating the most optimal distribution based on several important factors. In addition, Python also plays a role in easing the pains of transforming western music notation to traditional musical notation (Cipher notation).

Note: slides are intentionally text-minimal to support the actual talk.

Avatar for Trapsilo Bumi

Trapsilo Bumi

August 25, 2018

More Decks by Trapsilo Bumi

Other Decks in Programming

Transcript

  1. Combining Modern Tech with Traditional Music:
 Enhancing Angklung Performances with

    Python Trapsilo Bumi (HDE, Inc.) PyCon Malaysia, 25-26 August 2018 Github: @tbumi Email: [email protected]
  2. • Traditional musical instrument from West Java, Indonesia • Origins

    can be traced to centuries ago, used as a rhythmic instrument in ancient rituals • Circa 1930, Mr. Daeng Soetigna introduced its usage as a melodic instrument • Because of this invention, Angklung can now play a broad range of songs
  3. C D E 5 11 … C D E F

    1 3 5 6 8 10 11131517
  4. • Each player holds several angklung • The angklung have

    to be distributed in a way: • Angklung of one player don’t “collide” with each other • Each player gets a fair share of playing • Aesthetically good on the player, fair • Not all players are present at every rehearsal session
  5. Example of a Distribution John A 5 14 25 Bob

    D 3 9 16 Dave 5 19 23 Amy F 8 15 22 30 Chris A 7 …
  6. • Overall balance in the song • Not too many

    low notes, not too few high notes • Limitations of the team • Multiple songs in a row • 1 player max. 5-6 angklung “Control Table”
  7. Basic idea Do = F (no. 11) j . .

    . 0 -0-3 j -3-s s . . . -B-z c -.-z -B-z cn b . . . d . . . x . c . d x z J . . . M . z . B . N . c . v . c . . . 0 0 0 -b-q e -.-q -b-q -e-v s . x . z . . . z . 0 0 b . . . J . M . z . . . s . e -q-q q -.-m -q-m -q-e u . . -b-q e -.-q -b-q -m-j b . . b c . x . z . M . z . . . z . . M N . N . B . . . X C n . r -u-m q -.-s -5-s -r-m q . . . N -M-z x -c-v z . h . c . x . v . -c-x -z-M B . . . V . . . B . . . z . . 0 -b-q e -.-q -b-q -e-v b -.-v -c-x -z-M N . . . 0 z M . b -c-x -c-b B . . . G . . . H . B . z . . . Indonesia Pusaka Comp. Ismail Marzuki for row in wb.active.rows: new_row = [] for cell in row: ... new_row.append(cell) ... self.table[internal_row] += \ new_row Read List List
  8. RELATIVE_LIST = ['Z', 'S', 'X', 'D', 'C', 'V', 'G', 'B',

    'H', 'N', 'J', 'M', # 1rr .. 7rr 'z', 's', 'x', 'd', 'c', 'v', 'g', 'b', 'h', 'n', 'j', 'm', # 1r .. 7r 'q', '2', 'w', '3', 'e', 'r', '5', 't', '6', 'y', '7', 'u', # 1 .. 7 'Q', '@', 'W', '#', 'E', 'R', '%', 'T', '^', 'Y', '&', 'U', # 1t .. 7t 'I', '(', 'O', ')', 'P', '{', '+', '}'] # 1tt .. 5tt KEYSIG_LIST = ['G', 'G#', 'A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#'] KEYSIG_FLAT_LIST = ['G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb'] def relative_to_no_angklung(keysig, note): numeral_value = RELATIVE_LIST.index(note) - 18 + (KEYSIG_LIST.index(keysig) - 5) if numeral_value > 35: raise ValueError('Invalid note input (too high): ' + note) elif numeral_value >= 0: return str(numeral_value) else: numeral_value += 11 if numeral_value >= 0: return KEYSIG_LIST[numeral_value] else: numeral_value += 12 if numeral_value < 5: raise ValueError('Invalid note input (too low): ' + note) return KEYSIG_LIST[numeral_value] + 'g'
  9. Generating a distribution • Make a list of angklung to

    distribute based on the score • For each angklung in that list, choose a player to give the angklung to, considering several criteria • Avoid players which angklung collides with this angklung • Avoid players with too much play time • Choose a player where this angklung has a good size proportion
  10. distribution = {i: [] for i in range(num_players)} while len(angklung_to_distribute)

    > 0: angklung_candidate = angklung_to_distribute.pop() candidate_values = {} for player_idx, player_dist in distribution.items(): if angklung_candidate in player_dist: continue weight = 0 for player_angklung in player_dist: weight -= play_time[player_angklung] weight -= collision_table[pair(angklung_candidate, player_angklung)] if angklung_candidate in ANGKLUNG_LOW and \ player_angklung in ANGKLUNG_LOW: weight -= 1 weight -= 1 / abs(no_angklung_to_numeral(angklung_candidate) - no_angklung_to_numeral(player_angklung)) weight -= len(player_dist) * 3 candidate_values[player_idx] = weight if len(candidate_values) == 0: raise Exception("Too few players") candidate_values_sorted = sorted([(v, i) for i, v in candidate_values.items()], key=lambda t: t[0], reverse=True) distribution[candidate_values_sorted[0][1]].append(angklung_candidate) distribution = {i: sorted(angklungs, key=no_angklung_to_numeral) for i, angklungs in distribution.items()}
  11. Converting music scores to angklung scores Scorewriter program MusicXML xml.etree

    Python list structure Excel workbook https://github.com/tbumi/mxl2xlsx
  12. • Angklung is fun! But challenging • Problems problems problems,

    but can be solved with the right algorithms • Python to the rescue! • Start with a basic idea, and let python (and the community) do the rest