├── CNAME ├── CodeKlavier ├── __init__.py ├── CK_config.py ├── CK_configWriter.py ├── hello_classes.py ├── CK_display.py ├── midi_delegate.py ├── text_classes.py ├── CK_rec.py ├── Motifs.py └── CK_Setup.py ├── doc ├── build │ ├── html │ │ ├── .nojekyll │ │ ├── objects.inv │ │ ├── _static │ │ │ ├── up.png │ │ │ ├── down.png │ │ │ ├── file.png │ │ │ ├── plus.png │ │ │ ├── comment.png │ │ │ ├── minus.png │ │ │ ├── ajax-loader.gif │ │ │ ├── down-pressed.png │ │ │ ├── up-pressed.png │ │ │ ├── background_b01.png │ │ │ ├── comment-bright.png │ │ │ ├── comment-close.png │ │ │ ├── documentation_options.js │ │ │ ├── bizstyle.js │ │ │ └── pygments.css │ │ ├── .buildinfo │ │ ├── search.html │ │ ├── RunCodeKlavier.html │ │ ├── modules.html │ │ └── index.html │ └── doctrees │ │ ├── Hybrid.doctree │ │ ├── index.doctree │ │ ├── modules.doctree │ │ ├── motippets.doctree │ │ ├── CodeKlavier.doctree │ │ ├── HelloWorld.doctree │ │ ├── environment.pickle │ │ ├── Documentation.doctree │ │ └── RunCodeKlavier.doctree ├── source │ ├── modules.rst │ ├── Hybrid.rst │ ├── Motippets.rst │ ├── RunCodeKlavier.rst │ ├── index.rst │ ├── CodeKlavier.rst │ ├── Documentation.rst │ ├── HelloWorld.rst │ └── conf.py └── Makefile ├── _config.yml ├── ck_functions.ini ├── text ├── __init__.py └── text.py ├── hybrid ├── __init__.py └── README.md ├── ml_data ├── _ ├── README.md └── deprecated tests │ ├── 9 notes (all at 60 sec)_18-11-17.csv │ ├── test 3 (9 notes at 240 each)_18-11-17.csv │ ├── test 1 (9 notes with gap after every 3)_18-11-17.csv │ ├── test 4 (9 notes at 120)_18-11-17.csv │ ├── test 6 (9notest at 60)_18-11-17.csv │ ├── test 5 (9 notes at 240)_18-11-17.csv │ ├── deltatime_dif_test_18-11-14.csv │ ├── test 4 (12 notes)_18-11-16.csv │ ├── test 5 (12 notes, last 6 were staccato)_18-11-16.csv │ ├── test7 (mixed, last was a mistake (and incomplete)_18-11-18.csv │ └── test6 (soft and fast but perhaps some notes were missing - although this could be nice to include)_18-11-18.csv ├── motippets ├── __init__.py ├── default_setup.ini └── README.md ├── presenter ├── __init__.py └── README.md ├── ckalculator └── __init__.py ├── hello_world ├── __init__.py ├── SC │ ├── TPSamples │ │ ├── 36.wav │ │ ├── 37.wav │ │ ├── 38.wav │ │ ├── 39.wav │ │ ├── 40.wav │ │ ├── 41.wav │ │ ├── 42.wav │ │ ├── 43.wav │ │ ├── 44.wav │ │ ├── 45.wav │ │ ├── 46.wav │ │ ├── 47.wav │ │ ├── 48.wav │ │ ├── 49.wav │ │ ├── 50.wav │ │ ├── 51.wav │ │ ├── 52.wav │ │ ├── 53.wav │ │ ├── 54.wav │ │ ├── 55.wav │ │ ├── 56.wav │ │ ├── 57.wav │ │ ├── 58.wav │ │ ├── 59.wav │ │ ├── 60.wav │ │ ├── 61.wav │ │ ├── 62.wav │ │ ├── 63.wav │ │ └── 64.wav │ ├── CK_environment.scd │ ├── codespace.scd │ ├── toypiano_sampler.scd │ ├── CodeKlavier_hello_world_v_sampler.scd │ └── CodeKlavier_hello_world_v_RTP.scd ├── README.md ├── hello_world.py ├── instructions_nkk.py └── hello_world_nkk.py ├── logo.png ├── assets ├── images │ ├── CKAR.png │ ├── L-system example.png │ └── codeklavier image.png ├── chapter16_online_appendix.md ├── HDinfo ├── css │ └── style.scss ├── privacy.md ├── papers.md ├── papers.md.orig ├── videos.md ├── augmentedreality.md ├── ACTIVITIES.md ├── arquaticathome.md ├── arquaticnl.md └── arquatic.md ├── pyvenv.cfg ├── requirements.txt ├── requirements.txt.orig ├── setPythonPath.sh ├── ck_functions_ar.ini ├── original lambda mapping ├── _layouts └── default.html ├── instructions.md ├── .gitignore ├── README.md ├── codeklavier.py └── easter eggs /CNAME: -------------------------------------------------------------------------------- 1 | codeklavier.space -------------------------------------------------------------------------------- /CodeKlavier/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CodeKlavier/CK_config.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/build/html/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /ck_functions.ini: -------------------------------------------------------------------------------- 1 | [functions] 2 | 3 | -------------------------------------------------------------------------------- /text/__init__.py: -------------------------------------------------------------------------------- 1 | from text import text -------------------------------------------------------------------------------- /hybrid/__init__.py: -------------------------------------------------------------------------------- 1 | from hybrid import hybrid -------------------------------------------------------------------------------- /ml_data/_: -------------------------------------------------------------------------------- 1 | midi_note,velocity,duration,label 2 | -------------------------------------------------------------------------------- /motippets/__init__.py: -------------------------------------------------------------------------------- 1 | from motippets import motippets -------------------------------------------------------------------------------- /presenter/__init__.py: -------------------------------------------------------------------------------- 1 | from presenter import presenter -------------------------------------------------------------------------------- /ckalculator/__init__.py: -------------------------------------------------------------------------------- 1 | from ckalculator import ckalculator -------------------------------------------------------------------------------- /hello_world/__init__.py: -------------------------------------------------------------------------------- 1 | from hello_world import hello_world -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/logo.png -------------------------------------------------------------------------------- /presenter/README.md: -------------------------------------------------------------------------------- 1 | # Presenter Prototype 2 | 3 | Version used for lectures 4 | -------------------------------------------------------------------------------- /assets/images/CKAR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/assets/images/CKAR.png -------------------------------------------------------------------------------- /doc/build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/objects.inv -------------------------------------------------------------------------------- /doc/build/html/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/up.png -------------------------------------------------------------------------------- /doc/build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/down.png -------------------------------------------------------------------------------- /doc/build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/file.png -------------------------------------------------------------------------------- /doc/build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/plus.png -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/36.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/36.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/37.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/37.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/38.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/38.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/39.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/39.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/40.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/40.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/41.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/41.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/42.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/42.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/43.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/43.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/44.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/44.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/45.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/45.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/46.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/46.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/47.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/47.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/48.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/48.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/49.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/49.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/50.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/50.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/51.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/51.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/52.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/52.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/53.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/53.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/54.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/54.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/55.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/55.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/56.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/56.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/57.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/57.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/58.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/58.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/59.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/59.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/60.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/60.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/61.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/61.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/62.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/62.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/63.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/63.wav -------------------------------------------------------------------------------- /hello_world/SC/TPSamples/64.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/hello_world/SC/TPSamples/64.wav -------------------------------------------------------------------------------- /assets/chapter16_online_appendix.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /16_appendix 3 | --- 4 | 5 | # Chapter 16 - Online Appendix 6 | p -------------------------------------------------------------------------------- /assets/images/L-system example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/assets/images/L-system example.png -------------------------------------------------------------------------------- /doc/build/doctrees/Hybrid.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/Hybrid.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/index.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/modules.doctree -------------------------------------------------------------------------------- /doc/build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/comment.png -------------------------------------------------------------------------------- /doc/build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/minus.png -------------------------------------------------------------------------------- /doc/source/modules.rst: -------------------------------------------------------------------------------- 1 | CodeKlavier 2 | =========== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | CodeKlavier 8 | -------------------------------------------------------------------------------- /assets/images/codeklavier image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/assets/images/codeklavier image.png -------------------------------------------------------------------------------- /doc/build/doctrees/motippets.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/motippets.doctree -------------------------------------------------------------------------------- /pyvenv.cfg: -------------------------------------------------------------------------------- 1 | home = /Users/narcodeb/.pyenv/versions/3.9.7/bin 2 | include-system-site-packages = false 3 | version = 3.9.7 4 | -------------------------------------------------------------------------------- /doc/build/doctrees/CodeKlavier.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/CodeKlavier.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/HelloWorld.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/HelloWorld.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/environment.pickle -------------------------------------------------------------------------------- /doc/build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /doc/build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /doc/build/html/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/up-pressed.png -------------------------------------------------------------------------------- /ml_data/README.md: -------------------------------------------------------------------------------- 1 | # MIDI Data in csv format for implementing Machine Learning in the CK PIA (CodeKlavier Piano Input Analyser) 2 | -------------------------------------------------------------------------------- /doc/build/doctrees/Documentation.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/Documentation.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/RunCodeKlavier.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/doctrees/RunCodeKlavier.doctree -------------------------------------------------------------------------------- /doc/build/html/_static/background_b01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/background_b01.png -------------------------------------------------------------------------------- /doc/build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /doc/build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narcode/codeklavier/HEAD/doc/build/html/_static/comment-close.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pynput>=1.3.6 2 | fn==0.4.3 3 | numpy>=1.21 4 | sphinx 5 | websockets 6 | pyobjc-core 7 | pyobjc-framework-Cocoa 8 | pyobjc-framework-Quartz 9 | python-osc 10 | python-rtmidi 11 | six 12 | -------------------------------------------------------------------------------- /doc/build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 121367e8f6e62adbc1c578681bd73bc9 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /doc/build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: '', 3 | VERSION: '0.3.0', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: false, 8 | SOURCELINK_SUFFIX: '.txt' 9 | }; -------------------------------------------------------------------------------- /doc/source/Hybrid.rst: -------------------------------------------------------------------------------- 1 | Hybrid 2 | ============= 3 | 4 | TODO: write documentation. 5 | 6 | Hybrid python documentation 7 | ------------------------------ 8 | 9 | .. automodule:: hybrid.hybrid 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: 13 | -------------------------------------------------------------------------------- /doc/source/Motippets.rst: -------------------------------------------------------------------------------- 1 | Motippets 2 | ========= 3 | 4 | TODO: write documentation. 5 | 6 | Motippets python documentation 7 | ------------------------------ 8 | 9 | .. automodule:: motippets.motippets 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: 13 | -------------------------------------------------------------------------------- /assets/HDinfo: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /hdinfo 3 | --- 4 | 5 | # CodeKlavier Videos 🎹🎤 6 | 7 | ### This page gives a short explanation of the two videos featured during Hashidays 2023 8 | 9 | May/June 2023: Recording videos of ARquatic and MercTippets for HashiCorps HashiDays 2023 10 | 11 | -------------------------------------------------------------------------------- /requirements.txt.orig: -------------------------------------------------------------------------------- 1 | pynput>=1.3.6 2 | fn==0.4.3 3 | numpy==1.15.4 4 | sphinx 5 | <<<<<<< HEAD 6 | websockets 7 | pyobjc-core==5.2 8 | pyobjc-framework-Cocoa==5.2 9 | pyobjc-framework-Quartz==5.2 10 | ======= 11 | >>>>>>> master 12 | python-osc==1.7.2 13 | python-rtmidi 14 | six==1.12.0 15 | -------------------------------------------------------------------------------- /setPythonPath.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #set the Pythonpath so Python will recognize the CodeKlaviever package 4 | #run this script everytime you start a new shell session 5 | #alternatively: put it in your ~/bashrc 6 | #TODO: find options for windows users 7 | 8 | PYTHONPATH=$(pwd)'/CodeKlavier':$PYTHONPATH 9 | export PYTHONPATH 10 | -------------------------------------------------------------------------------- /hello_world/SC/CK_environment.scd: -------------------------------------------------------------------------------- 1 | // CodeKlavier Environment 2 | 3 | ~stop = Environment[ 4 | 'now' -> {|self| 5 | "stopping".postln; 6 | SkipJack.stop("pedalwatch"); 7 | ~hello.stop; 8 | ~hello2.stop; 9 | ~hello3.stop; 10 | ~ost.stop; 11 | ~ost1.stop; 12 | ~ost2.stop; 13 | ~down=0;~down1=0;~down2=0; 14 | ~op=0;~op1=0;~op2=0; 15 | } 16 | ]; 17 | 18 | ~stop.know = true; -------------------------------------------------------------------------------- /ck_functions_ar.ini: -------------------------------------------------------------------------------- 1 | [functions] 2 | 3 | function1: 25,27,31,33 -> (dropAll) 4 | function2: 37,39,44,46 -> (sendRuleAR 1.212) 5 | function3: 49,51,56,58 -> (sendRuleAR 2.323) 6 | function4: 61,63,68,70 -> (sendRuleAR 3.717) 7 | function5: 73,75,80,82 -> (storeCollect 1 4 7) 8 | function6: 85,87,92,94 -> (collectAll) 9 | function7: 72,73,74,75 -> (abraham) 10 | function8: 72,74,76,80 -> (create) 11 | function9: 72,74,76,78 -> (create) 12 | -------------------------------------------------------------------------------- /original lambda mapping: -------------------------------------------------------------------------------- 1 | [lambda] 2 | # lambda function : midi number mapped to the function ORIGINAL 3 | evaluate_function: 59 4 | identity_midi: 23 5 | select_first_midi: 0 6 | select_second_midi: 0 7 | successor_midi: 83, 95 8 | predecessor_midi: 0 9 | add_midi: 107 10 | subtract_midi: 71 11 | mult_midi: 0 12 | division_midi: 0 13 | greater_than_midi: 47 14 | equality_midi: 0 15 | less_than_midi: 0 16 | 17 | [articulation] 18 | # articulation name : threshold in seconds 19 | chord: 0.02 20 | staccato: 0.35 21 | sostenuto: 0.8 22 | 23 | [ar] 24 | dot: 35 25 | -------------------------------------------------------------------------------- /hello_world/SC/codespace.scd: -------------------------------------------------------------------------------- 1 | // code space 2 | ~path = thisProcess.nowExecutingPath.dirname 3 | 4 | 5 | // evaluate one from below, not both \\\ 6 | (~path ++ "/CK_environment.scd").load; 7 | 8 | // OPTION 1: to load internal toy pinao sampler (i.e. midi loopback): 9 | (~path ++ "/CodeKlavier_hello_world_v_sampler.scd").load; 10 | {2.do{(~path ++ "/toypiano_sampler.scd").load; 2.wait;};}.fork; 11 | 12 | // OPTION 2: to play with Robot Toy Piano instrument (i.e. midiout): 13 | (~path ++ "/CodeKlavier_hello_world_v_RTP.scd").load; 14 | 15 | 16 | ///////////// start coding ⬇ \\\\\\\\\\ 17 | -------------------------------------------------------------------------------- /doc/source/RunCodeKlavier.rst: -------------------------------------------------------------------------------- 1 | Run codeklavier 2 | =============== 3 | 4 | To help you run CodeKlavier, we have made a "run all" master wrapper script. It is in the CodeKlavier root directory and it is called ``codeklavier.py``. You can run it by typng ``./codeklavier.py -i`` and the script will start in interactive mode. Run ``./codeklavier.py --help`` to get more help. 5 | 6 | PythonPath 7 | ---------- 8 | Make sure you set the pythonpath before you start the script You can set the pythonpath by runnin ``. setPythonPath.sh`` from the root CodeKlavier directory (note the **dot-space** at the beginning) or add the pythonpath to your ``bash_profile``. 9 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/9 notes (all at 60 sec)_18-11-17.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 3 (9 notes at 240 each)_18-11-17.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | .. CodeKlavier documentation master file, created by 2 | sphinx-quickstart on Thu Feb 1 22:04:39 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to CodeKlavier's documentation! 7 | ======================================= 8 | 9 | Contents 10 | ======== 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | RunCodeKlavier 15 | HelloWorld 16 | Motippets 17 | Hybrid 18 | Documentation 19 | modules.rst 20 | 21 | 22 | Indices and tables 23 | ================== 24 | 25 | * :ref:`genindex` 26 | * :ref:`modindex` 27 | * :ref:`search` 28 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 1 (9 notes with gap after every 3)_18-11-17.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | -------------------------------------------------------------------------------- /assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | @import "{{ site.theme }}"; 5 | 6 | header { 7 | background-image: url('../images/codeklavier image.png'); 8 | background-position: 0; 9 | background-repeat: no-repeat; 10 | background-size: cover; 11 | } 12 | 13 | #headlink { 14 | text-decoration: none; 15 | color: #b5e853; 16 | } 17 | 18 | header h2 { 19 | background-color: black; 20 | border-radius: 10%; 21 | padding: 10px; 22 | width: 50%; 23 | border: 2px solid #b5e853; 24 | } 25 | 26 | .btn { 27 | background: black; 28 | border: 2px solid rgb(181, 232, 83); 29 | } 30 | 31 | .vids-cols { 32 | display: flex; 33 | flex-flow: row; 34 | justify-content: space-between; 35 | } 36 | -------------------------------------------------------------------------------- /assets/privacy.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /privacy 3 | --- 4 | 5 | # ARquatic App - Privacy Policy 6 | 7 | ## Last updated: April 16, 2021 8 | 9 | Codeklavier’s ‘ARquatic' app is solely used as an experience companion during 'ARquatic' concerts. We do not collect and share any information internally or with third parties. 10 | This project is an open-source artistic project exploring piano music and augmented reality. There is therefore no need to collect any data. 11 | 12 | ## Types of Data Collected 13 | 14 | ### Personal Data 15 | None 16 | 17 | ### Usage Data 18 | None 19 | 20 | ## Questions? 21 | You can always send an email to our producer and pianist anne.veinberg [at] gmail.com 22 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = CodeKlavier 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /CodeKlavier/CK_configWriter.py: -------------------------------------------------------------------------------- 1 | """ 2 | Write a configfile for CodeKlavier 3 | """ 4 | 5 | import configparser 6 | from CK_Setup import Setup 7 | 8 | def createConfig(configfile='my_settings.ini'): 9 | """Create a basic configfile 10 | 11 | TODO!!: avoid that the created configfile overwrites the existing file 12 | (if present)! 13 | 14 | :param string configfile: path and name of the configfile 15 | """ 16 | codeK = Setup() 17 | codeK.show_ports() 18 | myPort = codeK.get_port_from_user() 19 | codeK.open_port(myPort) 20 | device_id = codeK.get_device_id() 21 | 22 | config = configparser.ConfigParser() 23 | config.add_section('midi') 24 | config['midi']['port'] = str(myPort) 25 | config['midi']['noteon_id'] = str(device_id) 26 | 27 | with open(configfile, 'w') as f: 28 | config.write(f) 29 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 4 (9 notes at 120)_18-11-17.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,60,59,7.438792583000001,0,144,61,67,7.926577105000001,0,128,60,74,7.933750063000001,0.007172958,128,61,71,8.408285124999999,0.474535062,144,62,62,8.424772568,0,128,62,75,8.892010698,0.46723813000000003,144,60,63,8.910368333,0,144,61,71,9.398349228,0,128,60,75,9.409210233,0.010861005,128,61,72,9.870328650000001,0.46111841700000006, 3 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 6 (9notest at 60)_18-11-17.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,62,62,4.111337882,0,144,69,69,5.08367226,0,128,62,66,5.1234916120000005,0.039819352,144,73,73,6.110656095,0,128,69,67,6.133662457000001,0.023006362000000002,144,62,42,7.142344257,0,128,73,62,7.145294000000001,0.0029497430000000003,144,69,65,8.139568635,0,128,62,71,8.14756305,0.007994415000000001,128,69,69,9.100955305,0.9533922550000001, 3 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 5 (9 notes at 240)_18-11-17.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,61,63,4.450725253000001,0,144,74,72,4.694201985,0,128,61,67,4.705353728,0.011151743,128,74,72,4.937025170000001,0.23167144200000003,144,68,62,4.959396710000001,0,128,68,63,5.219154938000001,0.259758228,144,61,65,5.223249515000001,0,144,74,71,5.490338693000001,0,128,61,66,5.512000070000001,0.021661377000000002,128,74,71,5.719111218000001,0.207111148, 3 | -------------------------------------------------------------------------------- /CodeKlavier/hello_classes.py: -------------------------------------------------------------------------------- 1 | """ 2 | classes for Hello World. 3 | First prototype of the CodeKlavier 4 | 5 | """ 6 | import rtmidi 7 | 8 | class HelloWorld(object): 9 | """ class to handle the midi input and map it to characters 10 | """ 11 | 12 | def __init__(self, port, mapping, noteonid): 13 | """Setup the class 14 | 15 | :param int port: the portnumber 16 | :param dict mapping: the mapping to use 17 | :param noteonid: the note-on id 18 | """ 19 | self.port = port 20 | self.mapscheme = mapping 21 | self.noteonid = noteonid 22 | 23 | def __call__(self, event, data=None): 24 | """Deal with the cal function 25 | 26 | :param event: ? 27 | :param data: ? 28 | """ 29 | message, deltatime = event 30 | if message[0] != 254: 31 | if message[2] > 0: #only noteOn 32 | if (message[0] == self.noteonid): 33 | self.mapscheme.mapping(message[1]) 34 | 35 | if (message[0] == 176): #hardcoded pedal id (not pretty) TODO: make it dynamic 36 | self.mapscheme.stopSC(message[1]) 37 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% seo %} 10 | 11 | 12 | 13 | 14 |
15 |
16 |

{{ site.title | default: site.github.repository_name }}

17 |

{{ site.description | default: site.github.project_tagline }}

18 | 19 |
20 | {% if site.show_downloads %} 21 | Download as .zip 22 | Download as .tar.gz 23 | {% endif %} 24 | View on GitHub 25 |
26 |
27 |
28 | 29 |
30 |
31 | {{ content }} 32 |
33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /doc/build/html/_static/bizstyle.js: -------------------------------------------------------------------------------- 1 | // 2 | // bizstyle.js 3 | // ~~~~~~~~~~~ 4 | // 5 | // Sphinx javascript -- for bizstyle theme. 6 | // 7 | // This theme was created by referring to 'sphinxdoc' 8 | // 9 | // :copyright: Copyright 2012-2014 by Sphinx team, see AUTHORS. 10 | // :license: BSD, see LICENSE for details. 11 | // 12 | $(document).ready(function(){ 13 | if (navigator.userAgent.indexOf('iPhone') > 0 || 14 | navigator.userAgent.indexOf('Android') > 0) { 15 | $("li.nav-item-0 a").text("Top"); 16 | } 17 | 18 | $("div.related:first ul li:not(.right) a").slice(1).each(function(i, item){ 19 | if (item.text.length > 20) { 20 | var tmpstr = item.text 21 | $(item).attr("title", tmpstr); 22 | $(item).text(tmpstr.substr(0, 17) + "..."); 23 | } 24 | }); 25 | $("div.related:last ul li:not(.right) a").slice(1).each(function(i, item){ 26 | if (item.text.length > 20) { 27 | var tmpstr = item.text 28 | $(item).attr("title", tmpstr); 29 | $(item).text(tmpstr.substr(0, 17) + "..."); 30 | } 31 | }); 32 | }); 33 | 34 | $(window).resize(function(){ 35 | if ($(window).width() <= 776) { 36 | $("li.nav-item-0 a").text("Top"); 37 | } 38 | else { 39 | $("li.nav-item-0 a").text("CodeKlavier 0.3.0 documentation"); 40 | } 41 | }); -------------------------------------------------------------------------------- /assets/papers.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /publications 3 | --- 4 | 5 | # CodeKlavier Publications 📝 6 | 7 |

8 | ## 'The CodeKlavier: Appropriating the piano as a live coding instrument' 9 | **Authors:** Felipe Ignacio Noriega, Anne Veinberg
10 | **Publication:** Chapter 17 in book 'Re-thinking The Musical Instrument'edited by Mine Doganton-Dack
11 | [link](https://www.cambridgescholars.com/product/978-1-5275-7789-3) 12 | 13 |

14 | ## The sound of lambda 15 | **Authors:** Felipe Ignacio Noriega, Anne Veinberg
16 | **Publication:** FARM 2019: Proceedings of the 7th ACM SIGPLAN International Workshop on Functional Art, Music, Modeling, and DesignAugust 2019 Pages 56–60
17 | [link](https://dl.acm.org/doi/abs/10.1145/3331543.3342583) \ 18 | [Paper download](https://drive.google.com/file/d/1lEfXXN59y1iKI3wrd--RE0UZrG3-yzk4/view?usp=sharing) 19 | 20 |

21 | ## Coding with the piano: The first phase of the CodeKlavier's development 22 | **Authors:** Anne Veinberg, Felipe Ignacio Noriega
23 | **Publication:** International Computer Music Conference 2018
24 | [link](https://drive.google.com/file/d/1UIr2JyPqRw833OIkBgDrx2P6VjZcEKf1/view) 25 | 26 |

27 | ## Scheduled visual contact as a strategy for improved communication in a live coder and piano ensemble 28 | **Authors:** Anne Veinberg, Felipe Ignacio Noriega
29 | **Publication:** International Conference on Live Coding 2016
30 | [link](https://www.keyboardsunite.com/offzz/ICLC-paperrevised.pdf) 31 | -------------------------------------------------------------------------------- /CodeKlavier/CK_display.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | class CK_display(object): 4 | """ 5 | Class to handle display functionality 6 | """ 7 | 8 | def __init__(self, num_displays): 9 | """ 10 | initialize the number of display's and the corresponding UDP ports 11 | """ 12 | self._display1 = 1111 13 | self._display2 = 2222 14 | self._display3 = 3333 15 | self._display4 = 4444 16 | self._display5 = 5555 17 | 18 | def formatAndSend(self, msg='', encoding='utf-8', host='localhost', display=1, syntax_color='', spacing=True): 19 | """format and prepare a string for sending it over UDP socket 20 | 21 | :param str msg: the string to be sent 22 | :param str encoding: the character encoding 23 | :param str host: the UDP server hostname 24 | :param int display: the UDP destination port 25 | :param str syntax_color: the tag to use for syntax coloring (loop, primitive, mid, low, hi, snippet) 26 | :param boolean spacing: wheather to put a \n (new line) before the msg 27 | """ 28 | 29 | if display == 1: 30 | port = 1111 31 | elif display == 2: 32 | port = 2222 33 | elif display == 3: 34 | port = 3333 35 | elif display == 4: 36 | port = 4444 37 | elif display == 5: 38 | port = 5555 39 | 40 | if spacing: 41 | newline = '\n' 42 | else: 43 | newline = '' 44 | 45 | return self.__socket.sendto(bytes(syntax_color+newline+msg, encoding), (host, port)) -------------------------------------------------------------------------------- /hybrid/README.md: -------------------------------------------------------------------------------- 1 | # Hybrid Prototype 2 | The hybrid prototype allows for easy transition from the "hello world" prototype to the Motippets prototype without stopping any of the running code. Check the README.md in the HelloWorld and Motippets directory for more information about what these prototypes can do. 3 | 4 | The hybrid prototype comes with a 5 column display for the printed text, the first of which is for "hello world" and 2-5 are for Motippets. 5 | 6 | Column 1 - "hello world" 7 | Column 2 - Mot. Snippet 1 8 | Column 3 - Mot. Snippet 2 9 | Column 4 - Mot. Conditionals text 10 | Column 5 - Mot. Conditionals running loops 11 | 12 | 13 | ## Run 14 | Make sure you in the right directory and have installed SuperCollider and the required libraries as mentioned in the general [Read Me document](https://github.com/narcode/codeklavier-python/blob/master/README.md) 15 | 16 | To run hybrid codeklavier: ``python3 codeklavier.py -p hybrid`` 17 | To run display: Make sure you are in the Codeklavier folder of the codeklavier directory and then use ``python3 CK_socket.py -d5`` 18 | 19 | ## Using the hybrid 20 | Switching between the two prototypes is done by pressing the top Bb on the piano. All sound processes and the ongoing conditionals will continue running so the change will only impact the input mode for the piano. 21 | 22 | Be sure to evaluate the SuperCollider files that correspond with your desired code output extension 23 | 24 | ## Videos 25 | 26 | The hybrid is artisticly currently still under development but to get a taste of the visual display, you can watch a video from our concert at [In-Sonora Festival in Madrid in March 2018.] (https://youtu.be/F5O_WUdtOqY?t=1h31m1s) 27 | -------------------------------------------------------------------------------- /instructions.md: -------------------------------------------------------------------------------- 1 | ## Instructions to boot 2 | 3 | 1. In folder codeklavier-extras/websocket-server 4 | python3 server.py --local —-reset (only use local if running both CKAR app AND CK from the same laptop) 5 | 2. In codeklavier folder: python3 codeklavier -p ckalculator 6 | 3. Open app CodeklaviAR (if using two laptops, make sure the app is configured to send to the local ip of SC computer. You can find this via the system pref or by under the inet under en0 7 | 4. In folder codeklavier-supercollider/ck_ar: osc_defs.sc (evaluate everything) 8 | 9 | 10 | ## How to use: 11 | To make an axiom, the values must be within brackets and without a rule) 12 | For example: 13 | (2 1 2) 14 | 15 | To make a rule put the values of what you want changed, followed by the '.' and what it should become. 16 | For example: 17 | (2.1 0 1) 18 | 19 | You can also make 'no numbers' by in brackets making a comparison and adding a value to the True/False value. 20 | For example: 21 | (5 > 4 [eval] + 3) essentialy this becomes (True + 3) 22 | This translates to the 'N' token which removes the symbol 23 | 24 | For tree operatons, the commands are as follows. Besides the dot, the other dunctions are only accesible in the context of a function (ostinato) figure. Please note the ostinato should have a change of 2 semitones. 25 | dot: lowest A 26 | create tree: C 27 | drop tree: D, but short (make number first include evaluate!) 28 | collect tree: D but long (make number first include evaluate!) 29 | next: F, but short 30 | previous: F, but now tenuto 31 | Eventually these operations will only exist in the context of defining a new function (with ostinato and a note change of 2 semitones). More to follow 32 | transform: G 33 | Change shape: A 34 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/deltatime_dif_test_18-11-14.csv: -------------------------------------------------------------------------------- 1 | source_id,midi_note,velocity,deltatime,ck_deltatime,dif_deltatime 2 | 144, 60, 67,0.040772787000000005,12.639370326,0 3 | 128, 60, 127,0.04003023,12.679400556,0.04003022999999928 4 | 144, 62, 71,0.007736420000000001,13.606021880999998,0.9266213249999993 5 | 128, 62, 127,0.041713816,13.647735696999998,0.04171381599999968 6 | 144, 60, 75,0.00246109,14.600684185999999,0.9529484890000006 7 | 128, 60, 71,0.09435752800000001,14.695041713999998,0.09435752799999975 8 | 144, 62, 80,0.032358513000000005,15.630542794,0.9355010800000017 9 | 128, 62, 127,0.039575821000000004,15.670118615,0.03957582099999968 10 | 144, 60, 71,0.01897799,16.616933151999998,0.9468145369999981 11 | 128, 60, 97,0.047251323000000005,16.664184475,0.04725132300000112 12 | 144, 62, 80,0.033338385000000005,17.631192066000004,0.9670075910000051 13 | 128, 62, 65,0.07463865900000001,17.705830725000006,0.07463865900000144 14 | 144, 60, 75,0.027929962000000003,18.625795789000005,0.9199650639999994 15 | 128, 60, 96,0.048192048,18.673987837000006,0.048192048000000653 16 | 144, 62, 81,0.030882379,19.628544770000005,0.9545569329999992 17 | 128, 62, 60,0.08248707000000001,19.711031840000004,0.08248706999999911 18 | 144, 60, 68,0.011184694,20.608667216,0.8976353759999967 19 | 128, 60, 68,0.07459940100000001,20.683266617,0.0745994010000004 20 | 144, 62, 77,0.19082806700000002,21.588194037,0.9049274199999999 21 | 128, 62, 96,0.039538949000000004,21.637016906000003,0.0488228690000021 22 | 144, 60, 63,0.16493887000000002,22.562226730000003,0.9252098239999995 23 | 128, 60, 89,0.015405930000000002,22.612719642000002,0.05049291199999928 24 | 144, 62, 70,0.06501968000000001,23.662150549,1.0494309069999979 25 | 128, 62, 103,0.045155985,23.707306534,0.04515598500000095 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *.cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # Jupyter Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | error sending 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # Environments 83 | .env 84 | .venv 85 | env/ 86 | venv/ 87 | ENV/ 88 | bin/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # EXTRA 104 | .DS_Store 105 | 106 | #Allow html buld 107 | !doc/build 108 | 109 | # CK user files 110 | ck_functions.ini 111 | -------------------------------------------------------------------------------- /CodeKlavier/midi_delegate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """midi_delegate.py 3 | 4 | This file opens a delegate between nodejs and python's CodeKlavier. 5 | Used for the installation at NKK 2017 6 | """ 7 | 8 | #TODO: use CodeKlavier module 9 | 10 | import time 11 | from pynput.keyboard import Key, Controller 12 | from CK_Setup import Setup 13 | 14 | def run(codeK): 15 | """Run the CodeKlavier 16 | 17 | :param CodeKlavier.Setup.setup codeK: the setup file 18 | """ 19 | print("CodeKlavier is ON. Press Control-C to exit.") 20 | try: 21 | timer = time.time() 22 | keyboard = Controller() 23 | while True: 24 | msg = codeK.get_message() 25 | 26 | if msg: 27 | message, deltatime = msg 28 | # this filters the 'enter' delegate: 29 | if message[1] == 64 and message[2] == 1: 30 | print('deltatime: ', deltatime, 'msg: ', message) 31 | print('enter sent!') 32 | keyboard.press(Key.enter) 33 | keyboard.release(Key.enter) 34 | time.sleep(2) 35 | 36 | #this sends the break delegate 37 | if message[1] == 64 and message[2] == 2: 38 | break 39 | 40 | time.sleep(0.01) 41 | 42 | except KeyboardInterrupt: 43 | print('') 44 | finally: 45 | print("MIDI delegate auto-destruct") 46 | codeK.end() 47 | 48 | def main(): 49 | """Main function as example. 50 | """ 51 | 52 | codeK = Setup() 53 | 54 | # Start the CodeKlavier 55 | codeK = Setup() 56 | myPort = codeK.perform_setup() 57 | codeK.open_port(myPort) 58 | device_id = codeK.get_device_id() 59 | print('your device id is: ', device_id, '\n') 60 | run(codeK) 61 | 62 | if __name__ == "__main__": 63 | main() 64 | -------------------------------------------------------------------------------- /motippets/default_setup.ini: -------------------------------------------------------------------------------- 1 | [midi] 2 | port: 2 3 | device_id: 144 4 | noteoff_id: 0 5 | 6 | [snippets] 7 | snippet1 : ~snippet1 = Tdef(\1, {|ev| loop{ Ndef(~name.next,{|pitch=420,fx=88| SinOsc.ar(456*LFTri.kr(fx).range(100, pitch)) * EnvGen.kr(Env.perc) * ev.amp}).play(0,2);(1/ev.rit).wait;}}).play(~ts, quant:0).envir = (rit: ~tremoloL, amp: 0.036); 8 | 9 | mini_snippet_hi_1: [\pulse, \pulse2, \pulse3, \pulse4, \pulse5, \pulse6].do{|i| Ndef(i).map(\fx, Ndef(\krm3));}; ~tremoloH1; 10 | mini_unmap_hi_2: Ndef(\acc).set(\fx, ~tremoloH2.linlin(1, 16, 0, 15)); 11 | 12 | mini_snippet_mid_1: [\pulse, \pulse2, \pulse3, \pulse4, \pulse5, \pulse6].do{|i| Ndef(i).map(\pitch, Ndef(\krm1));}; ~tremoloM1; 13 | mini_unmap_mid_2: Ndef(\acc).set(\note, ~tremoloM2.linlin(1, 16, 180, 800)); 14 | 15 | mini_snippet_low_1: ~map_rhythm = true; ~tremoloL1; 16 | mini_unmap_low_1: ~map_rhythm = false; 17 | mini_unmap_low_2: Ndef(\acc).set(\amp, ~tremoloL2.linlin(1, 16, 0, 1.5)) 18 | mini_unmap_low_3: ~map_amplitude = false; 19 | mini_snippet_low_1_amp: ~map_amplitude = true; ~tremoloL1amp; 20 | 21 | snippet2 : ~snippet2 = Ndef(\acc, {|note=500, amp=0.036, cut=200, bw=0.5, fx=0.1| BPF.ar(Resonz.ar(SinOsc.ar([note.lag(1), note.lag(2)*3/2, note*2, note.lag(1.5)*4/3]), (note*LFTri.kr(fx).range(1/2, 8))+80, bw), 600, 0.8) * amp.lag(0.5)}).play(0,2); 22 | 23 | mini_snippet_hi_2: Ndef(\acc).map(\fx, Ndef(\krm2_3)); ~tremoloH2; 24 | mini_unmap_hi_1: [\pulse, \pulse2, \pulse3, \pulse4, \pulse5, \pulse6].do{|i| Ndef(i).set(\fx, ~tremoloH1.linlin(1, 16, 1, 88));} 25 | 26 | mini_snippet_mid_2: Ndef(\acc).map(\note, Ndef(\krm2_1)); ~tremoloM2; 27 | mini_snippet_mid_2b: Ndef(\acc).map(\note, Ndef(\krm2_1)); ~tremoloH2; 28 | mini_unmap_mid_1: [\pulse, \pulse2, \pulse3, \pulse4, \pulse5, \pulse6].do{|i| Ndef(i).set(\pitch, ~tremoloM1.linlin(1, 16, 200, 3000));}; 29 | 30 | mini_snippet_low_2: Ndef(\acc).map(\amp, Ndef(\krm2_2)); ~tremoloL2 31 | -------------------------------------------------------------------------------- /motippets/README.md: -------------------------------------------------------------------------------- 1 | # Motippets 2 | 3 | The Motippets prototype is able to parse selected melodic/harmonic motifs and map these to music making code snippets. Once a snippet is present, up to three of its variables can be manipulated through a tremolo recognition function. This function calculates the interval of the tremolo in real-time and sets this value to the associated variable. The keyboard is divided into three distinct ranges and we use mini-motifs to direct the system as to which variable is being manipulated at any given moment.This setup enables the pianist to code and manipulate snippets in parallel- a feature made possible by the use of the piano keyboard as a coding interface. 4 | 5 | Furthermore, in Motippets the performer is able to set up both ongoing and momentary conditionals. These conditionals test aspects of the pianist’s playing such as the number of notes played over a particular time period or the range within which the pianist IS or IS NOT playing. If a test is passed, an event occurs. All of the values and outcomes of these conditionals are set up by the pianist during the performance. 6 | 7 | The performer is relatively free to play anything on the piano but must ensure that the coding motifs are integrated into the performance. The structure is not set and should be reactionary to the interaction of the coded algorithms.You can watch a video of one version of Motippets [here](https://youtu.be/nzsW1w38JEc) 8 | 9 | 10 | ## Run 11 | Make sure you have installed supercollider and the required libraries before you 12 | start motippets. Then run: ``python3 codeklavier.py -p hybrid`` <--- be sure to avoid the top Bb! You can also run ``python3 codeklavier.py -p motippets`` but this version may not stay as upto date as the hybrid. 13 | 14 | 15 | ## Customise 16 | This prototype is musically customisable by adjusting the motifs used to trigger the snippets in the motifs class and/or adjusting the printed snippets in the default.ini 17 | -------------------------------------------------------------------------------- /doc/source/CodeKlavier.rst: -------------------------------------------------------------------------------- 1 | CodeKlavier package 2 | =================== 3 | 4 | CodeKlavier\.CK_Setup module 5 | ---------------------------- 6 | 7 | .. automodule:: CodeKlavier.CK_Setup 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | CodeKlavier\.CK_configWriter module 13 | ----------------------------------- 14 | 15 | .. automodule:: CodeKlavier.CK_configWriter 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | CodeKlavier\.Instructions module 21 | -------------------------------- 22 | 23 | .. automodule:: CodeKlavier.Instructions 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | CodeKlavier\.Mapping module 29 | --------------------------- 30 | .. We specifify the separate classes and not use automodule to include the __init__ method 31 | 32 | .. autoclass:: CodeKlavier.Mapping.Mapping_HelloWorld 33 | :members: 34 | :undoc-members: 35 | 36 | .. automethod:: __init__ 37 | 38 | .. autoclass:: CodeKlavier.Mapping.Mapping_HelloWorld_NKK 39 | :members: 40 | :undoc-members: 41 | 42 | .. automethod:: __init__ 43 | 44 | .. autoclass:: CodeKlavier.Mapping.Mapping_Motippets 45 | :members: 46 | :undoc-members: 47 | 48 | .. automethod:: __init__ 49 | 50 | CodeKlavier\.Motifs module 51 | -------------------------- 52 | 53 | .. automodule:: CodeKlavier.Motifs 54 | :members: 55 | :undoc-members: 56 | :show-inheritance: 57 | 58 | CodeKlavier\.hello\_classes module 59 | ---------------------------------- 60 | 61 | .. automodule:: CodeKlavier.hello_classes 62 | :members: 63 | :undoc-members: 64 | :show-inheritance: 65 | 66 | CodeKlavier\.midi\_delegate module 67 | ---------------------------------- 68 | 69 | .. automodule:: CodeKlavier.midi_delegate 70 | :members: 71 | :undoc-members: 72 | :show-inheritance: 73 | 74 | CodeKlavier\.motippets\_classes module 75 | -------------------------------------- 76 | 77 | .. automodule:: CodeKlavier.motippets_classes 78 | :members: 79 | :undoc-members: 80 | :show-inheritance: 81 | 82 | -------------------------------------------------------------------------------- /assets/papers.md.orig: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /publications 3 | --- 4 | 5 | # CodeKlavier Publications 📝 6 | 7 | <<<<<<< HEAD 8 | 9 | ### The sound of lambda 10 | Authors: Felipe Ignacio Noriega, Anne Veinberg 11 | Publication: FARM 2019: Proceedings of the 7th ACM SIGPLAN International Workshop on Functional Art, Music, Modeling, and DesignAugust 2019 Pages 56–60https://doi.org/10.1145/3331543.3342583 12 | 13 | ## Scheduled visual contact as a strategy for improved communication in a live coder and piano ensemble 14 | Authors: Anne Veinberg, Felipe Ignacio Noriega 15 | Publication: https://www.keyboardsunite.com/offzz/ICLC-paperrevised.pdf 16 | 17 | ## Coding with the piano: The first phase of the CodeKlavier's development 18 | Authors: Anne Veinberg, Felipe Ignacio Noriega 19 | Publication: https://drive.google.com/file/d/1UIr2JyPqRw833OIkBgDrx2P6VjZcEKf1/view 20 | 21 | 22 | ## In process: Writing Chapter 17 of the book .... 23 | ======= 24 |

25 | ## 'The CodeKlavier: Appropriating the piano as a live coding instrument' 26 | **Authors:** Felipe Ignacio Noriega, Anne Veinberg
27 | **Publication:** In process: Chapter 17 in book 'Re-thinking The Musical Instrument'edited by Mine Doganton-Dack
28 | 29 |

30 | ## The sound of lambda 31 | **Authors:** Felipe Ignacio Noriega, Anne Veinberg
32 | **Publication:** FARM 2019: Proceedings of the 7th ACM SIGPLAN International Workshop on Functional Art, Music, Modeling, and DesignAugust 2019 Pages 56–60
33 | [link](https://doi.org/10.1145/3331543.3342583D) 34 | 35 |

36 | ## Coding with the piano: The first phase of the CodeKlavier's development 37 | **Authors:** Anne Veinberg, Felipe Ignacio Noriega
38 | **Publication:** International Computer Music Conference 2018
39 | [link](https://drive.google.com/file/d/1UIr2JyPqRw833OIkBgDrx2P6VjZcEKf1/view) 40 | 41 |

42 | ## Scheduled visual contact as a strategy for improved communication in a live coder and piano ensemble 43 | **Authors:** Anne Veinberg, Felipe Ignacio Noriega
44 | **Publication:** International Conference on Live Coding 2016
45 | [link](https://www.keyboardsunite.com/offzz/ICLC-paperrevised.pdf) 46 | >>>>>>> master 47 | -------------------------------------------------------------------------------- /assets/videos.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /videos 3 | --- 4 | 5 | # CodeKlavier VIDEOS 🎥 🎹 6 | 7 |
8 | ### Introductory video by Creative Industries Fund NL: 9 |
10 | 11 |
12 | 13 |
14 | ## CodeKlavier in action: 15 |
16 | 17 |
18 |
In concert
19 | 20 |
21 | 22 |
23 | 24 |
25 |
@ studio
26 | 27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /doc/source/Documentation.rst: -------------------------------------------------------------------------------- 1 | Documentation 2 | ============= 3 | Every developer likes to have documentation, but no one really likes to write it. 4 | 5 | Sphinx and rst 6 | -------------- 7 | To help us with the documentation proces, CodeKlavier uses the Sphinx package that converts rst-files (that are easy to write) to html-files that are beautiful and easy to browse. On top of that: Sphinx can 'walk' over the python source code and generate the documentation out of the docstrings in the python code. 8 | 9 | Rst-files are plain text files with some basic formatting. You can underline words with === to indicate a header and you use '*' to use **boldface** and so on. There is enough material on the internet to help you with the basics. 10 | 11 | Installation 12 | ............ 13 | You can use ``pip3`` to install the Sphinx-package by running:: 14 | 15 | pip3 install sphinx 16 | 17 | Use pip3 because CodeKlavier uses python **3** and not python 2. 18 | 19 | .. NOTE:: 20 | If you used the ``requirements.txt`` file to install CodeKlavier, you have already installed Sphinx. 21 | 22 | Setup 23 | ..... 24 | The ``doc`` folder was created to put everything that deals with documentation. From that directory we made the setup by running ``sphynx-quickstart`` and answering the questions that pop up. This creates the ``source`` and ``build`` directories and provides you with a ``Makefile`` file. Some small tweaks to the ``source/conf.py`` were made to finalise the installation. 25 | 26 | Sphinx can autogenerate some documentation based on the docstrings from the python code. Make sure you enable the "autodoc" module in the ``conf.py`` file and the you insert the correct "path". With the command: ``sphinx-apidoc -o module-path`` you can include an entire package/module in one go and it generates and ``.rst`` file that you can include in the ``modules.rst`` file. 27 | 28 | How to write documentation 29 | -------------------------- 30 | Change existing rst-files, or create additional files in case you want to create a new page. 31 | 32 | For documeting the python code: please add appropiate docstring in the code itself. 33 | 34 | How to build the documentation 35 | ------------------------------ 36 | Most likely, you'll want to build towards html-code. You can make a build by running ``make html`` from the ``doc`` folder. This will run sphinx in html-mode and save an updated version of the html in the ``doc/build`` directory. 37 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 4 (12 notes)_18-11-16.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,60,68,2.310651642,0,144,68,78,2.492941015,0,128,60,62,2.499559765,0.0066187500000000005,144,61,69,2.678454489,0,128,68,65,2.683004715,0.004550226,128,61,73,2.8377936989999997,0.15478898400000002,144,60,63,2.8664984049999997,0,128,60,72,3.0225254059999997,0.156027001,144,68,78,3.0248349209999996,0,144,61,70,3.1958517509999997,0, 3 | 144,60,68,3.389230235,0,144,68,75,3.554421435,0,128,60,67,3.571806377,0.017384942,144,61,74,3.743210335,0,128,68,65,3.751710081,0.008499746,128,61,51,3.84548417,0.093774089,144,62,66,5.106427435,0,128,62,69,5.2680769949999995,0.16164956000000003,144,67,68,5.2894221109999995,0,144,66,79,5.460875688999999,0, 4 | 144,62,71,5.655568775999999,0,144,67,69,5.825010483999999,0,128,62,56,5.827182749999999,0.002172266,128,67,74,5.997253971999998,0.17007122200000002,144,66,74,6.001874876999998,0,128,66,65,6.187242124999998,0.185367248,144,62,66,6.194106615999998,0,144,67,69,6.371450649999998,0,128,62,65,6.393477649999998,0.022027,128,67,74,6.550653240999997,0.15717559100000003, 5 | 144,63,70,8.710378294999998,0,128,63,66,8.889673208999998,0.17929491400000003,144,69,54,8.915857811999999,0,128,69,84,8.980395043999998,0.064537232,144,74,59,9.083166786,0,144,63,70,9.250528574999999,0,128,74,69,9.269224763999999,0.018696189000000002,128,63,67,9.422506529,0.153281765,144,69,69,9.424731897,0,128,69,63,9.584736874999999,0.16000497800000002, 6 | 144,63,74,9.776700831,0,128,74,68,9.78777567,0.011074839000000001,128,63,68,9.955731231,0.167955561,144,69,67,9.959158887,0,128,69,52,10.139554123999998,0.180395237,144,74,76,10.141733740999998,0,128,74,73,10.252454339999998,0.110720599,144,66,71,13.205205894999999,0,128,66,61,13.383430280999999,0.178224386,144,63,70,13.385958936,0, 7 | 144,62,63,13.564004107,0,144,66,69,13.73227881,0,128,62,59,13.75268991,0.0204111,144,63,67,13.907499231000001,0,128,66,63,13.916913267000002,0.009414036,128,63,70,14.045880596000002,0.12896732900000002,144,62,58,14.081266696000002,0,144,66,65,14.250301735,0,128,62,67,14.258261521000001,0.007959786,128,66,66,14.419704117000002,0.16144259600000002, 8 | -------------------------------------------------------------------------------- /hello_world/README.md: -------------------------------------------------------------------------------- 1 | # "hello world" 2 | A work for Robot Toy Piano and acoustic midi piano performed by a (coder) pianist. 3 | 4 | “hello world” is the first prototype of the CodeKlavier created especially to live code the actions of a Robot Toy Piano through playing an acoustic midi piano as interface. The keys are individually mapped to alphanumeric characters and strings to allow the (coder) pianist to execute various code 5 | commands through corresponding motivic material. The system is built on top of Python 3.0 and SuperCollider. 6 | 7 | In true live coding spirit, a performance of "hello world" is not subject to a concrete structure and should unfold in its own way with every performance. Feel free to watch Anne Veinberg's [performance](https://youtu.be/ytpB8FB6VTU) of "hello world" and view a [score](https://drive.google.com/file/d/0B6qSeqXuDEKQSWNnSDVOdkJyaGNIVnVhNVlhbDZZLThWSzFz/view?usp=sharing) of the piece. 8 | 9 | 10 | ## To Run 11 | Make sure you in the right directory and have installed SuperCollider and the required libraries as mentioned in the general [Read Me document](https://github.com/narcode/codeklavier-python/blob/master/README.md). 12 | 13 | For the Robot Toy Piano version, run ``python3 codeklavier.py -p hello_world_rtp`` 14 | 15 | ## Versions and Extensions 16 | As an extension to the original "hello world", for [SHA2017](https://sha2017.org) a version that also incorporates sound processing was created. You can watch the presentation on [youtube](https://youtu.be/efU7trVAPvA). 17 | 18 | To run this version use ``python3 codeklavier.py -phello_world_v4.py`` 19 | 20 | To make your own custom mappings, use the Mapping.py file 21 | 22 | In September 2017, a special version of "hello world" was created for the Leiden Night of Art and Science (Leiden Nacht van Kunst en Kennis (NKK)). For this version, audience members were encouraged to try-out the CodeKlavier system and see what they could live code through piano playing. The key mapping was simplified so that non-pianists were also able to have a go and a Python tutorial was created to assist the participant. With the help of the tutorial, this version can theoretically run as an installation without further assistance, although some participants may find this too challenging or require more time to navigate through the system. 23 | 24 | A unique feature of the NKK version is that it utilized the tremolo as value function of the [Motippets](https://github.com/narcode/codeklavier/tree/master/mottipets) prototype. In the future, the concept behind this version will form the basis of the CodeKlavierEDU model - an educational CodeKlavier system. If you would like to know more about this version or the future CodeKlavierEDU model, please get in touch. 25 | 26 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test 5 (12 notes, last 6 were staccato)_18-11-16.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,62,71,0.830888285,0,128,62,73,0.983216749,0.152328464,144,60,63,1.0058213980000001,0,144,70,75,1.1698147710000002,0,128,60,68,1.177410215,0.007595444000000001,128,70,64,1.339540038,0.162129823,144,62,70,1.344424176,0,128,62,75,1.5115492640000001,0.167125088,144,60,66,1.5257801780000002,0,144,70,76,1.699228745,0, 3 | 144,62,71,1.871829101,0,128,70,64,1.8754906450000002,0.003661544,128,62,76,2.0355713750000004,0.16008073,144,60,65,2.0520157750000005,0,144,70,73,2.2403966450000006,0,128,60,69,2.2576207690000007,0.017224124,128,70,62,2.3581619330000008,0.10054116399999999,144,56,70,3.2986535250000006,0,128,56,64,3.4882387610000007,0.18958523600000002,144,57,65,3.493995564000001,0, 4 | 144,58,62,3.687497435000001,0,128,58,65,3.8212941660000013,0.133796731,144,56,61,3.865815953000001,0,128,56,70,4.024997991000001,0.15918203800000003,144,57,65,4.0524285240000015,0,128,57,67,4.200644215000001,0.148215691,144,58,59,4.240979338000002,0,128,58,65,4.392191161000001,0.15121182300000002,144,56,57,4.414070681000001,0,128,56,61,4.556639979000001,0.142569298, 5 | 144,58,68,4.780600106000001,0,128,58,71,4.897160546000001,0.11656044000000002,144,60,75,5.671073000000001,0,128,60,127,5.713344865000001,0.042271865000000006,144,61,56,5.909563706000001,0,128,61,127,5.948074565000001,0.038510859,144,62,73,6.104691344000001,0,128,62,127,6.142374535000001,0.037683191000000005,144,60,75,6.316782683000001,0,128,60,127,6.351314814000001,0.034532131, 6 | 144,62,78,6.774957920000001,0,128,62,127,6.810667781000001,0.035709861,144,60,72,7.001269865000001,0,128,60,127,7.036570158000001,0.035300293,144,61,81,7.227967968000001,0,128,61,127,7.265221831000001,0.037253863000000005,144,62,81,7.442621153000001,0,128,62,127,7.482467635000001,0.039846482,144,54,63,8.474565365,0,128,54,127,8.50929929,0.034733925, 7 | 144,55,56,8.946663401,0,128,55,98,8.989913893,0.043250492,144,54,63,9.179040291,0,128,54,89,9.237031403,0.057991112000000004,144,56,63,9.403749722999999,0,128,56,121,9.446871938,0.043122215000000005,144,55,56,9.646068968,0,128,55,90,9.691646713999999,0.045577746,144,54,68,9.866748691,0,128,54,64,9.941029588,0.074280897, 8 | -------------------------------------------------------------------------------- /doc/source/HelloWorld.rst: -------------------------------------------------------------------------------- 1 | hello world 2 | =========== 3 | 4 | Hello World is the first prototype of the CodeKlavier and it demonstrates the core principes of CodeKlavier. It uses a basic mapping from the piano (midi)keys to characters or predefined strings. These character/string translation is send to SuperCollider to generate sounds. In the original version of Hello World, it instructed a robot toy piano to play notes and motifes. When the piece is performed without the robot toy piano, the piece can also work with recorded samples. 5 | 6 | hello_world 7 | ----------- 8 | Run an infinite loop (or at least until keyboard intterupt) and run CodeKlavier. This programm set the callback and pass the key presses on towards SuperCollider. 9 | 10 | .. NOTE:: 11 | Make sure you have SuperCollider up and running before running the ``hello world`` application. Please reboot SuperCollider Server berfore you astart a live performance. 12 | 13 | Video tutorials 14 | ............... 15 | 16 | A video of the Hello World performance can be found `here `_. This is an early version; the piece evolved over time. A short video tutorial on the ``~ost`` function can be found `here `_ and the ``delay to pitch`` example can be found `here `_. 17 | 18 | instructions_nkk 19 | ---------------- 20 | For the *Leiden Nacht van Kunst en Cultuur* a special version is made, so the visitors can also try out the CodeKlavier. To teach them how to get used to the system and how to perform, they can first run through the ``instruction`` for the CodeKlavier. 21 | 22 | hello_world_nkk 23 | --------------- 24 | This is a special version of the CodeKlaver, made specifically for the *Leiden Nacht van Kunst en Cultuur*. It uses a seperate key-mapping that can be found in ``CodeKlavier.Mapping.Mapping_HelloWorld_NKK``. 25 | 26 | Hello World python documentation 27 | -------------------------------- 28 | 29 | The python scripts in the hello world folder contain documentation. 30 | 31 | Hello World 32 | ........... 33 | 34 | .. automodule:: hello_world.hello_world 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | Hello World NKK 40 | ............... 41 | .. automodule:: hello_world.hello_world_nkk 42 | :members: 43 | :undoc-members: 44 | :show-inheritance: 45 | 46 | Instructions 47 | ............ 48 | .. automodule:: hello_world.instructions_nkk 49 | :members: 50 | :undoc-members: 51 | :show-inheritance: 52 | -------------------------------------------------------------------------------- /hello_world/SC/toypiano_sampler.scd: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | -> toy piano sampler by narcode. April 2017 <- 4 | 5 | Thanks to Anne Veinberg for Recording this 6 | 7 | */ 8 | 9 | { 10 | // load the custom toy piano samples 11 | b = (); 12 | g = Group.new(s, \addToHead); 13 | ~pathsamples = thisProcess.nowExecutingPath.dirname; 14 | s.sync; 15 | 29.do{|i| 16 | ~num = 36 + i; 17 | b[i] = Buffer.read(s, ~pathsamples++"/TPSamples/"++~num++".wav"); 18 | }; 19 | s.sync; 20 | 21 | ~srcid = nil; // annerob: 1151127154 felipe 1429867122 anne -1869464304 22 | 23 | // sampler node: 24 | MIDIdef.noteOn(\toypiano, {arg ...args; 25 | var midinote = args[1]-56; 26 | // args.postln; 27 | midinote.postln; 28 | if (midinote < 64 && midinote >= 0) { 29 | Ndef(midinote.asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(6, group: g); 30 | Ndef((midinote.asString++"d0").asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(0); 31 | } 32 | }, chan: 0, srcID: ~srcid); // 1151127154 33 | 34 | 35 | // channel 1: 36 | MIDIdef.noteOn(\toypiano1, {arg ...args; 37 | var midinote = args[1]-56; 38 | /*args.postln;*/ 39 | midinote.postln; 40 | if (midinote < 64 && midinote >= 0) { 41 | Ndef(midinote.asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(20, group: g); 42 | Ndef((midinote.asString++"d1").asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(0); 43 | } 44 | }, chan: 1, srcID: ~srcid); // 1151127154 45 | 46 | 47 | // channel 2: 48 | MIDIdef.noteOn(\toypiano2, {arg ...args; 49 | var midinote = args[1]-56; 50 | var duplicate = midinote.asString++"d"; 51 | /*args.postln;*/ 52 | midinote.postln; 53 | 54 | if (midinote < 64 && midinote >= 0) { 55 | Ndef(midinote.asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(4, group: g); 56 | Ndef(duplicate.asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(0); 57 | } 58 | }, chan: 2, srcID: ~srcid); // 1151127154 59 | 60 | // channel 3: 61 | MIDIdef.noteOn(\toypiano3, {arg ...args; 62 | var midinote = args[1]-56; 63 | /*args.postln;*/ 64 | midinote.postln; 65 | 66 | if (midinote < 64 && midinote >= 0) { 67 | Ndef(midinote.asSymbol, {PlayBuf.ar(2, b[midinote], loop:0) * EnvGen.kr(Env.perc(0.01, 1.5))}).play(0); 68 | } 69 | }, chan: 3, srcID: ~srcid); // 1151127154 70 | 71 | 72 | s.sync; 73 | "Toy piano sampler ready!".postln; 74 | s.sync; 75 | // fx: 76 | ~gtail = Group.new(s, \addToTail); 77 | Ndef(\fx, {|del=1, amp=0.001| CombN.ar(SoundIn.ar(0), 0.2, del.reciprocal, 4)*amp}).play(0, group: ~gtail); 78 | s.sync; 79 | Ndef(\fx1, {|del=1, amp=0.001| CombN.ar(SoundIn.ar(0), 0.2, del.reciprocal, 1)*amp}).play(1, group: ~gtail); 80 | s.sync; 81 | Ndef(\fx2, {|del=2, amp=0.001, rate=1| GVerb.ar(FreqShift.ar(SoundIn.ar(0), LFTri.kr(rate.reciprocal).range(8000, 100)), 62, del)*amp}).play(0,2, group: ~gtail); 82 | s.sync; 83 | "fx ready!".postln; 84 | }.fork; 85 | -------------------------------------------------------------------------------- /hello_world/hello_world.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import configparser 4 | import getopt 5 | import rtmidi 6 | import sys 7 | import time 8 | 9 | # CodeKlavier Modules 10 | import CK_configWriter 11 | from CK_Setup import Setup 12 | from hello_classes import HelloWorld 13 | from Mapping import Mapping_HelloWorld 14 | 15 | def main(configfile='default_setup.ini'): 16 | """ 17 | Start hello world! 18 | 19 | :param int configfile: use this configuration file. Defaults to 'default_setup.ini'. 20 | """ 21 | 22 | #Read config and settings 23 | config = configparser.ConfigParser() 24 | config.read(configfile, encoding='utf8') 25 | 26 | try: 27 | myPort = config['midi'].getint('port') 28 | device_id = config['midi'].getint('noteon_id') 29 | except KeyError: 30 | raise LookupError('Missing key information in the config file.') 31 | 32 | if (myPort == None or device_id == None): 33 | raise LookupError('Missing key information in the config file.') 34 | 35 | codeK = Setup() 36 | codeK.print_welcome(27) 37 | codeK.open_port(myPort) 38 | 39 | # Use your favourite mapping of the keys 40 | mapping = Mapping_HelloWorld() 41 | 42 | print("\nCodeKlavier is ready and ON.") 43 | print("You are performing: HELLO WORLD") 44 | print("\nPress Control-C to exit.") 45 | 46 | codeK.set_callback(HelloWorld(myPort, mapping, device_id)) 47 | 48 | # Loop to program to keep listening for midi input 49 | try: 50 | while True: 51 | time.sleep(0.01) 52 | except KeyboardInterrupt: 53 | print('') 54 | finally: 55 | print("Bye-Bye :(") 56 | codeK.end() 57 | 58 | if (__name__ == '__main__'): 59 | try: 60 | options, args = getopt.getopt(sys.argv[1:],'hc:m:',['help', 'configfile=', 'makeconfig=']) 61 | selected_options = [x[0] for x in options] 62 | except getopt.GetoptError: 63 | print('Something went wrong with parsing the options') 64 | if ('-c' in selected_options or '--configfile' in selected_options) \ 65 | and ('-m' in selected_options or '--makeconfig' in selected_options): 66 | #cannot deal with creating a new one and using a specified config 67 | raise ValueError('Chooce either the "configfile-option" or the option to create a configfile. Not both.') 68 | for o, a in options: 69 | if o in ('-h', '--help'): 70 | print('Usage: python3 hello_world.py [OPTION]') 71 | print('') 72 | print('Where [OPTION] is:') 73 | print(' -h | --help') 74 | print(' Print this help text.') 75 | print('') 76 | print(' -c <> | --configgile <>') 77 | print(' Use configuration file <>. You can write this configuration file with the -m option') 78 | print('') 79 | print(' -m <> | --makeconfig <>') 80 | print(' Create a configfile and use it. If <> already exits, it will be over written.') 81 | sys.exit(0) 82 | if o in ('-c', '--configfile'): 83 | #use existing configfile 84 | main(configfile=a) 85 | if o in ('-m', '--makeconfig'): 86 | #create new configfile and use it 87 | CK_configWriter.createConfig(configfile=a) 88 | main(configfile=a) 89 | 90 | #no options were supplied: run hello_world with default settings 91 | main() 92 | -------------------------------------------------------------------------------- /text/text.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import configparser 4 | import getopt 5 | import sys 6 | import time 7 | 8 | # CodeKlavier Modules 9 | import CK_configWriter 10 | from CK_Setup import Setup 11 | from text_classes import TextPrint 12 | 13 | def main(text_id=1, configfile='default_setup.ini'): 14 | """ 15 | Start the Text Printer/ Typer 16 | 17 | :param string text_id: the text to load. 18 | :param string configfile: use this configuration file. Defaults to 'default_setup.ini'. 19 | """ 20 | 21 | #Read config and settings 22 | config = configparser.ConfigParser() 23 | config.read(configfile, encoding='utf8') 24 | 25 | try: 26 | myPort = config['midi'].getint('port') 27 | device_id = config['midi'].getint('noteon_id') 28 | pedal_id = config['midi'].getint('pedal_id') 29 | except KeyError: 30 | raise LookupError('Missing key information in the config file.') 31 | 32 | if (myPort == None or device_id == None): 33 | raise LookupError('Missing key information in the config file.') 34 | 35 | codeK = Setup() 36 | codeK.print_welcome(27) 37 | codeK.open_port(myPort) 38 | 39 | 40 | print("\nCodeKlavier is ready and ON.") 41 | print("You are performing: Fixed Text Typer") 42 | print("\nPress Control-C to exit.") 43 | 44 | #codeK.set_callback(TextPrint(myPort, device_id, pedal_id)) 45 | text = TextPrint(myPort, device_id, pedal_id, text_id) 46 | 47 | # Loop to program to keep listening for midi input 48 | try: 49 | while True: 50 | msg = codeK.get_message() 51 | 52 | if msg: 53 | text.printText(msg) 54 | time.sleep(0.01) 55 | 56 | except KeyboardInterrupt: 57 | print('') 58 | finally: 59 | print("Bye-Bye :(") 60 | codeK.end() 61 | 62 | if (__name__ == '__main__'): 63 | try: 64 | options, args = getopt.getopt(sys.argv[1:],'hc:m:',['help', 'configfile=', 'makeconfig=']) 65 | selected_options = [x[0] for x in options] 66 | except getopt.GetoptError: 67 | print('Something went wrong with parsing the options') 68 | if ('-c' in selected_options or '--configfile' in selected_options) \ 69 | and ('-m' in selected_options or '--makeconfig' in selected_options): 70 | #cannot deal with creating a new one and using a specified config 71 | raise ValueError('Chooce either the "configfile-option" or the option to create a configfile. Not both.') 72 | for o, a in options: 73 | if o in ('-h', '--help'): 74 | print('Usage: python3 hello_world.py [OPTION]') 75 | print('') 76 | print('Where [OPTION] is:') 77 | print(' -h | --help') 78 | print(' Print this help text.') 79 | print('') 80 | print(' -c <> | --configgile <>') 81 | print(' Use configuration file <>. You can write this configuration file with the -m option') 82 | print('') 83 | print(' -m <> | --makeconfig <>') 84 | print(' Create a configfile and use it. If <> already exits, it will be over written.') 85 | sys.exit(0) 86 | if o in ('-c', '--configfile'): 87 | #use existing configfile 88 | main(configfile=a) 89 | if o in ('-m', '--makeconfig'): 90 | #create new configfile and use it 91 | CK_configWriter.createConfig(configfile=a) 92 | main(configfile=a) 93 | 94 | main() -------------------------------------------------------------------------------- /assets/augmentedreality.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /augmentedreality 3 | --- 4 | # CodeKlavier meets Augmented Reality 📱 🌱 5 | 6 | ![CKAR](https://raw.githubusercontent.com/narcode/codeklavier/master/assets/images/CKAR.png) 7 | 8 | The CodeKlavier is a system which enables a pianist to code through playing the piano as a performative experience. The CK+AR (CodeKlavier + Augmented Reality) is the next step in our artistic mission of combining classically inspired pianistic, new media, and live coding performance practises into an innovative, united genre. In the CK+AR, the piano playing becomes the interface for coding and the coding unfolds as piano playing and as a visual AR experience, making the three mediums indistinguishable from one another (AR visuals + piano playing + live programming). 9 | 10 | The coding is done in the CodeKlavier language, which implements lambda calculus to create numbers and arithmetic operations that can be translated into symbols to specify Lindenmayer systems. L-systems are formal grammars that consist of a set of symbols (alphabet), a starting point (axiom) and a set of production rules which define symbol substitution. The production rules are applied recursively to successive generations, creating a tree-like structure. These structures, together with additional information extracted from the piano playing, is then used to construct the AR visuals as well as a sonic scape. 11 | 12 | ![Example of L-system tree](https://raw.githubusercontent.com/narcode/codeklavier/master/assets/images/L-system%20example.png) 13 | 14 | Our inspiration for working with L-systems comes primarily from its roots in nature and organic growth which we would like to bring to the musical and programming paradigms. Whilst L-systems are already widely used in generative art and music, we are interessted in exploring how this fairly simple model can be used by the piano coder to express complex structures and how its rules will shape the pianistic improvisation. Furthermore, Lindenmayer’s work was done here at the University of Utrecht in 1968 and building upon it through artistic exploration makes the Netherlands a particularly special location for the development of this project. 15 | 16 | We are collaborating with Patrick Borgeat for this CodeKlavier extension. Patrick is creating the augmented reality and L-systems engine. 17 | 18 | ## Impression 19 | Please watch our [short trailer](https://youtu.be/p65YavCUEuQ) for an impression 20 | 21 | ## Setup 22 | The CK+AR is best presented as a combination of a live performance (15 mins), a pre or post-talk, and an interactive installation where the public can create their own L-system “trees” with assistance from us if necessary. However, this structure is flexible and may be adjusted in discussion with the creators and venue. 23 | 24 | ### There are two primary modes of presentation: 25 | CodeKlavier with the AR as visuals on a large shared screen: 26 | This requires minimal equipment and setup time where the AR visuals are projected on a large screen in the performance space. The equipment required for such a presentation is an acoustic 88 key piano, Stereo PA system (with subwoofers and monitor if available), large screen and powerful projector or large LCD screen. 27 | 28 | ### CodeKlavier with the AR as a true interactive AR experience: 29 | In this type of presentation the audience is free to move around at all times so as to experience the augmented reality visuals from different perspectives. Each audience member will be able to either download an Android app or use an Android smartphone or tablet device provided for the performance. The equipment needed for such a performance would be all of the above alongside the provision of ±30 android tablets or smartphones. 30 | 31 | 32 | We would like to thank the Creative Industries Fund NL and our other sponsors for making this project possible. 33 | www.codeklavier.space 34 | 35 | 36 | -------------------------------------------------------------------------------- /hello_world/instructions_nkk.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tutorial for the Hello World NKK 3 | """ 4 | import configparser 5 | import getopt 6 | import rtmidi 7 | import sys 8 | import time 9 | 10 | # CodeKlavier Modules 11 | import CK_configWriter 12 | from CK_Setup import Setup 13 | from Mapping import Mapping_HelloWorld_NKK 14 | from Instructions import Instructions 15 | 16 | def main (configfile='../default_setup.ini'): 17 | # Start the CodeKlavier 18 | #Read config and settings 19 | config = configparser.ConfigParser() 20 | config.read(configfile, encoding='utf8') 21 | 22 | try: 23 | myPort = config['midi'].getint('port') 24 | device_id = config['midi'].getint('noteon_id') 25 | except KeyError: 26 | raise LookupError('Missing key information in the config file.') 27 | 28 | if (myPort == None or device_id == None): 29 | raise LookupError('Missing key information in the config file.') 30 | 31 | codeK = Setup() 32 | tutorial = Instructions() 33 | codeK.open_port(myPort) 34 | codeK.open_port_out(myPort) 35 | 36 | # Use your favourite mapping of the keys 37 | mapping = Mapping_HelloWorld_NKK() 38 | 39 | # class to handle the midi input and map it to characters 40 | #TODO: this is ugly! Move this to the CodeKlavier module 41 | class HelloWorld(object): 42 | def __init__(self, port): 43 | self.port = port 44 | 45 | def __call__(self, event, data=None): 46 | message, deltatime = event 47 | # print(message) 48 | if message[2] > 0: #only noteOn 49 | if (message[0] == device_id): 50 | mapping.mapping(message[1]) 51 | 52 | codeK.set_callback(HelloWorld(myPort)) 53 | 54 | tutorial.do_tutorial() 55 | codeK.send_message([0x90, 108, 127]) #send enter to codespace 56 | tutorial.level_four() 57 | 58 | # Loop to program to keep listening for midi input 59 | try: 60 | timer = time.time() 61 | while True: 62 | time.sleep(0.01) 63 | except KeyboardInterrupt: 64 | print('') 65 | finally: 66 | # print("Bye-Bye :(") 67 | codeK.end() 68 | 69 | if (__name__ == '__main__'): 70 | try: 71 | options, args = getopt.getopt(sys.argv[1:],'hc:m:',['help', 'configfile=', 'makeconfig=']) 72 | selected_options = [x[0] for x in options] 73 | except getopt.GetoptError: 74 | print('Something went wrong with parsing the options') 75 | if ('-c' in selected_options or '--configfile' in selected_options) \ 76 | and ('-m' in selected_options or '--makeconfig' in selected_options): 77 | #cannot deal with creating a new one and using a specified config 78 | raise ValueError('Chooce either the "configfile-option" or the option to create a configfile. Not both.') 79 | for o, a in options: 80 | if o in ('-h', '--help'): 81 | print('Usage: python3 instructions.py [OPTION]') 82 | print('') 83 | print('Where [OPTION] is:') 84 | print(' -h | --help') 85 | print(' Print this help text.') 86 | print('') 87 | print(' -c <> | --configgile <>') 88 | print(' Use configuration file <>. You can write this configuration file with the -m option') 89 | print('') 90 | print(' -m <> | --makeconfig <>') 91 | print(' Create a configfile and use it. If <> already exits, it will be over written.') 92 | sys.exit(0) 93 | if o in ('-c', '--configfile'): 94 | #use existing configfile 95 | main(configfile=a) 96 | if o in ('-m', '--makeconfig'): 97 | #create new configfile and use it 98 | CK_configWriter.createConfig(configfile=a) 99 | main(configfile=a) 100 | 101 | #no options were supplied: instructions hello_world with default settings 102 | main() 103 | -------------------------------------------------------------------------------- /CodeKlavier/text_classes.py: -------------------------------------------------------------------------------- 1 | """ 2 | classes for the Buffered Text Typer. 3 | Done For the Huyens Festival 2018 to type poems by Constantijn Huygens 4 | 5 | """ 6 | import rtmidi 7 | from Mapping import Mapping_Ckalculator 8 | 9 | 10 | class TextPrint(object): 11 | """ class to type one character of a pre-loaded text on every midi note on event 12 | """ 13 | 14 | def __init__(self, port, noteonid, pedal_id, text_id): 15 | """Setup the class 16 | 17 | :param int port: the portnumber 18 | :param int dict mapping: the mapping to use 19 | :param int noteonid: the note-on id 20 | :param int text_id: the id of the text to load 21 | """ 22 | self.mapscheme = Mapping_Ckalculator(True, False) 23 | self.port = port 24 | self.noteonid = noteonid 25 | self.pedalid = pedal_id 26 | self.text = text_id 27 | self.counter = 0 28 | 29 | def printText(self, event, data=None): 30 | """Deal with the call function 31 | 32 | :param event: ? 33 | :param data: ? 34 | """ 35 | message, deltatime = event 36 | if message[0] != 254: 37 | if (message[0] == self.noteonid and message[2] > 0): 38 | text = self.loadText(text_id=self.text) 39 | 40 | if self.counter < len(text): 41 | print(text[self.counter]) 42 | self.mapscheme.formatAndSend(text[self.counter], display=1, spacing=False, spacechar='') 43 | 44 | self.counter += 1 45 | 46 | def loadText(self, path=None, text_id=1): 47 | """ Load a text from a file 48 | 49 | :param path string: the path to the file containing the text 50 | "param text_id int: choose the text to load 51 | TODO: add loading, now it's hardcoded text 52 | """ 53 | if text_id == '1': 54 | text = 'OP MIJNEN GEBOORT-DAGH\n\n\ 55 | Noch eens September, en noch eens die vierde dagh\n\ 56 | Die mij verschijnen sagh!\n\ 57 | Hoe veel Septembers, Heer, en hoe veel’ vierde dagen\n\ 58 | Wilt ghij mij noch verdragen?\n\ 59 | Ick bidd om geen verlang: ’tkan redelyck bestaen,\n\ 60 | Het ghen’ ick heb gegaen:\n\ 61 | En van mijn’ wiegh tot hier zijn soo veel dusend schreden\n\ 62 | Die ick heb doorgetreden,\n\ 63 | (Met vallen, lieve God, en opstaen, soo ghij weett,)\n\ 64 | Dat die all ’t selve leed\n\ 65 | En all’ de selve vreughd naer mij hadd door te reisen,\n\ 66 | Sich drijmael sou bepeisen\n\ 67 | Wat besten oorber waer, gelaten of gedaen.\n\ 68 | Mij, Heere, laet vrij gaen;\n\ 69 | Mijn’ roll is afgespeelt, en all wat kan gebeuren\n\ 70 | Van lacchen en van treuren\n\ 71 | Is mij te beurt geweest, en all wat beuren sal\n\ 72 | Sal ’tselve niet met all,\n\ 73 | En d’ oude schaduw zijn van dingen die wat schijnen\n\ 74 | En komende verdwijnen.\n\ 75 | Wat wacht ick meer op aerd, waerom en scheid’ ick niet?\n\ 76 | ’K wacht, Heer, dat ghij ’tgebiedt.\n\ 77 | Maer, magh ick noch een’ gunst by d’andere begeeren,\n\ 78 | Laet mij soo scheiden leeren,\n\ 79 | Dat yeder een die ’t siet mijn scheiden en het sijn\n\ 80 | Wensch’ eenerhand te zijn.\n' 81 | else: 82 | text = 'DROOMEN YDELHEIT\n\n\ 83 | Wie weet wat droomen is? ick weet het; en wie niet,\n\ 84 | Die op sijn selven, neen; die in syn selven siet?\n\ 85 | Siet innewaerts, en denckt wat dencken is: dat’s droomen.\n\ 86 | Die sonder dencken is, is aen syn’ dood gekomen.\n\ 87 | Maer slapen scheelt soo veel van dood zijn, als de dood\n\ 88 | Van swijmen, en ’t geroll, van ’tliggen van een’ kloot.\n\ 89 | Wij dencken slapende: maer dampen die doen slapen\n\ 90 | Doen dat wij ons in ons aen schaduwen vergapen.\n\ 91 | De Reden doet wat, maer belemmert en verwert;\n\ 92 | Soo komt dat droomen ernst, en dencken duncken werdt.\n\ 93 | Gaet en bouwt redenen van hopen of van schroomen\n\ 94 | Op bij de Sonn of by de Maen gesufte droomen:\n\ 95 | Wat dunckt u, is ’t niet seer all eenerley gedrocht,\n\ 96 | Of wat ick hebb gedacht, of wat mij heeft gedocht?' 97 | 98 | return text 99 | -------------------------------------------------------------------------------- /doc/build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Search — CodeKlavier 0.3.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 44 | 48 | 49 |
50 |
51 |
52 |
53 | 54 |

Search

55 |
56 | 57 |

58 | Please activate JavaScript to enable the search 59 | functionality. 60 |

61 |
62 |

63 | From here you can search these documents. Enter your search 64 | words into the box below and click "search". Note that the search 65 | function will automatically search for all of the words. Pages 66 | containing fewer words won't appear in the result list. 67 |

68 |
69 | 70 | 71 | 72 |
73 | 74 |
75 | 76 |
77 | 78 |
79 |
80 |
81 |
82 |
83 | 95 | 99 | 100 | -------------------------------------------------------------------------------- /hello_world/hello_world_nkk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import configparser 4 | import getopt 5 | import rtmidi 6 | import sys 7 | import time 8 | 9 | # CodeKlavier Modules 10 | import CK_configWriter 11 | from CK_Setup import Setup 12 | from hello_classes import HelloWorld 13 | from Instructions import Instructions 14 | from Mapping import Mapping_HelloWorld_NKK 15 | 16 | def main(configfile='../default_setup.ini'): 17 | """ 18 | Start hello world! 19 | 20 | :param int configfile: use this configuration file. Defaults to 'default_setup.ini'. 21 | """ 22 | 23 | #Read config and settings 24 | config = configparser.ConfigParser() 25 | config.read(configfile, encoding='utf8') 26 | 27 | try: 28 | myPort = config['midi'].getint('port') 29 | device_id = config['midi'].getint('noteon_id') 30 | except KeyError: 31 | raise LookupError('Missing key information in the config file.') 32 | 33 | if (myPort == None or device_id == None): 34 | raise LookupError('Missing key information in the config file.') 35 | 36 | codeK = Setup() 37 | tutorial = Instructions() 38 | codeK.open_port(myPort) 39 | codeK.open_port_out(myPort) 40 | 41 | # Use your favourite mapping of the keys 42 | mapping = Mapping_HelloWorld_NKK() 43 | 44 | # class to handle the midi input and map it to characters 45 | #TODO: this is ugly! Move this to the CodeKlavier module 46 | class HelloWorld(object): 47 | def __init__(self, port): 48 | self.port = port 49 | 50 | def __call__(self, event, data=None): 51 | message, deltatime = event 52 | # print(message) 53 | if message[2] > 0: #only noteOn 54 | if (message[0] == device_id): 55 | mapping.mapping(message[1]) 56 | # forwarding only note on messages to tutorial terminal for NKK: 57 | codeK.send_message([message[0], message[1], message[2]]) 58 | if (message[0] == 176): #hardcoded pedal id (not pretty) 59 | mapping.stopSC(message[1]) 60 | 61 | codeK.set_callback(HelloWorld(myPort)) 62 | 63 | # Loop to program to keep listening for midi input 64 | try: 65 | # timer = time.time() 66 | while True: 67 | if tutorial.mode(): 68 | break 69 | time.sleep(0.01) 70 | except KeyboardInterrupt: 71 | print('') 72 | finally: 73 | # print("Bye-Bye :(") 74 | codeK.end() 75 | 76 | if (__name__ == '__main__'): 77 | try: 78 | options, args = getopt.getopt(sys.argv[1:],'hc:m:',['help', 'configfile=', 'makeconfig=']) 79 | selected_options = [x[0] for x in options] 80 | except getopt.GetoptError: 81 | print('Something went wrong with parsing the options') 82 | if ('-c' in selected_options or '--configfile' in selected_options) \ 83 | and ('-m' in selected_options or '--makeconfig' in selected_options): 84 | #cannot deal with creating a new one and using a specified config 85 | raise ValueError('Chooce either the "configfile-option" or the option to create a configfile. Not both.') 86 | for o, a in options: 87 | if o in ('-h', '--help'): 88 | print('Usage: python3 hello_world.py [OPTION]') 89 | print('') 90 | print('Where [OPTION] is:') 91 | print(' -h | --help') 92 | print(' Print this help text.') 93 | print('') 94 | print(' -c <> | --configgile <>') 95 | print(' Use configuration file <>. You can write this configuration file with the -m option') 96 | print('') 97 | print(' -m <> | --makeconfig <>') 98 | print(' Create a configfile and use it. If <> already exits, it will be over written.') 99 | sys.exit(0) 100 | if o in ('-c', '--configfile'): 101 | #use existing configfile 102 | main(configfile=a) 103 | if o in ('-m', '--makeconfig'): 104 | #create new configfile and use it 105 | CK_configWriter.createConfig(configfile=a) 106 | main(configfile=a) 107 | 108 | #no options were supplied: run hello_world with default settings 109 | main() 110 | -------------------------------------------------------------------------------- /doc/build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /CodeKlavier/CK_rec.py: -------------------------------------------------------------------------------- 1 | """CodeKlavier recording of midi events in .csv format. 2 | 3 | For Machine Learning PIA 4 | """ 5 | 6 | from CK_Setup import Setup 7 | import time 8 | import configparser 9 | import re 10 | import os 11 | 12 | 13 | class CK_Rec(object): 14 | """ 15 | Class to handle the recording of midi events in .csv format 16 | """ 17 | 18 | def __init__(self, configfile=None): 19 | self._configfile = configfile 20 | self._deltamem = [] 21 | 22 | def delta_difference(self, deltatime_in): 23 | # activesense compensation 24 | ck_deltatime_mem = self._deltamem 25 | 26 | ck_deltatime_mem.append(deltatime_in) 27 | #print('deltatimes stack: ', ck_deltatetime_mem) 28 | 29 | if len(ck_deltatime_mem) > 2: 30 | ck_deltatime_mem = ck_deltatime_mem[-2:] 31 | 32 | if len(ck_deltatime_mem) == 2: 33 | dif = ck_deltatime_mem[1] - ck_deltatime_mem[0] 34 | if dif < 0: 35 | dif = 0 36 | return dif 37 | else: 38 | return 0 39 | 40 | def record(self, framesize=10): 41 | """ 42 | Run a basic miditest to see how the CodeKlavier is receiving your midi. 43 | """ 44 | 45 | timestamp = time.strftime("%y-%m-%d") 46 | ck_deltatime = 0 47 | per_note = 0 48 | recfile = open('ml_data/_', 'w') 49 | headers = '' 50 | 51 | #Read config and settings 52 | config = configparser.ConfigParser() 53 | config.read(self._configfile, encoding='utf8') 54 | 55 | try: 56 | myPort = config['midi'].getint('port') 57 | note_on = config['midi'].getint('noteon_id') 58 | note_off = config['midi'].getint('noteoff_id') 59 | except KeyError: 60 | raise LookupError('Missing key information in the config file.') 61 | 62 | if (myPort == None or note_on == None): 63 | raise LookupError('Missing key information in the config file.') 64 | 65 | codeK = Setup() 66 | codeK.open_port(myPort) 67 | print('your note on id is: ', note_on, '\n') 68 | print("CodeKlavier is RECORDING. Press Control-C to save and exit.") 69 | for i in range(0,framesize): 70 | if framesize == 1: 71 | index = '' 72 | else: 73 | index = str(i) 74 | headers += 'midi_note'+index+',velocity'+index+',duration'+index+',label'+index 75 | 76 | recfile.write(headers+'\n') 77 | data_line = '' 78 | deltatime_mem = {} 79 | ostinato_length = 9 80 | note_counter = 1 81 | 82 | 83 | try: 84 | while True: 85 | msg = codeK.get_message() 86 | 87 | if msg: 88 | message, deltatime = msg 89 | ck_deltatime += deltatime 90 | per_note += deltatime 91 | if message[0] != 254: 92 | if message[0] == note_on: 93 | deltatime_mem[message[1]] = ck_deltatime 94 | velocity = message[2] 95 | if message[0] == note_off: 96 | 97 | if note_counter > 9: 98 | note_counter = 1 99 | 100 | per_note = 0 101 | dif = self.delta_difference(per_note) 102 | #midimsg = list(map(str, message)) #full msg not needed 103 | midinote = message[1] 104 | label = note_counter/ostinato_length 105 | #label = 0 106 | note_duration = ck_deltatime - deltatime_mem.pop(midinote) 107 | data_line += str(midinote) + ',' + str(velocity) + ',' + str(note_duration) + ',' + str(label) 108 | data_line += '\n' 109 | clean_line = re.sub(r"\[?\]?", '', data_line) 110 | print(clean_line) 111 | recfile.write(clean_line) 112 | data_line = '' 113 | note_counter += 1 114 | 115 | time.sleep(0.01) 116 | 117 | except KeyboardInterrupt: 118 | print('saving recording...') 119 | finally: 120 | recfile.close() 121 | title = input('Dear CK user, please type a comprehensive title for the recording and press ENTER:'); 122 | usertitle = title+'_'+timestamp+'.csv' 123 | os.rename("ml_data/_", "ml_data/"+usertitle) 124 | print("recording saved with title: ", usertitle) 125 | codeK.end() 126 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test7 (mixed, last was a mistake (and incomplete)_18-11-18.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,54,64,6.062783583000001,0,144,60,59,6.285908555000001,0,128,54,64,6.288989408000001,0.003080853,128,60,68,6.4763552650000005,0.18736585700000002,144,67,56,6.497915975000001,0,144,54,58,6.677899485000001,0,128,67,60,6.681048008000001,0.0031485230000000003,144,60,59,6.868776190000001,0,128,54,65,6.875277893000001,0.006501703,128,60,67,7.073225893,0.19794800000000004, 3 | 144,54,61,0,0,128,67,57,0.0021533050000000003,0.0021533050000000003,144,60,57,0.189864975,0,128,54,64,0.203171925,0.013306950000000001,144,67,54,0.414192185,0,128,60,62,0.4205487,0.006356515,128,67,71,0.552846693,0.132297993,144,58,71,2.278121065,0,144,68,74,2.486542223,0,128,58,65,2.4959246349999997,0.009382412000000001, 4 | 144,69,64,0,0,128,69,66,0.16153591,0.16153591,144,58,61,0.17745243,0,144,68,72,0.344554935,0,128,58,67,0.359301038,0.014746103000000002,128,68,68,0.5252448780000001,0.16594384,144,69,68,0.535958055,0,128,69,60,0.695357678,0.159399623,144,58,63,0.708585243,0,144,68,71,0.8753163150000001,0, 5 | 144,69,59,0,0,128,69,49,0.113731125,0.113731125,144,56,68,1.7224430930000003,0,128,56,66,1.8723975480000004,0.14995445500000001,144,64,65,1.8776299250000004,0,128,64,73,2.0160827880000003,0.138452863,144,67,65,2.044361228,0,144,56,65,2.1644145050000003,0,128,67,67,2.1796328880000004,0.015218383,128,56,69,2.2979575950000006,0.118324707, 6 | 144,67,54,0,0,128,67,55,0.099195855,0.099195855,144,56,62,0.111723995,0,144,64,63,0.23169214300000002,0,128,56,65,0.241289938,0.009597795000000001,128,64,46,0.34975129000000005,0.108461352,144,67,56,0.37050215000000003,0,128,67,71,0.435907343,0.065405193,144,55,62,1.2650660230000002,0,128,55,68,1.3642798230000002,0.09921380000000002, 7 | 144,68,63,0,0,128,68,92,0.06807840700000001,0.06807840700000001,144,55,60,0.10172652200000001,0,128,55,71,0.21127188000000002,0.10954535800000001,144,62,74,0.23194463200000004,0,128,62,77,0.34815004200000005,0.11620541000000001,144,68,85,0.35186406700000006,0,128,68,68,0.45316971000000006,0.101305643,144,55,71,0.45645156500000006,0,144,62,85,0.5741913970000001,0, 8 | 144,68,94,0,0,128,62,77,0.026568805,0.026568805,128,68,70,0.120422205,0.0938534,144,53,37,1.147272867,0,128,53,60,1.2511507020000001,0.103877835,144,61,56,1.2709216920000002,0,128,61,50,1.3764703970000003,0.10554870499999999,144,62,61,1.3993737750000004,0,144,53,74,1.5036762800000003,0,128,62,49,1.5073228700000003,0.0036465900000000003, 9 | 144,62,92,0,0,128,61,77,0.009641498,0.009641498,144,53,90,0.12661824300000002,0,128,62,65,0.14326901500000003,0.016650772,144,61,93,0.23921698500000002,0,128,53,75,0.30550846000000004,0.066291475,144,62,98,0.35535468000000003,0,128,61,78,0.37356593000000005,0.018211250000000002,128,62,76,0.5095270380000001,0.135961108,144,61,93,1.6449963680000002,0, 10 | 144,62,85,0,0,128,54,71,0.013838725000000001,0.013838725000000001,144,61,94,0.13167795799999998,0,128,62,78,0.16579129799999998,0.03411334,144,54,83,0.259693005,0,128,61,75,0.287617425,0.027924420000000002,144,62,77,0.40375927,0,128,54,70,0.416449413,0.012690143000000001,128,62,75,0.544577898,0.12812848500000001,144,61,67,0.54707714,0, 11 | 144,54,57,0,0,128,54,69,0.128902983,0.128902983,144,62,48,0.156030578,0,128,62,69,0.22924780800000003,0.07321723000000001,144,57,60,1.7021975900000001,0,128,57,75,1.8380733900000001,0.13587580000000002,144,54,63,1.865284715,0,128,54,62,1.996122658,0.130837943,144,63,65,2.0186285600000002,0,128,63,60,2.1585361680000004,0.13990760800000002, 12 | 144,54,62,0,0,128,57,70,0.009816625,0.009816625,144,63,67,0.14594683,0,128,54,67,0.15594304,0.00999621,144,57,63,0.28427703800000004,0,128,63,67,0.28904292800000003,0.00476589,144,54,65,0.43409522,0,128,57,63,0.436065795,0.001970575,128,54,65,0.6009904549999999,0.16492466000000003,144,63,61,0.6032709629999999,0, 13 | 144,56,62,0,0,128,56,65,0.127815548,0.127815548,144,54,63,0.13151921,0,128,54,63,0.26626166,0.13474245,144,63,56,0.27572379,0,128,63,49,0.384066793,0.10834300300000002,144,56,57,0.391614198,0,128,56,42,0.5240965200000001,0.132482322,144,54,62,0.52747856,0,144,63,61,0.6689682430000001,0, 14 | 144,56,57,0,0,144,54,59,0.13237284200000002,0,128,56,68,0.13487225700000002,0.002499415,128,54,65,0.256250195,0.121377938,144,63,61,0.28541220700000003,0,128,63,49,0.40369447,0.11828226300000001,144,51,75,1.2782725850000003,0,144,61,71,1.3974889320000001,0,128,51,67,1.4092276270000001,0.011738695,128,61,71,1.5074283750000002,0.098200748, 15 | 144,51,80,0,0,128,62,70,0.007639095,0.007639095,144,61,82,0.119292115,0,128,51,70,0.14953111,0.030238995,128,61,75,0.241094305,0.091563195,144,62,81,0.24333047200000002,0,144,51,86,0.36518933500000006,0,128,62,74,0.37977523500000004,0.0145859,144,61,87,0.49404500200000007,0,128,51,72,0.5279920650000001,0.033947063, 16 | -------------------------------------------------------------------------------- /assets/ACTIVITIES.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /activities 3 | --- 4 | 5 | # CodeKlavier Activities 🎹🎤 6 | 7 | ### This page gives a run down of public CodeKlavier presentations and milestones to date: 8 | (newest on top) 9 | 10 | May/June 2023: Recording videos of ARquatic and MercTippets for HashiCorps HashiDays 2023 11 | 12 | Winter 2022/23: "The Pianist Gardener" version of ARquatic in [ART+](https://artplus.app/) 13 | 14 | September/October 2022: ARquatic tour of botanical gardens around the Netherlands 15 | 16 | February 2022: Release book chapter "The CodeKlavier: Appropriating the piano as a live coding instrument" in [Rethinking the Musial Instrument](https://www.cambridgescholars.com/product/978-1-5275-7789-3) 17 | 18 | Summer 2021: ARquatic, CodeKlavier's music and augmented reality experience, has its premier and performances in the Netherlands. 19 | 20 | January 2021: CodeKlavier meets Mercury, Mercury Live Coding Sessions. Watch the video [here](https://youtu.be/e4sPKOlaYS8) 21 | 22 | October 2020: CodeKlavier meets Fokker organ. [Muziekgebouw Amsterdam](https://www.muziekgebouw.nl/nl/agenda/9130/Anne_Veinberg_Felipe_Ignacio_Noriega_Alcaraz/Anne_Veinberg_in_de_hoofdrol) 23 | 24 | August 2019: Paper, lecture and performance at [FARM Berlin 2019](https://icfp19.sigplan.org/home/farm-2019). Watch the video [here](https://youtu.be/K1ai2N9bSqI). Third residency with Patrick Borgeat working on the AR extension 25 | 26 | June 2019: Second residency with Patrick Borgeat working on the AR extension. 27 | 28 | May 2019: Performaces of the CKalcuλator at Sounds like Soup on the 19th and at Young Amsterdam Artists concert on the 23rd. Both concerts are in Amsterdam. Our second residency with Patrick Borgeat working on the AR extension will take place. 29 | 30 | March 2019: First residency with Patrick Borgeat working on the AR extension. Watch the teaser [here](https://youtu.be/p65YavCUEuQ) 31 | 32 | February 2019: Talk and performance with the Ckalcuλator at [Lambda Days](http://www.lambdadays.org/lambdadays2019) in Poland. Watch the video [here](https://youtu.be/0fL40oLU8C4) 33 | 34 | January 2019: Performance of new hybrid version for Disklavier at [Conlon X Gaudeamus](https://gaudeamus.nl/events/gaudeamus-x-conlon-disklavier-projection-works/) - Watch the [trailer](https://youtu.be/GHEOdT-t4Us)! 35 | We also performed with the CKalculator at the [International Conference on Live Coding](http://iclc.livecodenetwork.org/2019/ingles.html) 36 | 37 | November 2018: Performance at Splendor 38 | 39 | October 2018: Performance at [ARTikulationen in Graz](http://doctorartium.kug.ac.at/pdf/ARTikulationen2018Programm3.pdf). This was the first time we used our custom built KeyScanner. 40 | 41 | September 2018: Performance at the [Huygens Festival](https://huygensfestival.nl/) in Voorburg, Netherlands. We also did an [interview with Dennis Kastrup](https://www.radioeins.de/programm/sendungen/modo1316/strom-und-drang/codeklavier.html) about the project for Radio Eins. 42 | 43 | August 2018: CodeKlavier paper and performance are presented at the [International Computer Music Conference](https://icmc2018.org/) in Daegu, Korea! In the proceedings you can find our first CodeKlavier published paper. 44 | 45 | July 2018: CodeKlavier received its custom built KeyScanner by Andrew McPherson. 46 | 47 | June 2018: Performance and lecture-demonstration at MuSA 2018 at IMWI Karlsruhe, Germany. Our presentation included a special CodeKlavier "presentation mode" where we used various CodeKlavier piano techniques to live code the presentation. This event also featurde a performance of Huygbrid and a more developed version of the CKalculator. 48 | There were also performances of Huygbrid (previously Hybrid) and CKalculator at Ephemere in Studio Loos, Netherlands. Watch the video of CKalculator [here](https://youtu.be/Ea4pUYqb8BA). 49 | 50 | May 2018: Performance of two new prototypes, Hybrid and CKalculator at WORM in Rotterdam as part of the Algo~rhythms series. 51 | 52 | March 2018: Performance at the Huygens Festival Amuse in Voorburg, NL and at In-Sonora Festival in Madrid, Spain. Video from In-Sonora [here]( https://www.youtube.com/watch?v=F5O_WUdtOqY&t=5149s) 53 | 54 | February 2018: Recording of [Motippets](https://youtu.be/nzsW1w38JEc) version 1. 55 | 56 | December 2017: Mini-tour! "hello world" and Motippets were performed at the International Conference on Live Coding in Morelia, Mexico - watch video of Motippets [here](https://youtu.be/Kk71xkodu0k). We also gave a lecture-presentation at the Tandon School of Engineering, hosted by LiveCode.NYC, in New York and performed "hello world" at the Uncaged Toy Piano Festival. Watch video [here](https://youtu.be/N_Vpo5jzH_c). 57 | 58 | October 2017: CodeKlavier received a 2 year grant for further development from the [Creative Industries Fund NL](http://m.stimuleringsfonds.nl/nl/toekenningen/codeklavier/4410/) and our angel sponsor. 59 | 60 | September 2017: "hello world" is performed at the Gaudeamus Muziek week - a contemporary music festival held annually in Utrecht, Netherlands. A special interactive version of "hello world" is created as an interactive installation for Leiden's [Evening of Art and Science](http://nachtvankunstenkennis.nl/act/codeklavier). 61 | 62 | August 2017: [Still Hacking Anyway 2017, NL](https://sha2017.org/). 63 | Our first live presentation of the CodeKlavier. We also performed "Code Our Glance" where we play as a duo. A video of the event is available [here](https://youtu.be/efU7trVAPvA). 64 | 65 | May 2017: "hello world" is awarded the Conlon and Uncaged Festival's Composition Prize. Watch the video [here](https://youtu.be/ytpB8FB6VTU) 66 | 67 | April 2017: CodeKlavier received the starter's phase grant from the Creative Industries Fund NL. 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeKlavier 2 | 3 | ### Live coding with the piano as interface. 4 | 5 | An open source project by Felipe Ignacio Noriega and Anne Veinberg. 6 | 7 | CodeKlavier development started in April 2017 and currently has five modules (newest on top): 8 | + [*ARquatic*](https://codeklavier.space/arquatic) (A CodeKlavier Augmented Reality experience!) 9 | + [*Ckalcuλator*](https://github.com/narcode/codeklavier/tree/master/ckalculator) (Lambda-calculus with the piano!) 10 | + [*Hybrid*](https://github.com/narcode/codeklavier/blob/master/hybrid/README.md) (switching between the first two prototypes and includes a custom code display via udp sockets) 11 | + [*Motippets*](https://github.com/narcode/codeklavier/tree/master/motippets) (coding via pianistic gestures/motifs) 12 | + [*hello world*](https://github.com/narcode/codeklavier/blob/master/hello_world) (proof of concept prototype, with 1-1 mapping of piano keys to alphanumeric characters) 13 | 14 | More information about the specific prototypes can be found in their respective directories. 15 | 16 | ### Latest 17 | CodeKlavier made two videos for this year's [HashiDays event](https://hashidays.com/online/). The first is [ARquatic](https://codeklavier.space/arquatic) and the second uses the [Motippets](https://github.com/narcode/codeklavier/tree/master/motippets) module to code in [Mercury](https://www.timohoogland.com/mercury-livecoding/). With thanks to Simon Kelaita and Patrick Borgeat for the audio and video editing respectively. 18 | 19 | ### CodeKlavier in action 20 | Checkout our [videos page](https://codeklavier.space/videos) to see the Codeklavier in action or visit the [Activities page](https://codeklavier.space/activities) for info on past and future performances. 21 | 22 | ### Goals 23 |
24 |
The dream:
🐍🎹 An intuitive programming language with the piano as interface.
25 |
26 |
The starting-to-be-graspable dream:
👩🏼‍💻 A programming language for the piano as interface
27 |
28 |
The long term goal:
🎼🎧 a live coding music-domain programming language for the piano as interface
29 |
30 |
The mid term goal:
💾📌 strategy-specific releases of mini-language approaches for live coding through the piano
31 |
32 |
The short term goal:
📆📈 research-release-evaluation cycles of prototypes which tackle specific aspects of the system
33 | 34 | 35 | 36 | ## Equipment 37 | 1. An acoustic-MIDI piano such as a Disklavier, any piano fitted with a silent system or an acoustic intrument in combination with a MOOG piano bar or other MIDI keyscanner. We use a MIDI KeyScanner developed by Andrew McPherson and his team at Queen Mary University of London. If an acoustic-MIDI piano is not available, any 88-key MIDI keyboard will suffice providing this instrument is of suitable sensitivity for the pianist. 38 | 39 | 2. MIDI interface (if not integrated in the piano) 40 | 41 | ## Libraries 42 | Install with pip3 43 | 44 | 1. python-rtmidi 45 | 2. pynput 46 | 3. sphinx 47 | 4. numpy 48 | 5. python-osc (if you want to use the AR module and Caffeine Extension) 49 | 6. websockets (idem) 50 | 51 | Run ``pip3 install -r requirements.txt`` to install the required libraries. 52 | 53 | ## Modules 54 | __For this version please add the CodeKlavier directory to your sys.path so the CK modules are recognized__ 55 | 56 | You can run the ``setPythonPath.sh`` every time you start a new shell (type ``. setPythonPath.sh`` - not the **dot-space** before the command), or put the following lines in your ``~/.bash_profile`` or ``~/.bashrc`` or equivalent add the following lines (make sure you have the correct path!): 57 | 58 | `# Modules for the CodeKlavier 59 | PYTHONPATH="/path/to/your/codeklavier/project/folder:$PYTHONPATH" 60 | export PYTHONPATH` 61 | 62 | As an example, the path to the Codeklavier in my system looks like this: 63 | 64 | ` 65 | PYTHONPATH="/Users/narcodeb/Development/Repos/codeklavier-python/CodeKlavier:$PYTHONPATH" 66 | ` 67 | ## Extensions 68 | 69 | There are a number of different code output extensions for the CodeKlavier. The loading ini file for these can be found in the CodeKlavier-Extensions repository[https://github.com/codeklavier/codeklavier-extensions]. You will need to download/clone this directory in order to run CodeKlavier. 70 | 71 | If you are interested in collaborating on an extension for the CodeKlavier, don't hesitate to get in touch. 72 | 73 | Currently, outpute extensions exist for SuperCollider, Mercury, JavaScript, Augmented Reality and Hydra. 74 | 75 | 76 | ## Test run 77 | After installing the libraries, plug in your midi device and run the miditest by ``python3 miditest.py``. After you complete the setup and configuration, you will see the midi messages on the screen. After that run codeklavier.py -p hybrid -i base.ini (be sure to change the directory too match your setup Try playing an upward C major 3 note arpeggio starting on middle C. If everything works, your test is complete and you are ready to explore CK! 78 | 79 | 80 | ## Watch 81 | [Codeklavier Videos](http://codeklavier.space/videos) 82 | 83 | ## Publications 84 | [Publications page](https://codeklavier.space/publications) 85 | 86 | ## Support 87 | This project was made possible by the Creative Industries Fund NL, our angel sponsor and the festivals and venues that book us for paid concerts. However, our initial funding has come to an end so if you believe in the project and would like to support it, please consider "buying us a coffee". Every little bit counts and we greatly appreciate your support! 88 | 89 | [![ko-fi](https://www.ko-fi.com/img/donate_sm.png)](https://ko-fi.com/J3J7PGIE) 90 | -------------------------------------------------------------------------------- /ml_data/deprecated tests/test6 (soft and fast but perhaps some notes were missing - although this could be nice to include)_18-11-18.csv: -------------------------------------------------------------------------------- 1 | source_id0,midi_note0,velocity0,ck_deltatime0,dif_deltatime0,source_id1,midi_note1,velocity1,ck_deltatime1,dif_deltatime1,source_id2,midi_note2,velocity2,ck_deltatime2,dif_deltatime2,source_id3,midi_note3,velocity3,ck_deltatime3,dif_deltatime3,source_id4,midi_note4,velocity4,ck_deltatime4,dif_deltatime4,source_id5,midi_note5,velocity5,ck_deltatime5,dif_deltatime5,source_id6,midi_note6,velocity6,ck_deltatime6,dif_deltatime6,source_id7,midi_note7,velocity7,ck_deltatime7,dif_deltatime7,source_id8,midi_note8,velocity8,ck_deltatime8,dif_deltatime8,source_id9,midi_note9,velocity9,ck_deltatime9,dif_deltatime9, 2 | 144,67,48,1.8868562629999999,0,128,67,59,1.9758020749999998,0.088945812,144,66,65,1.997615083,0,128,66,73,2.077318293,0.07970321,144,62,59,2.1133731879999997,0,128,62,79,2.1725996149999998,0.059226427000000005,144,67,61,2.215369005,0,128,67,48,2.3282239899999997,0.112854985,144,66,68,2.3310755179999996,0,128,66,51,2.4354641199999993,0.104388602, 3 | 144,67,56,0,0,128,67,53,0.09797993,0.09797993,144,66,63,0.10297469000000001,0,128,66,52,0.20895676500000002,0.10598207500000001,144,62,44,0.24562450500000002,0,128,62,76,0.30708053500000004,0.06145603,144,67,37,1.421438622,0,128,67,75,1.4906765549999998,0.069237933,144,63,52,1.51137631,0,128,63,62,1.60053826,0.08916195, 4 | 144,67,55,0,0,144,63,68,0.124005798,0,128,67,68,0.127151615,0.0031458170000000004,128,63,50,0.233829543,0.106677928,144,61,61,0.245698223,0,144,67,52,0.338251183,0,128,61,54,0.355313948,0.017062765,128,67,53,0.441702845,0.08638889699999999,144,63,62,0.457831678,0,128,63,54,0.5614809430000001,0.103649265, 5 | 144,61,51,0,0,128,61,74,0.070543172,0.070543172,144,57,63,0.10861849200000001,0,128,57,58,0.201593917,0.092975425,144,68,59,0.241352635,0,128,68,92,0.306725515,0.06537288000000001,144,61,58,0.338315805,0,128,61,86,0.40257418500000003,0.06425838,144,57,58,0.44338468700000006,0,128,57,47,0.5562617350000001,0.11287704800000001, 6 | 144,61,62,0,0,128,61,81,0.07594386,0.07594386,144,57,65,0.11274866,0,128,57,65,0.214730712,0.101982052,144,68,70,0.243203477,0,128,68,61,0.327048765,0.083845288,144,60,59,1.415729647,0,128,60,66,1.491246072,0.075516425,144,61,68,1.520806535,0,128,61,72,1.598224572,0.07741803700000001, 7 | 144,60,59,0,0,128,60,61,0.081202967,0.081202967,144,61,65,0.10149604200000001,0,128,61,84,0.163497652,0.062001610000000006,144,62,54,0.225847607,0,128,62,56,0.319299477,0.09345187,144,60,59,0.33695379,0,128,60,62,0.42094466199999997,0.08399087200000001,144,61,63,0.44473342,0,128,61,61,0.528822605,0.08408918500000001, 8 | 144,54,63,0,0,128,54,56,0.10524609500000001,0.10524609500000001,144,67,58,0.12148470500000001,0,128,67,51,0.22679453,0.105309825,144,62,52,0.245747127,0,128,62,83,0.299346587,0.05359946,144,54,67,0.337350265,0,128,54,61,0.461386545,0.12403628000000001,144,67,68,0.468471087,0,128,67,74,0.57884731,0.11037622300000001, 9 | 144,54,64,0,0,144,67,62,0.13307375800000001,0,128,54,54,0.14201680000000003,0.008943042,128,67,75,0.24195408000000002,0.09993728,144,62,54,0.25825056,0,128,62,74,0.350286148,0.092035588,144,66,67,1.469213883,0,144,53,61,1.5805727980000002,0,128,66,62,1.5881718750000002,0.007599077,128,53,75,1.6990996400000002,0.110927765, 10 | 144,66,70,0,0,128,66,101,0.079640242,0.079640242,144,53,60,0.120097172,0,128,53,77,0.32389360700000003,0.203796435,144,60,62,0.35407048500000005,0,128,60,69,0.520164295,0.16609381,144,66,71,0.536272717,0,128,66,59,0.678589515,0.14231679800000002,144,53,64,0.68131658,0,128,53,71,0.781292247,0.099975667, 11 | 144,61,61,0,0,128,61,69,0.07833892,0.07833892,144,62,56,0.14132165800000002,0,128,62,70,0.210251348,0.06892969,144,54,51,0.243647915,0,128,54,50,0.347452745,0.10380483000000001,144,61,66,0.353666315,0,128,61,53,0.458288648,0.10462233300000001,144,62,52,0.5012952350000001,0,128,62,80,0.55832097,0.057025735, 12 | 144,61,58,0,0,128,61,50,0.10794929,0.10794929,144,62,54,0.14016156000000002,0,128,62,83,0.19389723500000003,0.053735675,144,54,37,0.251195345,0,128,54,75,0.31092237300000003,0.059727028,144,53,54,1.032670553,0,128,53,62,1.117339528,0.08466897500000001,144,55,43,1.240617228,0,128,55,58,1.3336262250000002,0.09300899700000001, 13 | 144,54,59,0,0,128,53,73,0.00196274,0.00196274,128,54,52,0.09459922200000001,0.092636482,144,55,45,0.11633676200000001,0,128,55,56,0.209847212,0.09351045000000001,144,53,59,0.21354583,0,128,53,75,0.338446457,0.124900627,144,54,59,0.34245324,0,128,54,52,0.43687398499999996,0.094420745,144,55,45,0.442367635,0, 14 | 144,50,54,0,0,128,50,57,0.09655761800000001,0.09655761800000001,144,58,50,0.10478052800000001,0,128,58,63,0.18125972000000004,0.076479192,144,59,66,0.21117118300000004,0,128,59,59,0.316456638,0.105285455,144,50,61,0.334400415,0,144,58,49,0.44480853,0,128,50,45,0.45315796799999997,0.008349438,128,58,57,0.530252785,0.07709481700000001, 15 | 144,50,54,0,0,144,58,55,0.10554438700000002,0,128,50,66,0.12660373700000002,0.02105935,128,58,70,0.21415414200000005,0.08755040500000001,144,59,32,0.25918018000000004,0,128,59,76,0.3183984800000001,0.0592183,144,49,63,1.4907783350000001,0,128,49,62,1.6157231650000001,0.12494483,144,50,65,1.6244229170000002,0,128,50,68,1.7222447170000004,0.09782180000000001, 16 | 144,49,67,0,0,128,61,50,0.018309055,0.018309055,144,50,65,0.14896258,0,128,49,68,0.162186567,0.013223987000000001,128,50,47,0.262956725,0.10077015800000001,144,61,45,0.26696406500000003,0,144,49,65,0.37527611000000005,0,128,61,65,0.3888882920000001,0.013612182,144,50,62,0.50788158,0,128,49,69,0.5108087120000001,0.0029271320000000003, 17 | 144,50,56,0,0,128,50,88,0.049004173000000005,0.049004173000000005,144,48,54,0.11778967800000001,0,128,48,43,0.24846509500000002,0.13067541700000002,144,51,55,0.260061553,0,128,51,96,0.309089898,0.049028345,144,50,52,0.35531594299999997,0,128,50,72,0.8417685580000001,0.48645261500000003,144,48,51,0.886868863,0,128,48,66,1.08601721,0.199148347, 18 | -------------------------------------------------------------------------------- /assets/arquaticathome.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /arquaticathome 3 | --- 4 | 5 | 6 | ## ARquatic at Home - A CodeKlavier Augmented Reality Home Experience 7 | 8 | Codeklavier’s ‘ARquatic at Home’ is an online event that brings music and Augmented Reality (AR) together to provide a unique live experience in the comfort of one's own home. 9 | 10 | In ARquatic, music provides the DNA of an underwater world that unfolds before your eyes. Full of fantasy structures artificially built from L-system rules, ‘ARquatic at Home’ will transform your home into a new-age theater you never imagined it to be. 11 | 12 | ## Streams 13 | 14 | Thursday December 2 \ 15 | 'ARquatic at Home' - Special stream for Music and Mixed Reality seminar, Nottingham University \ 16 | Time: 16:20 British Time 17 | The link of the stream is here [https://youtu.be/0sU8zzKJWyA](https://youtu.be/0sU8zzKJWyA) or click on the video below. 18 | 19 | 20 | 21 | Sunday December 5 \ 22 | 'ARquatic at Home' - part of [ChOreOgraph|ng COd|ng](http://varia.zone/en/cc-nlcl.html) \ 23 | Time: 14-16h GMT+1 24 | 25 | 26 | ## Past Streams 27 | 28 | Friday August 6 \ 29 | 'ARquatic at Home' - Special stream for those in lockdown or stuck at home due to bad weather \ 30 | Time: 20:30 Sydney/Melbourne (AUS) or 12:30 Central European Time. 31 | The link of the stream is here [https://youtu.be/F4cGi9Xy0_E](https://youtu.be/F4cGi9Xy0_E) or click on the video below. 32 | 33 | 34 | 35 | ARquatic can also be a live experience, for live show dates please visit our [ARquatic website](https://codeklavier.space/arquatic) 36 | 37 | ## Setting Up 38 | 39 | 'ARquatic at Home' is best experienced when having the streamed video page set up on a desktop or TV connected to a sound system for the duration of the show. The ARquatic App should be downloaded on a separate mobile device. For an optimal AR experience, a well-lit room is best. The app is available for download [here for Apple](https://apps.apple.com/nl/app/arquatic/id1557620712?l=en) and [here for Android](https://play.google.com/store/apps/details?id=space.codeklavier.arquatic&hl=en_US&gl=US). You will need an Apple iPhone SE/6S model (or later) or one of the Android phones listed [here](https://developers.google.com/ar/devices). You can also simply follow the link for the app download and try out the demo channel. If you do not own an AR supported device, a non-AR version will still show visuals on your Android phone. 40 | 41 | 42 | ## Motivation 43 | Our inspiration for working with L-systems comes primarily from its roots in nature and organic growth which we would like to bring to the musical and programming paradigms. Whilst L-systems are already widely used in generative art and music, we are interested in exploring how this simple model can be used by the piano coder to express complex structures and how its rules will shape the pianistic improvisation. Furthermore, Lindenmayer’s work was done at the University of Utrecht in 1968 and building upon it through artistic exploration, makes the Netherlands a particularly special location for the presentation of this project. 44 | 45 | 46 | ## About the Project 47 | 48 | ARquatic is a CodeKlavier project which combines live music, live coding and AR as an artistic experience unlike any other. The [CodeKlavier](https://codeklavier.space/) enables the pianist to grow the AR creatures by coding their structures through her playing with L-system rules. At the same time, the pianist and collaborating laptop musician are taking the audience on an enchanting musical and visual journey. 49 | 50 | ### About the technology 51 | 52 | The ‘ARquatic’ experience is made possible by three key technological elements and stages; CodeKlavier, Lindemayer and Unity. 53 | 54 | CodeKlavier: a system that enables the pianist to code by playing the piano. In ‘ARquatic Live’, this pianist is coding with lambda calculus to create numbers. These numbers are then translated into symbols used in the Lindenmayer systems engine. 55 | 56 | The L-systems engine is the second element and transforms the symbols into formal grammars defining the starting point and L-system rules. Together these form the L-system trees creating the structures of the AR visual elements which you see. 57 | 58 | These structures, along with some characteristics of the piano playing, are then applied to the visuals designed by Patrick Borgeat and rendered in Unity. This is the final step of the technological process and produces the AR visuals which you experience during the show on the ARquatic app. 59 | 60 | ## Credits 61 | [Anne Veinberg](https://anneveinberg.com/) - piano, CodeKlavier development \ 62 | [Felipe Ignacio Noriega](https://felipeignacio.info/) - live electronics, CodeKlavier development \ 63 | [Patrick Borgeat](https://borgeat.de/) - visuals, app development \ 64 | Simon Kelaita - audio mixing, video recording 65 | 66 | ## Sponsors 67 | CodeKlavier was made possible by the Creative Industries Fonds NL and our angel sponsor 68 | 69 | The performances in June and August are made possible the Fonds Podium Kunsten Balkonscenes grant 70 | 71 | ## Questions? 72 | Email arquatic@codeklavier.space 73 | 74 | ## Support 75 | This project was made possible by the Creative Industries Fonds NL and our angel sponsor. Ongoing work is limited to preparations for gigs at festivals and venues that book us for concerts. Do you believe in the project and would like to support us further? please consider "buying us a coffee". Every little bit counts and we greatly appreciate your support! 76 | 77 | [![ko-fi](https://www.ko-fi.com/img/donate_sm.png)](https://ko-fi.com/J3J7PGIE) 78 | -------------------------------------------------------------------------------- /codeklavier.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | CodeKlavier Masterscript 4 | 5 | This script will help you run the Codeklavier 6 | """ 7 | 8 | import configparser 9 | import getopt 10 | import sys 11 | import time 12 | 13 | import importlib 14 | 15 | from CK_Setup import Setup, BColors 16 | from CK_rec import CK_Rec 17 | import CK_config 18 | 19 | 20 | 21 | ck_deltatime_mem = [] 22 | 23 | VERSIONS = ('ckar', 'ckalculator', 'hybrid') 24 | 25 | def doHelp(): 26 | """ 27 | Show the help for running this script. 28 | """ 29 | print(BColors.HEADER + 'This script will help you to run the 🎹 CodeKlavier 🎹' + BColors.ENDC) 30 | print('') 31 | print(BColors.CKGREEN + 'Usage: ./codeklaver.py [OPTION]' + BColors.ENDC) 32 | print('Where [OPTION] is:') 33 | print(BColors.BOLD + '-h | --help' + BColors.ENDC) 34 | print('Show this help text.') 35 | 36 | print('') 37 | print(BColors.BOLD + '-p | --play' + BColors.WARNING + ' <>' + BColors.ENDC) 38 | print('Boot CodeKlavier with version <>') 39 | print('These versions are available: ' + (', ').join(VERSIONS)) 40 | print('') 41 | print(BColors.BOLD + '-i | --ini' + BColors.WARNING + ' <>' + BColors.ENDC) 42 | print('Boot CodeKlavier with configuration from <>') 43 | print('') 44 | print(BColors.BOLD + '-r | --rec' + BColors.ENDC) 45 | print('Boot CodeKlavier to record MIDI for machine learning') 46 | print('') 47 | print(BColors.BOLD + '-t | --test' + BColors.ENDC) 48 | print('Test and visualize if Codeklavier is receving MIDI') 49 | print('') 50 | print(BColors.UNDERLINE + 'Example:' + BColors.ENDC) 51 | print(BColors.CKGREEN + './codeklavier.py -p hybrid' + BColors.ENDC) 52 | print('') 53 | 54 | def miditest(configfile='default_setup.ini'): 55 | """ 56 | Run a basic miditest to see how the CodeKlavier is receiving your midi. 57 | 58 | :param string configfile: Path to the configuration file (default: default_setup.ini) 59 | """ 60 | #Read config and settings 61 | config = configparser.ConfigParser() 62 | config.read(configfile, encoding='utf8') 63 | 64 | try: 65 | myPort = config['midi'].getint('port') 66 | device_id = config['midi'].getint('noteon_id') 67 | pedal = config['midi'].getint('pedal_id') 68 | sostenuto = config['midi'].getint('pedal_midi_id') 69 | except KeyError: 70 | raise LookupError('Missing key information in the config file.') 71 | 72 | if (myPort == None or device_id == None): 73 | raise LookupError('Missing key information in the config file.') 74 | 75 | codeK = Setup() 76 | codeK.open_port(myPort) 77 | print('your device id is: ', device_id, '\n') 78 | print("CodeKlavier is ON. Press Control-C to exit.") 79 | try: 80 | while True: 81 | msg = codeK.get_message() 82 | 83 | if msg: 84 | message, deltatime = msg 85 | if message[0] in [device_id, pedal, sostenuto]: 86 | print('deltatime: ', deltatime, 'msg: ', message) 87 | 88 | time.sleep(0.01) 89 | 90 | except KeyboardInterrupt: 91 | print('') 92 | finally: 93 | print("Bye-Bye :(") 94 | codeK.end() 95 | 96 | def boot(configfile='default_setup.ini', version=None): 97 | """ 98 | Boot a specific version from the CodeKlavier 99 | 100 | :param string configfile: Path to the configuration file (default: default_setup.ini) 101 | :param string version: name of the version to boot 102 | """ 103 | if (version not in VERSIONS): 104 | raise ValueError(BColors.WARNING + 'This version doesn\'t exist. Please retry.' + BColors.ENDC) 105 | 106 | if version == 'ckar': 107 | version = 'ckalculator' 108 | module = importlib.import_module(version) 109 | version = getattr(module, version) 110 | eval(version.main(ar_hook=True)) 111 | else: 112 | module = importlib.import_module(version) 113 | version = getattr(module, version) 114 | eval(version.main()) 115 | 116 | if __name__ == '__main__': 117 | """ 118 | Catch the arguments that were used to start this function. 119 | 120 | Options are h, c, p, t, r 121 | """ 122 | 123 | showHelp = False 124 | test = False 125 | record = False 126 | config = None 127 | play = None 128 | 129 | try: 130 | options, args = getopt.getopt(sys.argv[1:],'h:p:i:rt',['help', 'play=', 'ini=', 'rec', 'test']) 131 | selected_options = [x[0] for x in options] 132 | 133 | for o, a in options: 134 | if o in ('-h', '--help'): 135 | showHelp = True 136 | if o in ('-p', '--play'): 137 | play = a 138 | if o in ('-i', '--ini'): 139 | config = a 140 | if o in ('-t', '--test'): 141 | test = True 142 | if o in ('-r', '--rec'): 143 | record = True 144 | 145 | except getopt.GetoptError: 146 | print('Something went wrong parsing the optional arguments') 147 | 148 | if showHelp: 149 | doHelp() 150 | sys.exit(0) 151 | 152 | if config == None: 153 | CK_config.inifile = 'default_setup.ini' 154 | else: 155 | CK_config.inifile = config 156 | 157 | if test: 158 | miditest(configfile=CK_config.inifile) 159 | sys.exit(0) 160 | 161 | if record: 162 | rec = CK_Rec(configfile=CK_config.inifile) 163 | rec.record(framesize=1) 164 | sys.exit(0) 165 | 166 | if play: 167 | boot(configfile=config, version=play) 168 | sys.exit(0) 169 | 170 | #no arguments -> print help 171 | doHelp() 172 | sys.exit(0) 173 | 174 | 175 | -------------------------------------------------------------------------------- /doc/build/html/RunCodeKlavier.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Run codeklavier — CodeKlavier 0.3.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 44 | 66 | 67 |
68 |
69 |
70 |
71 | 72 |
73 |

Run codeklavier

74 |

To help you run CodeKlavier, we have made a “run all” master wrapper script. It is in the CodeKlavier root directory and it is called codeklavier.py. You can run it by typng ./codeklavier.py -i and the script will start in interactive mode. Run ./codeklavier.py --help to get more help.

75 |
76 |

PythonPath

77 |

Make sure you set the pythonpath before you start the script You can set the pythonpath by runnin . setPythonPath.sh from the root CodeKlavier directory (note the dot-space at the beginning) or add the pythonpath to your bash_profile.

78 |
79 |
80 | 81 | 82 |
83 |
84 |
85 |
86 |
87 | 105 | 109 | 110 | -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # CodeKlavier documentation build configuration file, created by 5 | # sphinx-quickstart on Thu Feb 1 22:04:39 2018. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | import os 21 | import sys 22 | sys.path.insert(0, os.path.abspath('.')) 23 | sys.path.insert(0, os.path.abspath('../../')) 24 | 25 | 26 | # -- General configuration ------------------------------------------------ 27 | 28 | # If your documentation needs a minimal Sphinx version, state it here. 29 | # 30 | # needs_sphinx = '1.0' 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = ['sphinx.ext.autodoc', 36 | 'sphinx.ext.githubpages'] 37 | 38 | # Add any paths that contain templates here, relative to this directory. 39 | templates_path = ['_templates'] 40 | 41 | # The suffix(es) of source filenames. 42 | # You can specify multiple suffix as a list of string: 43 | # 44 | # source_suffix = ['.rst', '.md'] 45 | source_suffix = '.rst' 46 | 47 | # The master toctree document. 48 | master_doc = 'index' 49 | 50 | # General information about the project. 51 | project = 'CodeKlavier' 52 | copyright = '2018, CodeKlavier Team' 53 | author = 'CodeKlavier Team' 54 | 55 | # The version info for the project you're documenting, acts as replacement for 56 | # |version| and |release|, also used in various other places throughout the 57 | # built documents. 58 | # 59 | # The short X.Y version. 60 | version = '0.3' 61 | # The full version, including alpha/beta/rc tags. 62 | release = '0.3.0' 63 | 64 | # The language for content autogenerated by Sphinx. Refer to documentation 65 | # for a list of supported languages. 66 | # 67 | # This is also used if you do content translation via gettext catalogs. 68 | # Usually you set "language" from the command line for these cases. 69 | language = None 70 | 71 | # List of patterns, relative to source directory, that match files and 72 | # directories to ignore when looking for source files. 73 | # This patterns also effect to html_static_path and html_extra_path 74 | exclude_patterns = [] 75 | 76 | # The name of the Pygments (syntax highlighting) style to use. 77 | pygments_style = 'sphinx' 78 | 79 | # If true, `todo` and `todoList` produce output, else they produce nothing. 80 | todo_include_todos = False 81 | 82 | 83 | # -- Options for HTML output ---------------------------------------------- 84 | 85 | # The theme to use for HTML and HTML Help pages. See the documentation for 86 | # a list of builtin themes. 87 | # 88 | html_theme = 'alabaster' 89 | html_theme = "classic" 90 | html_theme = "bizstyle" 91 | 92 | # Theme options are theme-specific and customize the look and feel of a theme 93 | # further. For a list of options available for each theme, see the 94 | # documentation. 95 | # 96 | # html_theme_options = {} 97 | 98 | # Add any paths that contain custom static files (such as style sheets) here, 99 | # relative to this directory. They are copied after the builtin static files, 100 | # so a file named "default.css" will overwrite the builtin "default.css". 101 | html_static_path = ['_static'] 102 | 103 | # Custom sidebar templates, must be a dictionary that maps document names 104 | # to template names. 105 | # 106 | # This is required for the alabaster theme 107 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 108 | html_sidebars = { 109 | '**': [ 110 | 'relations.html', # needs 'show_related': True theme option to display 111 | 'searchbox.html', 112 | ] 113 | } 114 | 115 | 116 | # -- Options for HTMLHelp output ------------------------------------------ 117 | 118 | # Output file base name for HTML help builder. 119 | htmlhelp_basename = 'CodeKlavierdoc' 120 | 121 | html_show_sourcelink = False 122 | html_copy_source = False 123 | 124 | 125 | # -- Options for LaTeX output --------------------------------------------- 126 | 127 | latex_elements = { 128 | # The paper size ('letterpaper' or 'a4paper'). 129 | # 130 | # 'papersize': 'letterpaper', 131 | 132 | # The font size ('10pt', '11pt' or '12pt'). 133 | # 134 | # 'pointsize': '10pt', 135 | 136 | # Additional stuff for the LaTeX preamble. 137 | # 138 | # 'preamble': '', 139 | 140 | # Latex figure (float) alignment 141 | # 142 | # 'figure_align': 'htbp', 143 | } 144 | 145 | # Grouping the document tree into LaTeX files. List of tuples 146 | # (source start file, target name, title, 147 | # author, documentclass [howto, manual, or own class]). 148 | latex_documents = [ 149 | (master_doc, 'CodeKlavier.tex', 'CodeKlavier Documentation', 150 | 'CodeKlavier Team', 'manual'), 151 | ] 152 | 153 | 154 | # -- Options for manual page output --------------------------------------- 155 | 156 | # One entry per manual page. List of tuples 157 | # (source start file, name, description, authors, manual section). 158 | man_pages = [ 159 | (master_doc, 'codeklavier', 'CodeKlavier Documentation', 160 | [author], 1) 161 | ] 162 | 163 | 164 | # -- Options for Texinfo output ------------------------------------------- 165 | 166 | # Grouping the document tree into Texinfo files. List of tuples 167 | # (source start file, target name, title, author, 168 | # dir menu entry, description, category) 169 | texinfo_documents = [ 170 | (master_doc, 'CodeKlavier', 'CodeKlavier Documentation', 171 | author, 'CodeKlavier', 'One line description of project.', 172 | 'Miscellaneous'), 173 | ] 174 | -------------------------------------------------------------------------------- /doc/build/html/modules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | CodeKlavier — CodeKlavier 0.3.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 44 | 66 | 67 | 97 | 115 | 119 | 120 | -------------------------------------------------------------------------------- /CodeKlavier/Motifs.py: -------------------------------------------------------------------------------- 1 | """Motifs in Dictionaries. 2 | 3 | Here you can define the name of the motif and the series of midi-notes that 4 | make up that motif. 5 | Way more efficient than an unjustified class. 6 | 7 | TODO: re-order to have a config loader before execution of prototypes, etc... 8 | """ 9 | 10 | import configparser 11 | import os 12 | from CK_config import inifile 13 | 14 | config = configparser.ConfigParser() 15 | config.read(inifile, encoding='utf8') 16 | 17 | motifs = {} 18 | motifs_mel = {} 19 | 20 | mottipets_motifs = {} 21 | mottipets_motifs_mel = {} 22 | 23 | mini_motifs = {} 24 | mini_motifs_mel = {} 25 | 26 | conditional_motifs = {} 27 | conditional_motifs_mel = {} 28 | 29 | conditional_results_motifs = {} 30 | conditional_results_motifs_mel = {} 31 | 32 | motifs_lambda = {} 33 | motifs_ar = {} 34 | 35 | 36 | try: 37 | #chordal: 38 | for motif in config['chordal main motifs midi']: 39 | mottipets_motifs[motif] = config['chordal main motifs midi'].get(motif).split(',') 40 | 41 | for motif in config['chordal mini motifs']: 42 | mini_motifs[motif] = config['chordal mini motifs'].get(motif).split(',') 43 | 44 | for motif in config['chordal conditional motifs midi']: 45 | conditional_motifs[motif] = config['chordal conditional motifs midi'].get(motif).split(',') 46 | 47 | for motif in config['chordal conditional results motifs midi']: 48 | conditional_results_motifs[motif] = config['chordal conditional results motifs midi'].get(motif).split(',') 49 | 50 | #melodic: 51 | for motif in config['melodic main motifs midi']: 52 | mottipets_motifs_mel[motif] = config['melodic main motifs midi'].get(motif).split(',') 53 | 54 | for motif in config['melodic mini motifs']: 55 | mini_motifs_mel[motif] = config['melodic mini motifs'].get(motif).split(',') 56 | 57 | for motif in config['melodic conditional motifs midi']: 58 | conditional_motifs_mel[motif] = config['melodic conditional motifs midi'].get(motif).split(',') 59 | 60 | for motif in config['melodic conditional results motifs midi']: 61 | conditional_results_motifs_mel[motif] = config['melodic conditional results motifs midi'].get(motif).split(',') 62 | 63 | #all are lists 64 | identity_midi = config['lambda'].get('identity_midi').split(',') 65 | evaluate_function = config['lambda'].get('evaluate_function').split(',') 66 | select_first = config['lambda'].get('select_first_midi').split(',') 67 | select_second = config['lambda'].get('select_second_midi').split(',') 68 | successor = config['lambda'].get('successor_midi').split(',') 69 | predecessor = config['lambda'].get('predecessor_midi').split(',') 70 | add_midi = config['lambda'].get('add_midi').split(',') 71 | subtract_midi = config['lambda'].get('subtract_midi').split(',') 72 | mult_midi = config['lambda'].get('mult_midi').split(',') 73 | division_midi = config['lambda'].get('division_midi').split(',') 74 | equal_than_midi = config['lambda'].get('equality_midi').split(',') 75 | greater_than_midi = config['lambda'].get('greater_than_midi').split(',') 76 | less_than_midi = config['lambda'].get('less_than_midi').split(',') 77 | 78 | if len(config['ar']) > 1: 79 | dot = config['ar'].get('dot').split(',') 80 | create = config['ar'].get('create').split(',') 81 | clear_rule = config['ar'].get('clear').split(',') 82 | select = config['ar'].get('select').split(',') 83 | generation = config['ar'].get('generation').split(',') 84 | nextt = config['ar'].get('nextt').split(',') 85 | transform = config['ar'].get('transform').split(',') 86 | shape = config['ar'].get('shape').split(',') 87 | store_collection = config['ar'].get('store_collection').split(',') 88 | transp_even = config['ar'].get('transpositon_even').split(',') 89 | transp_odd = config['ar'].get('transposition_odd').split(',') 90 | 91 | 92 | except KeyError: 93 | raise LookupError('Missing sections in the config file or the config file does not exist. Maybe a typo?') 94 | 95 | 96 | # chordal: 97 | for motif in mottipets_motifs: 98 | motifs[motif] = list(map(int, mottipets_motifs[motif])) 99 | 100 | for motif in mini_motifs: 101 | mini_motifs[motif] = list(map(int, mini_motifs[motif])) 102 | 103 | for motif in conditional_motifs: 104 | conditional_motifs[motif] = list(map(int, conditional_motifs[motif])) 105 | 106 | for motif in conditional_results_motifs: 107 | conditional_results_motifs[motif] = list(map(int, conditional_results_motifs[motif])) 108 | 109 | # melodic: 110 | for motif in mottipets_motifs_mel: 111 | motifs_mel[motif] = list(map(int, mottipets_motifs_mel[motif])) 112 | 113 | for motif in mini_motifs_mel: 114 | mini_motifs_mel[motif] = list(map(int, mini_motifs_mel[motif])) 115 | 116 | for motif in conditional_motifs_mel: 117 | conditional_motifs_mel[motif] = list(map(int, conditional_motifs_mel[motif])) 118 | 119 | for motif in conditional_results_motifs_mel: 120 | #print('parsed motifs:', motif, mini_motifs_mel[motif]) 121 | conditional_results_motifs_mel[motif] = list(map(int, conditional_results_motifs_mel[motif])) 122 | 123 | # lambda calculus 124 | motifs_lambda['eval'] = list(map(int, evaluate_function)) 125 | motifs_lambda['zero'] = list(map(int, identity_midi)) 126 | motifs_lambda['true'] = list(map(int, select_first)) 127 | motifs_lambda['false'] = list(map(int, select_second)) 128 | motifs_lambda['successor'] = list(map(int, successor)) 129 | motifs_lambda['predecessor'] = list(map(int, predecessor)) 130 | motifs_lambda['addition'] = list(map(int, add_midi)) 131 | motifs_lambda['subtraction'] = list(map(int, subtract_midi)) 132 | motifs_lambda['multiplication'] = list(map(int, mult_midi)) 133 | motifs_lambda['division'] = list(map(int, division_midi)) 134 | motifs_lambda['equal'] = list(map(int, equal_than_midi)) 135 | motifs_lambda['greater'] = list(map(int, greater_than_midi)) 136 | motifs_lambda['less'] = list(map(int, less_than_midi)) 137 | 138 | # AR module 139 | if len(config['ar']) > 1: 140 | motifs_ar['dot'] = list(map(int, dot)) 141 | motifs_ar['create'] = list(map(int, create)) 142 | motifs_ar['clear_rule'] = list(map(int, clear_rule)) 143 | motifs_ar['generation'] = list(map(int, generation)) 144 | motifs_ar['select'] = list(map(int, select)) 145 | motifs_ar['next'] = list(map(int, nextt)) 146 | motifs_ar['transform'] = list(map(int, transform)) 147 | motifs_ar['shape'] = list(map(int, shape)) 148 | motifs_ar['store_collection'] = list(map(int, store_collection)) 149 | motifs_ar['transp_even'] = list(map(int, transp_even)) 150 | motifs_ar['transp_odd'] = list(map(int, transp_odd)) 151 | 152 | -------------------------------------------------------------------------------- /assets/arquaticnl.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /arquaticnl 3 | --- 4 | 5 | For [English](https://codeklavier.space/arquatic)🇬🇧 6 | 7 | # ARquatic Live - A CodeKlavier Augmented Reality Experience 8 | 9 | ## Over ARquatic 10 | ‘ARquatic’ van de CodeKlavier biedt het publiek een totaalervaring van geluid, muziek en Augmented Reality (AR). Live muziek levert de input voor een fantasierijke, associatieve onderwaterwereld, die zich voor uw ogen ontvouwt op uw smartphone. 11 | 12 | De AR-objecten en structuren worden gecreëerd volgens de regels van Lindenmayer-systemen, die o.a. gebruikt worden om 3D-bomen te creëren. 13 | ‘ARquatic’ legt ongebruikelijke objecten, geïnspireerd op water, over alledaagse omgevingen. De combinatie van de natuurlijke verschijning van de wereld om ons heen met de artificiële schoonheid van de AR-objecten stimuleert de verbeelding. 14 | 15 | ## Trailer 16 | 17 | 18 | 19 | ## Shows 20 | 21 | 22 | 4 september: 15.00 \ 23 | [Botanische Tuin Pinetum Blijdenstein](https://pinetum.nl/), Hilversum \ 24 | Concert met werken van Einaudi, Gershwin/Wild en eigen muziek 25 | 26 | 11 september: 13.00, 14.00, 15.00, 16.00 \ 27 | ARquatic tijdens Open Monumentendag \ 28 | [Arboretum Oudenbosch](https://www.arboretumoudenbosch.nl/) 29 | 30 | 17 september: 19.30, 20.15, 21.00, 21.45, 22.30 \ 31 | ARquatic tijdens [Nacht van Ontdekingen](https://www.nachtvanontdekkingen.nl/portfolio/arquatic/)\ 32 | Wintertuin - Hortus Botanicus, Leiden 33 | 34 | 24 september: 13.00, 14.00, 15.00, 16.00 \ 35 | [Vlinderhof](https://vlinderhof.com/) in Maximapark, Utrecht 36 | 37 | 25 september: 15.00 \ 38 | [Hortus Alkmaar](https://www.hortusalkmaar.nl/events/zondagmiddagconcert-arquatic/), Alkmaar \ 39 | Programma met werken van Einaudi, Gershwin/Wild en eigen muziek \ 40 | Kaartjes [hier](https://eventix.shop/s7r8q6k6) 41 | 42 | 2 oktober: 12.00, 13.00, 14.00, 15.00 \ 43 | [Hortus Nijmegen](https://www.hortusnijmegen.nl/agenda/), Nijmegen 44 | 45 | 46 | ---Eedere shows--- 47 | 48 | 49 | Vrijdag Januari 28 \ 50 | ARquatic tijdens [on-the-fly: Live Coding Hacklab](https://zkm.de/en/event/2022/01/on-the-fly-live-coding-hacklab) \ 51 | Zentrum voor Kunst en Media, Karlsruhe \ 52 | Tijd: 20.00 53 | 54 | Zondag December 5 \ 55 | Discussie over het CodeKlavier en ARquatic at Home - streamed event. \ 56 | Met Joana Chicau, Renick Bell, Timo Hoogland and Saskia Freeke 57 | Tijd: 14.00-16.00 58 | 59 | Donderdag December 2 \ 60 | ARquatic at Home - streamed event. \ 61 | [Meer info](https://codeklavier.space/arquaticathome) \ 62 | Tijd: 17.00 63 | 64 | Donderdag November 25 \ 65 | Discourse on XR/AR/VR \ 66 | Gesprek over ARquatic door Patrick Borgeat in [Update Festival](https://update.mplab.lv/program-2/) 67 | 68 | Dinsdag 7 September \ 69 | ARquatic in de Rode Bioscoop \ 70 | Tijd: 20.00 \ 71 | Prive evenement voor het Amsterdams Young Artist Foundation 72 | 73 | Vrijdag 27 Augustus \ 74 | ARquatic in [de Kwekerij](https://www.dekwekerijhilversum.nl/agenda/) \ 75 | Tijd: 16.00, 17.00, 18.00 \ 76 | Klik [hier](https://forms.gle/kDPZUJiEVHvyEyVZ6) te reserveren 77 | 78 | Vrijdag 6 Augustus \ 79 | ARquatic at Home - streamed event. \ 80 | [Meer info](https://codeklavier.space/arquaticathome) 81 | 82 | Zondag 6 Juni \ 83 | ARquatic Live in het [Pinetum, Hilversum](https://pinetum.nl/) \ 84 | Tijd: 14.00, 15.00, 16.00 \ 85 | Reservering is verplicht. Klik [hier](https://forms.gle/1mtK5oPnPk34KYtC9) om het formulier in te vullen 86 | 87 | 88 | Zondag 13 Juni \ 89 | ["Meer dan Muziek" Festival in Toets des Tijds, Amsterdam](www.toetsdestijds.com) \ 90 | Tijd: 17.00, 20.00 \ 91 | Kaartjes [bestellen](www.toetsdestijds.com) 92 | 93 | ## Download de app 94 | 95 | De ARquatic app is beschikbaar te downloaden: klik [hier voor Apple](https://apps.apple.com/nl/app/arquatic/id1557620712?l=en) en [hier voor Android](https://play.google.com/store/apps/details?id=space.codeklavier.arquatic&hl=en_US&gl=US). U heeft een Apple iPhone SE/6S (of later) of een Android van [deze](https://developers.google.com/ar/devices) lijst nodig. U kunt ook gewoon de link voor de app volgen en kijken of de demo op uw telefoon werkt. In dat geval werkt de app ook voor het live optreden. Als u geen geschikte mobiele telefoon heeft, dan kunt u nog steeds genieten van de visuals in 2D, maar niet van Augmented Reality. 96 | 97 | ## Motivatie 98 | L-systemen vinden hun oorsprong in de natuur en organische groei: daarom nemen wij deze principes in onze muzikale- en programmeerparadigma’s. L-systemen worden op dit moment al op grote schaal gebruikt in generatieve kunst en muziek. 99 | Wij onderzoeken hoe de piano-codeur met dit model complexe structuren tot uitdrukking kan brengen en hoe de regels van het systeem de improvisatie aan de piano beïnvloeden. Lindenmayer werkte aan de Universiteit van Utrecht in 1968. Daarom is Nederland een bijzondere locatie voor de presentatie van dit project. 100 | 101 | 102 | ## Over de technologie 103 | De ‘ARquatic Live’-ervaring wordt mogelijk gemaakt door drie belangrijke technologische elementen en fasen; CodeKlavier, Lindemayer en de ARquatic App. 104 | 105 | CodeKlavier: een systeem waarmee de pianist kan coderen door piano te spelen. In ‘ARquatic Live’ codeert de pianist met lambda-calculus om getallen te creëren. Deze nummers worden vervolgens vertaald in symbolen die worden gebruikt in de L-systeemengine. 106 | 107 | De L-systeemengine is het tweede element en zet de symbolen om in formele grammatica's die het startpunt en de L-systeemregels definiëren. Samen vormen deze de L-systeembomen die de structuren creëren van de AR-visuele elementen die u ziet. 108 | 109 | Deze structuren, samen met enkele kenmerken van het pianospel, worden vervolgens toegepast op de visuals ontworpen door Patrick Borgeat en weergegeven in de ARquatic App. Dit is de laatste stap van het technologische proces en levert de AR-visuals op die je tijdens de show ervaart op uw telefoon. 110 | 111 | ## Credits 112 | [Anne Veinberg](https://anneveinberg.com/) - piano, CodeKlavier creator \ 113 | [Felipe Ignacio Noriega](https://felipeignacio.info/) - live electronics, CodeKlavier creator \ 114 | [Patrick Borgeat](https://borgeat.de/) - visuals, app developer 115 | 116 | ## Sponsors 117 | 118 | Met dank aan het Stimuleringsfonds Creative Industrie en onze angel sponsor voor het mogelijk maken van de CodeKlavier project. 119 | 120 | Met dank aan het Fonds Podium kunsten Balkonscenes Fonds voor het mogelijk maken van de optredens in Juni en Augustus 2021. 121 | 122 | Met dank aan het Stimuleringsfonds Creative Industrie, het Prins Bernhard Cultuurfonds en de Gemeente Utrecht voor het mogelijk maken van de optredens in september en oktober 2022. Dit tournee is een samen werking met Stichting Present Sound. 123 | 124 | ## Vragen? 125 | Contact arquatic@codeklavier.space 126 | 127 | 128 | -------------------------------------------------------------------------------- /hello_world/SC/CodeKlavier_hello_world_v_sampler.scd: -------------------------------------------------------------------------------- 1 | // midi mappings: 2 | s.waitForBoot({ 3 | "starting MIDI...".postln; 4 | MIDIClient.init; 5 | s.sync; 6 | MIDIIn.connectAll; 7 | s.sync; 8 | m = MIDIOut.newByName("IAC Driver", "Bus 1"); 9 | s.sync; 10 | // hello world \\ 11 | ( 12 | t=TempoClock.default; 13 | s.sync; 14 | "setting variables and ostinatos...".postln; 15 | ~pitch = 0;~pitch1 = 0;~pitch2 = 0; ~pulsepitch = 0; 16 | // adjust the quant; 17 | ~quant=1/4; 18 | s.sync; 19 | // ostinatos: 20 | ~ost=Pdef(\ostinato1, {Pbind(\dur, Pseq([Pfuncn({1/h}, 1), Pfuncn({1/e},1), Pfuncn({1/l},1)], inf), \ctranspose, Pfunc{~pitch}, 21 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi], inf), 22 | \type, \midi, \midiout, m)}); 23 | ~ost.quant=~quant; 24 | ~ost1=Pdef(\ostinato2, {Pbind(\dur, Pseq([Pfuncn({1/o}, 1), Pfuncn({1/w},1), Pfuncn({1/r},1)], inf), \ctranspose, Pfunc{~pitch1}, 25 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi], inf), 26 | \type, \midi, \midiout, m)}); 27 | ~ost1.quant=~quant; 28 | ~ost2=Pdef(\ostinato3, {Pbind(\dur, Pseq([Pfuncn({1/d}, 1), Pfuncn({1/a},1), Pfuncn({1/n},1)], inf), \ctranspose, Pfunc{~pitch2}, 29 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi], inf), 30 | \type, \midi, \midiout, m)}); 31 | ~ost2.quant=~quant; 32 | s.sync; 33 | // random ostinatos 34 | 35 | ~rand=Tdef(\randostinato, { 36 | var rit = (1/2).rrand(4).round(0.5); 37 | var rit2 = (1/2).rrand(4).round(0.5); 38 | var rit3 = (1/2).rrand(4).round(0.5); 39 | var randrit = [Pfuncn({1/(h*rit)}, 1), Pfuncn({1/(e*rit2)},1), Pfuncn({1/(l*rit3)},1)]; 40 | var randpitch = ["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi].scramble; 41 | Pdef(\ostinato1, {Pbind(\dur, Pseq(randrit, inf);, \ctranspose, Pfunc{~pitch}, 42 | \midinote, Pseq(randpitch, inf), 43 | \type, \midi, \midiout, m)})}); 44 | s.sync; 45 | // hello pulse 46 | ~hello=Pdef(\hello, {Pbind(\dur, Pseq([2], inf), \ctranspose, Pfunc{~h1o}, \midinote, Pseq(["a2".namemidi], inf), \type, \midi, \midiout, m)}); 47 | ~hello.quant=~quant; 48 | ~hello2=Pdef(\hello2, {Pbind(\dur, Pseq([2], inf), \ctranspose, Pfunc{~h2o}, \midinote, Pseq(["a2".namemidi], inf), \type, \midi, \midiout, m)}); 49 | ~hello2.quant=~quant; 50 | ~hello3=Pdef(\hello3, {Pbind(\dur, Pseq([2], inf), \ctranspose, Pfunc{~h3o}, \midinote, Pseq(["a2".namemidi], inf), \type, \midi, \midiout, m)}); 51 | ~hello3.quant=~quant; 52 | s.sync; 53 | ~hello2.quant=~quant; 54 | ~h1o=~h2o=~h3o=0; 55 | s.sync; 56 | h=e=l=o=w=d=a=r=n=1; 57 | ~p = 1; // ???? 58 | s.sync; 59 | ~reset = Tdef(\reset, {1.do{h=e=l=o=w=d=a=r=n=1; t.tempo=1; 60 | ~h1o=~h2o=~h30=0; 61 | ~ost=Pdef(\ostinato1, {Pbind(\dur, Pseq([Pfuncn({1/h}, 1), Pfuncn({1/e},1), Pfuncn({1/l},1)], inf), \ctranspose, Pfunc{~pitch}, 62 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi], inf), 63 | \type, \midi, \midiout, m)}); 64 | ~ost1=Pdef(\ostinato2, {Pbind(\dur, Pseq([Pfuncn({1/o}, 1), Pfuncn({1/w},1), Pfuncn({1/r},1)], inf), \ctranspose, Pfunc{~pitch1}, 65 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi], inf), 66 | \type, \midi, \midiout, m)}); 67 | ~ost2=Pdef(\ostinato3, {Pbind(\dur, Pseq([Pfuncn({1/d}, 1), Pfuncn({1/a},1), Pfuncn({1/n},1)], inf), \ctranspose, Pfunc{~pitch2}, 68 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi], inf), 69 | \type, \midi, \midiout, m)}); 70 | } 71 | }); 72 | s.sync; 73 | ); 74 | ( 75 | "variables for fx".postln; 76 | ~eamp=0;~eamp2=0;~eamp3=0; 77 | ~del=1;~del2=1;~del3=3; 78 | ~r3=1; 79 | ); 80 | ( 81 | "starting routine for re-pitching with piano pedal...".postln; 82 | /// re-pitching: 83 | SkipJack({ 84 | 85 | // fx 86 | Tdef(\maps1, { 87 | inf.do{ 88 | /*"debug".postln;*/ 89 | Ndef(\fx).map(\del, Ndef(\krd, ~del)); 90 | Ndef(\fx).map(\amp, Ndef(\kra, ~eamp)); 91 | 92 | Ndef(\fx1).map(\del, Ndef(\krd2, ~del2)); 93 | Ndef(\fx1).map(\amp, Ndef(\kra2, ~eamp2)); 94 | 95 | Ndef(\fx2).map(\del, Ndef(\krd3, ~del3)); 96 | Ndef(\fx2).map(\amp, Ndef(\kra3, ~eamp3)); 97 | Ndef(\fx2).map(\rate, Ndef(\krr3, ~r3)); 98 | 0.1.wait; 99 | } 100 | }).play; 101 | 102 | 103 | /*var key = "narcode".scramble; 104 | Tdef(key.asSymbol, {*/ 105 | 1.do { 106 | 107 | if (~op == 1) { 108 | /*("op ---> running").postln;*/ 109 | 110 | MIDIdef.cc(\pedalpitch, {arg ...args; 111 | if (args[1] == 64) { 112 | ~pitch = args[0].linlin(0, 127, 0, 12).round(1); 113 | ("ostinato1 ***" + ~pitch + " semitones up").postln; 114 | } 115 | }); 116 | }; 117 | 118 | if (~op == 0) { 119 | /*("op ----> stopped").postln;*/ 120 | MIDIdef.cc(\pedalpitch).free; 121 | }; 122 | 123 | if (~op1 == 1) { 124 | MIDIdef.cc(\pedalpitchop1, {arg ...args; 125 | if (args[1] == 64) { 126 | ~pitch1 = args[0].linlin(0, 127, 0, 12).round(1); 127 | ("ostinato2 ***" + ~pitch1 + " semitones up").postln; 128 | } 129 | }); 130 | }; 131 | 132 | if (~op1 == 0) { 133 | MIDIdef.cc(\pedalpitchop1).free; 134 | }; 135 | 136 | if (~op2 == 1) { 137 | MIDIdef.cc(\pedalpitchop2, {arg ...args; 138 | if (args[1] == 64) { 139 | ~pitch2 = args[0].linlin(0, 127, 0, 12).round(1); 140 | ("ostinato3 *** " + ~pitch2 + " semitones up").postln; 141 | } 142 | }); 143 | }; 144 | 145 | if (~op2 == 0) { 146 | MIDIdef.cc(\pedalpitchop2).free; 147 | }; 148 | 149 | if (~down == 1) { 150 | ("down ---> running").postln; 151 | MIDIdef.cc(\pedalpitchd, {arg ...args; 152 | if (args[1] == 64) { 153 | ~pitch = args[0].linlin(0, 127, 0, -7).round(1); 154 | ("ostinato1 ***" + ~pitch + " semitones down").postln; 155 | } 156 | }); 157 | }; 158 | 159 | if (~down == 0) { 160 | /*("down ----> stopped").postln;*/ 161 | 162 | MIDIdef.cc(\pedalpitchd).free; 163 | }; 164 | 165 | if (~down1 == 1) { 166 | MIDIdef.cc(\pedalpitchd1, {arg ...args; 167 | if (args[1] == 64) { 168 | ~pitch1 = args[0].linlin(0, 127, 0, -7).round(1); 169 | ("ostinato2 ***" + ~pitch1 + " semitones down").postln; 170 | } 171 | }); 172 | }; 173 | 174 | if (~down1 == 0) { 175 | MIDIdef.cc(\pedalpitchd1).free; 176 | }; 177 | 178 | if (~down2 == 1) { 179 | MIDIdef.cc(\pedalpitchd2, {arg ...args; 180 | if (args[1] == 64) { 181 | ~pitch2 = args[0].linlin(0, 127, 0, -7).round(1); 182 | ("ostinato3 ***" + ~pitch2 + " semitones down").postln; 183 | } 184 | }); 185 | }; 186 | 187 | if (~down2 == 0) { 188 | MIDIdef.cc(\pedalpitchd2).free; 189 | }; 190 | }; }, 1, name: "pedalwatch"); 191 | ); 192 | s.sync; 193 | "CodeKlavier is ready and listening...".postln; 194 | }.fork; 195 | ); 196 | 197 | /// if you want to stop the pedal watcher: 198 | /*SkipJack.stop("pedalwatch");*/ 199 | -------------------------------------------------------------------------------- /hello_world/SC/CodeKlavier_hello_world_v_RTP.scd: -------------------------------------------------------------------------------- 1 | // midi mappings: 2 | s.waitForBoot({ 3 | "starting MIDI...".postln; 4 | MIDIIn.connectAll; 5 | s.sync; 6 | MIDIClient.init; 7 | s.sync; 8 | MIDIIn.connectAll; 9 | s.sync; 10 | m = MIDIOut.newByName("USB MIDI Interface", "USB MIDI Interface"); 11 | s.sync; 12 | // hello world \\ 13 | ( 14 | t=TempoClock.default; 15 | s.sync; 16 | "setting variables and ostinatos...".postln; 17 | ~pitch = 0;~pitch1 = 0;~pitch2 = 0; ~pulsepitch = 0; 18 | // adjust the quant; 19 | ~quant=1/4; 20 | s.sync; 21 | // ostinatos: 22 | ~ost=Pdef(\ostinato1, {Pbind(\dur, Pseq([Pfuncn({1/h}, 1), Pfuncn({1/e},1), Pfuncn({1/l},1)], inf), \ctranspose, Pfunc{~pitch}, 23 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi]-20, inf), 24 | \type, \midi, \midiout, m)}); 25 | ~ost.quant=~quant; 26 | ~ost1=Pdef(\ostinato2, {Pbind(\dur, Pseq([Pfuncn({1/o}, 1), Pfuncn({1/w},1), Pfuncn({1/r},1)], inf), \ctranspose, Pfunc{~pitch1}, 27 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi]-20, inf), 28 | \type, \midi, \midiout, m)}); 29 | ~ost1.quant=~quant; 30 | ~ost2=Pdef(\ostinato3, {Pbind(\dur, Pseq([Pfuncn({1/d}, 1), Pfuncn({1/a},1), Pfuncn({1/n},1)], inf), \ctranspose, Pfunc{~pitch2}, 31 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi]-20, inf), 32 | \type, \midi, \midiout, m)}); 33 | ~ost2.quant=~quant; 34 | s.sync; 35 | // random ostinatos 36 | 37 | ~rand=Tdef(\randostinato, { 38 | var rit = (1/2).rrand(4).round(0.5); 39 | var rit2 = (1/2).rrand(4).round(0.5); 40 | var rit3 = (1/2).rrand(4).round(0.5); 41 | var randrit = [Pfuncn({1/(h*rit)}, 1), Pfuncn({1/(e*rit2)},1), Pfuncn({1/(l*rit3)},1)]; 42 | var randpitch = ["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi].scramble; 43 | Pdef(\ostinato1, {Pbind(\dur, Pseq(randrit, inf);, \ctranspose, Pfunc{~pitch}, 44 | \midinote, Pseq(randpitch, inf), 45 | \type, \midi, \midiout, m)})}); 46 | s.sync; 47 | // hello pulse 48 | ~hello=Pdef(\hello, {Pbind(\dur, Pseq([2], inf), \ctranspose, Pfunc{~h1o}, \midinote, Pseq(["c#1".namemidi], inf), \type, \midi, \midiout, m)}); 49 | ~hello.quant=~quant; 50 | ~hello2=Pdef(\hello2, {Pbind(\dur, Pseq([2], inf), \ctranspose, Pfunc{~h2o}, \midinote, Pseq(["c#1".namemidi], inf), \type, \midi, \midiout, m)}); 51 | ~hello2.quant=~quant; 52 | ~hello3=Pdef(\hello3, {Pbind(\dur, Pseq([2], inf), \ctranspose, Pfunc{~h3o}, \midinote, Pseq(["c#1".namemidi], inf), \type, \midi, \midiout, m)}); 53 | ~hello3.quant=~quant; 54 | s.sync; 55 | ~hello2.quant=~quant; 56 | ~h1o=~h2o=~h3o=0; 57 | s.sync; 58 | h=e=l=o=w=d=a=r=n=1; 59 | ~p = 1; // ???? 60 | s.sync; 61 | ~reset = Tdef(\reset, {1.do{h=e=l=o=w=d=a=r=n=1; t.tempo=1; 62 | ~h1o=~h2o=~h30=0; 63 | ~ost=Pdef(\ostinato1, {Pbind(\dur, Pseq([Pfuncn({1/h}, 1), Pfuncn({1/e},1), Pfuncn({1/l},1)], inf), \ctranspose, Pfunc{~pitch}, 64 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi]-20, inf), 65 | \type, \midi, \midiout, m)}); 66 | ~ost1=Pdef(\ostinato2, {Pbind(\dur, Pseq([Pfuncn({1/o}, 1), Pfuncn({1/w},1), Pfuncn({1/r},1)], inf), \ctranspose, Pfunc{~pitch1}, 67 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi]-20, inf), 68 | \type, \midi, \midiout, m)}); 69 | ~ost2=Pdef(\ostinato3, {Pbind(\dur, Pseq([Pfuncn({1/d}, 1), Pfuncn({1/a},1), Pfuncn({1/n},1)], inf), \ctranspose, Pfunc{~pitch2}, 70 | \midinote, Pseq(["ab3".namemidi, "B3".namemidi, "C4".namemidi, "gb3".namemidi, "f3".namemidi, "db3".namemidi, "C4".namemidi]-20, inf), 71 | \type, \midi, \midiout, m)}); 72 | } 73 | }); 74 | s.sync; 75 | ); 76 | ( 77 | "variables for fx".postln; 78 | ~eamp=0;~eamp2=0;~eamp3=0; 79 | ~del=1;~del2=1;~del3=3; 80 | ~r3=1; 81 | ); 82 | ( 83 | "starting routine for re-pitching with piano pedal...".postln; 84 | /// re-pitching: 85 | SkipJack({ 86 | 87 | // fx 88 | Tdef(\maps1, { 89 | inf.do{ 90 | /*"debug".postln;*/ 91 | Ndef(\fx).map(\del, Ndef(\krd, ~del)); 92 | Ndef(\fx).map(\amp, Ndef(\kra, ~eamp)); 93 | 94 | Ndef(\fx1).map(\del, Ndef(\krd2, ~del2)); 95 | Ndef(\fx1).map(\amp, Ndef(\kra2, ~eamp2)); 96 | 97 | Ndef(\fx2).map(\del, Ndef(\krd3, ~del3)); 98 | Ndef(\fx2).map(\amp, Ndef(\kra3, ~eamp3)); 99 | Ndef(\fx2).map(\rate, Ndef(\krr3, ~r3)); 100 | 0.1.wait; 101 | } 102 | }).play; 103 | 104 | 105 | /*var key = "narcode".scramble; 106 | Tdef(key.asSymbol, {*/ 107 | 1.do { 108 | 109 | if (~op == 1) { 110 | /*("op ---> running").postln;*/ 111 | 112 | MIDIdef.cc(\pedalpitch, {arg ...args; 113 | if (args[1] == 1) { 114 | ~pitch = args[0].linlin(0, 127, 0, 12).round(1); 115 | ("ostinato1 ***" + ~pitch + " semitones up").postln; 116 | } 117 | }); 118 | }; 119 | 120 | if (~op == 0) { 121 | /*("op ----> stopped").postln;*/ 122 | MIDIdef.cc(\pedalpitch).free; 123 | }; 124 | 125 | if (~op1 == 1) { 126 | MIDIdef.cc(\pedalpitchop1, {arg ...args; 127 | if (args[1] == 1) { 128 | ~pitch1 = args[0].linlin(0, 127, 0, 12).round(1); 129 | ("ostinato2 ***" + ~pitch1 + " semitones up").postln; 130 | } 131 | }); 132 | }; 133 | 134 | if (~op1 == 0) { 135 | MIDIdef.cc(\pedalpitchop1).free; 136 | }; 137 | 138 | if (~op2 == 1) { 139 | MIDIdef.cc(\pedalpitchop2, {arg ...args; 140 | if (args[1] == 1) { 141 | ~pitch2 = args[0].linlin(0, 127, 0, 12).round(1); 142 | ("ostinato3 *** " + ~pitch2 + " semitones up").postln; 143 | } 144 | }); 145 | }; 146 | 147 | if (~op2 == 0) { 148 | MIDIdef.cc(\pedalpitchop2).free; 149 | }; 150 | 151 | if (~down == 1) { 152 | ("down ---> running").postln; 153 | MIDIdef.cc(\pedalpitchd, {arg ...args; 154 | if (args[1] == 1) { 155 | ~pitch = args[0].linlin(0, 127, 0, -7).round(1); 156 | ("ostinato1 ***" + ~pitch + " semitones down").postln; 157 | } 158 | }); 159 | }; 160 | 161 | if (~down == 0) { 162 | /*("down ----> stopped").postln;*/ 163 | 164 | MIDIdef.cc(\pedalpitchd).free; 165 | }; 166 | 167 | if (~down1 == 1) { 168 | MIDIdef.cc(\pedalpitchd1, {arg ...args; 169 | if (args[1] == 1) { 170 | ~pitch1 = args[0].linlin(0, 127, 0, -7).round(1); 171 | ("ostinato2 ***" + ~pitch1 + " semitones down").postln; 172 | } 173 | }); 174 | }; 175 | 176 | if (~down1 == 0) { 177 | MIDIdef.cc(\pedalpitchd1).free; 178 | }; 179 | 180 | if (~down2 == 1) { 181 | MIDIdef.cc(\pedalpitchd2, {arg ...args; 182 | if (args[1] == 1) { 183 | ~pitch2 = args[0].linlin(0, 127, 0, -7).round(1); 184 | ("ostinato3 ***" + ~pitch2 + " semitones down").postln; 185 | } 186 | }); 187 | }; 188 | 189 | if (~down2 == 0) { 190 | MIDIdef.cc(\pedalpitchd2).free; 191 | }; 192 | }; }, 1, name: "pedalwatch"); 193 | ); 194 | s.sync; 195 | "CodeKlavier is ready and listening...".postln; 196 | }.fork; 197 | ); 198 | 199 | /// if you want to stop the pedal watcher: 200 | /*SkipJack.stop("pedalwatch");*/ 201 | -------------------------------------------------------------------------------- /assets/arquatic.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /arquatic 3 | --- 4 | 5 | Voor [Nederlands](https://codeklavier.space/arquaticnl)🇳🇱 6 | 7 | # ARquatic - A CodeKlavier Augmented Reality Experience 8 | 9 | ## Concept 10 | 11 | Codeklavier’s ‘ARquatic’ is an audio and Augmented Reality experience where the live music provides the DNA of the underwater creatures unfolding before your eyes. Full of speculative, fantasy structures artificially built from [L-system](https://en.wikipedia.org/wiki/L-system) rules, ‘ARquatic’ superimposes unusual aquatic inspired objects in everyday environments. Whether you attend a live performance, tune in at home for a streamed experience or use ARquatic Anytime, the juxtaposition from the surroundings with the AR objects will stimulate one’s imagination by highlighting the contrasting beauty of the natural and the unnatural world. 12 | 13 | ## Trailer 14 | 15 | 16 | 17 | ## ARquatic Anytime 18 | 19 | After two summer tours, several live streams and conference presentations, we have now released a version of ARquatic that one can listen to and watch anytime, anywhere. Similar to the work we made for [ART+](https://artplus.app/) under "The pianist gardener", in ARquatic Anytime one can experience on demand. Just download the app, grab your headphones and you are good to go. 20 | 21 | ## Download 22 | The ARquatic app is available for download [here for Apple](https://apps.apple.com/nl/app/arquatic/id1557620712?l=en) and [here for Android](https://play.google.com/store/apps/details?id=space.codeklavier.arquatic&hl=en_US&gl=US). You will need an Apple iPhone SE/6S model (or later) or one of the Android phones listed [here](https://developers.google.com/ar/devices). You can also simply follow the link for the app download and try out the demo channel. It is useful to do this in advance in case your phone does not support AR but your tablet does - in which case, we advise you to bring your tablet! If you do not own an AR supported device, a non-AR version will still show visuals on your Android phone. 23 | 24 | ## Past Shows 25 | 26 | Tuesday June 13 \ 27 | ARquatic will be streamed during HashiCorp's HashiDays Online and on site. \ 28 | You can register for the online event for free [here](https://hashidays.com/online/) 29 | 30 | Friday Januari 28 \ 31 | ARquatic at the [on-the-fly: Live Coding Hacklab](https://zkm.de/en/event/2022/01/on-the-fly-live-coding-hacklab) \ 32 | Zentrum voor Kunst en Media, Karlsruhe \ 33 | Tijd: 20.00 34 | 35 | Summer Tour September - October 2022 \ 36 | Gardens and Festivals throughout the Netherlands \ 37 | More details on [Dutch site](https://codeklavier.space/arquaticnl) 38 | 39 | Thursday November 27 \ 40 | Discourse on XR/AR/VR \ 41 | Talk about ARquatic by Patrick Borgeat at [Update Festival](https://update.mplab.lv/program-2/) 42 | 43 | Thursday December 2 \ 44 | ARquatic: Mixed Reality and music \ 45 | Talk and stream of [ARquatic at Home](https://codeklavier.space/arquaticathome) for the Mixed Reality symposium at Nottingham University \ 46 | Time: 16h 47 | 48 | Sunday December 5 \ 49 | ARquatic and CodeKlavier collaboration discussion \ 50 | With Joana Chicau, Renick Bell, Timo Hoogland and Saskia Freeke \ 51 | More info to follow \ 52 | Time: 14-16h 53 | 54 | Friday August 27 55 | "ARquatic" at [de Kwekerij Hilverum](https://www.dekwekerijhilversum.nl/agenda/) \ 56 | Times: 16.00, 17.00 & 18.00 \ 57 | Click [here](https://forms.gle/kDPZUJiEVHvyEyVZ6) to make your reservation 58 | 59 | Friday August 6 \ 60 | "ARquatic at Home" - streamed version online \ 61 | More info [here](https://codeklavier.space/arquaticathome) 62 | 63 | Sunday June 6 64 | "ARquatic Live" at the [Pinetum Blijdenstein, Hilversum](https://pinetum.nl/) \ 65 | Times: 14.00, 15.00 & 16.00 \ 66 | Click [here](https://docs.google.com/forms/d/e/1FAIpQLSeAYk1hxl8dgQnCNXU6J_PYcoqnBeAUuDKNK2jzGA3xLDZ22w/viewform) to make your reservation 67 | 68 | Sunday June 13th \ 69 | ["More than just Music" Festival at Toets des Tijds, Amsterdam](toetsdestijds.com) and in combination with other performances. \ 70 | Times: 17.00 & 20.00 \ 71 | Tickets available [here](https://toetsdestijds.com/2021/04/22/whats-on-my-desk/) 72 | 73 | 74 | ## About the technology 75 | The ‘ARquatic’ experience is made possible by three key technological elements and stages; CodeKlavier, Lindemayer and the ARquatic App. 76 | 77 | CodeKlavier: a system that enables the pianist to code by playing the piano. In ‘ARquatic’, this pianist is using the [CKalcuλator](https://github.com/narcode/codeklavier/tree/master/ckalculator) module to create numbers using lambda calculus. These numbers are then translated into symbols used in the Lindenmayer systems engine. 78 | 79 | The L-systems engine is the second element and transforms the symbols into formal grammars defining the starting point and L-system rules. Together these form the L-system trees creating the structures of the AR visual elements which you see. 80 | 81 | These structures, along with some characteristics of the piano playing, are then applied to the visuals designed by Patrick Borgeat and rendered in Unity. This is the final step of the technological process and produces the AR visuals which you experience during the show on the ARquatic app. 82 | 83 | ## Motivation 84 | Our inspiration for working with L-systems comes primarily from its roots in nature and organic growth which we would like to bring to the musical and programming paradigms. Whilst L-systems are already widely used in generative art and music, we are interested in exploring how this simple model can be used by the piano coder to express complex structures and how its rules will shape the pianistic improvisation. Furthermore, Lindenmayer’s work was done here at the University of Utrecht in 1968 and building upon it through artistic exploration, makes the Netherlands a particularly special home for the development and presentation of this project. 85 | 86 | 87 | ## Credits 88 | [Anne Veinberg](https://anneveinberg.com/) - piano, CodeKlavier creator \ 89 | [Felipe Ignacio Noriega](https://felipeignacio.info/) - live electronics, CodeKlavier creator \ 90 | [Patrick Borgeat](https://borgeat.de/) - visuals, app developer 91 | 92 | ## Sponsors 93 | CodeKlavier was made possible by the Creative Industries Fonds NL and our angel sponsor. 94 | 95 | The summer tour of 2023 was made possible by Prins Bernhard Cultuurfonds, Gemeente Utrecht and the Creative Industries Funds NL. The performances in June and August 2021 are made possible the Fonds Podium Kunsten Balkonscenes grant. 96 | 97 | ## Questions? 98 | Email arquatic@codeklavier.space 99 | 100 | ## Support 101 | This project was made possible by the Creative Industries Fonds NL and our angel sponsor. Ongoing work is limited to preparations for gigs at festivals and venues that book us for concerts. Do you believe in the project and would like to support us further? please consider "buying us a coffee". Every little bit counts and we greatly appreciate your support! 102 | 103 | [![ko-fi](https://www.ko-fi.com/img/donate_sm.png)](https://ko-fi.com/J3J7PGIE) 104 | 105 | -------------------------------------------------------------------------------- /CodeKlavier/CK_Setup.py: -------------------------------------------------------------------------------- 1 | import time 2 | import rtmidi 3 | import sys 4 | 5 | class BColors: 6 | """Class with background colors for the terminal. 7 | """ 8 | HEADER = '\033[95m' 9 | CKBLUE = '\033[94m' 10 | CKGREEN = '\033[92m' 11 | WARNING = '\033[93m' 12 | FAIL = '\033[91m' 13 | ENDC = '\033[0m' 14 | BOLD = '\033[1m' 15 | UNDERLINE = '\033[4m' 16 | 17 | 18 | class Setup(object): 19 | """Helper class to setup the CodeKlavier with your piano. 20 | """ 21 | 22 | def __init__(self): 23 | self.__midiin = rtmidi.MidiIn() 24 | self.__midiout = rtmidi.MidiOut() 25 | self.__ports = self.__midiin.get_ports() 26 | self.__ports_out = self.__midiout.get_ports() 27 | 28 | def print_lines(self, length, lines): 29 | """Print ## lines with 0.2 sec delay 30 | 31 | :param int length: the line length (actuel length is 1 longer) 32 | :param int lines: number of lines to print (-1) 33 | """ 34 | for i in range(0, lines): 35 | num = length+(1) 36 | print('##'*num) 37 | #TODO: add codeKlavier logo 38 | time.sleep(0.2) 39 | 40 | def print_welcome(self, length): 41 | """Print the welcome lines 42 | 43 | :param int length: the line length (actual length is 1 longer) 44 | """ 45 | for i in range(0, 7): 46 | num = length+(1) 47 | if i == 0: 48 | print('##'*num) 49 | elif i == 1: 50 | print('## ### ### ### ## # ## ##### ### # ## ## ## ###') 51 | elif i == 2: 52 | print('# #### # ## # ## #### # ## #### # ## # ### ### #### # ##') 53 | elif i == 3: 54 | print('# #### # ## # ## ### ### #### ## # ### ### ### ###') 55 | elif i == 4: 56 | print('# #### # ## # ## #### # ## #### # ## # ### ### #### # ##') 57 | elif i == 5: 58 | print('## ### ### ### ## # ## ## # ### ### ## ## # ##') 59 | elif i == 6: 60 | print('##'*num) 61 | time.sleep(0.1) 62 | 63 | print("\nWelcome to the Codeklavier v0.5!\n") 64 | 65 | def show_ports(self): 66 | """Show the available MIDI devices. 67 | """ 68 | print("These are your detected MIDI devices:", '\n') 69 | for port in self.__ports: 70 | print(self.__ports.index(port), " -> ", port) 71 | 72 | def get_port_from_user(self): 73 | """Get a MIDI device from the user. 74 | 75 | :rtype: int 76 | """ 77 | selected_midiport = -1 78 | while selected_midiport < 0: 79 | try: 80 | choice = input("Please choose the MIDI device (number) you want to use and hit Enter:") 81 | selected_midiport = int(choice) 82 | if selected_midiport < 0 or selected_midiport >= len(self.__ports): 83 | print("Invalid number, please try again:") 84 | selected_midiport = -1 85 | else: 86 | return selected_midiport 87 | except KeyboardInterrupt: 88 | print('\n', "You want to quit? ¯\('…')/¯ ok, Bye bye.") 89 | sys.exit(0) 90 | except ValueError: 91 | print("Sorry, type a valid port numer!") 92 | 93 | def open_port(self, pnum): 94 | """Open the MIDI port. 95 | 96 | :param int pnum: the port number 97 | :raises Exception: when there are no midi ports 98 | """ 99 | try: 100 | print("Using Midi device: ", self.__ports[pnum]) 101 | 102 | if self.__ports: 103 | #TODO: do we need to check on the existence of ports? 104 | self.__midiin.open_port(pnum) 105 | # ignore sysex, timing and active sense 106 | self.__midiin.ignore_types(True, True, False) 107 | else: 108 | raise Exception(BColors.WARNING+"No midi ports! Maybe open a virtual device?"+BColors.ENDC) 109 | except IndexError: 110 | print(BColors.FAIL+"The chosen port in your config.ini file seems to be wrong\n", "\nplease check it and try again!"+BColors.ENDC) 111 | sys.exit(0) 112 | 113 | def open_port_out(self, num): 114 | """Open the midi port as output. 115 | 116 | :param int num: the midi portnumber to open 117 | """ 118 | print("opened midi out port") 119 | 120 | if self.__ports_out: 121 | self.__midiout.open_port(num) 122 | 123 | def close_port(self): 124 | """Close the MIDI in port 125 | """ 126 | self.__midiin.close_port() 127 | #TODO: add close out port too 128 | 129 | def get_message(self): 130 | """Get the MIDIin message 131 | """ 132 | return self.__midiin.get_message() 133 | 134 | def send_message(self, message): 135 | """Send a message to MIDIout 136 | 137 | :param message: the message to send 138 | """ 139 | return self.__midiout.send_message(message) 140 | 141 | def set_callback(self,cb): 142 | """Set the MIDIin callback function 143 | 144 | :param cb: the callback 145 | """ 146 | self.__midiin.set_callback(cb) 147 | 148 | def get_device_id(self): 149 | """Get the device id from the instrument. 150 | 151 | :rtype: int the device id 152 | """ 153 | print("Hit any note to get the device_id.") 154 | while True: 155 | msg = self.get_message() 156 | if msg: 157 | message, deltatime = msg 158 | if message[0] != 254: #active sense ignore 159 | device_id = message[0] 160 | if device_id: 161 | return device_id 162 | time.sleep(0.01) 163 | 164 | def perform_setup(self): 165 | """Wrapper function to make the entire setup. 166 | 167 | :rtype: int the MIDIin port 168 | """ 169 | self.print_welcome(27) 170 | self.show_ports() 171 | myPort = self.get_port_from_user() 172 | return myPort 173 | 174 | def end(self): 175 | """Close 176 | """ 177 | #print("Bye bye from CodeKlavier setup :(") 178 | self.close_port() 179 | del self.__midiin 180 | 181 | def main(): 182 | """Perform the main setup. 183 | """ 184 | codeK = Setup() 185 | my_midiport = codeK.perform_setup() 186 | codeK.open_port(my_midiport) 187 | 188 | if my_midiport >= 0: 189 | print("CodeKlavier is ON. Press Control-C to exit.") 190 | try: 191 | while True: 192 | msg = codeK.get_message() 193 | 194 | if msg: 195 | message, deltatime = msg 196 | print('deltatime: ', deltatime, 'msg: ', message) 197 | 198 | time.sleep(0.01) 199 | 200 | except KeyboardInterrupt: 201 | print('') 202 | finally: 203 | codeK.end() 204 | 205 | if __name__ == "__main__": 206 | main() 207 | -------------------------------------------------------------------------------- /doc/build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Welcome to CodeKlavier’s documentation! — CodeKlavier 0.3.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 40 | 59 | 60 |
61 |
62 |
63 |
64 | 65 |
66 |

Welcome to CodeKlavier’s documentation!

67 |
68 |
69 |

Contents

70 | 103 |
104 |
105 |

Indices and tables

106 | 111 |
112 | 113 | 114 |
115 |
116 |
117 |
118 |
119 | 134 | 138 | 139 | -------------------------------------------------------------------------------- /easter eggs: -------------------------------------------------------------------------------- 1 | # midinumber : easteregg text ICLC 2 | 9: Average number of times we pkill scsynth in a CK session 3 | 11: Number of functions in our CKalculator 4 | 16: This is our CodeKlavier's 16th performance 5 | 38: Number of performances at this ICLC 6 | 47: Click Nilson's lifetime 7 | 184: Number of past Alogiraves listed on algorave.com 8 | 190: Keys on stage 9 | 239: CK followers on facebook - you should like us now! 10 | 532: Days since CodeKlavier's first public performance 11 | 660: Days of working on the CodeKlavier 12 | 860: Madrid was founded in this year 13 | 1126: Approximate number of km that we are currently above sea level 14 | 1700: The piano has been around since then 15 | 1930: Year lambda calculus was first introduced by Alonso Church 16 | 1960: Year that lambda calculus gained place in computer science and linguistics 17 | 1982: Felipe was born 18 | 1986: Anne was born 19 | 20 | # midinumber : easteregg text Lambda Days 21 | 22 | 9: Average number of times we pkill scsynth in a CK session 23 | 17: This is CodeKlavier's 17th performance 24 | 38: Number of talks at Lambda Days this year 25 | 40: Pages in the current draft of a history of F# 26 | 105: Krakow's tallest building in meters. 27 | 190: Keys on stage 28 | 220: Approximate number of km that we are currently above sea level 29 | 234: CK followers on facebook - you should like us now! 30 | 327: Krakow's total city area in meters2. 31 | 564: Days since CodeKlavier's first public performance 32 | 643: Number of braces in F# 33 | 691: Days of working on the CodeKlavier 34 | 1700: The piano has been around since then 35 | 1860: Ignacy Jan Paderewski - the only pianist, composer and active politician was born. 36 | 1903: Alonzo Church was born 37 | 1910: The first volume of Principia Mathematica by Russel and White was published in this year 38 | 1912: The second volume of Principia Mathematica by Russel and White was published in this year. 39 | 1913: The third volume of Principia Mathematica by Russel and White was published in this year. 40 | 1930: Year lambda calculus was first introduced by Alonso Church 41 | 1960: Year that lambda calculus gained place in computer science and linguistics 42 | 1982: Felipe was born 43 | 1986: Anne was born 44 | 1990: Haskell first appeared. 45 | 1995: JavaScript was invented by Brendan Eich 46 | 1999: Erlang was founded 47 | 2009: Idris appeared. 48 | 2020: HOPL IV submission year 49 | 3011: Null checks in the C# project described by Don Syme 50 | 51 | Easter Eggs Lambda 52 | [easter eggs] 53 | # midinumber : easteregg text 54 | 9: Average number of times we pkill scsynth in a CK session 55 | 17: This is CodeKlavier's 17th performance 56 | 38: Number of talks at Lambda Days this year 57 | 105: Krakow's tallest building in meters. 58 | 190: Keys on stage 59 | 220: Approximate number of km that we are currently above sea level 60 | 234: CK followers on facebook - you should like us now! 61 | 327: Krakow's total city area in meters2. 62 | 564: Days since CodeKlavier's first public performance 63 | 643: Number of braces in F# 64 | 691: Days of working on the CodeKlavier 65 | 1700: The piano has been around since then 66 | 1860: Ignacy Jan Paderewski - the only pianist, composer and active politician was born. 67 | 1903: Alonzo Church was born 68 | 1910: The first volume of Principia Mathematica by Russel and White was published in this year 69 | 1912: The second volume of Principia Mathematica by Russel and White was published in this year. 70 | 1913: The third volume of Principia Mathematica by Russel and White was published in this year. 71 | 11: Number of functions in our CKalculator 72 | 16: This is our CodeKlavier's 16th performance 73 | 47: Click Nilson's lifetime 74 | 184: Number of past Alogiraves listed on algorave.com 75 | 239: CK followers on facebook - you should like us now! 76 | 532: Days since CodeKlavier's first public performance 77 | 660: Days of working on the CodeKlavier 78 | 860: Madrid was founded in this year 79 | 1126: Approximate number of km that we are currently above sea level 80 | 1930: Year lambda calculus was first introduced by Alonso Church 81 | 1960: Year that lambda calculus gained place in computer science and linguistics 82 | 1982: Felipe was born 83 | 1986: Anne was born 84 | 1990: Haskell first appeared. 85 | 1995: JavaScript was invented by Brendan Eich 86 | 1999: Erlang was founded 87 | 2009: Idris appeared. 88 | 2020: HOPL IV submission year 89 | 3011: Null checks in the C# project described by Don Syme 90 | 91 | EasterEggs- soup 92 | 8: Ingredients in vegan asparugus soup - olive oil, garlic, asparagus, gold potatoes,salt, pepper, vegetable broth. 93 | 9: Average number of times we pkill scsynth in a CK session 94 | 11: Number of lambda functions in our CKalculator 95 | 17: Years since the first residents moved to Ijburg 96 | 18: This is CodeKlavier's 18th performance 97 | 47: Click Nilson's lifetime 98 | 190: Keys on stage 99 | 220: Area of Ijburg in ha 100 | 251: CK followers on facebook - you should like us now! 101 | 652: Days since CodeKlavier's first public performance 102 | 778: Days of working on the CodeKlavier 103 | 1700: The piano has been around since then 104 | 1903: Alonzo Church was born 105 | 1910: The first volume of Principia Mathematica by Russel and White was published in this year 106 | 1912: The second volume of Principia Mathematica by Russel and White was published in this year. 107 | 1913: The third volume of Principia Mathematica by Russel and White was published in this year. 108 | 1930: Year lambda calculus was first introduced by Alonso Church 109 | 1960: Year that lambda calculus gained place in computer science and linguistics 110 | 1982: Felipe was born 111 | 1986: Anne was born 112 | 1990: Haskell first appeared. 113 | 1995: "No soup for you". Also, JavaScript was invented by Brendan Eich. 114 | 1999: Erlang was founded 115 | 2009: Idris appeared. 116 | 2020: HOPL IV submission year 117 | 6000: The earliest archaeological evidence for the consumption of soup dates back to 6000 BC, and it was hippopotamus soup. 118 | 119 | Easter Eggs YAA 120 | 5: Number of YAA prize winners in 2018 121 | 9: Average number of times we pkill scsynth in a CK session 122 | 11: Number of lambda functions in our CKalculator 123 | 16: Weeks it takes for a fetus to drink and pee 124 | 19: This is CodeKlavier's 19th performance 125 | 178: Years since Arti was built 126 | 190: Keys on stage 127 | 251: CK followers on facebook - you should like us now! 128 | 657: Days since CodeKlavier's first public performance 129 | 785: Days of working on the CodeKlavier 130 | 1700: The piano has been around since then 131 | 1903: Alonzo Church was born 132 | 1910: The first volume of Principia Mathematica by Russel and White was published in this year 133 | 1912: The second volume of Principia Mathematica by Russel and White was published in this year. 134 | 1913: The third volume of Principia Mathematica by Russel and White was published in this year. 135 | 1930: Year lambda calculus was first introduced by Alonso Church 136 | 1960: Year that lambda calculus gained place in computer science and linguistics 137 | 1982: Felipe was born 138 | 1986: Anne was born 139 | 1990: Haskell first appeared. 140 | 1995: JavaScript was invented by Brendan Eich. 141 | 1999: Erlang was founded 142 | 2009: Idris appeared. 143 | 2011: Felipe and Anne met during their studies at CVA 144 | 2012: YAA was founded 145 | 2015: Year that Felipe won the YAA 146 | 2020: HOPL IV submission year 147 | --------------------------------------------------------------------------------