Mollytime patches now can output mono or stereo sound, and they can have any number of generic inputs and outputs that can be routed to hardware ports or other programs.

I've decided that surround sound doesn't exist for now. I've got some ides for how to handle it, but it's kinda silly to bother right now since I don't have a surround sound system to test it with. I'll probably get some fancy headphones for it later, but it's not a 1.0 feature.

A friend is going to take a shot at a Windows port. Neither of us are familiar with the various Windows audio APIs, so I figure it's best if we just shoot for regular stereo outputs for now and worry about the dynamic i/o ports later. I'm hoping we can have that be a cross platform feature though.
Late last night I was thinking about adding the psmoveapi library to mollytime so I can use my old psvr wands with it, but now this morning I'm wondering if maybe someone else has already wrapped psmoveapi to translate it to midi and if I should just use that instead. I haven't found any such thing though.
anyone down for some drone I made some drone
(remember to turn the sound on) #mollytime
I really need to add a "fade out" button

well, in the other news mollytime has several filters now as of this weekend.

this video shows off some of the mind boggling effects mollytime is capable of now (this is an evolved version of the drum patch I posted a recording of a while back) and I'm very proud of it though I have to apologize I forgot to mute my browser and so there's a discord bloop in the recording just before the two minute mark I don't really feel like doing a retake right now
#mollytime

are you in the mood for some chill eerie slow experimental noise music? great, go find your headphones that have the good bass response, because I made some chill eerie slow experimental noise music #mollytime
here's what that patch looks like

I woke up this afternoon and realized this idea I had 98 days ago totally falls apart if you create a data dependency between invocations of the same function eg fn(fn()). Good thing I didn't build it!

I think instead I will probably have polyphony be implemented via shadow copies of polyphonic tiles.

https://mastodon.gamedev.place/@aeva/114968771707424143

another victory for daydreaming driven development
are you ready for 6 minutes and 26 seconds of uplifting harsh yet pleasant sounds because you'll never guess what i just made #mollytime
the patch for this one is a bit sprawling

I wrote a new screen for managing tile connections in mollytime, and I imagine a professional ui designer will feel real physical pain looking at this wonderful screenshot, which is why I decided to share it :3 It's pretty much the opposite of minimalism and it's sooooo functional and I can work a lot faster now ahahaha!

Now it only takes three or four clicks to toggle a wire whereas before it took more in some situations.

is it ugly enough to cause paint to peel? probably! is it intimidating to hypothetical new players? probably! however, this continues to be my guiding light:

https://mastodon.gamedev.place/@aeva/114612264992461462

This is how the old connection workflow worked if one of the sides of the selection had more than one possible option.

I have made a lot of patches with this old workflow and I am convinced now that despite what phones and tablets and unreal editor and windows 95 would have you believe, click-and-drag is an *awful* interaction verb and should not be used at all in frequently used actions.

https://mastodon.gamedev.place/@aeva/114842120034168266

The real victory today was ripping out the ADSR implementation and replacing it with a better one. Fixed a bunch of edge cases that had been bothering me, but also the new one is much simpler. The attack, decay, and release parameters now are the number of seconds to bring the amplitude from 0 to 1 or vice versa, and can be even modified while the envelope is running like on a proper synthesizer :O
That's the nice thing about this phase of the project. I can make major breaking changes to core functionality and I don't have to worry about things like versioning and such because "simply update every known patch file in existence by hand" is still a viable version migration strategy.
i think it's funny that it's been a little under half a year and i still haven't built any of the cool procedural wire drawing stuff i hashed out at the start of this devlog thread yet, because it turned out not to matter all that much in practice. i'd still like to take a shot at it, but it probably won't be soon
not every self playing patch is a winner but this one is named "barking frogs" #mollytime

I added a quantizer and a thing for generating random repeating sequences to mollytime tonight :D

This song is probably one of my favorite things I've made in a while ^_^

#mollytime

I don't have OBS set up on this machine right now, which is too bad, because otherwise you would have got to see me tinker with the patch while it was playing :)
I think this might be the first time that I've gotten a song stuck in my head that I made myself https://mastodon.gamedev.place/@aeva/115575598757344830

I wrote a python script to survey the distribution of opcodes in the mollytime example patches.

The bipolar-to-unipolar opcode is used 71 times, but the unipolar-to-bipolar opcode is only used 8 times so far. I'm reasonably sure that most of these are used to couple oscillator tiles to mix tiles.

I feel like this is probably a pretty good sign that having mix assume a 0-1 alpha like a normal lerp would was a mistake.

seems like it'll probably be a good idea to change the mix node to take a bipolar alpha value, and update the various random number generators to emit random bipolar values instead of unipolar values, but i'm gonna fiddle with this analysis script some more to better determine if that's a good idea or not

jfc I've written a lot of mollytime patches.

This table shows each opcode I've attached to a "mix" node, and how many times I've made that connection.

"const" is a numeric constant, "stu" is the bipolar-to-unipolar converter, "uts" is its inverse, "flp" is a flip-flop, and "midi_hz" is midi note number to hz.

It's unclear if making the mix alpha unipolar was a mistake or not. There's quite a lot of multiplies here, and I often use multiplies to pull values towards zero.

note -> mix is bizarre (that's a midi note from a connected midi device, so usually that's a magnitude of about 30 to 90), but midi_hz -> mix is *really* bizarre (that's hz from a midi note, so somewhere in the ballpark of 3 or 4 digits normally). I don't remember any of these, and its weird that note happened 4 times. I wonder if these are bugged patches
I think I'm gonna keep mix's alpha unipolar. It seems likely that if I were to change it to bipolar, I'd just end up flipping the number conversions the other way.

This is the whole opcode survey. This just lists the total counts of each opcode, no information about what they're connected to. Also this is only for the patches I've bothered to check in to git, since I'm not on my normal computer at the moment.

Each number is me dragging and dropping a tile ๐Ÿ˜…

Besides putting to rest whether or not I should change the behavior of the mix instruction, I also put this together to help me decide on categories for organizing the tiles, as the obvious categories are too lopsided.

However, my sister wisely convinced me that top level categories are a waste of time and it is more useful to organize by vibe, eg make tiles adjacent because they feel like they should be together, and so that is what I am planning on doing now.

I know she is correct because I'm already kinda doing that. Also consider, "oscillators" is a category that would make sense. The moon is an oscillator, and sin is an oscillator, but the moon absolutely should not be in the same drawer as sin. This is important.

Rewriting the part catalog in the pick-and-place mode didn't take long at all it turns out. Here's a short video showing how the new version works.

The main difference is you select the catalog page from a sidebar instead of paging through them like its mario paint.

idk why the background looks so distorted in the recording
ok whew yeah the new pick-and-place UI is much nicer to work with. here's a patch a made real quick to validate that it's a better workflow #mollytime
are you in the mood for roughly five minutes and thirty seconds of filtered feedback loops being gently agitated by random noise and the occasional saw wave? because you'll never guess what I made in #mollytime tonight
I rewrote my oscilloscope today
not shown in the video, but if you manage to send the signal off into infinity, the "beam" disappears from the oscilloscope. if you manage to generate NaNs, the oscilloscope screen wipes to black.

alright, I've added a thing that is very definitely not a monad, called "go" which I guess is a sort of macro or syntax sugar to allow you to make the order of a given input port's, uh, inputs... make the order of an input port's inputs explicit.

and then I used it to make a kinda terrible sequencer! enjoy :D

(this is a short video with sound, please turn your sound on! but only if you want to)

#mollytime

I realized there was a bug in that patch (that I don't feel like explaining), and so I recorded a new version for your enjoyment. Also I made the sequence a little more elaborate. #mollytime

I added a new tile called "tweak" which lets you adjust its value live with the mouse wheel when the mouse is hovering over it. I haven't added an indicator for it yet, but the scope tile works fine in the mean time.

Here's a simple FM patch I whipped up to demonstrate it.

(video demonstration with sound)
#mollytime

I really need to make it so I can save the tweak positions next because look er listen to this :O

I HAD A VIOLIN HIDDEN IN HERE THIS WHOLE TIME :O I HAD NO IDEA

(more video w/ sound)
#mollytime

I added a little indicator to the tweak tiles so you can see what the f im doing. Anyways here's four minutes and twenty one seconds of me doing. (video w/ sound) #mollytime
not the final appearance, that's just a widget I threw together in about a half hour tonight
my strategy of allocating registers by simply heap allocating a few hundred floats wrapped in shared pointers has held up astonishingly well so far, but I think I'm going to switch to allocating the register file as a single array up front when a patch is compiled, and then copying values that should persist out of the previous iteration's register file during the program change on the audio thread.
this makes polyphony a lot easier to reason about. the other thing that makes polyphony a lot easier to reason about, is I've decided to have the number of polyphonic lanes be configured in a non-existent patch settings screen, rather than try to infer them from the patch. you get however many midi voices you want times however generic helper lanes you want (such as two if you want to do something fancy for stereo)
if you don't do anything that would be intrinsically polyphonic, like use midi or check which lane you are in, then you get a monophonic patch. I think that is reasonable behavior.
I'm a bit closer to figuring out how to make functions workable, since I'm trying not to paint myself into a corner there while I rework how the compiler works. One of the big open problems was what to do when someone produces a patch with a function that calls itself. The answer turns out to be "nothing" :) It's literally not possible with my chosen priors to support recursion, nor is it useful to.
as it happens, you can already write recursive algorithms anyway because the language supports cycles in the execution graph just fine. it's actually better, because you can't accidentally create infinite loops that block execution forever or oom on accident this way. ironically, allowing functions to recur does not make explicit graph cycles, which makes it impossible to make work without any flow control or stack machine. it's more efficient not to support it at all.

anyways, I think I have a clearer vision now as to how I'm going to implement polyphony. the main unsolved problem right now is how to make diagnostic tools like the oscilloscope have a coherent UI.

also I had this great realization that the execution model is not all that different from that of a spread sheet. registers are addressed by identity rather than position, but that's the main difference. the register file thing will make it a lot more similar though.

side thought: this devlog thread has been long enough to make the mastodon web ui bug out for a while now, but i kinda wanna keep it rolling and see how bad it can get XD

I recorded a video of me constructing a self-playing #mollytime patch from scratch, and I'm pretty happy with how it turned out :O.

If you don't want watch in mostly silence as I set up the basic structure of the patch for ten minutes and thirty six seconds, the music picks up at around 10:36.

https://www.youtube.com/watch?v=Q7qHcTszBhU

"starlight" mollytime live jam

YouTube
#mollytime is polyphonic as of tonight btw
(video with sound)
it's also a crashy mess now. maybe I'll simply riir it in rust tomorrow. (joke)
fixed it ๐Ÿ˜Ž now it is nice and stable. no riiring necessary ๐Ÿ˜Œ
I kinda wanna put together a thing that takes the last sent general midi program number on a given midi channel and translates it to a scalar value or three that has them neatly ordered on a gradual spectrum so that mollytime patches can use it as a modulation parameter. eg ranking them on a spectrum from melodic to percussive or something like that
ah! i know what axis i should sort the general midi instruments on: bouba-to-kiki
now i want to throw together a little pygame app and do lots of a/b comparisons to science this out. what's the most affordable authoritative general midi synthesizer if you don't have a roland sound canvas handy? maybe the default windows one? (serious inquiry)

ok I wrote said pygame app and powered through ranking random instrument sounds in terms of relative kiki-ness, and made the resulting lookup table into a midi parameter tile in #mollytime.

this is the result:
(video with sound)

mollytime/src/kiki.inl at 4199b41915071c515fa2c8b89f67d6fc7c2781de ยท Aeva/mollytime

virtual synthesizer. Contribute to Aeva/mollytime development by creating an account on GitHub.

GitHub
I am intending on also scoring them with a separate bouba ranking, which I expect to mostly track as the inverse of kiki, but I think some sounds are both.
one thing critically missing from this data set is the weird percussion the general midi does with channel 10
@aeva
Nuked-SC55 and its forks would be authoritative to Roland's implementation, Yamaha idk. Yamaha has their octaves off by one among other differences but the XG extensions are the "other" common GM target
https://www.vogons.org/viewtopic.php?t=99447
[RELEASE] Nuked-SC55, low-level Roland SC-55 series emulator announcement \ VOGONS

@aeva browsers can do WebMIDI, no? Perfect for a survey.

Edit: sorry, that actually requires a hardware synth: https://developer.mozilla.org/en-US/docs/Web/API/Web_MIDI_API

But there are JS synths AFAICT.

Web MIDI API - Web APIs | MDN

The Web MIDI API connects to and interacts with Musical Instrument Digital Interface (MIDI) Devices.

MDN Web Docs
@floe main problem with doing a broader survey is I'd need to set up a infrastructure for getting the data back to me somehow, I'd need a lot more data, and the setup required of the survey participants makes it somewhat impractical
@aeva Hmmm. I think the setup part could be solved by having the whole thing in the browser, but infrastructure and particularly participant recruitment are definitely an issue... ๐Ÿค”
@aeva Ah, turns out you can embed a Google Form into another webpage, that might (mostly) solve the first issue. https://support.google.com/docs/answer/2839588?hl=en#zippy=%2Cembed-a-form-on-a-website-or-blog
Publish & share your form with responders - Google Docs Editors Help

To create online surveys and quizzes, use Google Forms. You can share your forms with collaborators or responders. Before responders can access your form, you need to publish it. When your form is

@aeva
Musescore has a very fancy soundfont these days which should be free to use. There's also the old https://github.com/lasconic/midiscore with samples for all the classics including the kiki-coded gunshot.
GitHub - lasconic/midiscore: Experiment with MIDI synthesizer in the browser and sheet music coming from MuseScore.com

Experiment with MIDI synthesizer in the browser and sheet music coming from MuseScore.com - lasconic/midiscore

GitHub
@viraptor that might do, or at least as much as anything. what i'm seeking is the most generic, average, general midi synth. so like, you pick up a random midi file, and you plug it into this hypothetical synthesizer and it sounds 51% correct or better at least 51% of the time
@aeva @viraptor I haven't looked at this in a long time, but that sounds like timidity to me.

@aeva to be compliant as a GM instrument, the synthesizer must release currently held notes when the program changes, so this plan will most likely break some existing GM material that relies on changing the patch between two notes to effect "two timbres glued together". So as a direct interface to timbre, the utility of doing a scalar probably isn't there, I do think the mapping could be used inspirationally, since it does have broad groupings - there are a lot of "macro oscillators" that have blending like that, like some of the modes in Plaits.

You might want to also look at MIDI-capable synths that focus on this kind of blended modulation like the Prophet VS.

@aeva one thinks that, and then one ASAN session later, the pain is gone
@lritter python has other plans
@lritter totally figured it out. no fancy tools, just the time honored debugging strat of doing something else for a few hours and then the answer comes to me right as i'm about to go to bed ๐Ÿ˜Ž
@aeva it's the only way to fly

@aeva then you probably recognize this chunk of code now:

https://mastodon.gamedev.place/@lritter/115656377927464801

@lritter yup, wrote my own today
@aeva any differences?

@lritter this is the "make it good later" version I put together yesterday https://github.com/Aeva/mollytime/blob/6926ed4725949b04584ac24647c6c107fcb190c3/src/patch.cpp#L3247

I want to rework it such that it keeps track of the actual age of a lane though, and not use the position relative to the head of the ring buffer as a proxy for age.

mollytime/src/patch.cpp at 6926ed4725949b04584ac24647c6c107fcb190c3 ยท Aeva/mollytime

virtual synthesizer. Contribute to Aeva/mollytime development by creating an account on GitHub.

GitHub
@aeva @lritter this is like walking through the front door of your mind-palace and the butler walks with a tray and says, "telephone, ma'am", and the person on the phone just tells you the answer
@JamesWidman @aeva this kind of shit happens to me all the time. one time on weed i got one of these epiphanies out of nowhere and i was like "HOLD ON. WHO DID THAT?" and then a voice said "never mind me sir, carry on"
@aeva youtube actually recommended this to me before I saw you mention it here, and I had taken a note to boost it later ๐Ÿ˜Š
@aeva this is my first time seeing mollytime and I'm completely sold, this is v cool
@aeva living the dream
@eniko if john mastodon didn't want it this way he would have fixed it before abdicating from the throne
@aeva @eniko it's kinda a weird issue since other clients work fine lol, why does the official web client just give up half way
@dotstdy @eniko that's a good point... i must make the thread even longer!
@aeva I love synths, I wish I knew wtf is happening ๐Ÿพ๐Ÿ’•
@aeva hooting and hollering at "the elderly"