{"id":13625060,"url":"https://github.com/pjagielski/punkt","last_synced_at":"2025-04-09T10:10:21.025Z","repository":{"id":38131860,"uuid":"254813352","full_name":"pjagielski/punkt","owner":"pjagielski","description":"Live coding music library/environment for Kotlin","archived":false,"fork":false,"pushed_at":"2023-03-31T19:20:21.000Z","size":2347,"stargazers_count":307,"open_issues_count":4,"forks_count":12,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-04-16T11:11:22.200Z","etag":null,"topics":["kotlin","live-coding","music","sequencer"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pjagielski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-04-11T07:12:21.000Z","updated_at":"2024-04-16T07:34:15.000Z","dependencies_parsed_at":"2023-02-09T20:46:01.530Z","dependency_job_id":"934c281b-ba82-4fda-bbb0-e3560b06469b","html_url":"https://github.com/pjagielski/punkt","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pjagielski%2Fpunkt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pjagielski%2Fpunkt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pjagielski%2Fpunkt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pjagielski%2Fpunkt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pjagielski","download_url":"https://codeload.github.com/pjagielski/punkt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248018061,"owners_count":21034048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kotlin","live-coding","music","sequencer"],"created_at":"2024-08-01T21:01:50.377Z","updated_at":"2025-04-09T10:10:20.997Z","avatar_url":"https://github.com/pjagielski.png","language":"Kotlin","funding_links":[],"categories":["Kotlin","Environments"],"sub_categories":[],"readme":"# PunKt - Kotlin Punk\n[![](https://jitpack.io/v/pjagielski/punkt.svg)](https://jitpack.io/#pjagielski/punkt)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/pjagielski/punkt/gradle.yml?branch=master)\n\nA live coding music library/environment for Kotlin. For software developers who want to dive into live coding music.\n\n\"Punkt\" is \"point\" in Polish.\n\n[![Punkt demo](screen.png)](https://youtu.be/T1kspTlFH0Y)\n\nDemos: \n* [Developers](https://youtu.be/T1kspTlFH0Y)\n* [Shape Of You Remix](https://youtu.be/TBDG_34yKys?t=182)\n* [Da Funk Remix](https://youtu.be/OdQQJPpL6Lo?t=136)\n* [Shape Of You inspired track](https://youtu.be/94xzNW6hxR8?t=80)\n\n## Rationale\n* **minimal** - just a sequencer playing samples and synths designed in SuperCollider  \n* **easy to install** - a library + template project, just `git clone`, run and enjoy\n* **no custom IDE** - could be started directly from IntelliJ IDEA or command line with any Kotlin-aware editor \n* **data-oriented** - patterns and melodies represented as data structure, making it easy to test and visualize\n\n### How to start\n0. Install [SuperCollider](https://supercollider.github.io/download) (at least 3.10) and [sc3-plugins](https://supercollider.github.io/sc3-plugins/)\n1. Clone [template project](https://github.com/pjagielski/punkt-template) `git clone https://github.com/pjagielski/punkt-template.git`\n2. Start SuperCollider, boot server (Server-\u003eBoot Server) and run [punkt-synths.scd](https://raw.githubusercontent.com/pjagielski/punkt/master/src/main/resources/punkt-synths.scd)\n(in case of \"Memory allocation problems\": clone [punkt project](https://github.com/pjagielski/punkt) and run `src/main/resources/punkt.scd` in SuperCollider.)\n3. Run `Main.kt` in `punkt-template`\n4. Profit! Just edit `src/main/kotlin/live.kts` in your favourite editor for live-coding \n\n### Why Kotlin?\n* **statically typed, compiled** - you get code completion and compile-time errors for free\n* **sequence API** - great standard library with lazy immutable sequences for making patterns\n* **DSL builders** - extension methods and operator overloading makes it easy to create powerful DSLs \n* **scripting** - a file watcher and API for compiling/evaluating script whenever it changes\n* **coroutines** - makes trivial to trigger an asynchronous event from anywhere in your code\n* **mainstream** - it's great to learn Clojure or Haskell, but it's even better that your project uses technology that reaches lots of potential users ;) \n\n### Minimal example\n\n```kotlin\n    patterns(beats = 8) {\n        + repeat(1).sample(\"bd_haus\")       \n    }\n```\nPlays \"bd_haus\" sample every beat.\n\nWhat happened here? `punkt` highly relies on durations to create patterns. If we want to play \"bd_haus\" sample every\nbeat, we could specify this by a list of beats, like `listOf(0, 1, 2, 3, ...)`. We could use `rangeTo` function (e.g. `0..7`) to\ncreate a fixed range of beats. In `punkt` instead, you specify the durations *between* the beats, and a\n*starting point* - which defaults to 0 by this `repeat` function (which is not `repeat` from Kotlin standard library). \nThis has some advantages:\n 1. in simple cases, you repeat single value or cycle through small series of values\n 2. this creates infinite sequence of beats, which is helpful if you don't know upfront how many beats you need ;) \n that's why we need to narrow the resulting collection to fixes number of beats with this `patterns(beats = 8) {..}` \n function.\n \n Another example: 4 on the floor beat:\n ```kotlin\n     patterns(beats = 8) {\n         + repeat(1).sample(\"bd_haus\") // every beat starting from 0\n         + repeat(2).sample(\"claps\", at = 1.0) // every even beat, starting from 1     \n         + repeat(1).sample(\"hat_2\", at = 0.5, amp = 0.5f) // every beat, starting from 0.5\n     }\n ```\nEvaluates to:\n\n| sample    | played at beats               |\n|-----------|-------------------------------|\n| \"bd_haus\" | [0,1,2,3,4,5,6,7]             |\n| \"claps\"   | [1,3,5,7]                     |\n| \"hat_2\"   | [0.5,1.5,2.5,3.5,4.5,5.5,6.5] | \n\n### Melody phrases\n`punkt` also uses similar technique to create melodies. But melodies, apart from time when the sound should play,\nrequire a note (pitch), which should play. To make it more musically correct, these notes should be part\nof some musical scale. That's why we start by creating a `scale` object using DSL from `scale` package:\n\n```kotlin\n    val scale = Scale(C.sharp(), minor)\n```\n*The notes of C# minor are: C#,D#,E,F#,G#,A,B (https://en.wikipedia.org/wiki/C-sharp_minor)*\n\nThen we can use `phrase` function, which takes sequence of degrees of given scale and sequence of durations to create a melody: \n```kotlin\n    patterns(beats = 8) {\n        + scale.low()\n            .phrase(\n                degrees(listOf(0,-4,-2,-1).flatMap { listOf(it,it,it) }),\n                cycle(0.75, 0.75, 0.5))\n            .synth(\"tr808\", amp = 0.2f)\n    }\n```\nThis creates following notes:\n\n| beats        | note | degree |\n|--------------|------|--------|\n| 0, 0.75, 1.5 | C#   |     0  |\n| 2, 2.75, 3.5 | F#   |    -4  |\n| 4, 4.75, 5.5 | A    |    -2  |\n| 6, 6.75, 7.5 | B    |    -1  |\n\nWhich is the \"Shape of you\" bassline ;)\n\n### More examples\nTB-303 pentatonic arpeggio with LFO\n```kotlin\n    val pentatonic = Scale(C.sharp(), pentatonic)\n    val lfo = LFO(1000, 3200, length = 1.5)\n    \n    patterns(beats = 8) {\n        + pentatonic.low()\n            .phrase(degrees(cycle(cycle((0..4)).take(10).toList())), cycle(0.25))\n            .synth(\"tb303\", amp = 0.2f)\n            .params(\"sus\" to 0.3, \"dec\" to 0.2, \"start\" to 100)\n            .params(\"cutoff\" to lfo)\n    }\n``` \n\n4-step chord progression with lead synth\n```kotlin\n    val scale = Scale(C.sharp(), minor)\n    val progression = listOf(Chord.I, Chord.IV, Chord.VI, Chord.VII)\n\n    patterns(beats = 8) {\n        + scale\n            .phrase(\n                progression.flatMap { listOf(it, null, it) }.toDegrees(),\n                cycle(1.0, 0.25, 0.75)\n            )\n            .synth(\"lead\", amp = 0.25f)\n            .params(\"cutoff\" to 1500)\n    }\n```\n\n### Inspirations\n* **[ORCΛ](https://github.com/hundredrabbits/Orca)** - simplicity (just a sequencer)\n* **[openRNDR](https://github.com/openrndr/openrndr)** - kotlin script-driven live coding\n* **[Leipzig](https://github.com/ctford/leipzig)** - music as data\n* **[FoxDot](https://github.com/Qirky/FoxDot)** - synth design, OSC implementation\n* **[Tidal](https://github.com/tidalcycles/Tidal)** - patterns, SuperDirt\n* **[Sonic-Pi](https://github.com/samaaron/sonic-pi)** - live loops, script-driven live coding\n\n### Changelog\n\n#### 0.3.0 - 09.09.2020\n* introduced separate tracks with global effects\n* new global effects: `reverb`, `delay`, `djf`\n* new effects: `djf`, `waveDist`, `squiz`\n* new synths: `piano`, `bass8`\n* new note methods: `amp`, `track`\n* fluent API for effects\n\n#### 0.2.0 - 17.05.2020\n* introduced effects\n* new effects: `lpf`, `hpf`, `delay`, `dist`, `chop`\n* new synth: `lead` \n* **BREAKING**: synth params API cleanup\n* events logging\n \n#### 0.1.0 - 20.04.2020\n* initial version ;)\n* `sample` and `loop` support\n* new synths: `tb303`, `tr808`, `plucklead`, `da-funk`\n\n### Roadmap\n* OSC/MIDI out\n* OSC/MIDI in\n* ~~add effects on separate channels~~ (0.3.0)\n* pattern randomization\n* visualization\n\n### License\nCopyright © 2020- Piotr Jagielski\n\nPunkt is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpjagielski%2Fpunkt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpjagielski%2Fpunkt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpjagielski%2Fpunkt/lists"}