{"id":17383896,"url":"https://github.com/mcandre/rouge","last_synced_at":"2025-04-15T10:09:54.520Z","repository":{"id":60864775,"uuid":"258387751","full_name":"mcandre/rouge","owner":"mcandre","description":"a work in progress BPSK modem","archived":false,"fork":false,"pushed_at":"2025-04-01T00:12:16.000Z","size":106437,"stargazers_count":10,"open_issues_count":16,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-15T10:09:31.519Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcandre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-24T02:47:47.000Z","updated_at":"2025-04-01T00:12:20.000Z","dependencies_parsed_at":"2024-01-09T03:01:58.312Z","dependency_job_id":"db28b4be-175d-4b42-9bc7-b7f8e4deea77","html_url":"https://github.com/mcandre/rouge","commit_stats":{"total_commits":41,"total_committers":1,"mean_commits":41.0,"dds":0.0,"last_synced_commit":"d88a82fbb7d6a478d733888a6be5c3aeb3fcd015"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcandre%2Frouge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcandre%2Frouge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcandre%2Frouge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcandre%2Frouge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcandre","download_url":"https://codeload.github.com/mcandre/rouge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249048738,"owners_count":21204306,"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":[],"created_at":"2024-10-16T07:44:06.693Z","updated_at":"2025-04-15T10:09:54.493Z","avatar_url":"https://github.com/mcandre.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rouge: a work in progress BPSK modem\n\n```text\n ^   A\n\u003eθ.θ\u003e/\n   ♯\n```\n\n# DISCLAIMER\n\nThis project is intended purely for educational research purposes. Make sure to support your local synth shop! The findings here are provisional and incomplete. No guarantees. Your mileage may vary, etc. etc.\n\n# EXAMPLES\n\nPO-32 factory default backup (first pattern active). [examples/p0.wav](examples/p0.wav)\n\n## Read/Write audio file samples\n\nRouge can manipulate WAVE PCM mono samples as 32-bit 2's complement integers.\n\n```console\n$ mplayer examples/p0.wav\n\n$ rouge \\\n   -in examples/p0.wav \\\n   \u003e/tmp/p0.pcm.dat\n\n$ rouge \\\n   -out /tmp/p0.copy.wav \\\n   -sampleRate 44100 \\\n   -bitDepth 16 \\\n   -channels 1 \\\n   -category 1 \\\n   \u003c/tmp/p0.pcm.dat\n\n$ mplayer /tmp/p0.copy.wav\n```\n\n`diff` can also confirm PCM data equivalence, as long as the metadata is identical.\n\n## Read BPSK samples\n\nThe next step is to apply the right phase shift keying algorithm to the signal. A simple BPSK attempt over a six-peak window yields some early results.\n\n```console\n$ rouge \\\n   -bpskIn /tmp/p0.pcm.dat \\\n   -innerThreshold 1000 \\\n   -outerThreshold 1200 \\\n   -bitWindow 6 \\\n   \u003e/tmp/p0.te.dat\n\n$ ls -Ahl /tmp/p0.te.dat\n-rw-r--r--  1 andrew  staff   5.2K May  3 12:53 /Users/andrew/Downloads/p0.te.dat\n\nThat's in the ball park for a file size to completely model all the PO-32 Tonic parameters.\n\n$ hexdump /tmp/p0.te.dat | head\n0000000 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66\n*\n00000f0 66 66 66 66 66 66 66 66 66 66 66 66 9a 45 84 08\n0000100 57 7d 16 b3 a3 df 56 b7 7c 13 f9 f5 b1 f0 25 49\n0000110 ab b6 73 d7 a6 dd 76 98 ef b8 0b 10 55 a6 3c f9\n0000120 f9 81 3b 68 dd 03 69 a9 f7 fe c8 28 d8 35 33 c6\n0000130 f4 66 86 6c 51 65 1b e2 b2 01 c9 3f 96 3a 91 3a\n0000140 de ac 98 a4 b8 3e 13 d1 4a 3f d5 fb 8c c3 f6 40\n0000150 d6 57 e9 ee 52 66 a3 7d 7b 5b ea fa 4f 41 28 5b\n0000160 20 64 1d fe ed de 17 54 76 dc c7 90 08 e9 0e 8c\n\n$ hexdump /tmp/p0.te.dat \u003e/tmp/p0.te-hex.txt\n```\n\nSecond pattern active. [examples/p1.wav](examples/p1.wav)\n\nRepeating the steps above for the second pattern, we have a basis for comparison in the encoded data:\n\n```console\n$ diff -u /tmp/p0.te-hex.txt /tmp/p1.te-hex.txt\n--- /tmp/p0.te-hex.txt\t2020-05-03 14:03:49.000000000 -0500\n+++ /tmp/p1.te-hex.txt\t2020-05-03 14:02:23.000000000 -0500\n@@ -315,6 +315,6 @@\n 0001470 ea 64 4c 2b 57 29 19 e8 ff 1b f4 d6 fd 8b 32 3d\n 0001480 1a 76 b8 e7 2b a6 94 53 83 6e fc d9 6b 28 f0 9d\n 0001490 2e ab 6e a9 c4 a1 8c c1 c0 6f 42 66 af 79 b4 6f\n-00014a0 8f 0e b4 42 3a c6 72 d1 13 19 6e 89 59 47 55 55\n-00014b0 55\n+00014a0 8f 0e b4 42 3a c6 f2 ad 69 4a 22 94 9b 92 aa aa\n+00014b0 aa\n 00014b1\n```\n\nThat is, eleven bytes differ in the backup stream when the active pattern is switched from the first pattern to the second.\n\nRepeating the steps above for the 3rd - 16th patterns yields similar results, though the size of the difference varies from somewhat larger to somewhat smaller. The bits preserving the active pattern ID are more complicated than they first appear.\n\nBased on the complexity of individual sound configurations and the size of the relative diff between pattern backup signals, we can conclude that only a handful of pattern settings are present in the diffs, enough to signify which sounds trigger on which 16 sequencer steps. If any effect or motion effect automation is applied, that remains default and would appear to be absent from the signal.\n\nA sound pattern preset could be directly represented with two bytes for trigger sequence on/off state across sixteen steps, with two additional bytes for accents, and two more bytes for fills, amounting to six bytes.\n\n```\n1: {\n\tTriggers: #-----#---#--#--\n\tAccents:  ----------------\n\tFills:    ----------------\n}\n```\n\nWith eight drum sounds, the pattern configuration is 48 bytes, or 24 hex pairs. In the neighborhood of how many hexpairs differ between the first factory pattern configuration and the selection of the second factory pattern configuration.\n\n## Additional notes\n\nRepeated export transmissions of the same active pattern yield identical hex decodings.\n\nThe last three bytes of each stream are repeated. So far, they are restricted to either `0x555555` or `0xaaaaaa`.\n\nThere are some string values in presets:\n\n```\nMicrotonicPresetV3: {\n\tTempo: 121.00000000 bpm\n\tPattern: a\n\tStepRate: 1/16\n\tSwing: 0.00000000%\n\tFillRate: 2.00000000x\n\tMastVol: 0.00000000 dB\n\tMutes: { Off, Off, Off, Off, Off, Off, Off, Off }\n\tDrumPatches: {\n\t\t1: {\n\t\t\tName: \"SC BD Power\"\n\t\t\tModified: true\n\t\t\tPath: \"./By Category/Bass Drum Patches/SC BD Power.mtdrum\"\n```\n\nUnknown whether the strings are preserved in PO-32 signals, they may just be for VST lookup convenience.\n\n## End Goal\n\nFind an analog + digital decoding sufficient to customize sounds:\n\n```\nMicrotonicDrumPatchV3: {\n\tOscWave: Sine\n\tOscFreq: 616.14874268 Hz\n\tOscAtk: 0.00000000 ms\n\tOscDcy: 71.25314331 ms\n\tModMode: Sine\n\tModRate: 279.64397346 Hz\n\tModAmt: +32.85273205 sm\n\tNFilMod: BP\n\tNFilFrq: 1005.14013672 Hz\n\tNFilQ: 0.70710677\n\tNStereo: Off\n\tNEnvMod: Exp\n\tNEnvAtk: 0.00000000 ms\n\tNEnvDcy: 60.78934776 ms\n\tMix: 50.00000000 / 50.00000000\n\tDistAmt: 0.00000000\n\tEQFreq: 1111.70104980 Hz\n\tEQGain: +34.53779602 dB\n\tLevel: 0.00000000 dB\n\tPan: 0.00000000\n\tOscVel: 28.42212677%\n\tNVel: 34.16033936%\n\tModVel: 0.00000000%\n}\n\nMicroTonicDrumPatchV1={\n\tName=\"NE RND Zeroto9\"\n\tModified=true\n\tPath=\"/Library/Audio/Presets/Sonic Charge/MicroTonic Drum Patches/Effect Patches/NE RND Zeroto9.mtdp\"\n\tOscWave=Triangle\n\tOscFreq=742.02076800Hz\n\tOscDcy=58.21029589ms\n\tModMode=Noise\n\tModRate=0 Hz\n\tModAmt=+22.19031754sm\n\tNFilMod=BP\n\tNFilFrq=149.74901463Hz\n\tNFilQ=1008.40029486\n\tNStereo=Off\n\tNEnvMod=Exp\n\tNEnvAtk=0.00000000ms\n\tNEnvDcy=216.86110703ms\n\tMix=66.51028097/33.48971903\n\tDistAmt=17.84428060\n\tEQFreq=5377.53820357Hz\n\tEQGain=+28.41660023dB\n\tLevel=+10.00000000dB\n\tPan=0.00000000\n\tOutput=A\n\tOscVel=100.00000000%\n\tNVel=100.00000000%\n\tModVel=100.00000000%\n}\n```\n\n# LICENSE\n\nBSD-2-Clause\n\n# RUNTIME REQUIREMENTS\n\n* [PO-32 Tonic](https://teenage.engineering/products/po-32)\n\n## Recommended\n\n* [Audacity](https://www.audacityteam.org/)\n* [ffmpeg](https://www.ffmpeg.org/)\n* [mplayer](http://www.mplayerhq.hu/)\n* [hexdump](http://man7.org/linux/man-pages/man1/hexdump.1.html)\n* [diff](https://linux.die.net/man/1/diff)\n\n# INSTALL FROM SOURCE\n\n```console\n$ go install github.com/mcandre/rouge/cmd/rouge@latest\n```\n\n# CONTRIBUTING\n\nFor more information on developing rouge itself, see [DEVELOPMENT.md](DEVELOPMENT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcandre%2Frouge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcandre%2Frouge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcandre%2Frouge/lists"}