java - 如何从已知点产生声音?

标签 java audio

我有 10 个点列表(每个点都是时间振幅对),其中每个列表属于已知频率

所以我有一个类InputValue,其中有两个字段sampleDate(long)和sampleValue(double),以及10个列表 - 列表samples800Hz、samples400Hz等等。

800Hz 列表每秒包含大约 1600 个点(不是固定值,因为数据采样器可能有不可预测的延迟),400Hz 列表每秒包含大约 800 个点,依此类推。

我怎样才能:

  • 从点列表生成声音
  • 将多个或所有列表混合到一种声音中?

如果我做对了,我需要将每个列表重新采样为一个采样率(java soundformat 可以采用自定义采样率,例如 1600,或者我应该使用标准采样率,最低为 8000?),然后填充样本缓冲区,例如

AudioFormat af = new AudioFormat( (float )1600, 8, 1, true, false );
SourceDataLine sdl = AudioSystem.getSourceDataLine( af );
sdl.open();
sdl.start();
for( int i = 0; i < 1600; i++ ) {
    buf[ 0 ] = ???
    sdl.write( buf, 0, 1 );
}
sdl.drain();
sdl.stop();

但是我如何告诉 sdl 我的振幅值属于​​某个频率?我怎样才能混合不同的频率?

顺便说一句,我可以不重新采样每个列表,而是创建 10 种具有不同采样率的音频格式(800Hz 为 1600,400Hz 为 800 等等),然后将 10 个 sdls 混合在一起吗?

最佳答案

听起来您正在尝试使用波表来生成声音。如果您只是简单地重新创建 800 Hz 音调,这很简单:

static int sample = 0;
for (int i = 0; i < 1600; i++) {
    buf[i] = samples800Hz[sample];
    sample = (sample + 1) % SAMPLES_800HZ_SIZE; 
}

假设您想要组合 800 Hz 和 1600 Hz 音调...只需将其添加在一起(您可能必须混合这些值,这样它们就不会削波):

static int sample1 = 0, sample2 = 0;
for (int i = 0; i < 1600; i++) {
    // Multiply each sample by 0.5; this gives us a 50% mix between the two
    buf[i] = (samples800Hz[sample1] * 0.5) + (samples1600Hz[sample2] * 0.5);
    sample1 = (sample1 + 1) % SAMPLES_800HZ_SIZE; 
    sample2 = (sample2 + 1) % SAMPLES_1600HZ_SIZE; 
}

现在我的答案不考虑您的系统运行回调的次数/帧数。你必须自己解决这个问题。另外,如果您想要生成多个音调而不是无休止地制作列表,我建议您查找波表振荡器。波表基本上是创建一个音调数组,然后调整您读取表的速度/相位以生成所需的频率。

祝你好运!

关于java - 如何从已知点产生声音?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45100012/

相关文章:

java - Hibernate 多个异常

c - 为什么 OpenMP 会搞乱这个 for 循环?

ios - 在 iOS 上播放多种声音会产生变形金刚般的噪音

javascript - Firefox 53.0.2 上的 MediaRecorder 不支持录音

java - 用Java播放音频

java - PreparedStatement.setTimestamp 没有将时间戳插入数据库

java - Android中面临DateFormat问题,CDT转换为IST

python - 如何在python中编写多声道wav文件

java - 如何在selenium中关闭Web驱动程序之前验证文件下载是否完成?

java - 无限滚动问题,向下滚动且 api 调用函数有效且列表位置转到第一项