【问题标题】:Generating WAV File Tones生成 WAV 文件音
【发布时间】:2014-12-16 21:55:01
【问题描述】:

我正在尝试以编程方式构建一个音频 WAV 文件,其中包含您在拨打电话号码时听到的标准英国铃声 n 秒。

我有found a source,它记录了音调的频率和持续时间,这是两个频率的正弦波:400Hz 和 450Hz。

我编写的代码会生成正确格式的 PCM WAV 文件,我可以使用 Windows Media Player 等音频播放器播放该文件,但是它生成的音调听起来比应有的频率低得多,所以不要认为我的论坛完全正确。

这就是我目前正在做的事情:

var duration = 10;
var bitsPerSample = 8;
var samplesPerSec = 8000;
var f1 = 400;
var f2 = 450;
var pattern = new[] {
            TimeSpan.FromMilliseconds(400),
            TimeSpan.FromMilliseconds(200),
            TimeSpan.FromMilliseconds(400),
            TimeSpan.FromMilliseconds(2000)
        };

var wavdata = new byte[duration * samplesPerSec]; // 10 seconds of wav data @ 8000 samples per sec, 8 bits per sample, 1 channel 

// Loop through each sample
for (var i = 0; i < wavdata.Length; i = i + (bitsPerSample / 8)) {

    // Get time in seconds of the current sample
    var time = Convert.ToDouble(i) / (Convert.ToDouble(bitsPerSample) / 8) / samplesPerSec;

    // Calculate the on off pattern
    var onoff = 0;
    var timeMilliseconds = time * 1000;
    var p = 0;
    while (timeMilliseconds >= 0) {
        timeMilliseconds = timeMilliseconds - pattern[p].TotalMilliseconds;
        onoff = onoff == 1 ? 0 : 1;
        if (++p >= pattern.Length) p = 0;
    }

    // Calculate the sample: (sin(time * 400) * 128 + sin(time * 450) * 128)) / 2
    var sample = onoff * (((Math.Sin(time * f1) * 128) + (Math.Sin(time * f2) * 128)) / 2);

    // Store sample
    wavdata[i] = Convert.ToByte(sample + 128);

}

如您所见,我使用的公式是:

sin(time-of-sample * frequency) * amplitude

我对两个组合频率使用了两次:

sin(time * 400) * 128
sin(time * 450) * 128

然后我将它们加在一起并除以 2 得到平均值。然后我乘以 1 或 0 以在音调之间获得静音以获得铃声。最后,当我将值存储在数据数组中时,我将样本偏移了 128,因为 WAV 文件数据表示为正数据或负数据。

我做错了什么?为什么这产生的音调比预期的要低得多?

【问题讨论】:

    标签: c# audio wav trigonometry


    【解决方案1】:

    你忘记了 Pi。正弦周期从 0...2π,而不是 0..1:

    var sample = onoff * (((Math.Sin(2 * Math.Pi * time * f1) * 127) + (Math.Sin(2 * Math.Pi * time * f2) * 127)) / 2);
    

    另外,请注意我将 128s 更改为 127s,因为如果 Sin 太接近 1 或 -1,浮点到字节的转换会溢出。可能有一种更好的方法可以做到这一点,它不会牺牲范围,但它可能对你正在做的事情无关紧要。

    如果我可以评论:代码进行了太多的单位转换。以秒和毫秒为单位的时间令人困惑。并且“样本”的范围应为 -1 到 1,然后将转换为字节作为单独的步骤。通过在该行内乘以 128,它将字节的概念与音频计算混合在一起,这有点令人困惑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 2019-05-29
      相关资源
      最近更新 更多