【问题标题】:play a waveform at a certain frequency in SDL callback function在 SDL 回调函数中以特定频率播放波形
【发布时间】:2023-03-03 11:45:01
【问题描述】:

我有一个 64 个样本长的波形。如果采样率为 44100 赫兹,如何播放(循环)此波形以播放任意频率?

频率 = 采样率 / 采样波形持续时间

因此频率应为 689hz(44100/64)。如果我希望它是 65.41hz(C-2),我必须这样做:

65.41 = 44100 / x

求解 x 产生 aprox。 674.208。所以我需要弄清楚以什么速度播放波形来获得这个频率。所以我们可以解这个方程:

64 * x = 674.208

得到大约 10.5。所以波形需要以原始速度的 10.5% 播放。

这是我的代码:

double smp_index = 0;
double freq = .105;

void callback(void *data, Uint8 *buf, int len){
    int i;
    s8 *out;
    out = (s8*) buf;
    if(smp_index < waveform_length){
        for(i = 0; i < len; i ++){
            out[i] = smpdata[(int)smp_index];
            smp_index +=freq;
            if(smp_index >= waveform_length)
                smp_index = 0;
        }
    }
}

所以生成的音频应该是关于音符 C-2,但它更像是 D-2。是演员表

(int)smp_index

导致问题?我看不出有任何其他方法可以做到这一点......

【问题讨论】:

    标签: c audio callback sdl waveform


    【解决方案1】:

    演员(int)smp_index 不是导致问题。它只是拉伸了波形 - 这是质量损失(也许您的波形数据应该超过 64 个样本),但不可能改变频率。最有可能的问题是:

            if(smp_index > realLength)
                smp_index = 0;
    

    应该是:

            if(smp_index >= realLength)
                smp_index -= realLength;
    

    我还有一些其他的笔记要给你:

    频率 = 采样率 / 采样波形持续时间

    嗯,如果“波形持续时间”是指波的周期,那么是的。 IE。如果您的 64 样本波形是周期为 64 的正弦波,那么可以。如果是 32 或 16,那么情况会有所不同。如果它不能除以 64(如 48 或 30),那么您的波形一开始就不是周期性的。

    现在:

    u32 waveform_length;
    out = (s8*) buf;
    if(smp_index < waveform_length){
    

    waveform_length 的值是多少?在我看来未初始化...

    【讨论】:

    • 我已经将 > 替换为 >=。代码中还有其他一些错别字,我已经修复了。波形长度长度在代码的其他地方初始化,它是从文件中读取的,我知道这是正确的,因为我将波形长度的值与读取文件的另一个程序进行了比较。
    • 这个波并不完全是正弦波,但是是的,我指的是它的周期。
    【解决方案2】:

    其实主要问题不在你的代码,而在你的推理。

    所以我们可以解这个方程:

    64 * x = 674.208

    得到大约 10.5。

    到目前为止一切顺利。 (实际上 674.208 应该是 674.246 但那是因为您之前将 65.41 四舍五入为 4 个有效数字。)

    所以波形需要以原始速度的 10.5% 播放。

    不!波形必须减慢 10.5 倍。这意味着它必须以1/10.5 = 0.095 或原始速度的 9.5% 播放。

    【讨论】:

    • 太棒了!这正是问题所在。就在这时,我几乎忘记了自己最初在做什么。
    • 优秀。感谢您的回复!
    • 我遇到了另一个问题。如果波形不是周期性的怎么办? :{
    • 那么你需要以某种方式(以循环方式)重新填充你的 smpdata[] 缓冲区,或者使用双缓冲区技术,所以当一个缓冲区正在播放时,第二个缓冲区被填充,然后他们被交换了。
    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多