kaplayjs / kaplay

🦖 A JavaScript/TypeScript Game Library that feels like a game. Make games fast, fun and fanstastic.
https://kaplayjs.com
MIT License
420 stars 31 forks source link

feat: Channels for audio playing #417

Open amyspark-ng opened 4 days ago

amyspark-ng commented 4 days ago

Is your feature request related to a problem? Please describe.

Let's say you'd like to have channels like sfx and music to play them on different volumes, that'd be kinda hard since you'd have to write them from zero (which i've done)

Describe the solution you'd like

Something along the lines of

play({ channel: "sfx" })

This way you can manage different sound volumes

dragoncoder047 commented 2 days ago

This is an interesting idea.

It might be good to implement, but I bet you could already do something like this pretty quickly by connecting it to a common gain node, now that #383 is done

const K = kaplay({global: false})

const sfxChannel = new GainNode(K.audioContext)
sfxChannel.connect(K.audioContext.destination);
const musicChannel = new GainNode(K.audioContext)
musicChannel.connect(K.audioContext.destination);
// and so on

// to use a channel
K.play("foo", { connectTo: sfxChannel });

only problem is that you aren't able to connect the gain nodes to KAPLAY's master node that way... waiting on #400 for that

amyspark-ng commented 2 days ago

Interesting, i managed to do something with creating custom classes and volumes from gamesaves and etc, but seems like a good approach

lajbel commented 1 day ago

This is an interesting idea.

It might be good to implement, but I bet you could already do something like this pretty quickly by connecting it to a common gain node, now that #383 is done

const K = kaplay({global: false})

const sfxChannel = new GainNode(K.audioContext)
sfxChannel.connect(K.audioContext.destination);
const musicChannel = new GainNode(K.audioContext)
musicChannel.connect(K.audioContext.destination);
// and so on

// to use a channel
K.play("foo", { connectTo: sfxChannel });

only problem is that you aren't able to connect the gain nodes to KAPLAY's master node that way... waiting on #400 for that

Can't we do that internally while looking for a good way of give people globals? Something simpler like Amy said, but that internally uses your method

Would be a great PR

amyspark-ng commented 1 day ago
class AudioChannel {
    muted: boolean,
    volume: number,
}

function playAudio(opts: audioPlayOpt & { channel: AudioChannel }) {
    play({
        volume: opts.channel.muted ? 0 : opts.channel.volume
    })
}

is what im doing right now, i store this channels in a game save so you can set volumes, is this a good API? im not sure

dragoncoder047 commented 1 day ago
    play({
        volume: opts.channel.muted ? 0 : opts.channel.volume
    })

is what im doing right now, i store this channels in a game save so you can set volumes, is this a good API? im not sure

It'll work for one-off and short sounds, but if you have longer sounds that might have the volume of the channel changed or muted while the sound is playing, it will not update, since the volume attribute of the audioPlay returned is not pointing to the same as the AudioChannel. You could try to jerry rig something with a Proxy but that would probably be too much work.

amyspark-ng commented 1 day ago
const audioPlayObject =play({
   volume: opts.channel.muted ? 0 : opts.channel.volume
   })
return audioPlayerObject

wouldn't this work? you could get the audioPlay object and then modify the pitch

dragoncoder047 commented 1 day ago
return audioPlayerObject

wouldn't this work? you could get the audioPlay object and then modify the pitch

Well, you'd kind of have to do it manually --

const myChannel: AudioChannel = ...;
const player: AudioPlay = playAudio("boom", { channel: myChannel });

// this doesn't update player.volume
myChannel.volume = ...;

// to change the sound mid-play
player.volume = ...;
amyspark-ng commented 1 day ago

well i'd use channels to manage sound effects volume and music volume sepparetely, idk about you, but changing it sepparetely doesn't look so bad