Here are a couple of links to very good synths / sounds from Dr. Pigeon. I used the second tool for an improvised album. Really cool tool.
This broken link made me sad tho: https://radio.haze.cool/public/jungle
I was looking forward to jungle radio
https://vimeo.com/313049496?turnstile=1.bljcR6EBA-gZ8gcx0Id8...
What about the sound is so nice / interesting / soothing that drives you to these lengths? What about it do you like?
I find your whole project really fascinating. I want to do something similar at some point, even though I don’t have the same kind of sound capturing my interest at the moment.
Thanks! I played a lot of FFXIV and idled a bit in between dungeons and often sat at the Aetherytes (teleport / fast travel locations). The ambiance was nice enough that I didn't feel the need to mute the game when tabbed out.
> What about the sound is so nice / interesting / soothing that drives you to these lengths? What about it do you like?
Most of the audio I keep playing (either music or ambiance) is usually unobtrusive. I appreciate less demanding audio because I can focus cognition towards the task at hand, usually work or games. This means I gravitate towards genres without vocals, like EDM, jungle, IDM, etc. I actually used to use a tool to loop music without gaps because the clip would annoy me[1].
For the aetheryte ambiance in particular, it was just low and novel enough to be relaxing, without constantly drawing my attention to it.
> I find your whole project really fascinating. I want to do something similar at some point, even though I don’t have the same kind of sound capturing my interest at the moment.
You could also try recreating my project on a new platform! I've actually recreated this tool as an iOS app because background play on iOS is toxic and changed between iOS versions. [2]
Even if you don't have an earworm it's fun to explore new APIs. I really liked CoreAudio and Web Audio.
[1]: https://github.com/NolanNicholson/Looper [2]: https://github.com/haze/Aetheryte.app
ffxiv plays the whirs at random intervals, pitches, and gain (volume). these are all added to create an illusion of life(?) that make it harder to detect when an asset is repeating. thankfully, ffxiv also provided values that gave the min and max values for each of the random parameters, so it was easy to translate into javascript:
const whirIndex = Math.floor(Math.random() * whirs.length);
const whirPlaybackRate = Math.random() * (1 - 0.794) + 0.794;
whirGainNode.gain.value = Math.random() * (1 - 0.6) + 0.6;
if you've ever built a graph by hand the flow is usually something like: allocate a node, set metadata, and connect. i do the following to setup the hum:
const humSource = audioContext.createBufferSource(); humSource.buffer = await loadSample( audioContext, isSafari ? "assets/hum.wav.opus.aac" : "assets/hum.wav.opus", ); humSource.playbackRate.value = 0.63; humSource.connect(humGainNode); humSource.loop = true; humSource.start(0);
it's actually ok that i connect the node before i set loop, because the node doesn't produce samples until i call start.
the other part of the ceremony is the whir loop. it's not actually a loop using conventional loop control flow. instead of using a while (true) with a random "sleep" in between, i instead use setTimeout to schedule the next whir at a random interval.
function chooseWhir() { const whirSource = audioContext.createBufferSource(); const whirIndex = Math.floor(Math.random() * whirs.length); const whirPlaybackRate = Math.random() * (1 - 0.794) + 0.794; whirGainNode.gain.value = Math.random() * (1 - 0.6) + 0.6; whirSource.buffer = whirs[whirIndex]; whirSource.playbackRate.value = whirPlaybackRate; whirSource.connect(whirGainNode); whirSource.start(0);
whirSource.onended = () => {
whirSource.disconnect(whirGainNode);
const nextWhirDelay = Math.floor(Math.random() \* 2001);
setTimeout(chooseWhir, nextWhirDelay);
};
}
same deal here: create a source node, select a random asset, playback rate (pitch), gain (volume), and connect it to the gain node (which stays constant in this process and only has it's value changed.) the key here is that when the source asset ends, instead of looping, we remove that node from the graph and add a new one (by calling chooseWhir again.) because there is an expected delay before the next whir, i'm ok with adding whatever latency is added by doing the random calculation, it's likely marginal.