java - 我正在尝试使用 java 的声音 API 获取 wav 文件的音量级别,但无法弄清楚

标签 java wav audio-streaming audio

我将处理大量音频文件,我不需要播放这些文件,但我希望能够定期(例如每秒)获取音量级别,这样我就可以粗略地绘制整个文件的总体音量水平。我已经使用 java Sound API 来读取文件的帧,但我不确定如何解释它们(我不确定如何处理小端以及将帧分成两个 channel ),我尝试将 AudioInputStream 发送到 SourceDataLine,并每秒在数据线上调用 getLevel(),但它总是返回 0。

最佳答案

如果您已签名 PCM,则从字节解码的值将具有 Java 短整数范围(-32768 到 32767)。然而,声波的本质是来回扫描,因此在任何单帧中,该值几乎可以在任何地方,因此与您听到的音量​​没有特别好的相关性。

所以,我怀疑您将不得不查看许多样本并进行某种总体分析。也许将所有与 0 的偏差作为绝对值相加,然后除以帧数?需要多少帧?好吧,如果我们想要包含以 50 cps 循环的低音声波,并且想要确保包含整个周期,则相当于一整秒帧的 1/50。如果采样率为 44100fps,则为 8805 帧!但也许使用这个滚动平均值会扭曲其他附近频率值的贡献?

请注意,我主要是自学成才,因此可能有更好的方法来做到这一点。

下面是我用来将小端轨道的帧转换为 -1 和 1 之间的 float (呃,0.999...)的代码行,其中 buffer 是一个字节数组:

float audioVal  = (float)( ( ( buffer[i+1] << 8 )   
    | ( buffer[i] & 0xff ) ) / 32768.0 ); 

如果您进行搜索,您会发现 Stack Overflow 上还有其他具有类似转换的帖子。 MSB 被移动并保留其符号。 LSB 使用 ff 十六进制进行 &'d,以确保“符号位”被解释为数值的一部分。 MSB 和 LSB 一起并除以最大可能的短整型值以“标准化”范围。我认为小端 16 位编码的帧的四个字节的顺序如下:b[0] = 左 LSB,b[1] = 左 MSB,b[2] = 右 LSB,b[3] = 右MSB。我不记得在哪里看到过这个官方定义或发布的。左右互换就尴尬了!

在找到移动平均线之前,您可能需要进行 ABS。也许可以将 ABS 内置到转换中以节省几个 CPU。

关于java - 我正在尝试使用 java 的声音 API 获取 wav 文件的音量级别,但无法弄清楚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4953045/

相关文章:

node.js - 记录传入的音频流 Node js

java - 如何从多个整数的输入中选择一个整数?

java - hive 计数 * 内存不足

java - 是否可以从 JCuda 将数据发送到定义为 Union 的 GPU 内存?

java - 基于命令(语音)识别的项目

python - 在 Django 中,用户可以将文件上传到服务器,然后移动到 Amazon S3 吗?

swift - 在 Swift 中连接两个音频文件并播放它们

android - 如何从Android中的资源目录播放音频文件

webrtc - 通过 WebRTC 切入和切出流媒体音乐

java gui 空指针异常