kira icon indicating copy to clipboard operation
kira copied to clipboard

Please cap how loud sounds can be

Open melody-rs opened this issue 7 months ago • 6 comments

messing around with volume calculations shouldn't hurt my ears this much

https://github.com/user-attachments/assets/f6619396-c245-4efa-9cf3-627c850a7556

melody-rs avatar Apr 08 '25 06:04 melody-rs

Can you show what the code is that caused this?

It's important that sounds can be played with positive gain, since some sounds are quiet and need to be louder, but I agree that what you posted here is not a desirable result.

tesselode avatar Apr 09 '25 07:04 tesselode

I was trying to replicate the code from https://github.com/mkxp-z/mkxp-z/pull/208/files#diff-3216992fdc41349399a23a9468d6e272ba8382e89f63d2beebd0d477b468372eR174-R200 and wrote this function to convert RPG Maker's 0-100 volume scale to kira::Decibels

    fn volume_to_db(&self) -> kira::Decibels {
        let amplitude = self.volume.map(|v| v as f32 / 100.0).unwrap_or(1.0);
        10.0_f2.powf(-(34.0 / 20.0) * (1.0 - amplitude) * 100.0).into()
    }

I realized I needed to use the inverse to actually do this properly, so I used amplitude.log10() * 4.0 / 7.0 + 1.0 instead. It's still too loud though and changing the amplitude has a minimal effect on the volume

melody-rs avatar Apr 12 '25 00:04 melody-rs

Not sure if my test is relevant / my code exempt of bug, but here's what I noticed lately when increasing volume above amplitude 1.0 (single streaming sound playing).

See it on Youtube (file too big to be uploaded here).

Roms1383 avatar Apr 19 '25 04:04 Roms1383

@melody-rs I don't think your code is right for converting amplitude to decibels. Here's my test code using your equation:

fn main() -> Result<(), Box<dyn Error>> {
	for i in (0..=100).step_by(10) {
		let volume = i as f32;
		println!("{} -> {:?}", volume, volume_to_db(volume));
	}

	Ok(())
}

fn volume_to_db(volume: f32) -> kira::Decibels {
	let amplitude = volume / 100.0;
	(amplitude.log10() * 4.0 / 7.0 + 1.0).into()
}

And here's the result I get:

0 -> Decibels(-inf)
10 -> Decibels(0.4285714)
20 -> Decibels(0.60058856)
30 -> Decibels(0.70121217)
40 -> Decibels(0.7726057)
50 -> Decibels(0.82798284)
60 -> Decibels(0.87322927)
70 -> Decibels(0.9114846)
80 -> Decibels(0.9446229)
90 -> Decibels(0.9738529)
100 -> Decibels(1.0)

As you go from an RPG Maker volume of 0-100, decibels should go from Decibels::SILENCE (-60dB) to Decibels::IDENTITY (0dB).

This site lists the correct conversion from amplitude to decibels:

dB = 20 * log10(amplitude)

This is for a 0.0-1.0 amplitude, so you should scale it beforehand for 0-100.

If you just want a perceptually linear ramp from silence to full volume, just do a linear interpolation from -60dB to 0dB with a factor of volume / 100.

tesselode avatar Apr 21 '25 06:04 tesselode

@Roms1383 if you play a sound too loud, it's going to get crunchy. That's just how digital audio works.

tesselode avatar Apr 21 '25 06:04 tesselode

@tesselode thanks for your reply, it makes perfect sense as far as I'm concerned. the feeling that louder sounds had a better outcome in prior versions might utterly be a false memory of mine.

Roms1383 avatar Apr 22 '25 07:04 Roms1383