From dd7065d94c4d5d3282a37a631584ee0fc38b0e87 Mon Sep 17 00:00:00 2001 From: soywiz Date: Mon, 3 Jul 2023 10:07:00 +0200 Subject: [PATCH 1/5] Fixes volume in music --- korau/src/commonMain/kotlin/korlibs/audio/sound/AudioData.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioData.kt b/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioData.kt index 43de3c17d5..d7e3b5201d 100644 --- a/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioData.kt +++ b/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioData.kt @@ -109,8 +109,7 @@ class AudioDataStream(val data: AudioData) : AudioStream(data.rate, data.channel override suspend fun clone(): AudioStream = AudioDataStream(data) } - -suspend fun AudioData.toSound(): Sound = nativeSoundProvider.createSound(this) +suspend fun AudioData.toSound(soundProvider: NativeSoundProvider = nativeSoundProvider): Sound = soundProvider.createSound(this) suspend fun VfsFile.readAudioData(formats: AudioFormat = defaultAudioFormats, props: AudioDecodingProps = AudioDecodingProps.DEFAULT): AudioData = this.openUse { formats.decode(this, props) ?: invalidOp("Can't decode audio file ${this@readAudioData}") } From 9d721cfe2bb1854336d2b383f79bc41c88beaac9 Mon Sep 17 00:00:00 2001 From: soywiz Date: Mon, 3 Jul 2023 10:07:14 +0200 Subject: [PATCH 2/5] Fixes volume in music --- .../commonMain/kotlin/korlibs/audio/sound/SoundAudioStream.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/korau/src/commonMain/kotlin/korlibs/audio/sound/SoundAudioStream.kt b/korau/src/commonMain/kotlin/korlibs/audio/sound/SoundAudioStream.kt index 46922e44a0..b7988956b7 100644 --- a/korau/src/commonMain/kotlin/korlibs/audio/sound/SoundAudioStream.kt +++ b/korau/src/commonMain/kotlin/korlibs/audio/sound/SoundAudioStream.kt @@ -38,7 +38,7 @@ class SoundAudioStream( @OptIn(ExperimentalStdlibApi::class) override fun play(coroutineContext: CoroutineContext, params: PlaybackParameters): SoundChannel { val nas: PlatformAudioOutput = soundProvider.createPlatformAudioOutput(coroutineContext, stream.rate) - nas.copySoundPropsFrom(params) + nas.copySoundPropsFromCombined(params, this) var playing = true var paused = false var newStream: AudioStream? = null From dec50709486b2426e9b33e5f3d1d76a6e9a87067 Mon Sep 17 00:00:00 2001 From: soywiz Date: Mon, 3 Jul 2023 10:07:25 +0200 Subject: [PATCH 3/5] Some improvements --- .../commonMain/kotlin/korlibs/audio/sound/AudioChannel.kt | 4 +++- korge-sandbox/src/commonMain/kotlin/Main.kt | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioChannel.kt b/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioChannel.kt index 20d6e60c41..054ade8e1a 100644 --- a/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioChannel.kt +++ b/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioChannel.kt @@ -5,7 +5,9 @@ import korlibs.time.seconds import kotlin.coroutines.CoroutineContext import kotlin.coroutines.coroutineContext -class AudioChannel { +class AudioChannel( + val nativeSoundProvider: NativeSoundProvider = korlibs.audio.sound.nativeSoundProvider +) { private var channel: SoundChannel? = null val state get() = channel?.state ?: SoundChannelState.INITIAL diff --git a/korge-sandbox/src/commonMain/kotlin/Main.kt b/korge-sandbox/src/commonMain/kotlin/Main.kt index 3bfa636572..8fa1d19063 100644 --- a/korge-sandbox/src/commonMain/kotlin/Main.kt +++ b/korge-sandbox/src/commonMain/kotlin/Main.kt @@ -1,4 +1,5 @@ +import korlibs.audio.sound.* import korlibs.event.* import korlibs.image.color.* import korlibs.image.font.* @@ -73,7 +74,12 @@ suspend fun main() = Korge( debug = false, forceRenderEveryFrame = false ) { - //return@Korge + val music = resourcesVfs["sounds/Snowland.mp3"].readMusic() +// val music = resourcesVfs["audio/music/${setup.resource}"].readSound() + music.volume = 0.1 + music.play(infinitePlaybackTimes) + + return@Korge //sceneContainer().changeTo({MainSprites10k()}); return@start //sceneContainer().changeTo({MainGraphicsText()}); return@start //sceneContainer().changeTo({MainUI()}); return@start From eda0317471fe14e2978a4d04d25a59ef80b6d1bc Mon Sep 17 00:00:00 2001 From: soywiz Date: Mon, 3 Jul 2023 10:29:33 +0200 Subject: [PATCH 4/5] Add tests ensuring it is fixed --- .../korlibs/audio/sound/AudioSamples.kt | 16 +++++++++- .../kotlin/korlibs/audio/sound/Sound.kt | 6 ++-- .../NativeSoundProviderTest.kt | 31 +++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 korau/src/commonTest/kotlin/korlibs.audio.sound/NativeSoundProviderTest.kt diff --git a/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioSamples.kt b/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioSamples.kt index 1c2f207ab1..23f4a6d072 100644 --- a/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioSamples.kt +++ b/korau/src/commonMain/kotlin/korlibs/audio/sound/AudioSamples.kt @@ -1,12 +1,12 @@ package korlibs.audio.sound -import korlibs.datastructure.iterators.fastForEach import korlibs.memory.FastShortTransfer import korlibs.memory.arraycopy import korlibs.memory.arrayinterleave import korlibs.memory.clamp01 import korlibs.audio.internal.SampleConvert import korlibs.audio.internal.coerceToShort +import korlibs.datastructure.iterators.* import korlibs.io.lang.assert import kotlin.math.absoluteValue import kotlin.math.max @@ -104,6 +104,7 @@ class AudioSamples(override val channels: Int, override val totalSamples: Int, v } fun scaleVolume(scale: Double): AudioSamples = scaleVolume(scale.toFloat()) + fun scaleVolume(channelScales: DoubleArray): AudioSamples = scaleVolume(FloatArray(channelScales.size) { channelScales[it].toFloat() }) fun scaleVolume(scale: Float): AudioSamples { data.fastForEach { channel -> @@ -113,6 +114,14 @@ class AudioSamples(override val channels: Int, override val totalSamples: Int, v } return this } + fun scaleVolume(channelScales: FloatArray): AudioSamples { + data.fastForEachWithIndex { ch, channel -> + for (n in channel.indices) { + channel[n] = (channel[n] * channelScales[ch]).toInt().coerceToShort() + } + } + return this + } fun setTo(that: AudioSamples): AudioSamples { that.copyTo(this) @@ -125,6 +134,11 @@ class AudioSamples(override val channels: Int, override val totalSamples: Int, v } } + fun clone(out: AudioSamples = AudioSamples(channels, totalSamples, Array(data.size) { ShortArray(data[0].size) })) : AudioSamples { + this.copyTo(out) + return out + } + override fun hashCode(): Int = channels + totalSamples * 32 + data.contentDeepHashCode() * 64 override fun equals(other: Any?): Boolean = (other is AudioSamples) && this.channels == other.channels && this.totalSamples == other.totalSamples && this.data.contentDeepEquals(other.data) diff --git a/korau/src/commonMain/kotlin/korlibs/audio/sound/Sound.kt b/korau/src/commonMain/kotlin/korlibs/audio/sound/Sound.kt index e2976383b6..5ebe5121e5 100644 --- a/korau/src/commonMain/kotlin/korlibs/audio/sound/Sound.kt +++ b/korau/src/commonMain/kotlin/korlibs/audio/sound/Sound.kt @@ -123,9 +123,11 @@ open class LogNativeSoundProvider : NativeSoundProvider() { ) : PlatformAudioOutput(coroutineContext, frequency) { val data = AudioSamplesDeque(2) override suspend fun add(samples: AudioSamples, offset: Int, size: Int) { - val addInfo = AddInfo(samples, offset, size) + val out = samples.clone() + out.scaleVolume(volume) + val addInfo = AddInfo(out, offset, size) onBeforeAdd(addInfo) - data.write(samples, offset, size) + data.write(out, offset, size) onAfterAdd(addInfo) } fun consumeToData(): AudioData = data.consumeToData(frequency) diff --git a/korau/src/commonTest/kotlin/korlibs.audio.sound/NativeSoundProviderTest.kt b/korau/src/commonTest/kotlin/korlibs.audio.sound/NativeSoundProviderTest.kt new file mode 100644 index 0000000000..5187174b69 --- /dev/null +++ b/korau/src/commonTest/kotlin/korlibs.audio.sound/NativeSoundProviderTest.kt @@ -0,0 +1,31 @@ +package korlibs.audio.sound + +import korlibs.io.async.* +import korlibs.io.file.std.* +import kotlin.test.* + +class NativeSoundProviderTest { + class DequeNativeSoundProvider : LogNativeSoundProvider() { + } + + @Test + fun test() = suspendTest { + val values = listOf(null, 1.0, 0.1).map { volume -> + val nativeSoundProvider = DequeNativeSoundProvider() + val sound = nativeSoundProvider + .createSound(resourcesVfs["wav8bit.wav"], streaming = true) + .also { if (volume != null) it.volume = volume } + sound.playAndWait() + val data = nativeSoundProvider.streams.first().data + (0 until 10).map { data.read(0).toInt() } + } + assertEquals( + listOf( + listOf(0, 1020, 2295, 3315, 4335, 5610, 6630, 7650, 8670, 9690), + listOf(0, 1020, 2295, 3315, 4335, 5610, 6630, 7650, 8670, 9690), + listOf(0, 102, 229, 331, 433, 561, 663, 765, 867, 969), + ), + values + ) + } +} From 775b6cf15942af258c26c9a3159bdd533a4c57d6 Mon Sep 17 00:00:00 2001 From: soywiz Date: Mon, 3 Jul 2023 10:30:25 +0200 Subject: [PATCH 5/5] Remove sampel code --- korge-sandbox/src/commonMain/kotlin/Main.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/korge-sandbox/src/commonMain/kotlin/Main.kt b/korge-sandbox/src/commonMain/kotlin/Main.kt index 8fa1d19063..b061ca64dc 100644 --- a/korge-sandbox/src/commonMain/kotlin/Main.kt +++ b/korge-sandbox/src/commonMain/kotlin/Main.kt @@ -74,12 +74,6 @@ suspend fun main() = Korge( debug = false, forceRenderEveryFrame = false ) { - val music = resourcesVfs["sounds/Snowland.mp3"].readMusic() -// val music = resourcesVfs["audio/music/${setup.resource}"].readSound() - music.volume = 0.1 - music.play(infinitePlaybackTimes) - - return@Korge //sceneContainer().changeTo({MainSprites10k()}); return@start //sceneContainer().changeTo({MainGraphicsText()}); return@start //sceneContainer().changeTo({MainUI()}); return@start