musicmaker
Videos
- edit
- /
- history
- /
- upload files
musicmaker
| author | linda303 |
| date | 2023-2026 |
| name | musicmaker.bsp |
[?] MUSICMAKER [_][#][X]
- a work-in-progress proof-of-concept. ^_^
- the idea is to make an in-engine groovebox / music workstation. @_@
- inspired by halfquake's (SoHL) music puzzle & music trackers (esp. protracker).
btw…
- no ai, no angelscript. yes autism! :P
- supports svencoop versions 5.0+. maybe xash? NEED PLAYTESTERS! :(
- .rmf & .jmf are included. DIY! <3
- more crunchiness? enter legowelt. remember to convert! :3
Tags
Rate this map
4.7 / 5 (3 votes)
Reviews
Comments & discussion
Rules:
- Feedback should be constructive.
- For discussion not related to this map, post in the forum.
- If you need help installing maps, please read the installation guide.
There are over 1676 maps for Sven Co-op! Here are a few:
page revision: 537, last edited: 13 Sep 2026 02:04













am i delighted to announce that this actually works: indeed, here is a prototype of an audio step sequencer i have been "soldering" for about a month non-stop. about 1200+ relay entities of the synthesiser (which itself is 3000+ ents) all set a string variable to be copied to the sequencer, which is going to be approximately 700! 800! 900! 1000! more! entities! basically, the sequencer copies the last played sample from the piano synth. yeah, there will be way more features and buttons and whatnot, i just wanted to share my progress on this right away!
https://en.wikipedia.org/wiki/Music_sequencer
in other news… unfortunately, i didnt get any feedback this past month (in this comment section), but i expect you are as excited as i am to see this "map" being fully realised! as you may or may not know, i dont use discord, so i am unaware if anyone is talking about this map at all… yknow, because who uses these web 1.0 forums anyway, amirite? anyway, as always, enjoy and stay tuned - i will add play/stop/reset and tempo controlling buttons (it is at 500ms or 120BPM, cos 60000ms/500ms=120bpm at the moment as a placeholder).
P.S. 64 steps per channel is possible (top-down) but it might actually not fit in the "screen" lol. besides, i wanna keep it legible for low resolutions ^_^
P.P.S. actually, i might reconsider. i could just use the other *walls*… that was actually the original idea of the "room", where every surface is a certain program. but it was too grandiose a mountain at the time. now though… i feel like i can go for 64 channels after i finish the buttons! :P
edit1: all other channels are now working =)
edit2: the "pads" (steps) now allow mouse dragging, like the piano :D
edit3: currently having difficulties trying to actually STOP the sequencer lol (with a button). its either a frame perfect target reset, since all entities create a temporary copy of themselves on delayed triggers, or im just gonna change the message (trigger after action) and m_iszNewValue (source value) of trigger_changevalues, which was pretty smart of me in retrospect, to make it all modular. thanks, past me! :)
edit4: ive finally done the play/stop/reset buttons, oh, and the sequencer no longer autostarts by itself. next up (for me, but also for you, my darlings) is the tempo slider (also known as vari-speed or pitch control, but not to be confused with pitch shifting) with some crazy arithmetics done behind the scenes to round the (fractional) result (but not the actual value) of the division from milliseconds to BPM for a more readable LED output… but first! i gotta add secondary functions for the right mouse button actions on the steps/pads for resetting samples individually. i have to do that for all 64 buttons, yay :D
edit5: alright, the tempo button is here, but for some reason the numeric display doesnt update. could be because im working with floating 3 point decimal values… well, its not finished yet, but it should be showing at least something, right? anyway, im trying my best to figure this out! oh, and by the way, DO NOT try decreasing the delay below 0.100, you have been warned! :D
edit6: having some technical difficulties with the division action of trigger_copyvalues… what one must do if two $i (integer) custom keyvalues result in a non-whole value, with decimals? it seems to not work or im doing something wrong… please take a look at the updated map, where the TEMPO button is: i am dividing 60000 by 500, which should be 120, but neither does it show on the display, nor does it via game_texts. idk why…
btw unsigned 8bit samples *are* supposed to sound this crunchy (clippy), i.e. not having enuff headroom :P
https://en.wikipedia.org/wiki/Clipping_(audio)
https://en.wikipedia.org/wiki/Audio_bit_depth#Dynamic_range_and_headroom
dats cos its basically an .iff with a header… just look up 8SVX =)
https://en.wikipedia.org/wiki/Interchange_File_Format
https://en.wikipedia.org/wiki/8SVX
yes, indeed, these crunchy PCMs in the samples folder should work as-is on an amiga. guh :o
but anywayz, svengine doesnt downsample (thx (NOT) fmod-ex), so AFAIK it should sound better in goldsrc/xash3d ^_^
https://en.wikipedia.org/wiki/Downsampling_(signal_processing)
https://developer.valvesoftware.com/wiki/WAV
correct me if im wrong…
P.S. oh, and yes, the piano samples are public domain, because i made them. enjoy! ^_^
P.P.S. sequencer tmrw MAYBE, im getting sidetracked! @_@
edit1: hmm. okay. im gonna focus on optimising the performance today. the per-tick arithmetics sounded like a good temporary solution at the time, but its biting me in the arse right now. time to get those frames back up! brb ^_^
edit2: well that was sort of easy lol. just had to tweak a few spawnflags and trigger delays, making sure theyre not in a race condition (fighting over the same tick) and we're sorted. now musicmaker_new is back to speed, ~1000fps. enjoy! =)
next step (for me, cos im the only one making this, haha…) is to implement sequencing i/o for the other half of the ambient_generics… that'll be about 1200 (one thousand two hundred) MORE entities, yeah. i am DETERMINED to finish this, nothing can stop me now! >:)
edit3: progress going rather slowly these days. all it is that i have to do is literally just rename/route entities and its targets going from 1 to 25, 3 times for each entity, of which there are 1200 in total. basically, soldering… over and over again…
edit4: okay so its been a few weeks. lemme tell u SOMETHING: it works. IT WORKS!!! after over a THOUSAND entities done in one sitting, well, this particular update, making a total of over 3500 entities (3k synth + 500 seq), i managed to make all 64 sequencer steps being fully functional - they successfully copy the variable, a string of the custom $s keyvalue, to other relays to be sequenced… the only thing left to do is to make a "timer" thingie, which will manage the tempo (BPM) and do the infinite cycle (im currently thinking of making another relay do the "loop" while its targets' values are being changed, but idk if it'll work since all delayed entities are essentially a copy of themselves and that copy cannot be changed, hmm… yeah… its gonna take a while…
huh. as a sidenote… TIL that it actually matters WHEN you set this variable for maps that dont have RAD compiled (like my map).
for example, if you use default configs, you most likely have r_dynamic set to 1. when you load in, you get the worst performance, because as far as goldsrc is concerned, all possible texels/lightmaps are fully lit and dynamic. now, if you change this variable on runtime or even in the menu (before loading in), you get a few frames back, but it can be even better. check this out: if you set r_dynamic 0 in your userconfig.cfg or autoexec.cfg or as a launch parametre (with a prepended "+" plus), you will get the best performance possible. as to why? i dont really know. precaching something something…
i was wondering what did i do wrong here (besides not compiling with RAD), because i was getting frame timings as low as 33.3ms, but apparently it was just the dynamic lighting variable (which isnt needed to be enabled in my case). mind boggling! @_@
edit1: no, this isnt me discovering a variable today, no. simply compare the framerate with this cvar on, off and set at init. you will notice that the best fps is with the latter. but yes, this works with all maps… where you dont need a flashlight, that is =)
speaking of flashlights, id like to share a (unrelated) script i made years ago:
the light effect (EF_DIMLIGHT), which btw can be applied to brush entities as a keyvalue effects, is dynamic as long as you hold the key, and when the key is depressed, the effect stays in last position even with the flashlight drained of charge, which is pretty neat. this goes without saying, but lightmaps (affecting entities specifically) are baked-in and arent affected by r_dynamic, those are fixed with a BLACK_HIDDEN tool texture. but anyway, ive lots of these scripts for sven, including TASes of a few maps, though those are very much framerate-perfect, which is near impossible in multiplayer ;)
https://twhl.info/wiki/page/entity_attribute:_entity_effects
edit2: alright so i will have to remove all \newlines in game_texts, because trigger_save corrupts .save data, according to svenwiki & svenmanor. so all texts are gonna be one-liners… ill try to think of something. you probably dont care about this anyway…
this is it. brainstorming time.
to get to the sequencing part, first i need to figure out how to make dynamic effects apply ONLY to the last key pressed. currently, the piano/synth is just polyphonic, meaning it can already play multiple sounds at the same time (thanks goldsrc), BUT it CANNOT play simultaneously two or more patches/voices with different effects (monotimbrality).
https://en.wikipedia.org/wiki/Polyphony
https://en.wikipedia.org/wiki/Timbrality
"All multitimbral instruments are polyphonic, but not all polyphonic instruments are multitimbral."
so i came up (it was unironically revealed to me in a dream) with a little scheme and this is subject to change:
INDEPENDENT SFX
…
trigger_cameratarget -> multi_manager
1. trigger_changevalue (0s) = $i_boolean_var (int; 0) -> trigger_relay
2. trigger_changevalue (0.001s) = $i_boolean_var (int; 1) -> trigger_relay
3. trigger_relay (0s) -> ambient_generic
…
(it looks better on paper)
it involves setting a boolean to some sort of an "entity-in-the-middle", a "relay", which should also have a "delay before trigger" keyvalue (for timings/delays), but i doubt it works. it all heavily relies on setting custom keyvalues, that not all entities may support (in svengine)… well, there is only one way to find out! if this works, this will be perhaps the most overengineered goldsrc map ever, dare i say… ^_^
https://www.svenmanor.com/entity-guide/custom_keyvalues
after this spaghetti i/o, which i have to do for every ambient_generic (over a 100, so about 200 MORE ents in total with the rest of the logic ents, which will definitely halve the framerate, RIP listenservers…), all signals (keystrokes) will feed to the step sequencer, which is going to have 16 steps with 4 channels (16*4=64 more buttons). IF it wont be laggy, i am making a tracker out of it with even more steps. the many trigger_conditions will check for the true cases (booleans) and finally… sequence a step. oh and a second trigger_condition (again, for each and every sound/voice) is for the aforementioned independent effects. @_@
but then it gets even more ambitious - a sequencer typically has controls for the tempo, so i need to also implement quantisation of all the steps - rounding them a certain amount of times and at a certain timing (and one should be able to toggle this off). this is where the previously mentioned "delay before trigger" comes in. and… yeah. i KNOW this is possible, but its just… so tedious!
https://en.wikipedia.org/wiki/Quantization_(music)
so i would need some kind of a… timer? a really precise one at that, down to the thousandth of a second. then it will use a trigger_copyvalue to copy the time a sound was played, round it with the other steps and voila. this is just a note to my future self :P
ANYWAY, this will take me months! so, whoever reads this, i hope you are doing well! <3
P.S. cant believe that before this, having been inspired by halfquake's music puzzle, i thought that the only way to do this is via moving func_pushables on func_trains through trigger_multiples… which is only possible in spirit of half life engine, because it has a garrys-mod-esque parenting system for entities. anyway, yeah, but no, i actually do have a few prototype maps i made years ago, trying to achieve the same in svengine. it takes a really long time to plan this out and also find motivation… but no matter, i can and will do this!!!
edit1: some POGress: today im starting to work on the 16-step sequencer "application" and im already halfway through… the bad news is that it went from 1000fps down to 100fps! this time its not due to brushwork, but actually to edicts! thats right, entdata is so large, svengine might as well be the only engine this map will work on… hopefully not to anyone's surprise! im sure you all know this is a PoC. if it crashes - it crashes… not much i can do, except maybe separating the example program or increasing entity polling rates… or unless the devs release a 64-bit binary or something? =)
edit2: okay. NOT A BOOLEAN! im gonna store them as unique $s strings for copying later. more entdata, but more flexibility. only one small issue: there are 1500 entities responsible for the setting of the variables. it's stupidly primitive, but still could be too much for the engine to handle. we shall see
edit3: i got carried away… perhaps i will look into multitimbrality in the future, after the sequencer is done.
edit4: hi, future me here. remember when i said it made my frames garbage? well, i fixed it. i explained it somewhere above already…
there is now a way to feed/play built-in .wav audio files (plural!) from /svencoop/sound/* via ambient_generics using a custom *sentences.txt file. for example, you can finally toy around with individual built-in base game sounds, like HEV/VOX audio samples, changing their dynamic effects, including but not limited to, TIME STRETCHING!. this makes BEAT SLICING! possible! BUT WAIT! not only that, but you no longer have to monotonously bulk-rename 88 files every time you want to use custom samples! just put them in the sound/ folder and add a path to them. the catch is you only get 25 in total… ^_^
you can read more about how this works here:
https://twhl.info/wiki/page/sentences.txt
https://wiki.svencoop.com/Mapping/Sentences_Replacement_Guide
you can experiment with sentences.txt either by editing ambient_generics or with speak / spk commands (requires speak_enabled 1):
or here:
https://mfaizsyahmi.github.io/sentences.101
p.s. this was always possible, of course, but this time musicmaker has its own musicmaker_sentences.txt
hey guys, i need someone to test something for me in multiplayer, please ^_^
if you click on the CAMERA button in the menubar, does it trigger every camera that players currently use? if YES, that is NOT supposed to happen, please reply here! but if only the !activator's trigger_camera is affected, then this is expected behaviour and all is well. THANKS! <3
P.S. if you would be so kind to also test this with commandmenu.txt, which requires admin privileges. it targets multi_managers directly, and i wonder if it triggers them globally as well…
WHOOPS!! >_< only after testing trigger_numericdisplays did i notice that game_texts are frame sensitive! right now they are triggered after 10ms, meaning that IF a listenserver (idk about svenDS) is slower than 100 frames per second or >= 10 milliseconds of frame time, it is going to have a wrong output, because, well, per-frame trigger_copyvalue + goldsrc game_text strings + fps_max 100 (which btw ALWAYS adds 0.5 since steampipe 2013) + sys_ticrate 100 + svengine netcode = desynchronisation! for example, HUD-MSG says "9", but its actually "10", or vice versa! so, in the next update (today) they will be (are) delayed up to 100ms, for low-end computers/servers. oh and you get a 4-digit LCD :)
P.S. use cl_showfps 3, stats or frametime (with developer on) to see the TIME between FRAMES - arch enemy of speedrunners and THE reason for failed (mistimed) bunnyhops, when people are NOT using frame RATES exactly divisible by 1000/I, where I is a whole number/integer :P this is just a fun little fact for those who ACTUALLY READ THE MANUAL!!!
https://www.jwchong.com/hl/game.html#frame-rate
https://wiki.sourceruns.org/FPS-Effects.html
setting a custom cursor_sprite for trigger_camera will dump memory into game_text strings XD
i WISH i could attach a picture, but it basically looks like a bunch of fragmentated .spr pieces, looping, if they are animated, where a text character would be xdd
it cannot be undone, it corrupts every other game_text message, but HUD-MSGs can still be read in console
ok… i might need some help with this @_@
how does one make trigger_cameratarget's heal/hurt mouse_action_* work with trigger_copyvalue (?) for increasing/decreasing some other entity's keyvalue? i even tried targetting a trigger_changevalue directly, but it doesnt do any arithmetics, with or without the health actions. seems like only the replace operation works, not add or subtract??? thx in advance ^_^
basically, i wanna make a "slider", e.g. for ambient_generic's lforate keyvalue, where a click or a held mouse event adds/subtracts to it. thats the idea. at the moment, my map has a lot of OR gates, which look like an abacus. these two point entities for each trigger_cameratarget should be able to completely replace the entire spaghetti i/o, right? ^_^
without understanding how this entity works, i cant progress any further, because i cant copy inputs for the sequencer, so this is it, then…
P.S. i also need game_texts to notify of the current values!
edit1: got impatient and figured it out with trigger_conditions myself! see map source files ^_^
edit2: hi, future me here. eventually, i ditched the heal/hurt idea and instead went with simple arithmetics on some custom keyvalues (variables), which you can learn about here:
https://www.svenmanor.com/entity-guide/custom_keyvalues
trigger_cameratarget’s Hurt and Heal mouse actions are not meant to trigger logic entities. They apply damage or healing to the chosen mouse target so they will not make a trigger_changevalue or trigger_copyvalue do arithmetic. Use a mouse action such as Trigger On instead.
The part about Replace working on ambient_generic’s lforate, while Add and Sub do not, is probably not a mistake on your end.
lforate is a keyvalue that belongs specifically to ambient_generic and those do not always support direct arithmetic the same way base or custom keyvalues do.
A workaround worth trying:
Add a custom tracker value to the ambient_generic, for example:
Make a trigger_changevalue for increasing it:
Make a trigger_copyvalue that writes the tracked value back into the real sound key:
Point the camera target’s mouse Trigger On action at that trigger_changevalue.
For decreasing use a second trigger_changevalue with Sub instead of Add.
The math happens on the custom keyvalue first, then the result gets copied into lforate.
You could also try a float tracker such as $f_lforate_tracker with smaller step values although $i_ matches the FGD definition of lforate more directly.
For a more slider-like feel the camera target’s drag-repeat settings may also help. Leaving the Block Drag Repeating Action option at No and adjusting Mouse Digital Action Reset Time should make repeated stepping easier while dragging or holding and moving the mouse.
If the value changes correctly but the sound does not audibly update right away, ambient_generic may need a retrigger or some extra testing around live lforate updates.
hey, thanks for chiming in, mate! i appreciate you
riiight, i knew that, which is why i tried it with a *dummy* func_button first, with its health kv, thinking that this way i could limit the maximum amount of damage actions possible, without relying on a trigger_condition to reset on a value of >= 1000 AND <= -1… it'd have no target, i only needed a dummy entity to do math on. but it didnt work! func_button was triggered instantly with trigger_cameratarget's heal/hurt action, so it was either 1000 health or 0 - i wasnt asking for a boolean! but thats another mystery…
okay, so custom keyvalues. variables, right? um, i also know about this, but then i thought… why would i do that if lforate can be math'd on directly? but then you said:
which would explain a few things, yeah. thanks! i did not think about that. actually, i had a pretty similar setup to yours. i just didnt resort to sven-isms =)
i see that lforate accepts integers, so… do i need to use trigger_copyvalue's integer rounding conversion?
Float-to-string/-int conversion (m_iFloatConversion): 16 (Integer, rounded)?
also, you didnt mention their flags. im using constant with start on and 0 copy-interval kv (every server tick), as well as multiple destinations flag, because im using a *wildcard* in the destination entity/key field (s_*). is that all i need, or is that expensive to the netcode, considering that im gonna do it about ~20 more times with 88 targets each..?
anyway, i tested it and it works! thanks. BUT!!! i have one more question. i also wanna be able to do the same to game_texts, appending to the end of their strings AND replacing the number. for example, "ambient_generic's lforate is N", where N would be the current value of lforate. i heard that it would be very prone to memory leaks. how bad is that, exactly? are we talking in minutes or hours? the furthest i've gotten is game_text literally appending infinitely, adding numbers on top of each other, until it overflows and crashes the game. i am basically once again stuck, because even if that works, i also need some sort of text notification with it, too. im thinking about trigger_numericdisplay, but im curious to hear how does concatenation work with game_texts?
edit1: figured it out using a trigger_condition!
edit2: remember when i said "it updates on every server frame"? yeah, so, that might be a bit harsh on the netcode. im thinking… it should be toggled off after use, right? well, its not as easy as it sounds, when everything is already timed and it's hard to keep track of things when stuff is 3d and not code, who wouldve thought!!! idk. i WILL figure it out! :P
edit3: figured it out. see comments above. cheers
1. "fadein", "fadeout", "spinup" and "spindown" keyvalues are measured in centiseconds (10 milliseconds)
2. "pitch" with "pitchstart" can be converted to cents (pitch interval)
3. sven's .fgd has sawtooth and sinusoid "lfotype" waveform shapes! thats 2 more types to play with! some half life's ambient_generic presets can be finally made smoother, as an actual *wave*, unlike the default square/triangular discontinuous, incremental "steps" ^_^