You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修正C语言正弦波生成代码:解决频率减半时长翻倍问题

问题分析与解决方案

你的代码出现频率减半、时长翻倍的问题,核心原因是样本格式不匹配,还有一处循环条件的小问题,具体修正如下:

问题根源

  1. 样本字节数不匹配:
    你在代码中使用int类型(通常为4字节)存储样本并写入文件,但播放时用aplay -f S16_LE指定的是16位有符号小端整数(仅2字节)。这导致播放器把每个4字节的int拆成两个独立的16位样本,相当于样本总数翻倍,因此频率变为原来的1/2(220Hz),时长变为原来的2倍(20秒)。
  2. 循环条件冗余:
    while (i <= sample_rate * duration)会多生成1个样本,虽然对时长影响极小,但不符合预期的10秒样本数。

修改后的代码

#include <stdio.h>
#include <math.h>
#include <stdint.h>  // 用于int16_t类型

double sine(double amp, double freq, double time);

int main(int argc, char *argv[])
{
    int sample_rate = 48000;
    double freq = 440;
    double amp = 1;
    double duration = 10;
    double time = 0;
    double val = 0;
    int16_t temp = 0;  // 使用明确的16位有符号整数,匹配S16_LE格式
    int i = 0;

    FILE *fp = fopen("sine.bin", "wb");
    if (fp == NULL)
    {
        return -1;
    }
    // 修正循环条件,生成恰好sample_rate*duration个样本
    while (i < sample_rate * duration)
    {
        val = 32767.0 * sine(amp, freq, time);
        temp = (int16_t) val;  // 转换为16位有符号整数
        // 写入2字节的样本,匹配S16_LE格式
        fwrite((const void*) &temp, sizeof(int16_t), 1, fp);
        i++;
        time = i / (1.0 * sample_rate);  // 调整顺序,先递增i再计算时间,逻辑更直观
    }
    fclose(fp);  // 别忘了关闭文件,避免资源泄漏
}

double sine(double amp, double freq, double time)
{
    return amp * sin(2.0 * M_PI * freq * time);
}

关键修改点

  • 使用int16_t类型(来自<stdint.h>)替代int,确保样本是16位有符号整数,完全匹配S16_LE格式。
  • 调整fwrite的第二个参数为sizeof(int16_t),保证每个样本只写入2字节。
  • 修正循环条件为i < sample_rate * duration,生成精确的10秒样本(48000*10=480000个样本)。
  • 添加fclose(fp),避免文件资源泄漏。

编译与播放

保持原命令不变即可:

gcc sound.c -Wall -Wextra -lm -o sound && ./sound
aplay -r 48000 -f S16_LE sine.bin

内容的提问来源于stack exchange,提问作者Ishaan Vatus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 12:57:12