Skip to content

Commit

Permalink
Adds AudioChannel to KorGE (#2025)
Browse files Browse the repository at this point in the history
  • Loading branch information
soywiz authored Nov 12, 2023
1 parent 860d452 commit 3061e87
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
57 changes: 57 additions & 0 deletions korge/src/common/korlibs/korge/audio/AudioChannel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package korlibs.korge.audio

import korlibs.audio.sound.*
import korlibs.audio.sound.fade.*
import korlibs.datastructure.*
import korlibs.korge.view.*
import korlibs.math.interpolation.*
import korlibs.time.*
import kotlinx.coroutines.*
import kotlin.reflect.*

fun audioChannel(isLocal: Boolean = false): AudioChannel.Provider = if (isLocal) AudioChannel.ProviderLocal else AudioChannel.ProviderGlobal

class AudioChannel(val name: String, val viewsContainer: ViewsContainer, val isLocal: Boolean = false) {
interface Provider {
operator fun getValue(viewsContainer: ViewsContainer, property: KProperty<*>): AudioChannel
}
object ProviderLocal : Provider {
override operator fun getValue(viewsContainer: ViewsContainer, property: KProperty<*>): AudioChannel = viewsContainer.views.extraCache("audio-channel-ref-local-${property.name}") {
AudioChannel(property.name, viewsContainer, isLocal = true)
}
}
object ProviderGlobal : Provider {
override operator fun getValue(viewsContainer: ViewsContainer, property: KProperty<*>): AudioChannel = viewsContainer.views.extraCache("audio-channel-ref-global-${property.name}") {
AudioChannel(property.name, viewsContainer, isLocal = false)
}
}
val views get() = viewsContainer.views
private val channelName = "sound-channel-$name"
internal var channel: SoundChannel?
set(value) {
views.setExtra(channelName, value)
}
get() = views.getExtraTyped(channelName)

fun play(sound: Sound, params: PlaybackParameters = PlaybackParameters.DEFAULT) {
channel?.stop()
channel = sound.play(
when {
isLocal -> (viewsContainer as CoroutineScope?)?.coroutineContext ?: views.views.coroutineContext
else -> views.views.coroutineContext
}, params)
}

fun stop() {
channel?.stop()
channel = null
}

suspend fun fadeIn(time: TimeSpan = DEFAULT_FADE_TIME, easing: Easing = DEFAULT_FADE_EASING) {
channel?.fadeIn(time, easing)
}

suspend fun fadeOut(time: TimeSpan = DEFAULT_FADE_TIME, easing: Easing = DEFAULT_FADE_EASING) {
channel?.fadeOut(time, easing)
}
}
25 changes: 25 additions & 0 deletions korge/test/common/korlibs/korge/audio/AudioChannelTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package korlibs.korge.audio

import korlibs.audio.sound.*
import korlibs.korge.tests.*
import korlibs.korge.view.*
import korlibs.time.*
import kotlin.test.*

class AudioChannelTest : ViewsForTesting() {
val ViewsContainer.musicChannel by audioChannel()

@Test
fun test() = viewsTest {
val soundProvider = LogNativeSoundProvider()
val instance1 = musicChannel
val instance2 = musicChannel
assertSame(instance1, instance2)
val tone = AudioTone.generate(0.1.seconds, 0.0).toSound(soundProvider)
assertNull(instance1.channel)
instance1.play(tone)
assertNotNull(instance2.channel)
instance2.stop()
assertNull(instance1.channel)
}
}

0 comments on commit 3061e87

Please sign in to comment.