Skip to content

Instantly share code, notes, and snippets.

@kyay10
Created December 9, 2023 23:03
Show Gist options
  • Save kyay10/0ef9d00a128bb8fb6c7f3c3cfabd6c3b to your computer and use it in GitHub Desktop.
Save kyay10/0ef9d00a128bb8fb6c7f3c3cfabd6c3b to your computer and use it in GitHub Desktop.
A Kotlin beep function
import kotlinx.coroutines.delay
import java.io.InputStream
import java.nio.ByteBuffer
import javax.sound.sampled.AudioFormat
import javax.sound.sampled.AudioInputStream
import javax.sound.sampled.AudioSystem
import javax.sound.sampled.Clip
import kotlin.math.sin
import kotlin.time.Duration
import kotlin.time.DurationUnit
// Based on https://gist.github.com/jbzdak/61398b8ad795d22724dd
suspend fun beep(freq: Double, duration: Duration) = AudioSystem.getClip().runUsing {
require(format.encoding == AudioFormat.Encoding.PCM_SIGNED) { "Unknown encoding" }
require(format.sampleSizeInBits == 16) { "Weird sample size. Dunno what to do with it." }
val frames = (duration * format.frameRate.toDouble()).toInt(DurationUnit.SECONDS)
val data = buildBytes(frames * format.frameSize / 2) {
val freqFactor = (Math.PI / 2) * freq / format.frameRate
val ampFactor = Short.MAX_VALUE.toDouble()
for (frame in 0 until frames)
putShort((ampFactor * sin(frame * freqFactor)).toInt().toShort())
}
open(data.inputStream(), frames.toLong())
start()
delay(duration)
}
fun Clip.open(inputStream: InputStream, frameCount: Long) = open(AudioInputStream(inputStream, format, frameCount))
inline fun buildBytes(capacity: Int, block: ByteBuffer.() -> Unit): ByteArray =
ByteBuffer.allocate(capacity).apply(block).array()
inline fun <T : AutoCloseable?, R> T.runUsing(block: T.() -> R): R = use(block)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment