{"id":19323119,"url":"https://github.com/ojack/fubbles","last_synced_at":"2025-08-18T11:45:40.418Z","repository":{"id":70842882,"uuid":"435927420","full_name":"ojack/fubbles","owner":"ojack","description":null,"archived":false,"fork":false,"pushed_at":"2022-05-05T13:21:06.000Z","size":35563,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-24T05:45:32.678Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ojack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-12-07T15:13:17.000Z","updated_at":"2022-05-05T09:00:56.000Z","dependencies_parsed_at":"2023-04-12T13:33:11.854Z","dependency_job_id":null,"html_url":"https://github.com/ojack/fubbles","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ojack/fubbles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojack%2Ffubbles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojack%2Ffubbles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojack%2Ffubbles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojack%2Ffubbles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ojack","download_url":"https://codeload.github.com/ojack/fubbles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojack%2Ffubbles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270988004,"owners_count":24680662,"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","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-10T01:45:08.780Z","updated_at":"2025-08-18T11:45:40.368Z","avatar_url":"https://github.com/ojack.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [WIP] fubbles /// function scribbles\nfreehand drawing editor and livecodable sequencer\n\n![screenshot of editor](assets/fubbles.png)\n\nThe basic structure of this app is a drawing editor and a code editor within the same interface. Drawing with the mouse in the square on the left creates a set of x and y values in time. These values are looped in time, creating a repeating pattern.\n\nVarious parameters of a drawing can be used as functions or lfos within a live-coded program. It can also be used to trigger discrete events such as a note on or note off event. Hydra and Tone.js are currently bundled within this app, but you can also use WebMidi to use fubbles as a control surface for another program, or load other javascript libraries to control sound directly.\n\n### Basic Usage\nNote: this project is in its vary early stages and most or all of the syntax will most likely change. \n\nTo draw in the editor, select a color in the top right of the screen, and then draw something in the square on the left hand side of the screen. Each drawing is refered to by the variable `f` followed by an index number, and is represented by a different color on the screen. For example, `f0` is used to reference the first drawing (in red). \n\nThe following is a basic example using the x position of the red line to control the size of a square:\n\n```javascript\nshape(4, () =\u003e f0.x/width).out()\n```\n\nTo run this code, copy and paste it into the editor on the right side of the screen. Press Ctrl + Enter to run the code. Click on the red square at the top to select the red drawing tool (which corresponds to f0), and then draw something inside the square on the left. \n\nHere is an example using the x position of the red line to control the size of the square, and the y position to control the hue:\n```javascript\nshape(4, () =\u003e f0.x/width)\n  .color(1, -1)\n  .hue(() =\u003e f0.y/height)\n  .out()\n```\n\nYou can also send midi out from the parameters of the drawing. The midi can be continuous control values or discrete notes. For example, the following code sends  a midi node events every 250 milliseconds, where the y position of the drawing corresponds to the pitch of the note. In this example, `trigger` and `interval` are specific properties that can be set on the object f0. `trigger` is a function, that should be called everytime an event should occur. \n`interval` is the interval (in milliseconds) at which an event should occur. \n`quantize` is a utility function that accepts a value, and an array of values that that value should be mapped to. \n\n```javascript\n//\nnotes = [57, 59, 61, 64, 66, 69, 71, 73, 76, 78, 81, 83, 85, 88, 90]\n//\n//\nf0.set({\n  interval: 250,\n  trigger: ({ y }) =\u003e {\n     const i = quantize(1 - y/height, notes)\n      midi.note( i, 100, 20, 0) // sends a midi note with parameters (note value, velocity, duration, midi channel)\n  }\n})\n```\n\nThe `interval` parameter can also be a function. For example, the following function sets a random interval between each successive event:\n```javascript\nchoose = (arr) =\u003e () =\u003e arr[Math.floor(Math.random()*arr.length)]\n//\nf0.set({\n  interval: choose([150, 400]),\n   trigger: ({ y }) =\u003e {\n     const i = quantize(1 - y/height, notes)\n      midi.note( i, 100, 20, 0) // sends a midi note with parameters (note value, velocity, duration, midi channel)\n  }\n})\n```\n\n### Cloning and running\n\nYou need local certs in order to run this using https. e.g.:\n```\nopenssl req -x509 -out certs/server.cer -keyout certs/server.key \\\n  -newkey rsa:2048 -nodes -sha256 \\\n  -subj '/CN=localhost' -extensions EXT -config \u003c( \\\n   printf \"[dn]\\nCN=localhost\\n[req]\\ndistinguished_name = dn\\n[EXT]\\nsubjectAltName=DNS:localhost\\nkeyUsage=digitalSignature\\nextendedKeyUsage=serverAuth\")\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fojack%2Ffubbles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fojack%2Ffubbles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fojack%2Ffubbles/lists"}