packbat [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=40166 [no workspaces] screen on boot (v0.1.0f) <img style="margin-bottom:16px" border=0 src="/media/40166/2024-04-16 13-49-16--Picotron bug snapshot.png" alt="" /> <p>On boot (running NixOS 23.11 with KDE Plasma version 5.27.10) it shows a green &quot;no workspaces&quot; screen with a weird cursor glitch and the SFX workspace icon replaced with a desktop one ... until we click another workspace, at which point everything is fixed.</p> <p>Edit: GIF of bug:<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <img style="margin-bottom:16px" border=0 src="/media/40166/2024-04-16t13-49-16-picotron-noworkspacesbug-30fps.gif" alt="" /> <p></div></div></div></p> https://www.lexaloffle.com/bbs/?tid=141769 https://www.lexaloffle.com/bbs/?tid=141769 Tue, 16 Apr 2024 17:46:00 UTC Feature request: 'modwheel' mapping <p>One feature of electronic music is varying instrument parameters during the performance - for example, adjusting the depth of the lowpass filter sweep on an acid bassline. I think if there were a way to specify in the instrument design that one (or more) knobs was mapped to a value controlled by the tracker, it would be very easy to do these kinds of musical manipulations.</p> https://www.lexaloffle.com/bbs/?tid=141717 https://www.lexaloffle.com/bbs/?tid=141717 Sun, 14 Apr 2024 12:13:32 UTC The Packbats' 2-node Instrument Collection <p> <table><tr><td> <a href="/bbs/?pid=146304#p"> <img src="/bbs/thumbs/pico64_packbats_2node-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=146304#p"> packbats_2node</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=146304#p"> [Click to Play]</a> </td></tr></table> </p> <p><a href="https://www.lexaloffle.com/bbs/?tid=141544">As previously threatened</a>, we have created a collection of simple (1-2 nodes, 1-2 envelopes) Picotron instrument patches for anyone to use in their programs. All of the instrument patches are released as <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC-0 public domain</a> - you are free to use, modify, and sell without credit. (Although we would appreciate credit if you do make something with it as long as the thing is not, like, evil or bigoted - Nazis, TERFs, and channers, go away.)</p> <p>With the 1.0 release, there are 25 instruments (<a href="https://www.lexaloffle.com/bbs/files/40166/2node-v1.mp3">mp3 preview</a>), sorted into five categories:</p> <p><strong>Drum Kit</strong></p> <ul> <li>kick</li> <li>tom</li> <li>snare</li> <li>hi hat</li> <li>crash cymbal</li> </ul> <p><strong>Pitched Idiophones</strong></p> <ul> <li>marimba</li> <li>celesta</li> <li>steelpan</li> <li>glass pad</li> </ul> <p><strong>Chordophones</strong></p> <ul> <li>piano</li> <li>shamisen</li> <li>guitar</li> <li>e guitar</li> <li>violin*</li> <li>harp</li> </ul> <p><strong>Aerophones</strong></p> <ul> <li>pipe</li> <li>flute</li> <li>organ</li> <li>oboe*</li> <li>trumpet</li> </ul> <p><strong>Electrophones</strong></p> <ul> <li>synth bass</li> <li>fm bass</li> <li>acid bass</li> <li>64ish pulse</li> <li>bleepbloop</li> </ul> <p>Directions for use are simple: use the scrollbar or mousewheel to navigate the list, click the name of the instrument to get a short preview, and click &quot;copy&quot; to put the data on your clipboard for pasting into sfx.p64's instrument editor. The volumes are roughly (by ear) matched to the default triangle wave instrument to aid in mixing.</p> <p><strong>* Technical note:</strong> the violin and oboe instruments will not preview correctly in the instrument editor, as ENV 1 on each uses a special 0 value on FREQ and SPD, respectively. With this setting, the vibrato of each of these will be synchronized with the SPD of the SFX in which they are used. To change this, simply change this value in the righthand column.</p> <p>Old post text:<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"><a href="https://www.lexaloffle.com/bbs/?tid=141544">As previously threatened</a>, we have created a collection of simple (1-2 nodes, 1-2 envelopes) Picotron instrument patches for anyone to use in their programs. All of the instrument patches are released as <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC-0 public domain</a> - you are free to use, modify, and sell without credit. (Although we would appreciate credit if you do make something with it as long as the thing is not, like, evil or bigoted - Nazis, TERFs, and channers, go away.)</p> <p>Directions for use are simple: use the scrollbar or mousewheel to navigate the list, click the name of the instrument to get a short preview, and click &quot;copy&quot; to put the data on your clipboard for pasting into sfx.p64's instrument editor.</p> <p>Planned for 1.0:</p> <ul> <li>five more instrument patches (thanks to everyone who's made suggestions so far!)</li> <li>a list that's sorted in a way that makes sense instead of being a total jumble</li> </ul> <p>Edit: Small update to add the marimba - current instrument list:</p> <ul> <li>piano</li> <li>violin</li> <li>pipe</li> <li>organ</li> <li>kick</li> <li>snare</li> <li>hi hat</li> <li>crash cymbal</li> <li>synth bass</li> <li>fm bass</li> <li>acid bass</li> <li>glass pad</li> <li>guitar</li> <li>trumpet</li> <li>celesta</li> <li>flute</li> <li>e guitar</li> <li>shamisen</li> <li>64ish pulse</li> <li>bleepbloop</li> <li>marimba</li> </ul> <p>Edit 2:</p> <ul> <li>harp</li> <li>oboe<br /> </div></div></div></li> </ul> https://www.lexaloffle.com/bbs/?tid=141626 https://www.lexaloffle.com/bbs/?tid=141626 Wed, 10 Apr 2024 18:37:35 UTC Picotron synth fan presets? <p>Thinking about putting together a collection of free instruments for the community - simple stuff with one or two nodes and one or two envelopes, like this:</p> <img style="margin-bottom:16px" border=0 src="/media/40166/Picotron-Synth-Screenshot_20240408_092710.png" alt="" /> <p>...so as to leave a lot of room for modification by users.</p> <p><strong>What instruments would y'all want in a free patch collection?</strong> Right now we have crude versions of:</p> <ul> <li>violin</li> <li>piano</li> <li>pipe</li> <li>organ</li> <li>kick</li> <li>snare</li> <li>hat</li> <li>crash</li> </ul> <p>but a single .sfx file can hold up to 24 instruments, so it feels like we should offer more than eight.</p> <p>edit: <a href="https://www.lexaloffle.com/bbs/?tid=141626">instrument collection cart!</a></p> https://www.lexaloffle.com/bbs/?tid=141544 https://www.lexaloffle.com/bbs/?tid=141544 Mon, 08 Apr 2024 13:18:29 UTC Picotron instrument design rudiments (latest version: 2.0) <p>Over a week or so in late March and early April, we've been working on instrument.txt - a detailed (~4.6k words) guide to Picotron's built-in instrument editor, designed for musicians who have Picotron but know nothing about synthesizer sound design. In <a href="/media/40166/instrument_2.txt">this guide (currently version 2.0)</a> (<a href="/media/40166/instrument.txt.html">html version</a>, <a href="https://packbat.neocities.org/instrument-txt">web version</a>), we:</p> <ul> <li>Detail the Picotron instrument editor UI;</li> <li>Explain how each element - output mixer, oscillators, envelopes, and effects - works; and</li> <li>Guide you through putting this to practice by making a series of simple instruments, including organ sounds, 'piano' sounds, kick drums, snare(-adjacent) drums, and cymbals and hi hats.</li> </ul> <p>If you've been wanting to play with Picotron's tracker but not known how to make it work, we hope this sets you up to make lots of sounds.</p> <h2>Changelog</h2> <p><a href="/media/40166/instrument_2.txt">2.0:</a></p> <ul> <li>added info on the space bar halt-sound control and the random and looping envelope options.</li> <li>clarifications of wording throughout, notably including ADSR values in Exercise 1 and a full rewrite of the &quot;Simple Piano&quot; exercise</li> <li>corrections to a few errors (e.g. to change wavetable, you have to click the WT-# label specifically)</li> </ul> <p><a href="/media/40166/instrument.txt">1.2:</a></p> <ul> <li>initial public release</li> </ul> https://www.lexaloffle.com/bbs/?tid=141467 https://www.lexaloffle.com/bbs/?tid=141467 Fri, 05 Apr 2024 16:15:56 UTC three speed (free BGM loop) <p> <table><tr><td> <a href="/bbs/?pid=145074#p"> <img src="/bbs/thumbs/pico64_threespeed_bgm-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=145074#p"> threespeed_bgm</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=145074#p"> [Click to Play]</a> </td></tr></table> </p> <p>Been experimenting to get the hang of the synth, and we figured we'd donate some of the fruits of that experimentation to the community. Two channels, eight music patterns, six SFX, four instruments, <a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC 4.0</a>. Would love to hear if y'all use it (or its instrument designs) for anything.</p> https://www.lexaloffle.com/bbs/?tid=141261 https://www.lexaloffle.com/bbs/?tid=141261 Sat, 30 Mar 2024 04:10:04 UTC Laser Rot (Free Music Jam submission) <p> <table><tr><td> <a href="/bbs/?pid=141904#p"> <img src="/bbs/thumbs/pico8_packbats_laser_rot-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=141904#p"> packbats_laser_rot</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=141904#p"> [Click to Play]</a> </td></tr></table> </p> <p>This PICO-8 chiptune was composed for <a href="https://itch.io/jam/pico-8-free-music-jam">the 2024 PICO-8 Free Music Jam</a>. It uses three channels - bass and bass percussion on channel 0, melody and mid percussion on channel 1, and high percussion on channel 2 - and requires 16 SFX and 24 music patterns, no custom SFX instruments. The full loop is approximately 1 minute 16 seconds long. You can probably interrupt the high percussion on channel 2 if you need a second channel for sound effects.</p> <p>This piece of music is being released under a <a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 license</a>. Visualizers are provided by <a href="https://www.lexaloffle.com/bbs/?tid=140061">Bikibird's album cart</a>. The cover art is based on the image <a href="https://commons.wikimedia.org/wiki/File:Time_destroyed_CD.JPG">&quot;Time destroyed CD&quot; by Bernd Hutschenreuther</a>, used under a <a href="https://creativecommons.org/licenses/by-sa/3.0/deed.en">Creative Commons Attribution-ShareAlike 3.0 license</a>, and processed with <a href="https://imagemagick.org/">ImageMagick</a> and <a href="https://bikibird.itch.io/depict">Depict</a>.</p> https://www.lexaloffle.com/bbs/?tid=140354 https://www.lexaloffle.com/bbs/?tid=140354 Sun, 25 Feb 2024 02:22:35 UTC &quot;Cuban Cake Walk&quot; by James Timothy Brymn <p> <table><tr><td> <a href="/bbs/?pid=141167#p"> <img src="/bbs/thumbs/pico8_cubancakewalk_brymn-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=141167#p"> cubancakewalk_brymn</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=141167#p"> [Click to Play]</a> </td></tr></table> </p> <p>This cart, which uses one of <a href="https://www.lexaloffle.com/bbs/?uid=49583"> @bikibird</a>'s visualizers provided courtesy of <a href="https://itch.io/jam/pico-8-free-music-jam">the PICO-8 Free Music Jam</a> (in a beta version, as a co-organizer we helped with testing), contains an arrangement of the music of someone we'd never heard of: <a href="https://imslp.org/wiki/Cuban_Cake_Walk_%28Brymn%2C_James_Timothy%29">James Timothy Brymn's &quot;Cuban Cake Walk&quot;</a>.</p> <p>And that's a shame, because (a) Lieutenant James Tim Brymn was apparently an absolutely legendary Black American arranger, composer, and bandleader, one of the people who helped give birth to jazz as we know it today, and (b) while we didn't manage to include the entire composition in this, &quot;Cuban Cake Walk&quot; is a delightful piece of music with a really fun bouncy groove. And if we hadn't clicked on the IMSLP website on a day when it was being featured, we'd know none of this.</p> <p>So, tossing this up for all y'all, declaring my arrangement to be public domain, feel free to drop this in anything that needs it. The melody and bass line are in channels 0 and 1, main harmony in channel 2, and occasional supplemental harmony in channel 3; we would restrict game SFX to channels 2 and 3 personally.</p> https://www.lexaloffle.com/bbs/?tid=140105 https://www.lexaloffle.com/bbs/?tid=140105 Mon, 05 Feb 2024 20:26:24 UTC &quot;no ending&quot; (2-channel BGM loop) <p> <table><tr><td> <a href="/bbs/?pid=140937#p"> <img src="/bbs/thumbs/pico8_noending_by_packbats-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=140937#p"> noending_by_packbats</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=140937#p"> [Click to Play]</a> </td></tr></table> </p> <p>Someone randomly mentioned Minecraft on the official unofficial Discord, and with <a href="https://itch.io/jam/pico-8-free-music-jam">the PICO-8 Free Music Jam</a> starting tomorrow (plug!), that inspired this chill but slightly dissonant background loop. Approximately two and a quarter minutes long, uses 00, 01, and 02 for custom SFX instruments, total of 15 SFX and 16 patterns.</p> <p>Music is <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC-BY-NC-SA 4.0</a>, art is <a href="https://flickr.com/photos/reedexter/2405683888/">&quot;Twilight&quot; by RDexter on Flickr</a>, <a href="https://creativecommons.org/licenses/by-nc/2.0/">CC-BY-NC 2.0</a>.</p> https://www.lexaloffle.com/bbs/?tid=140051 https://www.lexaloffle.com/bbs/?tid=140051 Wed, 31 Jan 2024 16:53:00 UTC tanh soft clipping for PCM <p>One of the basic problems you might want to solve in doing PCM synthesis is limiting a signal to the range between -1 and +1. Obviously you can just use a mid() function to get hard clipping - the value just locks to the endpoints - but this often has unpleasant side effects. For example, if you hard clip the output, the sound will snap abruptly from smooth to harsh as the volume increases, with very little transition between these. So, people often want to round off that transition, let the sound get gradually harsher, and one of the smoothest options is to use the tanh - hyperbolic tangent - function. Looking at <a href="https://commons.wikimedia.org/wiki/File:Hyperbolic_Tangent.svg">a graph of this function</a>, you can see that it smoothly transitions from reproducing the original x value to squishing it between -1 and 1, just as we often want.</p> <p>So, I did a bit of experimenting today with sine waves and came up with the following code snippet:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--to use table: -- tanh = lut[x\0x.01] or sgn(x) function lut_tanh() --lookup table of tanh -- between -3 and +3 -- with step size 1/256 local tanh={} for i_x=-768,768 do --naive formula is --tanh = 1 - 2/(1+exp(2x)) local x=i_x&gt;&gt;8 --=i_x*0x.01 --inspired by https://www.math.utah.edu/~beebe/software/ieee/tanh.pdf formula: --1. from 0 to x_small=0x0.01bb, tanh(x) = x --2. for x&gt;=0x5.3300, naive formula returns 1 if abs(x)&lt;=0x.01bb then tanh[i_x]=x else tanh[i_x]=1-2/(1+0x2.b7e1^(2*x)) end end return tanh end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>To my ears, with these values, driving a sine wave with an input volume as low as 0.03 sounds only about as bad as the original sine wave does with so few bits to work with, and driving all the way up to 16 there's not a lot of artifacting to the distortion. With some antialiasing you could probably do even better than that.</p> <p>This function uses 1537 entries in the lookup table, which I think is about 1.4% of Lua memory. I know my ears aren't very trained when it comes to analyzing synth sounds, so feel free to edit this if it seems like too much or not enough, but it seems to me like a fairly practical compromise for PCM slingers.</p> https://www.lexaloffle.com/bbs/?tid=139823 https://www.lexaloffle.com/bbs/?tid=139823 Sat, 13 Jan 2024 19:25:50 UTC PICO-8 Free Music Jam <p>Oh hey, a thing we're doing is live!</p> <p><a href="https://itch.io/jam/pico-8-free-music-jam"><img style="margin-bottom:16px" border=0 src="/media/40166/pico 8 free music jam cover by parak00pa.png" alt="" /></a></p> <p><a href="https://itch.io/jam/pico-8-free-music-jam">The PICO-8 Free Music Jam</a> is an itch.io jam for musicians with a very simple concept: PICO-8 devs want music to put in their carts, we're gonna make music for their carts.</p> <p>It'll be running for the full month of February - no ratings, no competition, just music for PICO-8. And if you wanna get started making music, in PICO-8 or at all, there's loads of resources linked on the jam page.</p> <p>(edit: And many thanks to the folks in the #music-sfx channel of the official unofficial PICO-8 Discord who came together to hatch this idea and hammer out the details, and to <a href="https://www.lexaloffle.com/bbs/?uid=55005"> @paraK00PA</a> for the awesome cover art!)</p> https://www.lexaloffle.com/bbs/?tid=55621 https://www.lexaloffle.com/bbs/?tid=55621 Thu, 04 Jan 2024 16:21:41 UTC Random PICO-8 top tips thread <p>I don't know if this exists, but I think it would be cool to have a thread of Stuff You Might Not Have Figured Out From Just Messing Around Making Things.</p> <p>Here's two to start with, from a musician perspective:</p> <ol> <li> <p><strong>If you can, leave SFX 00 through 07 empty.</strong> It will help with adding music later - be that you adding music or because those slots can be used for custom SFX instruments that give a lot of character and flavor to compositions.</p> </li> <li><strong>Decide how many channels to reserve for music.</strong> The 4 SFX channels of PICO-8 have to be used by both music and sound effects, and both music and sound effects benefit from having more channels - so think about which is more important to you, and which sound effects can interrupt each other. You can also, if some sound effects are only played sparsely (maybe you have a clicky sound while navigating menus!), try having one channel of music that is interrupted briefly by the sparse effect and then resumes.</li> </ol> https://www.lexaloffle.com/bbs/?tid=53452 https://www.lexaloffle.com/bbs/?tid=53452 Tue, 18 Jul 2023 15:57:56 UTC midi 046 Concert Harp <p> <iframe src="sfxp2.php?id=40166_27" width="402" height="300" style="border:none; overflow:hidden" scrolling="no" allow="autoplay"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_27"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_27.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_27"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_27" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>Was listening to some old compositions of mine and realized that I had a nice little instrument that hadn't made it into the midi library!</p> <p>For the demo, I used the same trick I used then, and split the melody across two separate SFX so the tails of each note could ring out while the next note played. Bit of a faff to do, but it produces a very good effect.</p> <p> <table><tr><td> <a href="/bbs/?pid=126381#p"> <img src="/bbs/thumbs/pico8_hifesosani-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=126381#p"> hifesosani</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=126381#p"> [Click to Play]</a> </td></tr></table> </p> <p>As noted in the cart, at least to me, it still sounds good and has a harp-ish vibe with various combinations of Buzz, Dampen, and Reverb; Detune doesn't work because the bulk of the SFX is the triangle wave.</p> https://www.lexaloffle.com/bbs/?tid=51783 https://www.lexaloffle.com/bbs/?tid=51783 Mon, 27 Feb 2023 20:30:48 UTC State Variable Filter for PCM <p>So, let's say you're building a synthesizer using the serial PCM output and you want a filter. What do?</p> <p>Well, what I did was follow a link <a href="https://www.lexaloffle.com/bbs/?uid=24137"> @luchak</a> posted a while ago in the Discord to <a href="https://www.musicdsp.org/en/latest/Filters/92-state-variable-filter-double-sampled-stable.html">this SVF filter design by Andrew Simper, Laurent de Soras, and Steffan Diedrichsen</a>. And then get blasted with noise, because a design that works great with double-precision floating-point numbers is not so great with 16b.16b fixed-point PICO-8 numbers.</p> <p><em>Edit: I recommend using the <a href="https://www.lexaloffle.com/bbs/?pid=126689#p">code snippet downthread</a> rather than this one.</em></p> <p>Now, I'm not good enough at math to prove mathematically that this is stable, but I'm good enough at hacking together testing code to feel confident that, as long as:</p> <ul> <li>the signal being fed into the filter remains in the range -1 to 1,</li> <li>the resonance remains in the range 0 to 1, and</li> <li>the cutoff remains in the range 0 to 2756.25 (the Nyquist frequency for PICO-8's 5512.5 Hz PCM output)</li> </ul> <p>...this should produce an output that remains within the range <del>-3 to 3</del> -3.5 to 3.5 and is usable.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--this is the initialization section; do it outside the sample calculation loop local f_low,f_band=0,0 --these are the filter parameters --I haven't tested changing them while the filter is running but that's what I plan to do, so, here's hoping. local res=0 to 1 local freq=-2.0*sin(cutoff frequency/22050)--sin( 0.5 * cutoff frequency/(2*sampling frequency) ) --after you set freq and res, these two are derived local drive=max(0,.05*res-.0125)--0 for res&lt;0.25, increase linearly to 0.0375 for res=1 local damp=min(2.0*(1.0 - res^0.25), min(2.0, 2.0/freq - freq*0.5)) -- -- -- do the calculations here to generate osc, your signal to be filtered -- -- --2x oversampled filter local f_notch=osc-damp*f_band f_low+=freq*f_band local f_high=f_notch-f_low f_band-=drive*f_band*f_band*f_band--distortion f_band+=freq*f_high--filter local out=(f_notch or f_low or f_high or f_band)&gt;&gt;1--half here... f_notch=osc-damp*f_band f_low+=freq*f_band f_high=f_notch-f_low f_band-=drive*f_band*f_band*f_band--distortion f_band+=freq*f_high--filter out+=(f_notch or f_low or f_high or f_band)&gt;&gt;1--...and half here</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>To show it off, here's my current very incomplete version of a button keyboard cart. Same keyboard keys as you use for SFX editor note entry; left-right arrows to change octave. This filter is set up with a cutoff frequency of A5 (880 Hz) and a resonance of 1.<br /> <table><tr><td> <a href="/bbs/?pid=124936#p"> <img src="/bbs/thumbs/pico8_pb_pcmk_filter_demo-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=124936#p"> pb_pcmk_filter_demo</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=124936#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=51387 https://www.lexaloffle.com/bbs/?tid=51387 Sat, 28 Jan 2023 03:25:33 UTC PCM synth for cart background music: hard but possible? <p>I think ever since <a href="https://www.lexaloffle.com/bbs/?uid=23375"> @carlc27843</a>'s <a href="https://www.lexaloffle.com/bbs/?tid=41991">Impossible Mission R.T.</a> cart came out, people have been wondering if they could make background music for a cart using PCM synthesis. carlc27843's <a href="https://www.lexaloffle.com/bbs/?tid=42362">Emulated Amstrad CPC Chiptunes</a> post discusses using its engine that way, <a href="https://www.lexaloffle.com/bbs/?uid=24137"> @luchak</a> has had to let people know that the <a href="https://www.lexaloffle.com/bbs/?tid=47284">RP-8</a> groovebox <em>can't</em> be used that way ... folks are curious.</p> <p>I don't know a lot about digital audio synthesis, but from the conversations that have happened in the PICO-8 Discord, it sounds like there's roughly three sides to the equation:</p> <h3>Cost</h3> <ul> <li><strong>How many tokens and bytes are cart designers willing to give up to the soundtrack?</strong> <a href="https://www.lexaloffle.com/bbs/?uid=49583"> @bikibird</a>'s <a href="https://www.lexaloffle.com/bbs/?tid=49108">Speako8 Speech Synthesis Library</a> is under a thousand tokens - is that a good target?</li> <li><strong>What percentage of PICO-8's CPU budget?</strong> Four voices with 25% CPU seems possible in a few different ways, but is that too much to give up to background music?</li> <li><strong>How much memory, Lua and addressable?</strong> Most forms of synthesis probably run out of CPU first, but this could be a question if you're making a lot of lookup tables.</li> </ul> <h3>Usability</h3> <ul> <li><strong>How do you program tracks?</strong> Does it use PICO-8's built-in tracker with its own sound sources? Does it have a custom editor?</li> <li><strong>How do you add them to your games?</strong> Presumably you copy a bunch of code into memory and add a function or coroutine to your game loop, but where and how do you store tracks?</li> </ul> <h3>Quality</h3> <ul> <li><strong>How many simultaneous voices?</strong> PICO-8's built-in tracker allows 4 simultaneous sounds, but most game BGM is built with 2 or 3.</li> <li><strong>What effects can you add?</strong> Reverb is probably out of budget, but echo is possible (if memory-expensive), and distortion and compression are totally feasible. As are filters - certainly low pass, high pass, band pass, and notch.</li> <li><strong>What kind of synth do you make?</strong></li> </ul> <p>It's definitely possible to make:</p> <ul> <li>Simple waveform synthesis (e.g. sine, square/pulse, sawtooth, triangle)</li> <li>FM synthesis</li> <li>Sample-based synthesis (very storage-expensive!)</li> <li>Wavetable synthesis (the original PPG Wave synthesizers only had 8-bit samples! but this is also storage-expensive, if less than sample-based synthesis)</li> <li>Subtractive synthesis with any of the above as oscillators</li> </ul> <p>...but the more processing you do, the more sound design tools you add, the more expensive your result will be.</p> <h3>Conclusion?</h3> <p>I don't really have one? But I think it would be good to have a space on the official forums where people who are thinking about this stuff can talk about it. I haven't made a lot of games, so I don't know what what a good budget would be for game developers ... and I haven't made much music with much outside PICO-8 and, like, an actual piano, so I don't know what a good synthesizer would be for game soundtrack composers. And I know barely anything about software synthesis, so I don't know what's possible, what's easy, what's hard, or why my low-pass filter makes hell noises if I give it the wrong parameters.</p> <p>I think it would be cool to share knowledge, and the forums seems like the best place to do it.</p> https://www.lexaloffle.com/bbs/?tid=51246 https://www.lexaloffle.com/bbs/?tid=51246 Wed, 18 Jan 2023 18:45:26 UTC line()-based Cubic Bezier Curve <p> <table><tr><td> <a href="/bbs/?pid=122890#p"> <img src="/bbs/thumbs/pico8_pb_line_cbez-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=122890#p"> pb_line_cbez</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=122890#p"> [Click to Play]</a> </td></tr></table> </p> <p>I know a lot of people have posted functions for drawing cubic bezier curves, but I'm tossing my own into the pot because why not. Just skimming threads, it feels like most people use pset() to draw them pixel by pixel; this one uses line() to draw them segment by segment.</p> <p>Some animated gifs, because they're fun:<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"><br /> demo of the editor in the cart:</p> <img style="margin-bottom:16px" border=0 src="/media/40166/cbez0 7_7.gif" alt="" /> <p>drawing demo, dividing the curve into segments:</p> <img style="margin-bottom:16px" border=0 src="/media/40166/cbez0 7_6.gif" alt="" /> <p>drawing demo, dividing the curve dynamically based on pixel precision:</p> <img style="margin-bottom:16px" border=0 src="/media/40166/cbez0 7_5.gif" alt="" /> <p></div></div></div></p> <p>To save you digging into the cart, here's the two versions of the algorithm I'd recommend, based on my testing. If you want to see how fast they run, there's a pause menu item in the code that draws sets of 5000 random bezier curves with a bunch of different algorithm parameters in two sizes - 16-pixel square bounding box and 128-pixel square bounding box - and adds up the total CPU needed at 60 FPS.</p> <ol> <li> <p>The polynomial coefficients function. All of the other code uses this.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--coefficient fn (39 tokens, shared by all) function cubic_coef(p0,p1,p2,p3) --coefs for cubic bezier return p0, -3*p0+3*p1, 3*p0-6*p1+3*p2, -p0+3*p1-3*p2+p3 end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> </li> <li> <p>Fixed-segments option. This one has 16 segments, which (a) is convenient numerically and (b) doesn't get too messy for small curves but doesn't look too chunky for large ones. From the benchmark, you could draw 220 big curves or 250 small curves in one 60 FPS frame.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--fixed 16 points (+80 tokens) function cbez_16(x0,y0,x1,y1,x2,y2,x3,y3) --cubic bez, dt predefined --precalculate polynomial coefs local a0,a1,a2,a3=cubic_coef(x0,x1,x2,x3) local b0,b1,b2,b3=cubic_coef(y0,y1,y2,y3) --set endpoint for first segment -- by poking ram with coords poke2(0x5f3c,x0) poke2(0x5f3e,y0) -- --optional: clear error to avoid bugs -- poke(0x5f35,0)--4 tokens for t=0x.1,1,0x.1 do line( a0+t*(a1+t*(a2+t*a3)), b0+t*(b1+t*(b2+t*b3)) ) end end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> </li> <li> <p>Adaptive-segments option. This one is a bit faster for small curves - like 320/frame - but much slower for large curves - like 110/frame.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--recursive, fixed 2px precision -- (+186 tokens) function cbez_recurs2(x0,y0,x1,y1,x2,y2,x3,y3) --cubic bez, adaptive points --precalculate polynomial coefs local a0,a1,a2,a3=cubic_coef(x0,x1,x2,x3) local b0,b1,b2,b3=cubic_coef(y0,y1,y2,y3) --set endpoint for first segment -- by poking ram with coords poke2(0x5f3c,x0) poke2(0x5f3e,y0) -- --optional: clear error to avoid bugs -- poke(0x5f35,0)--4 tokens --poly function local function xy(t) return a0+t*(a1+t*(a2+t*a3)), b0+t*(b1+t*(b2+t*b3)) end --subdividing draw function local function crawl(tp,tn,xp,xn,yp,yn) --draw curve recursively to tn local tm=(tp+tn)&gt;&gt;1 local xm,ym=xy(tm) --luchak fast abs local xerr,yerr=(xp+xn)&gt;&gt;1,(yp+yn)&gt;&gt;1 xerr-=xm yerr-=ym if xerr^^(xerr&gt;&gt;31)&gt;2 or yerr^^(yerr&gt;&gt;31)&gt;2 then --not precise enough; recurse crawl(tp,tm,xp,xm,yp,ym) crawl(tm,tn,xm,xn,ym,yn) else --close enough; draw line(xm,ym) line(xn,yn) end end local x5,y5=xy(.5) crawl(0,.5,x0,x5,y0,y5) crawl(.5,1,x5,x3,y5,y3) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>(Shoutout to <a href="https://www.lexaloffle.com/bbs/?uid=24137"> @luchak</a>, from whom I swiped this fast abs function - I think it ended up reducing runtime by about 3%, which might not be worth it but hey.)</p> </li> </ol> <p>There's probably ways to optimize these further that I haven't thought of - I'm just not very good at that - so please feel free to sound off with any suggestions.</p> <p>Also, I tried to make good comments, but let me know if anything's unclear.</p> https://www.lexaloffle.com/bbs/?tid=50777 https://www.lexaloffle.com/bbs/?tid=50777 Fri, 23 Dec 2022 14:04:01 UTC extcmd(&quot;audio_rec&quot;) limit is 2 minutes, not 8 minutes (v0.2.5e) <p>Out of curiosity, I was testing to confirm that the new limit on length of audio recordings via extcmd(&quot;audio_rec&quot;) was per-instance and not per-session ... and discovered that the length of recording I got was 2 minutes instead of the 8 minutes listed in the v0.2.5d changelog.</p> <p>An 8-minute limit makes sense to me but a 2-minute one doesn't, so I'm assuming this is an error of some sort.</p> <p>edit: confirmed fixed in v0.2.5g.</p> https://www.lexaloffle.com/bbs/?tid=50654 https://www.lexaloffle.com/bbs/?tid=50654 Wed, 14 Dec 2022 17:46:30 UTC midi 10:050 High Tom <p>Taking a crack today at building drum kit SFX - I've labeled this one as a &quot;High Tom&quot;, but if you play it on a lower note than C2, I think it'll probably serve for whatever tom you need. You do need to take care of fading out the notes yourself, though - the SFX ends on a held G1, just to let the drums have a longer sustain than 32 ticks.</p> <p> <iframe src="sfxp2.php?id=40166_26" width="402" height="300" style="border:none; overflow:hidden" scrolling="no" allow="autoplay"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_26"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_26.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_26"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_26" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> https://www.lexaloffle.com/bbs/?tid=49640 https://www.lexaloffle.com/bbs/?tid=49640 Tue, 04 Oct 2022 22:55:59 UTC midi 050 and midi 051 SynthStrings <p>The trouble with the General Midi 1 standard is that it doesn't include any explanation of what any of the names mean, so I had to spend multiple seconds of research on going to the GM-1 Wikipedia page and scrolling down to the best guess of the editors there. Apparently, by &quot;SynthStrings&quot;, they probably mean <a href="https://reverb.com/news/a-brief-history-of-string-synths">a string synthesizer, or string synth</a>, an electronic instrument originally intended as a relatively cheap and portable substitute for a strings section, but which people later started to use as an instrument in its own sake.</p> <p>So, that's what I tried to imitate. And since GM-1 has two SynthStrings program numbers and says nothing about how they should differ, I just tried to follow what GeneralUser GS seemed to do and make the second version a little brighter in timbre.</p> <p>Here's 050 SynthStrings 1:<br /> <iframe src="sfxp2.php?id=40166_24" width="402" height="300" style="border:none; overflow:hidden" scrolling="no" allow="autoplay"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_24"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_24.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_24"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_24" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>...and 051 SynthStrings 2:<br /> <iframe src="sfxp2.php?id=40166_25" width="402" height="300" style="border:none; overflow:hidden" scrolling="no" allow="autoplay"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_25"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_25.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_25"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_25" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> https://www.lexaloffle.com/bbs/?tid=49617 https://www.lexaloffle.com/bbs/?tid=49617 Mon, 03 Oct 2022 22:19:04 UTC midi 074 Recorder <p>Another simple one, although there's some pretty aggressive ... can you even call it tremolo if it's this slow? In imitation of the <a href="https://github.com/sgossner/VCSL">VCSL</a> sample I was using as inspiration. Makes for an interesting effect, which I think fits the folk-instrument vibes.</p> <p> <iframe src="sfxp2.php?id=40166_23" width="402" height="300" style="border:none; overflow:hidden" scrolling="no" allow="autoplay"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_23"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_23.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_23"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_23" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> https://www.lexaloffle.com/bbs/?tid=49588 https://www.lexaloffle.com/bbs/?tid=49588 Sun, 02 Oct 2022 21:08:41 UTC