From 1bc2d9bfb6402806631bad9d1c9152da03ab0cf8 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Wed, 13 Dec 2023 06:56:20 +0800 Subject: [PATCH] Fix bugs --- audio-sources/build.gradle.kts | 1 + .../audiosources/impl/FileAudioSource.kt | 41 +++++++++---------- .../com/eimsound/daw/impl/PlayPositionImpl.kt | 13 +++--- .../daw/impl/clips/audio/AudioClipImpl.kt | 2 +- .../daw/window/panels/FileSystemBrowser.kt | 12 +++++- 5 files changed, 39 insertions(+), 30 deletions(-) diff --git a/audio-sources/build.gradle.kts b/audio-sources/build.gradle.kts index ba961bad..f46bf2fe 100644 --- a/audio-sources/build.gradle.kts +++ b/audio-sources/build.gradle.kts @@ -14,6 +14,7 @@ kotlin { sourceSets { named("commonMain") { dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${extra["eim.dependencies.kotlinx.coroutines"]}") implementation("be.tarsos.dsp:core:${extra["eim.dependencies.tarsos"]}") implementation("com.googlecode.soundlibs:mp3spi:1.9.5.4") { exclude("com.googlecode.soundlibs", "tritonus_share") diff --git a/audio-sources/src/commonMain/kotlin/com/eimsound/audiosources/impl/FileAudioSource.kt b/audio-sources/src/commonMain/kotlin/com/eimsound/audiosources/impl/FileAudioSource.kt index 5c914165..e3201f13 100644 --- a/audio-sources/src/commonMain/kotlin/com/eimsound/audiosources/impl/FileAudioSource.kt +++ b/audio-sources/src/commonMain/kotlin/com/eimsound/audiosources/impl/FileAudioSource.kt @@ -37,7 +37,7 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { override var length = 0L private set override val isClosed get() = stream == null - override val isRandomAccessible get() = isWav || isFlac + override val isRandomAccessible get() = stream?.markSupported() == true || isFlac private var _position = 0L override var position: Long get() = _position @@ -46,8 +46,11 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { _position = value.coerceIn(0, length - 1) if (isFlac) { - flacDecoder?.seek(_position) + flacDecoder?.let { synchronized(it) { it.seek(_position) } } buffer.empty() + } else if (isWav) { + stream?.reset() + stream?.skip(_position * frameSize) } } @@ -58,18 +61,11 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { private var flacDecoder: FLACDecoder? = null private var pcmData: ByteData? = null private var tempBuffer: ByteArray? = null + private var isFloatData = false private lateinit var buffer: RingBuffer init { run { -// AudioSourceManager.instance.fileSourcesCache[file]?.get()?.let { -// memoryAudioSource = it -// sampleRate = it.sampleRate -// channels = it.channels -// length = it.length -// return@run -// } - val randomStream = JFlacRandomFileInputStream(file.toFile()) var format = AudioSystem.getAudioFileFormat(randomStream) if (format is MpegAudioFileFormat) { @@ -86,13 +82,17 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { isFlac = format.type == FlacFileFormatType.FLAC sampleRate = format.format.sampleRate channels = format.format.channels - if (channels < 0 || length < 0) throw UnsupportedOperationException("Unsupported file!") + if (channels < 0 || length < 0) throw UnsupportedOperationException("Unsupported format: $format") frameSize = channels * (bits / 8) newFormat = AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sampleRate, bits, channels, frameSize, sampleRate, false) + isFloatData = format.format.encoding == AudioFormat.Encoding.PCM_FLOAT if (isWav) { - stream = AudioSystem.getAudioInputStream(randomStream).apply { mark(0) } + val s = AudioSystem.getAudioInputStream(randomStream).apply { mark(0) } + stream = if (format.format.encoding != AudioFormat.Encoding.PCM_SIGNED) { + AudioSystem.getAudioInputStream(newFormat, s) ?: throw UnsupportedOperationException("Unsupported format: $format") + } else s } else if (isFlac) { stream = randomStream buffer = RingBuffer() @@ -105,12 +105,6 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { throw UnsupportedOperationException(e) } } - -// if (readAll) { -// isFirstTimeToClose = true -// memoryAudioSource = AudioSourceManager.instance.createMemorySource(this) -// AudioSourceManager.instance.fileSourcesCache[file] = WeakReference(memoryAudioSource!!) -// } } } @@ -135,8 +129,11 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { var thisLen = len2 if (thisLen > buffer.available) thisLen = buffer.available if (thisLen < frameSize) { - val frame = d.readNextFrame() ?: break - val data = d.decodeFrame(frame, pcmData) + val data = synchronized(d) { + val frame = d.readNextFrame() + if (frame == null) null + else d.decodeFrame(frame, pcmData) + } ?: break pcmData = data buffer.resize(data.len * 2) buffer.put(data.data, 0, data.len) @@ -156,7 +153,9 @@ class DefaultFileAudioSource(override val file: Path) : FileAudioSource { } override fun nextBlock(buffers: Array, length: Int, offset: Int): Int { - val sampleCount = length.coerceAtMost(buffers.firstOrNull()?.size ?: 0) + var sampleCount = length.coerceAtMost(buffers.firstOrNull()?.size ?: 0) + if (_position > this.length) return 0 + else if (_position + sampleCount > this.length) sampleCount = (this.length - _position).toInt() // read into temporary byte buffer var byteBufferSize = sampleCount * frameSize var lTempBuffer = tempBuffer diff --git a/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/PlayPositionImpl.kt b/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/PlayPositionImpl.kt index 2c2ba23c..656ffc4b 100644 --- a/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/PlayPositionImpl.kt +++ b/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/PlayPositionImpl.kt @@ -79,16 +79,17 @@ class PlayPositionImpl( private var lastTime = 0 private fun checkTimeInPPQ() { - if (_timeInPPQ !in projectRange) if (isProjectLooping) { - _timeInPPQ = projectRange.first - } else { - isPlaying = false - _timeInPPQ = projectRange.last - } if (timeToPause > 0) { if (_timeInPPQ > lastTime && timeToPause > 0) timeToPause -= bufferSize if (timeToPause <= 0) _isPlaying = false lastTime = _timeInPPQ + } else if (_timeInPPQ !in projectRange) { + if (isProjectLooping) { + _timeInPPQ = projectRange.first + } else { + isPlaying = false + _timeInPPQ = projectRange.last + } } } } \ No newline at end of file diff --git a/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/clips/audio/AudioClipImpl.kt b/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/clips/audio/AudioClipImpl.kt index 9eb956d1..f7cd6933 100644 --- a/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/clips/audio/AudioClipImpl.kt +++ b/daw/src/jvmMain/kotlin/com/eimsound/daw/impl/clips/audio/AudioClipImpl.kt @@ -131,7 +131,7 @@ class AudioClipImpl( override fun fromJson(json: JsonElement) { super.fromJson(json) json as JsonObject - json["file"]?.let { target = AudioSourceManager.createFileAudioSource(Path(it.asString())) } + json["file"]?.let { target = AudioSourceManager.createCachedFileSource(Path(it.asString())) } json["volumeEnvelope"]?.let { volumeEnvelope.fromJson(it) } json["bpm"]?.let { bpm = it.asFloat() } json["timeStretcher"]?.let { diff --git a/daw/src/jvmMain/kotlin/com/eimsound/daw/window/panels/FileSystemBrowser.kt b/daw/src/jvmMain/kotlin/com/eimsound/daw/window/panels/FileSystemBrowser.kt index e5fdd6de..f834e15e 100644 --- a/daw/src/jvmMain/kotlin/com/eimsound/daw/window/panels/FileSystemBrowser.kt +++ b/daw/src/jvmMain/kotlin/com/eimsound/daw/window/panels/FileSystemBrowser.kt @@ -159,12 +159,20 @@ object FileSystemBrowser : Panel { val interactionSource = remember { MutableInteractionSource() } Box(Modifier.padding(horizontal = 4.dp), content = c) Box(Modifier.fillMaxSize() - .draggable(draggableState, Orientation.Horizontal, interactionSource = interactionSource) + .draggable( + draggableState, Orientation.Horizontal, interactionSource = interactionSource, + onDragStopped = { + fileBrowserPreviewer.position.isPlaying = true + } + ) .pointerInput(Unit) { detectTapGestures({ fileBrowserPreviewer.position.isProjectLooping = !fileBrowserPreviewer.position.isProjectLooping - }) { fileBrowserPreviewer.playPosition = it.x / width[0].toDouble() } + }) { + fileBrowserPreviewer.playPosition = it.x / width[0].toDouble() + fileBrowserPreviewer.position.isPlaying = true + } } .pointerHoverIcon(PointerIcon.HorizontalResize) ) {