终于完成了。代码如下:
- //=================== 头文件包含 ============================================
- #include "STC32G144K246.H"
- #include "intrins.h"
-
- #include "yinxiao1.h"
- #include "yinxiao2.h"
- #include "yinxiao3.h"
- #include "yinxiao4.h"
- #include "yinxiao5.h"
- #include "yinxiao6.h"
- #include "yinxiao7.h"
-
-
- //=================== 主时钟和采样率定义宏 =================================
- #define FOSC 96000000UL // 系统主时钟 96MHz (由PLL产生)
- #define PLL_CLK 480000000UL // PLL输出时钟 480MHz
- #define SampleRate 16000 // 定义采样率
-
- //=================== I2S配置 ============================================
- #define MCKOE 0 // I2S主时钟输出使能, 0:禁止I2S主时钟输出, 1:允许I2S主时钟输出
-
- #define I2SEN 0x04 // I2S使能位, 0x00:关闭, 0x04:使能
- #define I2S_MODE 2 // I2S模式, 0:从发送, 1:从接收, 2:主发送, 3:主接收,
-
- #define PCMSYNC 0 // PCM同步模式, 0: 长同步, 1: 短同步
- #define STD_MODE 0 // I2S标准模式, 0: I2S标准格式, 1: MSB对齐格式, 2:LSB对齐格式, 3:PCM模式
- #define CKPOL 0 // I2S时钟极性, 0:SCLK空闲时为低电平, 1:SCLK空闲时为高电平
- #define DATLEN 0 // 数据长度, 0:16位, 1:24位, 2:32位, 3:保留
- #define CHLEN 0 // 声道长度(在PCM模式下), 0:16位, 1: 32位
-
- // 分频系数计算
- #define I2S_MCLKDIV (FOSC / (8 * 16 * 2 * SampleRate))
- #define I2S_BCLKDIV (FOSC / (16 * 2 * SampleRate))
-
- //=================== 音频处理参数 ========================================
- #define MAX_ACTIVE 2 // 最大同时播放数
- #define VOLUME_SCALE 2 // 音量衰减系数,防止多个音频同时播放时溢出
-
- //=================== 类型定义 ============================================
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- typedef signed int s16;
- typedef signed long s32;
-
- // 扩展音频索引变量
- u16 yinxiao1_index;
- u16 yinxiao2_index;
- u16 yinxiao3_index;
- u16 yinxiao4_index;
- u16 yinxiao5_index;
- u16 yinxiao6_index;
- u16 yinxiao7_index;
-
- // 扩展音频播放状态
- bit yinxiao1;
- bit yinxiao2;
- bit yinxiao3;
- bit yinxiao4;
- bit yinxiao5;
- bit yinxiao6;
- bit yinxiao7;
-
- // 时间戳变量
- u16 start_time1;
- u16 start_time2;
- u16 start_time3;
- u16 start_time4;
- u16 start_time5;
- u16 start_time6;
- u16 start_time7;
- u16 current_time;
-
- // 按键状态变量
- bit key1_pressed;
- bit key2_pressed;
- bit key3_pressed;
- bit key4_pressed;
- bit key5_pressed;
- bit key6_pressed;
- bit key7_pressed;
-
- s16 buffer[2];
- bit flip;
- bit flip_local;
-
-
- //=================== 延时函数 ==============================================
- void delay_ms(u16 ms)
- {
- u16 i;
- while(ms--)
- {
- i = 4000;
- while(i--);
- }
- }
-
- //=================== PLL时钟初始化 ==========================================
- void pll_init(void)
- {
- HPLLCR = 0x10; // 选择HIRC作为PLL输入
- HPLLPDIV = 8; // 预分频8, HIRC 48MHz/8 = 6MHz
- HPLLCR |= 0x0e; // 倍频80, 6MHz*80 = 480MHz
- HPLLCR |= 0x80; // 使能HPLL
-
- delay_ms(10);
-
- CLKDIV = 5; // 系统时钟分频: 480MHz/5 = 96MHz
- CLKSEL = 0x04; // 选择HPLL/2作为主时钟源
-
- delay_ms(10);
- }
-
-
- //=================== 计算活跃音频数量的函数 =================================
- u8 get_active_count(void)
- {
- u8 count = 0;
- if (yinxiao1) count++;
- if (yinxiao2) count++;
- if (yinxiao3) count++;
- if (yinxiao4) count++;
- if (yinxiao5) count++;
- if (yinxiao6) count++;
- if (yinxiao7) count++;
- return count;
- }
-
- //=================== 查找最旧音频的函数 ====================================
- u8 find_oldest_channel(u8 exclude_channel)
- {
- u16 oldest_time = 0xFFFF;
- u8 oldest_channel = 0;
-
- if (yinxiao1 && (1 != exclude_channel) && start_time1 < oldest_time) {
- oldest_time = start_time1;
- oldest_channel = 1;
- }
- if (yinxiao2 && (2 != exclude_channel) && start_time2 < oldest_time) {
- oldest_time = start_time2;
- oldest_channel = 2;
- }
- if (yinxiao3 && (3 != exclude_channel) && start_time3 < oldest_time) {
- oldest_time = start_time3;
- oldest_channel = 3;
- }
- if (yinxiao4 && (4 != exclude_channel) && start_time4 < oldest_time) {
- oldest_time = start_time4;
- oldest_channel = 4;
- }
- if (yinxiao5 && (5 != exclude_channel) && start_time5 < oldest_time) {
- oldest_time = start_time5;
- oldest_channel = 5;
- }
- if (yinxiao6 && (6 != exclude_channel) && start_time6 < oldest_time) {
- oldest_time = start_time6;
- oldest_channel = 6;
- }
- if (yinxiao7 && (7 != exclude_channel) && start_time7 < oldest_time) {
- oldest_time = start_time7;
- oldest_channel = 7;
- }
-
- return oldest_channel;
- }
-
- //=================== 停止指定音频的函数 ====================================
- void stop_channel(u8 channel)
- {
- switch(channel) {
- case 1: yinxiao1 = 0; yinxiao1_index = 0; start_time1 = 0; break;
- case 2: yinxiao2 = 0; yinxiao2_index = 0; start_time2 = 0; break;
- case 3: yinxiao3 = 0; yinxiao3_index = 0; start_time3 = 0; break;
- case 4: yinxiao4 = 0; yinxiao4_index = 0; start_time4 = 0; break;
- case 5: yinxiao5 = 0; yinxiao5_index = 0; start_time5 = 0; break;
- case 6: yinxiao6 = 0; yinxiao6_index = 0; start_time6 = 0; break;
- case 7: yinxiao7 = 0; yinxiao7_index = 0; start_time7 = 0; break;
- }
- }
-
- //=================== 启动指定音频的函数 ====================================
- void start_channel(u8 channel)
- {
- switch(channel) {
- case 1: yinxiao1 = 1; yinxiao1_index = 0; start_time1 = current_time; break;
- case 2: yinxiao2 = 1; yinxiao2_index = 0; start_time2 = current_time; break;
- case 3: yinxiao3 = 1; yinxiao3_index = 0; start_time3 = current_time; break;
- case 4: yinxiao4 = 1; yinxiao4_index = 0; start_time4 = current_time; break;
- case 5: yinxiao5 = 1; yinxiao5_index = 0; start_time5 = current_time; break;
- case 6: yinxiao6 = 1; yinxiao6_index = 0; start_time6 = current_time; break;
- case 7: yinxiao7 = 1; yinxiao7_index = 0; start_time7 = current_time; break;
- }
- }
-
- //=================== 8位无符号转16位有符号 ==================================
- s16 convert_u8_to_s16(u8 sample)
- {
- // 8位无符号(0-255)转16位有符号(-32768-32767)
- // 静音值128 -> 0
- return ((s16)(sample - 0x80)) << 8;
- }
-
- //=================== 固定音量衰减 ==========================================
- s16 apply_fixed_volume(s32 sum)
- {
- // 固定衰减,确保多个音频同时播放时不会溢出
- // 最多同时播放2个音频,衰减2倍足够
- sum = sum / VOLUME_SCALE;
-
- // 硬限幅,防止极端情况
- if (sum > 32767) {
- return 32767;
- } else if (sum < -32768) {
- return -32768;
- } else {
- return (s16)sum;
- }
- }
-
- //=================== 主函数 ==============================================
- void main(void)
- {
- u8 active_count;
- u8 oldest_channel;
- s32 temp_sum;
-
- // 初始化系统
- WTST = 0x00;
- CKCON = 0x00;
- EAXFR = 1;
-
- // 初始化PLL时钟
- pll_init();
-
- // 初始化IO口
- P2M0 = 0x00;
- P2M1 = 0x00;
- P2PU = 0xff;
-
- P7M0 = 0x00;
- P7M1 = 0x00;
- P7PU = 0xff;
-
- I2SMD = 0xff;
- I2SSR = 0x00;
- I2SCR = 0x80 + 0x00;
- HSCLKDIV = 1;
- I2S_CLKDIV = 1;
- I2SMCKDIV = I2S_MCLKDIV;
- I2SPRH = (MCKOE << 1) + (I2S_BCLKDIV & 1);
- I2SPRL = I2S_BCLKDIV / 2;
- I2SCFGH = I2S_MODE;
- I2SCFGL = (PCMSYNC << 7) + (STD_MODE << 4) + (CKPOL << 3) + (DATLEN << 1) + CHLEN;
- P_SW3 = (P_SW3 & 0x3f) | (2 << 6);
- I2SCFGH |= I2SEN;
-
- // 初始化音频播放状态
- yinxiao1_index = 0; yinxiao1 = 0; start_time1 = 0;
- yinxiao2_index = 0; yinxiao2 = 0; start_time2 = 0;
- yinxiao3_index = 0; yinxiao3 = 0; start_time3 = 0;
- yinxiao4_index = 0; yinxiao4 = 0; start_time4 = 0;
- yinxiao5_index = 0; yinxiao5 = 0; start_time5 = 0;
- yinxiao6_index = 0; yinxiao6 = 0; start_time6 = 0;
- yinxiao7_index = 0; yinxiao7 = 0; start_time7 = 0;
- current_time = 0;
-
- // 初始化按键状态
- key1_pressed = 0; key2_pressed = 0; key3_pressed = 0; key4_pressed = 0;
- key5_pressed = 0; key6_pressed = 0; key7_pressed = 0;
-
- // 初始化双缓冲区
- flip = 0;
- flip_local = 0;
- buffer[0] = 0;
- buffer[1] = 0;
-
- EA = 1; // 开启全局中断
-
- while (1)
- {
- if (flip_local != flip)
- {
- temp_sum = 0;
-
- // 更新时间计数器
- current_time++;
- if (current_time > 60000) {
- current_time = 0;
- if (yinxiao1) start_time1 = current_time;
- if (yinxiao2) start_time2 = current_time;
- if (yinxiao3) start_time3 = current_time;
- if (yinxiao4) start_time4 = current_time;
- if (yinxiao5) start_time5 = current_time;
- if (yinxiao6) start_time6 = current_time;
- if (yinxiao7) start_time7 = current_time;
- }
-
- // 按键检测
- if (P71 == 0) {
- if (!key1_pressed) {
- key1_pressed = 1;
- if (yinxiao1) {
- yinxiao1_index = 0;
- start_time1 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(1);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(1);
- }
- }
- } else {
- key1_pressed = 0;
- }
-
- if (P72 == 0) {
- if (!key2_pressed) {
- key2_pressed = 1;
- if (yinxiao2) {
- yinxiao2_index = 0;
- start_time2 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(2);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(2);
- }
- }
- } else {
- key2_pressed = 0;
- }
-
- if (P73 == 0) {
- if (!key3_pressed) {
- key3_pressed = 1;
- if (yinxiao3) {
- yinxiao3_index = 0;
- start_time3 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(3);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(3);
- }
- }
- } else {
- key3_pressed = 0;
- }
-
- if (P74 == 0) {
- if (!key4_pressed) {
- key4_pressed = 1;
- if (yinxiao4) {
- yinxiao4_index = 0;
- start_time4 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(4);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(4);
- }
- }
- } else {
- key4_pressed = 0;
- }
-
- if (P75 == 0) {
- if (!key5_pressed) {
- key5_pressed = 1;
- if (yinxiao5) {
- yinxiao5_index = 0;
- start_time5 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(5);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(5);
- }
- }
- } else {
- key5_pressed = 0;
- }
-
- if (P76 == 0) {
- if (!key6_pressed) {
- key6_pressed = 1;
- if (yinxiao6) {
- yinxiao6_index = 0;
- start_time6 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(6);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(6);
- }
- }
- } else {
- key6_pressed = 0;
- }
-
- if (P77 == 0) {
- if (!key7_pressed) {
- key7_pressed = 1;
- if (yinxiao7) {
- yinxiao7_index = 0;
- start_time7 = current_time;
- } else {
- active_count = get_active_count();
- if (active_count >= MAX_ACTIVE) {
- oldest_channel = find_oldest_channel(7);
- if (oldest_channel != 0) {
- stop_channel(oldest_channel);
- }
- }
- start_channel(7);
- }
- }
- } else {
- key7_pressed = 0;
- }
-
- // 音频混合处理 - 简单累加,不做动态调整
- if (yinxiao1) {
- temp_sum += convert_u8_to_s16(yinxiao1_pcm[yinxiao1_index++]);
- if (yinxiao1_index >= yinxiao1_pcm_len) {
- yinxiao1 = 0;
- yinxiao1_index = 0;
- start_time1 = 0;
- }
- }
-
- if (yinxiao2) {
- temp_sum += convert_u8_to_s16(yinxiao2_pcm[yinxiao2_index++]);
- if (yinxiao2_index >= yinxiao2_pcm_len) {
- yinxiao2 = 0;
- yinxiao2_index = 0;
- start_time2 = 0;
- }
- }
-
- if (yinxiao3) {
- temp_sum += convert_u8_to_s16(yinxiao3_pcm[yinxiao3_index++]);
- if (yinxiao3_index >= yinxiao3_pcm_len) {
- yinxiao3 = 0;
- yinxiao3_index = 0;
- start_time3 = 0;
- }
- }
-
- if (yinxiao4) {
- temp_sum += convert_u8_to_s16(yinxiao4_pcm[yinxiao4_index++]);
- if (yinxiao4_index >= yinxiao4_pcm_len) {
- yinxiao4 = 0;
- yinxiao4_index = 0;
- start_time4 = 0;
- }
- }
-
- if (yinxiao5) {
- temp_sum += convert_u8_to_s16(yinxiao5_pcm[yinxiao5_index++]);
- if (yinxiao5_index >= yinxiao5_pcm_len) {
- yinxiao5 = 0;
- yinxiao5_index = 0;
- start_time5 = 0;
- }
- }
-
- if (yinxiao6) {
- temp_sum += convert_u8_to_s16(yinxiao6_pcm[yinxiao6_index++]);
- if (yinxiao6_index >= yinxiao6_pcm_len) {
- yinxiao6 = 0;
- yinxiao6_index = 0;
- start_time6 = 0;
- }
- }
-
- if (yinxiao7) {
- temp_sum += convert_u8_to_s16(yinxiao7_pcm[yinxiao7_index++]);
- if (yinxiao7_index >= yinxiao7_pcm_len) {
- yinxiao7 = 0;
- yinxiao7_index = 0;
- start_time7 = 0;
- }
- }
-
- // 固定音量衰减,确保不溢出
- buffer[flip_local] = apply_fixed_volume(temp_sum);
-
- flip_local = flip;
- }
- }
- }
-
- //=================== I2S中断服务函数 ======================================
- void I2S_ISR(void) interrupt I2S_VECTOR
- {
- if (I2SSR & 0x02)
- {
- if (I2SSR & 0x04)
- {
- I2SDRH = (u8)(buffer[flip] >> 8);
- I2SDRL = (u8)(buffer[flip] & 0xFF);
- }
- else
- {
- I2SDRH = (u8)(buffer[flip] >> 8);
- I2SDRL = (u8)(buffer[flip] & 0xFF);
- flip = !flip;
- }
- }
- }
复制代码 哪位大佬有灵感菇的那个魔性音乐的音频?我想换上去试试
编译后的程序:
电子琴.hex
(371.92 KB, 下载次数: 0)
主程序:
main.c
(17.66 KB, 下载次数: 0)
音频文件:
yinxiao1.h
(154.56 KB, 下载次数: 0)
yinxiao2.h
(152 KB, 下载次数: 0)
yinxiao3.h
(85.68 KB, 下载次数: 0)
yinxiao4.h
(121.39 KB, 下载次数: 0)
yinxiao5.h
(126.49 KB, 下载次数: 0)
yinxiao6.h
(89.5 KB, 下载次数: 0)
yinxiao7.h
(79.3 KB, 下载次数: 0)
B站视频:[url=【电子琴还能这样做?那换一组劲爆的音频文件不是要起飞?】https://www.bilibili.com/video/B ... e8ecff012a751924660]【电子琴还能这样做?那换一组劲爆的音频文件不是要起飞?】https://www.bilibili.com/video/B ... e8ecff012a751924660[/url]
|