Pythonでライブをしよう!FoxDotを使った新時代のPython活用法 / pyconjp-2019

7560933eeba917db748c562b05fea3a3?s=47 sin-tanaka
September 17, 2019

Pythonでライブをしよう!FoxDotを使った新時代のPython活用法 / pyconjp-2019

PyCon JP 2019 の発表資料です

7560933eeba917db748c562b05fea3a3?s=128

sin-tanaka

September 17, 2019
Tweet

Transcript

  1. PythonͰϥΠϒΛ͠Α͏ʂ FoxDotΛ࢖ͬͨ ৽࣌୅ͷPython׆༻๏ MFWFM"MM ాத৻ଠ࿠ !@TJO@UBOBLB  IBTIUBHQZDPOKQQZDPOKQ@

  2. ର৅ͷํ w 1ZUIPOॻ͚Δ w Իූ͸ಡΊͳ͍͚Ͳ1ZUIPO͸ಡΊΔ w ϓϩάϥϛϯάͰԻָΛͭ͘Δ͜ͱʹڵຯ͕͋Δ w ԻָϊίτνϣοτϫΧϧ w

    Իָ༻ޠͷղઆ౳͸ল͖·͢
  3. ాத৻ଠ࿠ ʢגʣ೔ຊγεςϜٕݚ(FFL-BC/"("/0ελοϑ Իָͱਂ໷ϥδΦ͕޷͖ !@TJO@UBOBLB

  4. <"%>גࣜձࣾ೔ຊγεςϜٕݚ +4- • ࡢ೥ʹҾ͖͖ͭͮɺࠓ೥΋1Z$PO+1εϙϯαʔ • ࠓ೥͸ͳΜͱ(PME • ௕໺ݝ௕໺ࢢͷձࣾ • 1ZUIPO%KBOHPΛ࢖༻ͨ͠8FCΞϓϦέʔγϣϯͷडୗ։ൃٴͼɺαʔόʔϨε

    ΞʔΩςΫνϟΛ࢖༻ͨ͠ϑϩϯτΤϯυҊ݅΍*P5Ҋ݅ͱ͍ͬͨϓϩμΫτ։ൃ ΋΍ͬͯ·͢ • ίϛϡχςΟεϖʔεʮ(&&,-"#/"("/0ʯͷӡӦ • ࠓ೥౓͔ΒϚείοτΩϟϥΫλʔ͕஀ੜ
 • ؔ౦ݍͷ͓٬༷Λத৺ʹϦϞʔτϫʔΫͰ͓࢓ࣄΛ΍Βͤͯ௖͍͍ͯΔ
  5. ϥΠϒίʔσΟϯά֓ཁ 'PY%PUͷ࢖͍ํ %&.0 1ZUIPOͷจ๏ͰಡΈղ͘ ΞδΣϯμ

  6. Ϟνϕʔγϣϯ w ΋ͱ΋ͱझຯͰ%5. w ϥΠϒίʔσΟϯάͷଘࡏ͸஌ͬͯͨ w ͱ͸͍͑ϓϩάϥϛϯά͢Δඞཁͳ͘ͳ͍ʁ!

  7. Ϟνϕʔγϣϯ 4PVSDFIUUQTXJSFEKQBMHPSBWFTMJWFDPEJOHEKT

  8. Ϟνϕʔγϣϯ 4PVSDF(PPHMFը૾ݕࡧ

  9. ϥΠϒίʔσΟϯάͱ͸

  10. ϥΠϒίʔσΟϯάͬͯԿʁ > Live coding is a new direction in electronic

    music and video, and is getting somewhere interesting. Live coders expose and rewire the innards of software while it generates improvised music and/or visuals. All code manipulation is projected for your pleasure. ɹɹɹɹɹɹɹɹɹɹɹɹtoplap.org/about ΑΓҾ༻ w 0OUIFqZQSPHSBNNJOH w +VTUJOUJNFQSPHSBNNJOH BLB Իָө૾ΛΠϯλϥΫςΟϒʹੜ੒͢Δ ϥΠϒɾύϑΥʔϚϯε
  11. ԿͰϥΠϒίʔσΟϯάʁ !%"8΍γʔέϯαͰ΋ಉ͜͡ͱͰ͖ΔͷͰ͸ʁ ΞϧΰϦζϛοΫͳΞϓϩʔν͕Մೳ ࠶ݱੑ ࡞ΓࠐΈ ۮવੑ ଈڵੑ ϧʔύʔΛ࢖ͬͨϥΠϒύϑΥʔϚϯε͕ํ޲ੑ͍͔ۙ΋ʁ

  12. Ͳ͏΍ͬͯϥΠϒίʔσΟϯάʁ

  13. Ͳ͏΍ͬͯϥΠϒίʔσΟϯάʁ ιϑτ໊ ݴޠ 'PY%PU 1ZUIPO 5JEBM$ZDMF )BTLFMM 4POJD1J 3VCZ 0WFSUPOF

    $MPKVSF
  14. 'PY%PU w 4VQFS$PMJEFSΛ1ZUIPO͔Βૢ࡞Ͱ͖ΔϥΠϒϥϦ w 4VQFS$PMJEFSʜԻ੠߹੒༻ͷϓϩάϥϛϯάݴޠٴ ͼ؀ڥ w IUUQTGPYEPUPSH w IUUQTHJUIVCDPN2JSLZ'PY%PU

  15. 'PY%PU 6TFS X1ZUIPO4ZOUBY 04$ 0QFO4PVOE$POUSPM

  16. 1 Clock.bpm = 120 2 Root.default = ‘C’ 3 Scale.default

    = ‘major’ 4 5 d1 >> play(“X-O-”) 6 d2 >> play(“#”, dur=32) 7 8 p1 >> pluck([0,1,2,3,4,3,2,1], dur=1/2, amp=1.5) 9 p2 >> blip(P[0,var([2,4])], dur=1/4, oct=6) 10 11 vo >> loop(‘some/path/file.wav’, dur=4)
  17. 1 Clock.bpm = 120 2 Root.default = ‘C’ 3 Scale.default

    = ‘major’ 4 5 d1 >> play(“X-O-”) 6 d2 >> play(“#”, dur=32) 7 8 p1 >> pluck([0,1,2,3,4,3,2,1], dur=1/2, amp=1.5) 9 p2 >> blip(P[0,var([2,4])], dur=1/4, oct=6) 10 11 vo >> loop(‘some/path/file.wav’, dur=4) SynthDefs
  18. 1 Clock.bpm = 120 2 Root.default = ‘C’ 3 Scale.default

    = ‘major’ 4 5 d1 >> play(“X-O-”) 6 d2 >> play(“#”, dur=32) 7 8 p1 >> pluck([0,1,2,3,4,3,2,1], dur=1/2, amp=1.5) 9 p2 >> blip(P[0,var([2,4])], dur=1/4, oct=6) 10 11 vo >> loop(‘some/path/file.wav’, dur=4) PlayerObject SynthDefs
  19. 1 Clock.bpm = 120 2 Root.default = ‘C’ 3 Scale.default

    = ‘major’ 4 5 d1 >> play(“X-O-”) 6 d2 >> play(“#”, dur=32) 7 8 p1 >> pluck([0,1,2,3,4,3,2,1], dur=1/2, amp=1.5) 9 p2 >> blip(P[0,var([2,4])], dur=1/4, oct=6) 10 11 vo >> loop(‘some/path/file.wav’, dur=4) PatternObject PlayerObject SynthDefs
  20. 1 Clock.bpm = 120 2 Root.default = ‘C’ 3 Scale.default

    = ‘major’ 4 5 d1 >> play(“X-O-”) 6 d2 >> play(“#”, dur=32) 7 8 p1 >> pluck([0,1,2,3,4,3,2,1], dur=1/2, amp=1.5) 9 p2 >> blip(P[0,var([2,4])], dur=1/4, oct=6) 10 11 vo >> loop(‘some/path/file.wav’, dur=4) TimeDependentVar PatternObject PlayerObject SynthDefs
  21. 4ZOUI%FGT w 'PY%PUͷσϑΥϧτͰ༻ҙ͞Ε͍ͯΔԻ৭܈  QMBZʜυϥϜԻݯ w TUSPS1BUUFSO0CKFDUΛ౉͢ w ֤จࣈʹผʑͷԻݯׂ͕ΓৼΒΕ͍ͯΔ 

    MPPQʜࣗલͰ༻ҙͨ͠Ի੠ϑΝΠϧͷϧʔϓ w Ի੠ϑΝΠϧͷύεΛ౉͢  ͦΕҎ֎ʜγϯηαΠβʔͬΆ͍Ի৭ w MJTUPS1BUUFSO0CKFDUΛ౉͢
  22. 1MBZFS0CKFDU w 4ZOUI%FGTΛૢ࡞͢Δ w ଐੑΛฤू͢Δ͜ͱͰԻ৭΍Իߴɺ௕͞౳ΛมߋՄೳ 1 p9 >> pluck(dur=1) 2

    3 # 音の長さ(default: play=1/2, other=1) 4 p9.dur = 2 5 6 # 音量(default: 1) 7 p9.amp = 2 8 9 # 音高 10 p9.degree = [0,1,2,3] 11 12 # オクターブ(default: 5) 13 p9.oct = 7
  23. w ܁Γฦ͠Λදݱ͢ΔΦϒδΣΫτ w MJTUͷ಄ʹ1Λ͚ͭΔ w ࢖͍͜ͳ͢ͱ৑௕ͳίʔυΛආ͚ΒΕΔ 1 # list 2

    plain_list = [0,1,2,3] 3 4 # PatternObject 5 plain_pattern = P[0,1,2,3] 6 1BUUFSO0CKFDU
  24. w 1ZUIPOͷMJTUͱ͸ҧ͏ڍಈ w ศརͳϝιου͕ੜ͑ͯΔ 1 plain_list = [0,1,2,3] 2 plain_pattern

    = P[0,1,2,3] 3 4 # add 5 plain_list + [4,5,6,7] # [0, 1, 2, 3, 4, 5, 6, 7] 6 plain_pattern + [4,5,6,7] # P[4, 6, 8, 10] 7 8 # mul 9 plain_list * 2 # [0, 1, 2, 3, 0, 1, 2, 3] 10 plain_pattern * 2 # P[0, 1, 4, 6] 11 12 plain_pattern.reverse() # P[3,2,1,0] 13 plain_pattern.shuffle() # P[3,1,2,0] 14 plain_pattern.trim(3) # P[0,1,2] 15 1BUUFSO0CKFDU
  25. 5JNF%FQFOEFOU7BSJBCMFT w ࣌ؒͰมԽ͢Δ஋ w $MPDLʹґଘ 1 # 4拍ごとに0→1→2→3のように変化 2 time_depend_var

    = var([0,1,2,3],4) 3 4 # 4拍ごとに0→1→2→3のように徐々に変化 5 time_depend_var_linear = linvar([0,1,2,3],4) 6 7 # Clockに依存するので実行ごとに結果が変わる 8 print(time_depend_var) 9 print(time_depend_var_linear) 10
  26. DEMO

  27. ͜Εͬͯ1ZUIPOͳͷ͔ɾɾɾʁ

  28. 1ZUIPOͷจ๏ʹ౰ͯ͸ΊͯΈΔ

  29. 1ZUIPOͷจ๏ͰಡΈղ͘'PY%PU 1 # 何をしているのか? 2 d1 >> play(“X-O-”) 3 4

    # シフト演算子? 5 x = 0b_0001_0001 6 7 # 左シフト演算子 8 bin(x << 3) # 0b_1000_1000 9 # 右シフト演算子 10 bin(x >> 3) # 0b_10 11
  30. w ಛघϝιου w @@IPHF@@ TFMG 1 class OverrideCall: 2 """

    3 instanceを関数呼び出ししたときの挙動を上書きする 4 """ 5 def __call__(self): 6 return 'call' 7 8 foo = OverrideCall() 9 10 foo() # 'call' 1ZUIPOͷจ๏ͰಡΈղ͘'PY%PU
  31. w γϑτԋࢉࢠͷಈ͖Λ্ॻ͖ 1 foo = '' 2 3 class OverrideShift:

    4 def __rshift__(self, other): 5 return 'override shift' 6 7 bar = OverrideShift() 8 bar >> foo # override shift 9 1ZUIPOͷจ๏ͰಡΈղ͘'PY%PU
  32. ú 1 plain_list = [0,1,2,3] 2 plain_pattern = P[0,1,2,3] 3

    1ZUIPOͷจ๏ͰಡΈղ͘'PY%PU
  33. w EJDUͷΑ͏ʹΞΫηεͨ͠ͱ͖ͷಈ͖Λ্ॻ͖ 1 class ExtDict: 2 def __getitem__(self, args): 3

    return args 4 5 d = ExtDict() 6 d['foo', 'bar'] # ('foo', 'bar') 7 1ZUIPOͷจ๏ͰಡΈղ͘'PY%PU
  34. ࠓ೔࿩ͨ͜͠ͱ·ͱΊ w ϥΠϒίʔσΟϯάͱ͍͏จԽ w 1ZUIPOͱ͍͑͹ʜ w σʔλ෼ੳ w 8FC w

    ϥΠϒίʔσΟϯάˡ/FX w 1ZUIPOͷಛघΫϥεͰ৭ʑมΘΔ w ԋࢉࢠͷڍಈ w ࣙॻతʹΞΫηεͨ͠ͱ͖ͷڍಈ౳ʑʜ
  35. More info… w GPYEPUPSH w UPQMBQPSH w -JWFDPEJOHͷਪਐஂମ w 1Z$PO$;

    w 3ZBO,JSLCSJEF1SPHSBNNJOH.VTJDGPS1FSGPSNBODF-JWFDPEJOH XJUI'PY%PUIUUQTXXXZPVUVCFDPNXBUDI W93/'#;M#FV*UT w 1ZUIPO-JWF$PEJOHc0,$PNQVUFS w ٕज़ॻలͰ൦෍IUUQTPLDPNQVUFSCPPUIQNJUFNT w ZPQQBPSH w ϥΠϒίʔσΟϯάͷॻ੶ग़ͨ͠ΓେֶͰߨ͍ٛͯ͠Δํͷ)1
  36. ͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ