packbat [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=40166 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="sfxp.php?id=40166_27" width="769" height="97" style="border:none; overflow:hidden"></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="sfxp.php?id=40166_26" width="769" height="97" style="border:none; overflow:hidden"></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="sfxp.php?id=40166_24" width="769" height="97" style="border:none; overflow:hidden"></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="sfxp.php?id=40166_25" width="769" height="97" style="border:none; overflow:hidden"></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="sfxp.php?id=40166_23" width="769" height="97" style="border:none; overflow:hidden"></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 midi 019 Church Organ <p>This one turned out to be a relatively simple process:</p> <ol> <li>Select the &quot;Organ&quot; waveform.</li> <li>Make it as huge as possible.</li> </ol> <p> <iframe src="sfxp.php?id=40166_22" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_22"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_22.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_22"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_22" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>The preview sounds terrible because it loops the vibrato weirdly, but when used as an actual instrument, the vibrato works as normal.</p> https://www.lexaloffle.com/bbs/?tid=49575 https://www.lexaloffle.com/bbs/?tid=49575 Sat, 01 Oct 2022 22:06:00 UTC midi 005 FM Piano <p>Wikipedia said that the Electric Piano 2 slot is often an FM piano patch, so I went in and tried to make something with a similar vibe:</p> <p> <iframe src="sfxp.php?id=40166_21" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_21"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_21.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_21"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_21" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> https://www.lexaloffle.com/bbs/?tid=49405 https://www.lexaloffle.com/bbs/?tid=49405 Mon, 19 Sep 2022 23:44:45 UTC midi 040 Violin <p>This one ended up being really simple:</p> <p> <iframe src="sfxp.php?id=40166_19" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_19"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_19.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_19"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_19" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>...but there's a couple tricks to using it in a way that feels violin-y.</p> <p>First, you have to think about what exactly the violinist is doing at any given moment in order to navigate the notes they're being asked to play. For those who do not know violin performance well: the way a violin produces sound during normal play is by using a tensioned stick with hair coated in rosin attached to it - the aforementioned bow - to scrape along a string, imparting energy to the string that then causes it to vibrate and make sound. And, crucially, the bow is only so long, and can only be moved so slowly across the string ... so, as the violinist plays, they regularly have to stop and change direction.</p> <p>Plus, the way a violin creates a <em>specific</em> note is not, as with a piano, by pressing a key, but by pressing a finger on a string to hold it against a fingerboard - there are no frets, and to change a note, the violinist has to move their finger to a new position.</p> <p>So, in my demo of it:</p> <p> <table><tr><td> <a href="/bbs/?pid=117417#p"> <img src="/bbs/thumbs/pico8_yodonakafi-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=117417#p"> Violin demo</a><br><br> by <a href="/bbs/?uid=40166"> packbat</a> <br><br><br> <a href="/bbs/?pid=117417#p"> [Click to Play]</a> </td></tr></table> </p> <p>...I use a lot of glides to represent places where a single stroke of the bow is being used to play multiple notes, and at the part at the end of the loop where the notes jump around a bunch, I chop off (sorta) the ends of the notes to give the impression of the gaps between notes from when the violinist had to move quickly.</p> <p>Oh, and the second trick to it.</p> <p>This SFX has built into it a point where the violinist runs out of bow and has to do another downstroke. (This is something I copied from the <a href="https://github.com/sgossner/VSCO-2-CE">VS Chamber Orchestra</a> sample I referenced when designing the note - it's not included in soundfonts like FluidR3.) If you're holding a note for a long time - 341 ticks, 2.83 seconds - the volume will drop off and there will be a moment like at the start of the SFX where the texture of the note roughens ... because the fictional violinist playing the note ran out of bow and had to do a second stroke. If you don't want that, you can change the loop points to stop before the repeat; if you <em>do</em> want that, you can adjust things to make it happen at the right tempo for your specific piece of music.</p> https://www.lexaloffle.com/bbs/?tid=49334 https://www.lexaloffle.com/bbs/?tid=49334 Wed, 14 Sep 2022 15:34:09 UTC Custom SFX instruments not transferred when copy+pasting patterns <p><strong>Steps to reproduce:</strong></p> <ol> <li> <p>Create a custom SFX instrument.</p> </li> <li> <p>Create an SFX using this instrument.</p> </li> <li> <p>Add the latter SFX (but not the former) to a music pattern.</p> </li> <li> <p>Select the pattern and copy.</p> </li> <li>In a new PICO-8 cart, select a pattern and paste.</li> </ol> <p><strong>Expected behavior:</strong></p> <p>All necessary data to reproduce the original pattern should be transferred. (Notably, this occurs when pasting into the BBS.)</p> <p><strong>Observed behavior:</strong></p> <p>The SFX instrument is not copied, and only the SFX specifically included in the pattern are copied.</p> https://www.lexaloffle.com/bbs/?tid=49316 https://www.lexaloffle.com/bbs/?tid=49316 Tue, 13 Sep 2022 01:29:49 UTC midi 008 Celesta <p>I'm gonna be honest: did this one next because I remembered my opening a soundfont in LMMS for the first time, browsing around, and going &quot;wait, did that say <a href="https://www.lexaloffle.com/bbs/?tid=2145">Celeste</a>?!&quot;</p> <p>(It did, but it's a case of shared etymology - it means the heavens. Or the sky.)</p> <p> <iframe src="sfxp.php?id=40166_18" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_18"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_18.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_18"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_18" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>In keeping with the real-world version, this is a transposing instrument - plays an octave above the note entered. There is some artifacting on D#6, however.</p> https://www.lexaloffle.com/bbs/?tid=49310 https://www.lexaloffle.com/bbs/?tid=49310 Mon, 12 Sep 2022 20:04:13 UTC midi 001 Bright Acoustic Piano <p>This is a duplicate of <a href="https://www.lexaloffle.com/bbs/?tid=49269">this earlier piano SFX</a> as far as <a href="https://www.lexaloffle.com/bbs/?tid=49265">the midilib project</a> is concerned, but I wanted to share my attempt at replicating ... I think the sample I was referencing was an upright piano? As best as I could.</p> <p> <iframe src="sfxp.php?id=40166_17" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_17"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_17.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_17"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_17" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>As with the others, this is free to use, although credit is appreciated; <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#SFX_Instruments">the manual entry on custom SFX instruments</a> should explain how to use it.</p> https://www.lexaloffle.com/bbs/?tid=49278 https://www.lexaloffle.com/bbs/?tid=49278 Sun, 11 Sep 2022 01:30:48 UTC midi 013 Xylophone <p>No cart preview right now, but posting the SFX so people can use it: my latest best shot at a xylophone sound:</p> <p> <iframe src="sfxp.php?id=40166_16" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_16"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_16.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_16"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_16" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>Free to use, credit appreciated; <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#SFX_Instruments">manual section on SFX instruments is here</a> if it's not something you're familiar with.</p> https://www.lexaloffle.com/bbs/?tid=49277 https://www.lexaloffle.com/bbs/?tid=49277 Sun, 11 Sep 2022 01:21:43 UTC midilib custom SFX instrument project <p>So, PICO-8's built-in tracker has a startling amount of customization, but it can be kinda tricky actually making a <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#SFX_Instruments">custom SFX instrument</a> when you want one - so a few of us on the Discord, me and <a href="https://www.lexaloffle.com/bbs/?uid=45958"> <a href="https://www.lexaloffle.com/bbs/?uid=45958"> @jo560hs</a></a> and <a href="https://www.lexaloffle.com/bbs/?uid=49583"> @bikibird</a>, were thinking it might be interesting to look at <a href="https://pjb.com.au/muscript/gm.html">the list of General Midi 1 instruments</a> as a shopping list and see how many we can knock off.</p> <p>And as a bonus, if we can complete the list, <a href="https://www.lexaloffle.com/bbs/?uid=45958"> <a href="https://www.lexaloffle.com/bbs/?uid=45958"> @jo560hs</a></a> was talking about possibly making an sf2 soundfont for folks who like playing with those.</p> <p>So, if you wanna jump in and add stuff to the catalog, the guidelines we decided on for convenience of people hunting down instruments afterwards are these:</p> <ul> <li>tag the post with <code>midilib</code></li> <li>use a subject line of the format <code>midi [number] [name]</code></li> <li>(ideally, each instrument should be posted in its own thread, so specific ones can be found more easily)</li> <li>embed your SFX there so people can hear it and copy it</li> <li>let folks know if you have any special requirements (I generally assume something akin to CC-BY, where people can use them freely if they credit you, but let us know!)</li> </ul> <p>As people create more instruments, we'll try to look in the <a href="https://www.lexaloffle.com/bbs/?cat=7#tag=midilib">midilib tag</a> and update everyone on what people have been doing, so folks who feel like doing whatever can see what's missing.</p> <p>I've made <a href="https://www.lexaloffle.com/bbs/files/40166/GM1%20list.txt">a text file with a list of all the GM-1 instruments and their numbers</a> - feel free to ask questions, promote your threads, and so on here.</p> <h3>Clarifying note about duplicates</h3> <p>Quick heads-up, because it seems to have been the source of a little confusion: yes, we do want to complete the list of SFX ... but even when people have already made SFX for a particular MIDI patch, <strong>please share your versions!</strong> I can tell you right now: I have <em>eight different pianos</em> downloaded to my hard drive that I can use as instruments in LMMS, plus four more in each of the two big sf2 soundfonts I downloaded, <em>plus</em> a bunch of presets for LMMS's built-in synths, <em>plus</em> all the other soundfonts I have ... and I have zero regrets. Just as much as we want this project to create a PICO-8 sf2 soundfont for producers to play with, we want this project to create a library of sounds for <em>PICO-8 composers</em> to play with. And variety is great because it lets people choose the perfect sound for their tracks.</p> <p>So, please, post duplicates when you have them. Having more options is terrific.</p> <h3>Instruments as of 2023-03-16</h3> <p><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> <p><a href="https://www.lexaloffle.com/bbs/?tid=49266">midi 000 acoustic grand piano</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49269">midi 001 bright acoustic piano</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49278">midi 001 Bright Acoustic Piano</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49273">midi 002 electric grand piano</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49263">midi 003 Honky-Tonk Piano</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49405">midi 005 FM Piano</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49279">midi 006 harpsichord</a> by jo560hs</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49310">midi 008 Celesta</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49276">Midi 010 Glockenspiel</a> by dw817<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49277">midi 013 Xylophone</a> by packbat</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49575">midi 019 Church Organ</a> by packbat</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49264">midi 029 Overdriven Guitar</a> by packbat</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=39431">midi 034 Electric Pick Bass</a> by Gabe_8_bit<br /> <a href="https://www.lexaloffle.com/bbs/?tid=39431">midi 037 Slap Bass 2</a> by Gabe_8_bit<br /> <a href="https://www.lexaloffle.com/bbs/?tid=50848">midi 038 synth bass 1</a> by jo560hs</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49334">midi 040 Violin</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=51783">midi 046 Concert Harp</a> by packbat</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49617">midi 050 SynthStrings 1</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49617">midi 051 SynthStrings 2</a> by packbat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49623">MIDI 051 Synth String 2</a> by dw817</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=50848">midi 058 tuba</a> by jo560hs</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=51852">midi 070 Bassoon</a> by wasiknighit</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49282">midi 073 flute</a> by SmellyFishstiks<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49487">midi 073 flute</a> by ericb<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49588">midi 074 Recorder</a> by packbat</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=49321">midi 122 Seashore</a> by jasondelaat<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49320">midi 125 Helicopter</a> by jasondelaat</p> <p><a href="https://www.lexaloffle.com/bbs/?tid=50848">midi 10:35 acoustic bass drum</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49813">midilib 10:36 Bass Drum 1</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=50848">midi 10:38 acoustic snare</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=50848">midi 10:39 hand clap</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49813">midilib 10:42 Closed Hi-Hat</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49813">midilib 10:44 Pedal Hi-Hat</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49813">midilib 10:46 Open Hi-Hat</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49813">midilib 10:49 Crash Cymbal 1</a> by jo560hs<br /> <a href="https://www.lexaloffle.com/bbs/?tid=49640">midi 10:050 High Tom</a> by packbat (note: can be used for other toms)<br /> <a href="https://www.lexaloffle.com/bbs/?tid=50848">midi 10:51 ride cymbal 1</a> by jo560hs<br /> </div></div></div></p> https://www.lexaloffle.com/bbs/?tid=49265 https://www.lexaloffle.com/bbs/?tid=49265 Sat, 10 Sep 2022 20:53:19 UTC midi 029 Overdriven Guitar <p>For anyone who wants it, an SFX imitating an electric guitar with overdrive:</p> <p> <iframe src="sfxp.php?id=40166_15" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_15"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_15.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_15"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_15" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>Free to use, credit appreciated.</p> <p>(If you are not already familiar, <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#SFX_Instruments">the manual has a brief explanation of how custom SFX instruments work</a>.)</p> https://www.lexaloffle.com/bbs/?tid=49264 https://www.lexaloffle.com/bbs/?tid=49264 Sat, 10 Sep 2022 20:41:02 UTC midi 003 Honky-Tonk Piano <p>A group of us on the Discord were talking about how it'd be useful it'd be to have a big library of SFX instruments, so here's one I made a while ago to act as a ragtime piano:</p> <p> <iframe src="sfxp.php?id=40166_14" width="769" height="97" style="border:none; overflow:hidden"></iframe><a style="cursor:pointer; font-size:8pt" onclick=' var el = document.getElementById("sfxcode_40166_14"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("/bbs/sfxc/40166_14.txt", function (retdata){ var el = document.getElementById("sfxcode_40166_14"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [sfx] </a> <textarea rows=3 class=lexinput id="sfxcode_40166_14" style="width:480px;background-color:#fed;display:none;overflow:hidden; font-size:4pt;"></textarea> </p> <p>Free to use, credit appreciated.</p> <p>(If you are not already familiar, <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#SFX_Instruments">the manual has a brief explanation of how custom SFX instruments work</a>.)</p> https://www.lexaloffle.com/bbs/?tid=49263 https://www.lexaloffle.com/bbs/?tid=49263 Sat, 10 Sep 2022 20:39:06 UTC Interrupting pause when key is held (Edit: cause identified) <p>So, I'm working on a toy musical keyboard program, and I want to use SDL scancodes to detect which keys are being held - but I know that PICO-8 will pause if you hit the &quot;P&quot; key (whatever key that happens to be in the user's keyboard layout). So I want to detect when a &quot;P&quot; input is being received and stop it...</p> <p>...but my current code:</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>--interrupt pause on P while stat(30) do if stat(31)==&quot;p&quot; or &quot;◆&quot; then --suppress pause poke(0x5f30,1) 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> <p>only works for the <em>initial</em> press - when the key starts repeating, stat(30) doesn't detect the input but PICO-8 pauses anyway.</p> <p>Any suggestions? I'd rather not interrupt <em>all</em> pause inputs - that makes things difficult for Splore users.</p> <p><strong>Edit:</strong> Apologies to <a href="https://www.lexaloffle.com/bbs/?uid=15232"> @dw817</a>, whose explanations I apparently completely failed to parse: <a href="https://www.lexaloffle.com/dl/docs/pico-8_changelog.txt">in the changelog for 0.2.2b</a> it is noted that holding the pause button will <em>always</em> bring up the hardware pause menu, even when pause would otherwise be suppressed. This rules out any solution that involves the player holding down P that I can implement as cart programmer. (Shoutout to <a href="https://www.lexaloffle.com/bbs/?uid=42963"> @cubee</a>'s <a href="https://www.lexaloffle.com/bbs/?tid=49257">description of a related bug</a> which cued me in.)</p> https://www.lexaloffle.com/bbs/?tid=49241 https://www.lexaloffle.com/bbs/?tid=49241 Thu, 08 Sep 2022 21:20:11 UTC