C语言 写一个简易音乐播放器

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

#define SAMPLE_RATE 44100 // 采样率
#define AMPLITUDE 32767 // 振幅
#define NO_SAMPLES 44100 // 样本数

// 声明一个结构体用于表示音符
typedef struct {
    double frequency; // 频率
    double duration; // 持续时间
} note;

// 声明一个函数用于计算给定音符的采样值
int calculate_sample(note n, double time) {
    int sample = AMPLITUDE * sin(2 * M_PI * n.frequency * time);
    return sample;
}

// 声明一个函数用于播放单个音符
void play_single_note(note n) {
    int samples_per_note = SAMPLE_RATE * n.duration; // 计算每个音符的样本数
    double time_per_sample = 1.0 / SAMPLE_RATE; // 计算每个样本的时间间隔

    // 循环遍历每一个样本并计算采样值,然后将其写入标准输出
    for (int i = 0; i < samples_per_note; i++) {
        double time = i * time_per_sample;
        int sample = calculate_sample(n, time);
        putchar(sample & 0xFF);
        putchar((sample >> 8) & 0xFF);
    }
}

// 声明一个函数用于播放和弦
void play_chord(note* notes, int num_notes) {
    int samples_per_chord = SAMPLE_RATE * notes[0].duration; // 计算每个和弦的样本数
    double time_per_sample = 1.0 / SAMPLE_RATE; // 计算每个样本的时间间隔

    // 循环遍历每一个样本并计算采样值,然后将其写入标准输出
    for (int i = 0; i < samples_per_chord; i++) {
        double time = i * time_per_sample;
        int sample = 0;
        
        // 对于和弦中的每个音符,计算其采样值并将其添加到当前样本上
        for (int j = 0; j < num_notes; j++) {
            int note_sample = calculate_sample(notes[j], time);
            sample += note_sample;
        }
        
        // 将样本缩放到正确的振幅范围内并将其写入标准输出
        sample /= num_notes;
        sample = fmin(sample, AMPLITUDE);
        sample = fmax(sample, -AMPLITUDE);
        putchar(sample & 0xFF);
        putchar((sample >> 8) & 0xFF);
    }
}

int main() {
    // 声明一些简单的音符
    note c = {261.63, 1};
    note d = {293.66, 1};
    note e = {329.63, 1};
    note f = {349.23, 1};
    note g = {392.00, 1};
    note a = {440.00, 1};
    note b = {493.88, 1};

    // 播放一些简单的旋律和和弦
    play_single_note(c);
    play_single_note(d);
    play_single_note(e);
    play_single_note(f);
    play_single_note(g);
    play_single_note(a);
    play_single_note(b);

    note c_chord[] = {c, e, g};
    play_chord(c_chord, 3);

    note f_chord[] = {f, a, c};
    play_chord(f_chord, 3);

    // 完成
    return 0;
}

该代码使用正弦函数来计算采样值,并使用标准输出来播放音乐。它支持单独播放单个音符和播放和弦。通常,音符和和弦中的每个音符都表示为持续时间和频率的组合。

相关推荐
小鸡吃米…4 小时前
机器学习 - K - 中心聚类
人工智能·机器学习·聚类
好奇龙猫5 小时前
【AI学习-comfyUI学习-第三十节-第三十一节-FLUX-SD放大工作流+FLUX图生图工作流-各个部分学习】
人工智能·学习
沈浩(种子思维作者)5 小时前
真的能精准医疗吗?癌症能提前发现吗?
人工智能·python·网络安全·健康医疗·量子计算
minhuan5 小时前
大模型应用:大模型越大越好?模型参数量与效果的边际效益分析.51
人工智能·大模型参数评估·边际效益分析·大模型参数选择
Cherry的跨界思维5 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
MM_MS5 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
ASF1231415sd5 小时前
【基于YOLOv10n-CSP-PTB的大豆花朵检测与识别系统详解】
人工智能·yolo·目标跟踪
水如烟6 小时前
孤能子视角:“意识“的阶段性回顾,“感质“假说
人工智能
Carl_奕然6 小时前
【数据挖掘】数据挖掘必会技能之:A/B测试
人工智能·python·数据挖掘·数据分析
旅途中的宽~6 小时前
《European Radiology》:2024血管瘤分割—基于MRI T1序列的分割算法
人工智能·计算机视觉·mri·sci一区top·血管瘤·t1