[{"data":1,"prerenderedAt":498},["ShallowReactive",2],{"project-proteus":3},{"id":4,"title":5,"body":6,"caseStudy":455,"caseStudyType":472,"demoBackground":473,"demoMode":473,"demoUrl":473,"description":474,"extension":475,"headTitle":476,"links":477,"meta":484,"navigation":114,"ogImage":485,"path":487,"refreshLabel":473,"robots":473,"schemaOrg":488,"seo":492,"sitemap":493,"stem":496,"__hash__":497},"projects\u002Fprojects\u002Fproteus.md","Proteus",{"type":7,"value":8,"toc":449},"minimark",[9,14,21,24,27,30,56,67,70,73,77,86,313,317,326,352,362,376,379,421,425,445],[10,11,13],"h2",{"id":12},"context","Context",[15,16,17],"blockquote",{},[18,19,20],"p",{},"\"It's possible that our grandchildren will look at us and say 'You mean people used to listen to the same thing over and over again?'\" - Brian Eno",[18,22,23],{},"This is a fairly simple start to a larger idea.",[18,25,26],{},"I attended a lecture in 2014 by Dr. Andy Farnell on Procedural Audio who spoke, in part, about the distinction between fixed and performance mediums (i.e., film vs. stage, album vs. concert), noting that while a theatre performance has a fixed structure and the story evokes a mood, it also adapts itself to the space and time of the specific performance.",[18,28,29],{},"Though, undoubtedly, much of the draw of performance art is owed to community and social connection, I think there's a case to be made that some of the power of performance is in its subtle unpredictability.",[18,31,32,33,43,44,49,50,55],{},"While the world of popular cinematic storytelling is, at least in part, beginning to push itself out of a fixed format (",[34,35,39],"a",{"href":36,"rel":37},"https:\u002F\u002Fwww.npr.org\u002F2018\u002F12\u002F28\u002F680671691\u002Fblack-mirror-bandersnatch",[38],"nofollow",[40,41,42],"em",{},"Black Mirror: Bandersnatch"," \u002F ",[34,45,48],{"href":46,"rel":47},"https:\u002F\u002Fhelp.netflix.com\u002Fen\u002Fnode\u002F62526",[38],"Netflix's growing library of interactive content",") and the world of video gaming, which has long touted interactive storytelling, is ",[34,51,54],{"href":52,"rel":53},"https:\u002F\u002Fyoutu.be\u002Fd8B1LNrBpqc",[38],"approaching cinematic realism",", popular recorded music is still very much fixed.",[18,57,58,59,66],{},"Procedural music itself is not a new thing, the video game and contemporary composition communities have been exploring it for a long while (Steve Reich's ",[34,60,63],{"href":61,"rel":62},"https:\u002F\u002Fwww.npr.org\u002Fsections\u002Fdeceptivecadence\u002F2015\u002F01\u002F27\u002F381575433\u002Ffifty-years-of-steve-reichs-its-gonna-rain",[38],[40,64,65],{},"It's Gonna Rain"," was recorded in 1965). But, as of yet, nothing seems to exist in the realm of song.",[18,68,69],{},"The possibly obvious solution that I would like to explore would be to record a song in such a way that you have some number (say 10) of each individual part (i.e., 10 takes of the vocal, 10 of the drums, 10 of the guitar, etc.). Then on playback, you choose a random selection of each part. On a simple song with 5 parts (Guitar, Vocals, Drums, Bass, Synth), this would yield 100,000 unique combinations.",[18,71,72],{},"Widespread internet accessibility and the popularity of streaming music could make this potentially very achievable.",[10,74,76],{"id":75},"first-prototype","First prototype",[18,78,79,80,85],{},"So I started simply and created a test using ",[34,81,84],{"href":82,"rel":83},"http:\u002F\u002Fsox.sourceforge.net\u002F",[38],"SoX"," and PHP to combine the parts of a short piece into a new random composite file. And this is what can be found at the top of this page.",[87,88,93],"pre",{"className":89,"code":90,"language":91,"meta":92,"style":92},"language-php shiki shiki-themes github-dark","\u003C?php\n\n\u002F\u002F Choose one of each of the other tracks\n$rhythm = $rhythmArray[array_rand($rhythmArray)];\n$piano = $pianoArray[array_rand($pianoArray)];\n$synth = $synthArray[array_rand($synthArray)];\n$clarinet = $clarinetArray[array_rand($clarinetArray)];\n\n\u002F\u002F Full filename\n$newfile = create_unique_filename();\n\n\u002F\u002F Use SoX CLI to create the new mix\nexec(\"sox -m $rhythm $piano $synth $clarinet Audio\u002F$newfile\");\n\n?>\n\n\u003Caudio src=\"Audio\u002F\u003C?php echo $newfile; ?>\" preload=\"auto\" \u002F>\n","php","",[94,95,96,109,116,123,142,158,174,190,195,201,216,221,227,264,269,275,280],"code",{"__ignoreMap":92},[97,98,101,105],"span",{"class":99,"line":100},"line",1,[97,102,104],{"class":103},"snl16","\u003C?",[97,106,108],{"class":107},"sDLfK","php\n",[97,110,112],{"class":99,"line":111},2,[97,113,115],{"emptyLinePlaceholder":114},true,"\n",[97,117,119],{"class":99,"line":118},3,[97,120,122],{"class":121},"sAwPA","\u002F\u002F Choose one of each of the other tracks\n",[97,124,126,130,133,136,139],{"class":99,"line":125},4,[97,127,129],{"class":128},"s95oV","$rhythm ",[97,131,132],{"class":103},"=",[97,134,135],{"class":128}," $rhythmArray[",[97,137,138],{"class":107},"array_rand",[97,140,141],{"class":128},"($rhythmArray)];\n",[97,143,145,148,150,153,155],{"class":99,"line":144},5,[97,146,147],{"class":128},"$piano ",[97,149,132],{"class":103},[97,151,152],{"class":128}," $pianoArray[",[97,154,138],{"class":107},[97,156,157],{"class":128},"($pianoArray)];\n",[97,159,161,164,166,169,171],{"class":99,"line":160},6,[97,162,163],{"class":128},"$synth ",[97,165,132],{"class":103},[97,167,168],{"class":128}," $synthArray[",[97,170,138],{"class":107},[97,172,173],{"class":128},"($synthArray)];\n",[97,175,177,180,182,185,187],{"class":99,"line":176},7,[97,178,179],{"class":128},"$clarinet ",[97,181,132],{"class":103},[97,183,184],{"class":128}," $clarinetArray[",[97,186,138],{"class":107},[97,188,189],{"class":128},"($clarinetArray)];\n",[97,191,193],{"class":99,"line":192},8,[97,194,115],{"emptyLinePlaceholder":114},[97,196,198],{"class":99,"line":197},9,[97,199,200],{"class":121},"\u002F\u002F Full filename\n",[97,202,204,207,209,213],{"class":99,"line":203},10,[97,205,206],{"class":128},"$newfile ",[97,208,132],{"class":103},[97,210,212],{"class":211},"svObZ"," create_unique_filename",[97,214,215],{"class":128},"();\n",[97,217,219],{"class":99,"line":218},11,[97,220,115],{"emptyLinePlaceholder":114},[97,222,224],{"class":99,"line":223},12,[97,225,226],{"class":121},"\u002F\u002F Use SoX CLI to create the new mix\n",[97,228,230,233,236,240,243,246,249,252,255,258,261],{"class":99,"line":229},13,[97,231,232],{"class":107},"exec",[97,234,235],{"class":128},"(",[97,237,239],{"class":238},"sU2Wk","\"sox -m ",[97,241,242],{"class":128},"$rhythm",[97,244,245],{"class":128}," $piano",[97,247,248],{"class":128}," $synth",[97,250,251],{"class":128}," $clarinet",[97,253,254],{"class":238}," Audio\u002F",[97,256,257],{"class":128},"$newfile",[97,259,260],{"class":238},"\"",[97,262,263],{"class":128},");\n",[97,265,267],{"class":99,"line":266},14,[97,268,115],{"emptyLinePlaceholder":114},[97,270,272],{"class":99,"line":271},15,[97,273,274],{"class":103},"?>\n",[97,276,278],{"class":99,"line":277},16,[97,279,115],{"emptyLinePlaceholder":114},[97,281,283,286,289,292,294,297,299,302,305,307,310],{"class":99,"line":282},17,[97,284,285],{"class":103},"\u003C",[97,287,288],{"class":107},"audio",[97,290,291],{"class":107}," src",[97,293,132],{"class":103},[97,295,296],{"class":238},"\"Audio\u002F\u003C?php echo ",[97,298,257],{"class":128},[97,300,301],{"class":238},"; ?>\"",[97,303,304],{"class":107}," preload",[97,306,132],{"class":103},[97,308,309],{"class":238},"\"auto\"",[97,311,312],{"class":103}," \u002F>\n",[10,314,316],{"id":315},"from-proof-to-toolchain","From proof to toolchain",[18,318,319,320,325],{},"The idea, however, isn't satisfied with the proof of concept largely for its lack of portability. So I started looking into the ",[34,321,324],{"href":322,"rel":323},"https:\u002F\u002Fwww.matroska.org\u002Findex.html",[38],"Matroska"," container format. Since the Matroska format can contain any number of streamable tracks, it would be possible to package up the parts of the song into a distinct file.",[18,327,328,329,334,335,340,341,345,346,351],{},"So in early 2021, I started to work on expanding the idea with two ",[34,330,333],{"href":331,"rel":332},"https:\u002F\u002Fflutter.dev\u002F",[38],"Flutter","-based desktop applications (",[34,336,339],{"href":337,"rel":338},"https:\u002F\u002Fgithub.com\u002Fhowardah\u002Fmultiplay",[38],"here"," and ",[34,342,339],{"href":343,"rel":344},"https:\u002F\u002Fgithub.com\u002Fhowardah\u002Fmultiplay_mixer",[38],") to read and write Matroska files using ",[34,347,350],{"href":348,"rel":349},"https:\u002F\u002Fffmpeg.org\u002F",[38],"FFmpeg",". This second proof of concept worked as well but had two main issues:",[353,354,355,359],"ol",{},[356,357,358],"li",{},"Visually it was hard to break out of the Google\u002FFlutter style.",[356,360,361],{},"As soon as the complexity of a song file moved beyond a very simple test, playback of the audio became very slow.",[18,363,364,365,370,371,375],{},"So a little while later, in mid-2022, I decided to address the first issue by replacing the Flutter applications with ",[34,366,369],{"href":367,"rel":368},"https:\u002F\u002Fwww.electronjs.org\u002F",[38],"ElectronJS"," applications in order to make use of the flexibility of CSS styling and, at the same time, decided to name the project after the Greek sea-god ",[34,372,5],{"href":373,"rel":374},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FProteus",[38],", who represents mutability and is the root of the adjective \"protean\".",[18,377,378],{},"After making a first test of the authoring app in Electron, I found that, though the styling issues were much improved, the performance issues were not and, furthermore, the bundled application created by Electron was enormous.",[18,380,381,382,387,388,393,394,399,400,405,406,409,410,340,415,420],{},"So, after a little more research, I found ",[34,383,386],{"href":384,"rel":385},"https:\u002F\u002Ftauri.app\u002F",[38],"Tauri",", which offers nearly everything that I was looking for with Electron but with significantly improved performance, largely thanks to its ",[34,389,392],{"href":390,"rel":391},"https:\u002F\u002Fwww.rust-lang.org\u002F",[38],"Rust","-based backend. Since the Tauri backend is written in Rust, I began working on ",[34,395,398],{"href":396,"rel":397},"https:\u002F\u002Fgithub.com\u002FProteus-Audio\u002Fproteus-cli",[38],"Rust-based tools"," (",[34,401,404],{"href":402,"rel":403},"https:\u002F\u002Fcrates.io\u002Fcrates\u002Fproteus_audio",[38],"cargo",") to compile and play back my Matroska files \u002F Proteus Audio (",[94,407,408],{},".prot",") files, as well as the ",[34,411,414],{"href":412,"rel":413},"https:\u002F\u002Fgithub.com\u002FProteus-Audio\u002Fproteus-author",[38],"Authoring",[34,416,419],{"href":417,"rel":418},"https:\u002F\u002Fgithub.com\u002FProteus-Audio\u002Fproteus-player",[38],"Playback"," applications.",[10,422,424],{"id":423},"current-state","Current state",[18,426,427,428,433,434,439,440,444],{},"There's still much to do with the project, but this last year I published the first draft of a working project at ",[34,429,432],{"href":430,"rel":431},"https:\u002F\u002Fprot.dev",[38],"prot.dev"," including a Mac\u002FLinux\u002FWindows compatible authoring app and a playback app. I do not have the time that I would like to dedicate to it, but the project is still very active and I’m hoping to look for funding in 2027 or 2028 to try and commission works from various artists who might wish to explore the format. If you would like to follow along, you can keep tabs on this page or watch the ",[34,435,438],{"href":436,"rel":437},"https:\u002F\u002Fgithub.com\u002FProteus-Audio",[38],"GitHub repos",". If you'd like to talk about the idea, feel free to ",[34,441,443],{"href":442},"\u002Fcontact\u002F","give me a shout","!",[446,447,448],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":92,"searchDepth":111,"depth":111,"links":450},[451,452,453,454],{"id":12,"depth":111,"text":13},{"id":75,"depth":111,"text":76},{"id":315,"depth":111,"text":316},{"id":423,"depth":111,"text":424},{"role":456,"year":457,"status":458,"disciplines":459,"stack":463,"challenge":464,"outcome":465,"primaryAction":466,"related":469},"Creator · product, interaction & systems design","2021—present","Active exploration",[460,461,462],"Procedural audio","Desktop software","Interaction design",[392,386,350,324],"Make recorded music variable and expressive without sacrificing portability or playback performance.","An open-source .prot toolchain and authoring\u002Fplayback experiments for assembling unique song performances.",{"title":467,"link":430,"source":468},"Explore Proteus","website",{"label":470,"to":471},"Hear the music behind the tools","\u002Fsound","Development case study",null,"Proteus is a project to create a flexible, open-source, and cross-platform audio authoring tool.","md","ATH: Dev - Proteus",[478,480],{"title":479,"link":430,"source":468},"Website",{"title":481,"link":482,"source":483},"GitHub","https:\u002F\u002Fgithub.com\u002Forgs\u002FProteus-Audio\u002Frepositories","github",{},{"url":486},"\u002Fimages\u002Fdev\u002Fproteus.webp","\u002Fprojects\u002Fproteus",[489],{"name":5,"applicationCategory":490,"@type":491},"MultimediaApplication","SoftwareApplication",{"title":5,"description":474},{"loc":487,"changefreq":494,"priority":495},"monthly",0.7,"projects\u002Fproteus","euPfMYW_IiNDGBrM3m35aFaUDtaYuFa7ItmATpIOprs",1786815543276]