我正在尝试从 C# 中的实时音频中确定“每分钟节拍数”。不过,我检测到的不是音乐,只是持续不断的敲击声。我的问题是确定这些抽头之间的时间,因此我可以确定“每分钟抽头”我曾尝试使用 WaveIn.cs 类,但我并不真正了解它的采样方式。我一秒钟没有得到一定数量的样本来分析。我想我真的只是不知道如何在一秒钟内读取确切数量的样本来了解样本之间的时间。
任何帮助我朝着正确的方向前进将不胜感激。
我正在尝试从 C# 中的实时音频中确定“每分钟节拍数”。不过,我检测到的不是音乐,只是持续不断的敲击声。我的问题是确定这些抽头之间的时间,因此我可以确定“每分钟抽头”我曾尝试使用 WaveIn.cs 类,但我并不真正了解它的采样方式。我一秒钟没有得到一定数量的样本来分析。我想我真的只是不知道如何在一秒钟内读取确切数量的样本来了解样本之间的时间。
任何帮助我朝着正确的方向前进将不胜感激。
我不确定您使用的是哪个 WaveIn.cs 类,但通常使用录制音频的代码,您要么 A) 告诉代码开始录制,然后在稍后的某个时间告诉代码停止,然后你会得到返回一个包含在此时间段内记录的数据的数组(通常是 short[] 类型);或 B)告诉代码以给定的缓冲区大小开始记录,并且当每个缓冲区都被填充时,代码会回调到您定义的方法,并引用已填充的缓冲区,并且此过程将继续进行,直到您告诉它停止录制。
假设您的录音格式是每个样本 16 位(也就是 2 个字节),每秒 44100 个样本,单声道(1 个通道)。在 (A) 的情况下,假设您开始录制,然后在 10 秒后停止录制。您最终将得到一个长度为 441,000 (44,100 x 10) 个元素的 short[] 数组。我不知道您使用什么算法来检测“抽头”,但假设您在此数组中的元素 0、元素 22,050、元素 44,100、元素 66,150 等处检测抽头。这意味着您正在查找每个 . 5 秒(因为 22,050 是每秒 44,100 个样本的一半),这意味着您每秒有 2 次敲击,因此是 120 BPM。
在 (B) 的情况下,假设您以 44,100 个样本(又名 1 秒)的固定缓冲区大小开始录制。随着每个缓冲区的进入,您会在元素 0 和元素 22,050 处找到抽头。通过与上述相同的逻辑,您将计算出 120 BPM。
希望这可以帮助。一般来说,对于节拍检测,最好记录相对较长的时间,并通过大量数据来计算节拍。试图估计“瞬时”速度更加困难并且容易出错,就像实时估计录音的音高比录制完整音符更难一样。
我认为您可能会将样本与“水龙头”混淆。
样本是表示给定时刻声波高度的数字。一个典型的波形文件可能每秒采样 44,100 次,因此如果您有两个立体声通道,则每秒有 88,200 个 16 位数字(样本)。
如果你把所有这些数字都画出来,你会得到这样的结果:
(来源:vbaccelerator.com)
What you are looking for is this peak ------------^
那是水龙头。
假设我们讨论的是同一个 WaveIn.cs,WaveLib.WaveInRecorder 的构造函数将 WaveLib.WaveFormat 对象作为参数。这允许您设置音频格式,即。采样率,位深度等。只需扫描音频样本的峰值,或者您正在检测“轻拍”并记录峰值之间样本的平均距离。
由于您知道音频流的采样率(例如 44100 个样本/秒),因此将您的平均峰值距离(以样本为单位)乘以 1/(采样率)以得到轻敲之间的时间(以秒为单位),除以60 以获取轻拍之间的时间(以分钟为单位),并反转以获取轻拍/分钟。
希望有帮助