【发布时间】:2020-01-04 18:46:52
【问题描述】:
我正在寻找一种在 Kotlin/Java 中生成和播放声音的方法。我一直在搜索并尝试了不同的解决方案,但并不是很令人满意。 我不是在寻找可以让我将混响添加到现有声音的 Java Control 类,也不是在寻找让我进行 MIDI 排序的 javax.sound.midi 包。相反,我想通过以下方式从头开始构建声音作为声音向量/列表:
fun createSinWaveBuffer(freq: Double, ms: Int, sampleRate: Int = 44100): ByteArray {
val samples = (ms * sampleRate / 1000)
val output = ByteArray(samples)
val period = sampleRate.toDouble() / freq
for (i in output.indices) {
val angle = 2.0 * Math.PI * i.toDouble() / period
output[i] = (Math.sin(angle) * 127f).toByte()
}
//output.forEach { println(it) }
return output
}
然后我想播放声音,并让扬声器的实际输出与发送到函数的输入参数相匹配,包括频率、长度等。当然,创建两个像这样具有不同频率的声音向量应该求和将它们放在一起或至少取平均值应该会导致两个音调同时播放。
这在matlab中很简单,如果你有一个向量y,像这样
t=0:1/samplerate:duration;
y=sin(2*pi*freq*t);
做事
sound(y,sampleRate)
虽然在 Java 中可能没有那么简单或干净的解决方案,但我仍然觉得应该可以播放自定义声音。
在这里和其他地方搜索了一下之后,这是我现在正在尝试的最干净的解决方案之一(即使它使用 sun.audio,其他建议也更加混乱):
import sun.audio.AudioPlayer
import sun.audio.AudioDataStream
import sun.audio.AudioData
private fun playsound(sound: ByteArray) {
val audiodata = AudioData(sound)
val audioStream = AudioDataStream(audiodata)
AudioPlayer.player.start(audioStream)
}
但是 playsound(createSinWaveBuffer(440.0, 10000, 44100)) 在我的扬声器中听起来不正确。听起来波涛汹涌,不是 440 赫兹,不是纯正弦波,也不是十秒。 我错过了什么?
【问题讨论】:
-
如果我对这个 API 的简单搜索有任何好处,那么我认为选择音频播放器不是一个维护良好的选项,它是面向未来的。不过我可能错了。
-
您在寻找桌面解决方案还是 Android 解决方案?
-
不要使用
sun.audio类 - 它们不是官方 API 的一部分,在现代 Java 版本中根本不起作用。查看javax.sound.sampled类。 javasound 标签信息有很多示例链接。 -
一般情况下,不要使用
sun类。 -
@hendrik 一个桌面解决方案。如果它可以用任何标准的 java/kotlin 类来完成,那就太好了(我真的不明白为什么不能,因为它是你可以要求计算机做的最基本的事情之一),但是我猜嵌入式 c/c++ 文件或 .dll 库也可以。
标签: java audio kotlin signal-processing javasound