首页 > 系统相关 >【旧文更新】【优秀课设】基于Linux粤嵌GEC6818开发板的电子乐队程序设计(四种模式:和弦模式、键盘模式、鼓点模式、编曲模式)

【旧文更新】【优秀课设】基于Linux粤嵌GEC6818开发板的电子乐队程序设计(四种模式:和弦模式、键盘模式、鼓点模式、编曲模式)

时间:2024-05-29 14:33:19浏览次数:19  
标签:课设 bmppath bmp lcd 模式 编曲 240 100

【旧文更新】【优秀课设】基于Linux粤嵌GEC6818开发板的电子乐队程序设计(四种模式:和弦模式、键盘模式、鼓点模式、编曲模式)

文章目录

关于旧文新发

为何要进行旧文新发?
因为我在2023年博客之星评选中发现 有的人转载、抄袭他人文章 稍微改动几下也能作为高质量文章入选
所以我将把我的旧文重新发一次 然后也这样做

2023年博客之星规则:
在这里插入图片描述

模式介绍

三种音源独立设计:钢琴、钢琴和弦、鼓点
四种模式:和弦模式、键盘模式、鼓点模式、编曲模式
键盘模式包含16个按键 包含所有音名 所有调式皆可弹奏
和弦模式包含C/Am调式常用的16个和弦 包括不协和音程进行

GEC6818开发板是粤嵌公司提供的

资源:

download.csdn.net/download/weixin_53403301/66915088

所有音源资源:

music.163.com/#/album?id=130101018

<iframe allowfullscreen="true" data-mediaembed="bilibili" frameborder="0" id="yhITzoaA-1691748406314" src="https://player.bilibili.com/player.html?aid=232187375"></iframe>

【满分课设开源】基于Linux GEC6818的电子乐队系统设计(和弦模式、键盘模式、鼓点模式、编曲模式)

展示

先上和弦模式、键盘模式、鼓点模式、编曲模式的四个模式实物图:
和弦模式16键,键盘模式16键,鼓点模式8键,编曲模式16键。
每个按键上都写有此按键的对应音名。
切换、按下其他按键时有声音淡出功能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

摘要

本次所进行的系统设计名为《基于GEC6818开发板的电子乐队系统设计》,诣在通过程序的编写、编译,在基于Linux系统的GEC6818开发板上实现电子乐队系统。
此系统诣在为对音乐感兴趣的人提供一个方便的、小巧的、简洁的应用程序,使其能够进行演奏、音乐试验等。虽然功能上不如专业的电钢琴、MIDI键盘等乐器,但更便于携带,也适合多人乐队使用。
该电子乐队系统具有模式多,音色多,音源质量好等特点,与同类产品相比,具有以下特色和创新。
该电子乐队系统是基于搭载Linux系统内核的GEC6818开发板所实现的,程序代码部分由C语言所编写。
该电子乐队系统共有和弦模式、键盘模式、鼓点模式和编曲模式四个模式。
该电子乐队系统具有多种模式,占用资源少,界面简洁,成本低廉,制作容易,音色质量高,音源音高准确,并可替换和更新音源,还能进行简单的编曲,能够演奏现代音乐系统中的所有调式(包括中国古典乐调式),能用多台设备实现简单的乐队演奏,不同于市场上常见的或其他小组设计的普通Linux系统开发板电子乐器系统。
普通Linux系统开发板电子乐器系统多具有音色单一、按键数量少、可演奏的调式唯一、不可编曲、不可更新音源等缺点。此电子乐队系统也可以作为市场上的电子乐器系统的改进和升级版本。
关键词:Linux,电子乐队,GEC6818,编曲,C语言,电子乐器。

功能及特色:
和弦模式、键盘模式、鼓点模式、编曲模式。
和弦模式16键,键盘模式16键,鼓点模式8键,编曲模式16键。
每个按键上都写有此按键的对应音名。
切换、按下其他按键时有声音淡出功能
可选择钢琴、电子鼓、吉他、贝司等所有可添加的音色。
采用FL Studio 12软件进行编曲混音制成音源。
此软件本身需付费使用(也可进行破解免费使用),音源也须付费购买,本身音源质量高,再经过混音后导出的音源听起来更舒服、质量更高。
采用mplayer播放器,播放16位WAV顶级无损格式,采样率44100,比特率1411kbps。
音频有效频率范围为0-22050Hz,能使人感受到部分超声波。
音高频率为国际七音十二等律音阶频率标准,绝对音高准确,每一个音阶的频率都为上一个音阶频率的√(12&2)倍;相邻音区、相同音名的音频频率倍数关系为2。
A4音的频率为440Hz。
现代音乐七音十二等律音阶系统中Ionian调式(自然大调)、Dorian调式,Phrygian调式、Lydian调式、Mixolydian调式、Aeolian调式(自然小调)、Locrian调式、和声小调、旋律小调中所对应的C、C#、D、D#、E、F、F#、G、G#、A、A#、B调式,共108种调式。
以及中国现代古典乐七音十二等律音阶系统的宫(C)、商(D)、角(E)、变徵(Gb)、徵(G)、羽(A)、变宫(B或Cb)调式中所对应的C、C#、D、D#、E、F、F#、G、G#、A、A#、B调式,共84种调式。
或其他十二等律音阶系统中的调式。
多个模式循环切换,能弹奏旋律,能快速弹奏和弦,能进行编曲并播放编曲后的伴奏,能打鼓点节奏。
能在弹奏一个音源时调节音量。
按键响应快、非常灵敏,能弹奏出琶音、连音等操作,快速弹奏时不卡顿。
能用于乐队演出,同时弹奏多种音色、旋律、鼓点节奏。
可添加、更新音源,增加更多音色、模式。
所有对音乐感兴趣的人,包括但不限于乐队、启蒙者、初学者、编曲工作者、作曲家、歌手、DJ、娱乐K歌者等。
主要面向乐队、编曲工作者、娱乐K歌者、歌手、DJ等。
也可用于简单的音乐教学。
程序编写中,函数的调用方式中多达18个线程,其中和弦模式、键盘模式和鼓点模式各4个线程,编曲模式6个线程。
使用多线程模式调用函数,可以有效降低系统的延时,达到灵敏度高的特点。在快速演奏时,不会因为速度过快造成发音不全的现象,可以演奏出琶音、连音等高端操作。

此电子乐队系统适用于所有对音乐有兴趣爱好的人,不仅可以给刚刚初学音乐的人使用,弹奏简单的C自然大调旋律,也可以给作曲家、乐队使用。适用人群广泛。
乐队可以通过多设备协调使用,达到演出的目的;初学者可以弹奏键盘模式下的简单旋律;作曲家、编曲工作者、DJ可以通过此系统试验自己所写的旋律、节奏、鼓点、Demo;歌手、娱乐K歌者可以通过此系统的和弦模式和编曲模式弹奏和弦,达到弹唱的目的;音乐启蒙者也可以通过此系统启蒙学习音乐,并且音名规范、音高频率标准。
使用并推广此系统,也可以感染更多的人来喜欢音乐、玩音乐、加强对音乐的兴趣。且界面简洁,便于操作,功能方面比市面上的大多数产品都要强大,推广到市场上绝对能大卖。

代码

# include <stdio.h>		//导入基本函数库
# include <sys/stat.h>		//打开文件等的函数库
# include <fcntl.h>		//打开文件等的函数库
# include <unistd.h>		//关闭文件、延时等的函数库
# include <sys/mman.h>		//内存分配的相关函数库
# include <strings.h>		//结构体函数库
# include <linux/input.h>		//linux系统下的硬件输入函数库
# include <stdlib.h>		//系统命令函数库
# include <pthread.h>		//多线程模式函数库

int tx,ty; 	//定义触摸板坐标变量
//int tp;  	// 定义触摸板压力值变量
int flag=0; 	 //定义触摸板函数指标
int ins,bet;  	// 定义和弦、键盘模式按键位置变量和鼓点模式按键位置变量
char *kill = "killall -SIGKILL mplayer";  // 杀死mplayer
char *mkpp = "mkfifo /pipe";  //创建管道 根目录下
char *chpp = "chmod 777 /pipe";  //更改管道属性
char *play_up = "echo seek +5 > /pipe";  //快进5
char *play_down = "echo seek -5 > /pipe";  // 快退5
char *sound_up = "echo volume +10 > /pipe";  //音量+10
char *sound_down = "echo volume -10 > /pipe";  //音量+10
char *play_pause = "echo pause > /pipe";  //暂停 继续
char *sound_down_20 = "echo volume -20 > /pipe";
char *sound_down_30 = "echo volume -30 > /pipe";
char *sound_down_50 = "echo volume -50 > /pipe";

int fade_out(void) 		//音频淡出函数
{
	system(sound_down_20);
	system(sound_down_30);
	system(sound_down_50);
	return 0;
}

struct chord_image{	//定义和弦图片结构体类 图片路径 显示坐标起始位置x y 宽高w h
	char bmppath[20];
	int x;
	int y;
	int w;
	int h;
};

struct chord_image chord_img[16] = {	//16张和弦图片定义 显示图片的位置不同 第一排8个 第二排8个 共16个 图片大小100*240
	{.bmppath = "C7.bmp",.x=0,.y=0,.w=100,.h=240},
	{.bmppath = "C.bmp",.x=0,.y=240,.w=100,.h=240},
	{.bmppath = "Dm7.bmp",.x=100,.y=0,.w=100,.h=240},
	{.bmppath = "Dm.bmp",.x=100,.y=240,.w=100,.h=240},
	{.bmppath = "Em7.bmp",.x=200,.y=0,.w=100,.h=240},
	{.bmppath = "Em.bmp",.x=200,.y=240,.w=100,.h=240},
	{.bmppath = "Fm.bmp",.x=300,.y=0,.w=100,.h=240},
	{.bmppath = "F.bmp",.x=300,.y=240,.w=100,.h=240},
	{.bmppath = "G7.bmp",.x=400,.y=0,.w=100,.h=240},
	{.bmppath = "G.bmp",.x=400,.y=240,.w=100,.h=240},
	{.bmppath = "Am7.bmp",.x=500,.y=0,.w=100,.h=240},
	{.bmppath = "Am.bmp",.x=500,.y=240,.w=100,.h=240},
	{.bmppath = "Dsus4.bmp",.x=600,.y=0,.w=100,.h=240},
	{.bmppath = "D7.bmp",.x=600,.y=240,.w=100,.h=240},
	{.bmppath = "Gsus4.bmp",.x=700,.y=0,.w=100,.h=240},
	{.bmppath = "E7.bmp",.x=700,.y=240,.w=100,.h=240}
};

struct key_image{	//定义键盘图片类
	char bmppath[20];
	int x;
	int y;
	int w;
	int h;
};

struct key_image key_img[16] = {	//16张键盘图片
	{.bmppath = "Db4.bmp",.x=0,.y=0,.w=100,.h=240},
	{.bmppath = "C4.bmp",.x=0,.y=240,.w=100,.h=240},
	{.bmppath = "Eb4.bmp",.x=100,.y=0,.w=100,.h=240},
	{.bmppath = "D4.bmp",.x=100,.y=240,.w=100,.h=240},
	{.bmppath = "Fb4.bmp",.x=200,.y=0,.w=100,.h=240},
	{.bmppath = "E4.bmp",.x=200,.y=240,.w=100,.h=240},
	{.bmppath = "Gb4.bmp",.x=300,.y=0,.w=100,.h=240},
	{.bmppath = "F4.bmp",.x=300,.y=240,.w=100,.h=240},
	{.bmppath = "Ab4.bmp",.x=400,.y=0,.w=100,.h=240},
	{.bmppath = "G4.bmp",.x=400,.y=240,.w=100,.h=240},
	{.bmppath = "Bb4.bmp",.x=500,.y=0,.w=100,.h=240},
	{.bmppath = "A4.bmp",.x=500,.y=240,.w=100,.h=240},
	{.bmppath = "Cb5.bmp",.x=600,.y=0,.w=100,.h=240},
	{.bmppath = "B4.bmp",.x=600,.y=240,.w=100,.h=240},
	{.bmppath = "Db5.bmp",.x=700,.y=0,.w=100,.h=240},
	{.bmppath = "C5.bmp",.x=700,.y=240,.w=100,.h=240}
};

struct beat_image{	//定义鼓点图片类
	char bmppath[20];
	int x;
	int y;
	int w;
	int h;
};

struct beat_image beat_img[8] = {	//8张鼓点图片定义 显示图片的位置不同 第一排4个 第二排4个 共8个 图片大小200*240
	{.bmppath = "Kick.bmp",.x=0,.y=0,.w=200,.h=240},
	{.bmppath = "SnareC.bmp",.x=0,.y=240,.w=200,.h=240},
	{.bmppath = "Snare.bmp",.x=200,.y=0,.w=200,.h=240},
	{.bmppath = "Crash.bmp",.x=200,.y=240,.w=200,.h=240},
	{.bmppath = "Hat.bmp",.x=400,.y=0,.w=200,.h=240},
	{.bmppath = "SnareA.bmp",.x=400,.y=240,.w=200,.h=240},
	{.bmppath = "Clap.bmp",.x=600,.y=0,.w=200,.h=240},
	{.bmppath = "Ride.bmp",.x=600,.y=240,.w=200,.h=240}
};


	struct chord_music{	//定义和弦音频类 wav文件的mplayer播放指令
		char wavplay[60];
	};
	// mplayer 播放器 -slave命令模式 -quiet除杂 -input file=/pipe设置通道 *.wav文件名 &后台运行
	struct chord_music chord_wav[16] = {	//定义16个和弦音源
		{.wavplay = "mplayer -slave -quiet -input file=/pipe C7.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe C.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Dm7.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Dm.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Em7.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Em.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Fm.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe F.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe G7.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe G.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Am7.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Am.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Dsus4.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe D7.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe Gsus4.wav &"},
		{.wavplay = "mplayer -slave -quiet -input file=/pipe E7.wav &"}	
	};

struct key_music{	//定义键盘音频类
	char wavplay[60];
};

struct key_music key_wav[16] = {	//16种键盘音源
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Db4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe C4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Eb4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe D4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Fb4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe E4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Gb4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe F4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Ab4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe G4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Bb4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe A4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Cb5.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe B4.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Db5.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe C5.wav &"}	
};

struct beat_music{	//定义鼓点音频类
	char wavplay[60];
};

struct beat_music beat_wav[8] = {	//定义8个不同鼓点音源
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Kick.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe SnareC.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Snare.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Crash.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Hat.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe SnareA.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Clap.wav &"},
	{.wavplay = "mplayer -slave -quiet -input file=/pipe Ride.wav &"}
};

//定义判断是否打开文件的函数
int open_jugg(int i)	
{
	//char *j = "oepn_parm";
	//printf("%s=%d\n",j,i);
	if (i< 0)	//i小于0 则打开失败 返回0
	{
		//printf("failure\n");
		return 0;
	}
	else	//否则打开成功 返回1
	{
		//printf("success\n");
		return 1;
	}
}

//定义lcd屏显示颜色的函数 起始坐标xy 宽高wh BGR颜色值bgr 透明的值tou
int lcd_display(int x, int y, int w, int h, int b, int g, int r, int tou)
{
	int lcd = open("/dev/fb0",O_RDWR);	//以可读可写模式打开lcd驱动
	//printf("LCD=%d\n",open_jugg(lcd));	//判断是否打开
	
	int i,j;	//定义LCD每个像素位置变量
	char *buf = mmap(NULL,800*480*4,PROT_WRITE,MAP_SHARED,lcd,0);	//分配内存 像素buf数组
	//将BGR值赋值到每个像素对应的数组当中
	for(j=y;j<(y+h);j++)
	{
		for(i=x;i<(x+w);i++)
		{
			buf[0+4*i+800*4*j] = b;
			buf[1+4*i+800*4*j] = g;
			buf[2+4*i+800*4*j] = r;
			buf[3+4*i+800*4*j] = tou;	
			//write(lcd,buf,4);	
		}
		//write(lcd,buf,4*800);
	}
	write(lcd,buf,800*480*4);		//将数组的值写入到lcd屏内
	close(lcd);	//关闭释放LCD
	munmap(buf,800*480*4); //释放内存
	return 0;
}

// lcd显示图片 定义指针bmp图片路径 起始坐标 宽 高 透明度
int lcd_dis_bmp(char *bmppath, int x, int y, int w, int h, int tou)
{
	int lcd = open("/dev/fb0",O_RDWR);	//打开LCD屏驱动
	//printf("LCD=%d\n",open_jugg(lcd));	//判断LCD是否打开
	int bmp = open(bmppath,O_RDWR);	//打开bmp图片
	//printf("BMP=%d\n",open_jugg(bmp));	//判断是否打开图片
	
	lseek(bmp,54,SEEK_SET);	//移动光标 从起始点开始 平移量54 跳过BMP格式图片的前54个编码部分 
	char bmpbuf[w*h*3];	//定义bmpbuf图片数组
	read(bmp,bmpbuf,w*h*3);	//读取bmp的数值
	
	int i,j;	//定义LCD每个像素位置变量
	char *buf = mmap(NULL,800*480*4,PROT_WRITE,MAP_SHARED,lcd,0);	//分配内存 像素buf数组
	//将BGR值赋值到每个像素对应的数组当中
	for(j=y;j<y+h;j++)
	{
		for(i=x;i<x+w;i++)
		{
			buf[0+4*i+800*4*j] = bmpbuf[0+3*(i-x)+w*3*(h-1-j+y)];	//将bmp图片对应像素的值写入到LCD屏的像素数组中
			buf[1+4*i+800*4*j] = bmpbuf[1+3*(i-x)+w*3*(h-1-j+y)];
			buf[2+4*i+800*4*j] = bmpbuf[2+3*(i-x)+w*3*(h-1-j+y)];
			buf[3+4*i+800*4*j] = tou;
			//write(lcd,buf,4);	
		}
		//write(lcd,buf,4*800);
	}
	write(lcd,buf,800*480*4);		//写入到LCD屏中
	close(lcd);	//关闭LCD
	close(bmp);	//关闭图片
	munmap(buf,800*480*4); //释放内存	
}


//触摸板扫描函数 获取一次触摸板坐标
int touch_scan()
{
	int tsfd = open("/dev/input/event0",O_RDWR); 	//打开触摸板驱动
	printf("TOUCH=%d\n",open_jugg(tsfd));	//判断是否打开 若打开 则显示TOUCH=1
	struct input_event ts;	//定义输入事件ts类
	bzero(&ts,sizeof(ts));  //清空数据
	while(1)	//循环读取数据
	{
		read(tsfd,&ts,sizeof(ts));	//读取输入事件值
		if(ts.type == EV_ABS)  //绝对坐标事件
		{
			if(ts.code == ABS_X)	//读取x坐标值 赋值给tx
			{
				tx = ts.value;
				flag++;	//指标+1
				// printf("flag=%d",flag);
			}
			if(ts.code == ABS_Y)	//读取y坐标值 赋值给ty
			{
				ty = ts.value;
				flag++;	//指标+1
				// printf("flag=%d",flag);
			}
		}
		
		// if (ts.type == EV_KEY)   //压力
		// {
			// if(ts.code == BTN_TOUCH)
			// {
				// tp = ts.value;
				// flag++;
			// }
		// }
		if (ty>100)		//排除掉屏幕上分100像素的 用于控制按钮的部分
		{
			int a=tx/100;		//判断和弦、键盘模式的x轴坐标位置变量 一排8个键 共2排16个键 x轴共800像素 分为8个部分
			int b=ty/240;		//判断y轴坐标位置变量 共两排 y轴共480个像素 分为两个部分
			int c=tx/200;		//判断鼓点模式的x轴坐标位置变量 一排4个键 共2排8个键 x轴共800像素 分为4个部分
			//printf("b=%d\n",b);
			if(b==0)		//当y轴变量为0时 即为第一排按键
			{
				ins=a*2;		//和弦、键盘模式变量赋值 第一排分别为0/2/4/6/8/12/14 对应的第ins号图片/音频
				bet=c*2;		//鼓点模式变量赋值 第一排分别为0/2/4/6 对应的第bet号图片/音频
				//printf("0=%d\n",i);
			}
			if(b==1)		//当y轴变量为1时 即为第二排按键
			{
				ins=a*2+1;		//和弦、键盘模式变量赋值 第一排分别为1/3/5/7/9/11/13/15 对应的第ins号图片/音频
				bet=c*2+1;		//鼓点模式变量赋值 第一排分别为1/3/5/7 对应的第bet号图片/音频
				//printf("1=%d\n",i);
			}
		}
		if (flag == 2)	//当指标为2时 中断循环 指标清0 这样可以一次函数只读取一次触摸板坐标值
			{
				flag=0;
				break;
			}			
	}
	return 0;
}

int ex_i=0;		//编曲模式录入和弦序号变量
int exbuf[50];	//编曲模式录入变量
int ex=0;		//编曲模式进行循环时的计数变量
float bpm_one=6.0;		//bpm值变量 默认为60/10=6.0 浮点数
int ex_result=0;		//判断编曲模式是否录制完成的变量 为1时则完成录入
int ex_j=4;		//编曲模式单节重复次数计数变量 默认为4

//定义编曲模式多线程模式下的编曲和弦音频播放函数
void *chord_ex(void *arg)  	
{
	fade_out();
	system(kill);
	system(chord_wav[exbuf[ex]].wavplay);
	if(tx>450&&tx<550&&ty>0&&ty<100)  //中上按钮右边音量+
	{
		system(sound_up);
	}
	if(tx>250&&tx<350&&ty>0&&ty<100)  //中上按钮左边边音量-
	{
		system(sound_down);
	}
}
//和弦模式下的和弦播放函数
void *chord_play(void *arg)
{
	system(chord_wav[ins].wavplay);		//用系统指令代码的方式输入对应第ins号的音频播放指令
	if(tx>450&&tx<550&&ty>0&&ty<100)  //中上按钮右边音量+
	{
		system(sound_up);
	}
	if(tx>250&&tx<350&&ty>0&&ty<100)  //中上按钮左边边音量-
	{
		system(sound_down);
	}
}
void *chord_res(void *arg)		//定义按下和弦后 显示屏对应的位置闪烁后又重新恢复显示的多线程函数
{
	lcd_display(chord_img[ins].x+10,chord_img[ins].y+180,80,45,255,255,255,0);
	lcd_dis_bmp(chord_img[ins].bmppath,chord_img[ins].x,chord_img[ins].y,chord_img[ins].w,chord_img[ins].h,0);
	lcd_dis_bmp(chord_img[ins].bmppath,chord_img[ins].x,chord_img[ins].y,chord_img[ins].w,chord_img[ins].h,0);
	lcd_display(350,0,100,100,0,255,0,0);
	lcd_display(750,0,50,50,0,0,255,0);
}
void *chord_jugg(void *arg)		//定义和弦判断多线程函数
{
	if (ty>100)		//排除掉屏幕上分100像素的 用于控制按钮的部分
	{
		fade_out();
		system(kill);		//清理mplayer播放器
		pthread_t chordplay;	//多线程0 运行和弦播放函数
		pthread_create(&chordplay,NULL,chord_play,NULL);
		pthread_t chordres;		//多线程1 运行和弦按键恢复显示的函数
		pthread_create(&chordres,NULL,chord_res,NULL);
	}
}
void *chord_resex(void *arg)		//定义变去面试按下和弦后 显示屏对应的位置闪烁后又重新恢复显示的多线程函数
{
	lcd_display(chord_img[ins].x+10,chord_img[ins].y+180,80,45,255,255,255,0);
	lcd_dis_bmp(chord_img[ins].bmppath,chord_img[ins].x,chord_img[ins].y,chord_img[ins].w,chord_img[ins].h,0);
	lcd_dis_bmp(chord_img[ins].bmppath,chord_img[ins].x,chord_img[ins].y,chord_img[ins].w,chord_img[ins].h,0);
	lcd_display(350,0,100,100,255,0,0,0);
	lcd_display(750,0,50,50,0,0,255,0);
}
void *chord_juggex(void *arg)		//定义和编曲模式弦判断多线程函数
{
	if (ty>100)		//排除掉屏幕上分100像素的 用于控制按钮的部分
	{
		fade_out();
		system(kill);		//清理mplayer播放器
		pthread_t chordplay;	//多线程12 运行和弦播放函数
		pthread_create(&chordplay,NULL,chord_play,NULL);
		pthread_t chordresex;		//多线程13 运行和弦按键恢复显示的函数
		pthread_create(&chordresex,NULL,chord_resex,NULL);
	}
}

//定义多线程模式下的键盘音频播放函数 同和弦模式
void *key_play(void *arg)
{
	system(key_wav[ins].wavplay);
	if(tx>450&&tx<550&&ty>0&&ty<100)  //中上按钮右边音量+
	{
		system(sound_up);
	}
	if(tx>250&&tx<350&&ty>0&&ty<100)  //中上按钮左边边音量-
	{
		system(sound_down);
	}
}
void *key_res(void *arg)		//定义键盘按键闪烁及恢复函数
{
	lcd_display(key_img[ins].x+10,key_img[ins].y+180,80,45,255,255,255,0);
	lcd_dis_bmp(key_img[ins].bmppath,key_img[ins].x,key_img[ins].y,key_img[ins].w,key_img[ins].h,0);
	lcd_dis_bmp(key_img[ins].bmppath,key_img[ins].x,key_img[ins].y,key_img[ins].w,key_img[ins].h,0);
	lcd_display(350,0,100,100,0,255,0,0);
	lcd_display(750,0,50,50,0,0,255,0);
}
void *key_jugg(void *arg)		//定义键盘判断函数
{
	if (ty>100)		//排除掉屏幕上分100像素的 用于控制按钮的部分
	{
		fade_out();
		system(kill);
		pthread_t keyplay;		//多线程2 运行键盘播放函数
		pthread_create(&keyplay,NULL,key_play,NULL);
		pthread_t keyres;		//多线程3 运行键盘恢复函数
		pthread_create(&keyres,NULL,key_res,NULL);
	}
}

//定义多线程模式下的鼓点音频播放函数 同和弦模式
void *beat_play(void *arg)
{
	system(beat_wav[bet].wavplay);
	if(tx>450&&tx<550&&ty>0&&ty<100)  //中上按钮右边音量+
	{
		system(sound_up);
	}
	if(tx>250&&tx<350&&ty>0&&ty<100)  //中上按钮左边边音量-
	{
		system(sound_down);
	}
}
void *beat_res(void *arg)		//定义鼓点按键闪烁及恢复函数
{
	lcd_display(beat_img[bet].x+15,beat_img[bet].y+185,150,45,255,255,255,0);
	lcd_dis_bmp(beat_img[bet].bmppath,beat_img[bet].x,beat_img[bet].y,beat_img[bet].w,beat_img[bet].h,0);
	lcd_dis_bmp(beat_img[bet].bmppath,beat_img[bet].x,beat_img[bet].y,beat_img[bet].w,beat_img[bet].h,0);
	lcd_display(350,0,100,100,0,255,0,0);
	lcd_display(750,0,50,50,0,0,255,0);
}
void *beat_jugg(void *arg)		//定义鼓点判断函数
{
	if (ty>100)		//排除掉屏幕上分100像素的 用于控制按钮的部分
	{
		fade_out();
		system(kill);
		pthread_t beatplay;		//多线程4 运行鼓点播放函数
		pthread_create(&beatplay,NULL,beat_play,NULL);
		pthread_t beatres;		//多线程5 运行鼓点恢复函数
		pthread_create(&beatres,NULL,beat_res,NULL);
	}
}

//编曲模式显示函数
void *chord_disex(void *arg)
{
	lcd_dis_bmp("Chords_All.bmp",0,0,800,480,0);  	//显示对应的和弦总体图片
	lcd_dis_bmp("Chords_All.bmp",0,0,800,480,0);
	lcd_display(350,0,100,100,255,0,0,0);		//显示中上位置 100*100大小的绿色按钮 用于切换模式
	lcd_display(750,0,50,50,0,0,255,0);		//显示右上位置 50*50大小的红色按钮 用于关闭程序
	lcd_display(0,0,50,50,0,0,255,0);
}

//定义和弦模式初始化显示函数
void *chord_dis(void *arg)
{
	lcd_dis_bmp("Chords_All.bmp",0,0,800,480,0);  	//显示对应的和弦总体图片
	lcd_dis_bmp("Chords_All.bmp",0,0,800,480,0);
	lcd_display(350,0,100,100,0,255,0,0);		//显示中上位置 100*100大小的绿色按钮 用于切换模式
	lcd_display(750,0,50,50,0,0,255,0);		//显示右上位置 50*50大小的红色按钮 用于关闭程序
}
//定义键盘模式初始化显示函数
void *key_dis(void *arg)
{
	lcd_dis_bmp("Keys_All.bmp",0,0,800,480,0);  	//显示对应的键盘总体图片
	lcd_dis_bmp("Keys_All.bmp",0,0,800,480,0);
	lcd_display(350,0,100,100,0,255,0,0);
	lcd_display(750,0,50,50,0,0,255,0);
}
//定义鼓点模式初始化显示函数
void *beat_dis(void *arg)
{
	lcd_dis_bmp("Beats_All.bmp",0,0,800,480,0);  	//显示对应的鼓点总体图片
	lcd_dis_bmp("Beats_All.bmp",0,0,800,480,0);
	lcd_display(350,0,100,100,0,255,0,0);
	lcd_display(750,0,50,50,0,0,255,0);
}

void *ex_play(void *arg)   	//编曲模式循环播放函数
{
	int l;
	for(l=0;l<ex_j;l++)
	{
		pthread_t chordex;		//多线程14 运行编曲播放函数
		pthread_create(&chordex,NULL,chord_ex,NULL);
		sleep(bpm_one);
	}		
}
//主函数
int main(void)
{
	//初始化 建立管道 更改管道属性 杀死已有的mplayer播放器进程
	system(mkpp);
	system(chpp);
	system(kill);
	
	while(1)	//循环进行
	{
		
		pthread_t chorddis;		//多线程6 进行和弦模式初始化显示函数
		pthread_create(&chorddis,NULL,chord_dis,NULL);
		
		while(1)	//和弦模式循环
		{
			lcd_display(350,0,100,100,0,255,0,0);		//一直显示按键
			lcd_display(750,0,50,50,0,0,255,0);
			touch_scan();		//执行触摸板扫描函数
			//printf("x=%d,y=%d,p=%d\n",tx,ty,tp);	
			if(tx>350&&tx<450&&ty>0&&ty<100)  //中上按钮位置切换
				{
					//printf("Centry Up kill\n");
					fade_out();
					system(kill);			//杀死已有进程
					tx=0;		//触摸板坐标变量清零 防止连续判断
					ty=0;
					break;
				}
			if(tx>750&&tx<800&&ty>0&&ty<50)  //右上按钮关闭程序
				{
					fade_out();
					system(kill);		//杀死已有进程
					return 0;		//强制中断主函数
				}
			pthread_t chords;		//多线程7 进行和弦模式判断函数
			pthread_create(&chords,NULL,chord_jugg,NULL);	
		}
		
		pthread_t keydis;		//多线程8 进行键盘模式初始化显示函数
		pthread_create(&keydis,NULL,key_dis,NULL);
		
		while(1)	//键盘模式循环 同和弦模式循环
		{
			lcd_display(350,0,100,100,0,255,0,0);
			lcd_display(750,0,50,50,0,0,255,0);
			touch_scan();
			//printf("x=%d,y=%d,p=%d\n",tx,ty,tp);
			if(tx>350&&tx<450&&ty>0&&ty<100)  //切换
				{
					//printf("Centry Up kill\n");
					fade_out();
					system(kill);
					tx=0;
					ty=0;
					break;
				}
			if(tx>750&&tx<800&&ty>0&&ty<50)  //关闭
				{
					fade_out();
					system(kill);
					return 0;
				}
			pthread_t keys;		//多线程9 进行键盘模式判断函数
			pthread_create(&keys,NULL,key_jugg,NULL);		
		}
		
		pthread_t beatdis;		//多线程10 进行鼓点模式初始化显示函数
		pthread_create(&beatdis,NULL,beat_dis,NULL);
		
		while(1)	//鼓点模式循环 同和弦模式循环
		{
			lcd_display(350,0,100,100,0,255,0,0);
			lcd_display(750,0,50,50,0,0,255,0);
			touch_scan();
			//printf("x=%d,y=%d,p=%d\n",tx,ty,tp);
			if(tx>350&&tx<450&&ty>0&&ty<100)  //切换
				{
					//printf("Centry Up kill\n");
					fade_out();
					system(kill);
					tx=0;
					ty=0;
					break;
				}
			if(tx>750&&tx<800&&ty>0&&ty<50)  //关闭
				{
					fade_out();
					system(kill);
					return 0;
				}
			pthread_t beats;		//多线程11 进行鼓点模式判断函数
			pthread_create(&beats,NULL,beat_jugg,NULL);	
		}
		
		pthread_t chorddisex;		//多线程15 进行编曲模式初始化函数
		pthread_create(&chorddisex,NULL,chord_disex,NULL);
		while(1)	//编曲模式循环 大部分同和弦模式循环
		{
			lcd_display(350,0,100,100,255,0,0,0); //显示蓝色
			lcd_display(750,0,50,50,0,0,255,0);
			lcd_display(0,0,50,50,0,0,255,0);
			touch_scan();
			//printf("x=%d,y=%d,p=%d\n",tx,ty,tp);
			if(tx>350&&tx<450&&ty>0&&ty<100)  //切换
				{
					//printf("Centry Up kill\n");
					fade_out();
					system(kill);
					tx=0;
					ty=0;
					break;
				}
			if(tx>750&&tx<800&&ty>0&&ty<50)  //关闭
				{
					fade_out();
					system(kill);
					return 0;
				}
			if(tx>0&&tx<50&&ty>0&&ty<50)  //中断 开始播放编曲程序
				{
					ex_result=1;
				}
			//printf("i=%d\n",i);
			if(ex_i>0&&ex_result==1)
			{
				fade_out();
				system(kill);
				if(exbuf[ex_i-3]<1)
				{
					bpm_one=6.0;
				}
				else
				{
					bpm_one=6/exbuf[ex_i-3];  //第ex_i-3次录入的和弦编号为bpm值除以10 如按键位置为6 则bpm为60 每拍的时间为1s
				}
				int j,k;
				if(exbuf[ex_i-2]<1)
				{
					j=1;		//默认循环次数值为1
				}
				else
				{
					j=exbuf[ex_i-2];  //第ex_i-2次录入的和弦编号为单节和弦循环次数值
				}
				if(exbuf[ex_i-1]<1)
				{
					ex_j=4;		//默认单节和弦循环次数值为4
				}
				else
				{
					ex_j=exbuf[ex_i-1];		//第ex_i-1次录入的和弦编号为单节中一个和弦重复循环次数的值
				}
				for(k=0;k<j;k++)
				{
					for(ex=0;ex<ex_i-3;ex++)
					{
						pthread_t explay;		//多线程17 进行和弦模式判断函数
						pthread_create(&explay,NULL,ex_play,NULL);	
						sleep(bpm_one*ex_j);
					}
				}
				ex_i=0;
				ex_result=0;
			}
			else
			{
				pthread_t chordsex;		//多线程16 进行编曲模式判断函数
				pthread_create(&chordsex,NULL,chord_juggex,NULL);	
				exbuf[ex_i]=ins;  		//将按键位置赋值给exbuf变量 录入8个和弦 和一个bpm变量 一个循环次数变量
				ex_i++;
			}
		}
			
	}
	return 0;
}

附录:关于旧文新发

为何要进行旧文新发?
因为我在2023年博客之星评选中发现 有的人转载、抄袭他人文章 稍微改动几下也能作为高质量文章入选
所以我将把我的旧文重新发一次 然后也这样做

2023年博客之星规则:

  1. 自2023年1月1日起算起,平均每周创作过至少一篇高质量且非付费专栏的原创文章即可入围。由于博客之星是年度评选,所以统计时间一直截止到2023年12月17日。
  2. 高质量博文为80分以上原创博文,质量分查询地址:https://www.csdn.net/qc
  3. 入围条件补充说明:当前的入围状态为动态,一旦未达到每周平均创作过至少一篇高质量且非付费专栏的原创文章入围资格将会跳出入围资格,若当前还未入围者通过后期创作也可入围,当下并非最终结果。

标签:课设,bmppath,bmp,lcd,模式,编曲,240,100
From: https://blog.csdn.net/weixin_53403301/article/details/139294875

相关文章

  • 分清策略的驱动模式:事件驱动概念
    如何理解事件驱动概念?比方说我是一家理发店的店长,我设计好了一套从顾客进店开始的流程我把这套流程交给门口的迎宾人员,请问什么时候这个迎宾人员会去执行这套流程?答案是:客人来了事件驱动其实就是,当某一个事情发生以后,我执行对应的操作。也就是if条件:执行事件判断一下驱动方......
  • 什么是代理模式?
    代理模式(ProxyPattern)是程序设计中一种重要的设计模式,其定义是为其他对象提供一种代理以控制对这个对象的访问。以下是关于代理模式的详细解释:一、定义与简介代理模式的主要作用是在客户端和目标对象之间增加一个代理对象,作为中介来控制对目标对象的访问。在某些情况下,一个......
  • SSH连接NAT网络模式VirtualBox虚拟机
    Host:Windows11Target:Ubuntu22onVirtualBox原理:使用网络端口转发功能,把本地端口映射到虚拟机的22端口。1.配置端口转发NAT网络模式下,依次点击:虚拟机-->网络-->适配器1-->高级-->端口转发。 2.填写网络参数Name:ssh(随便写,最好填写和功能相关的字符串);Prot......
  • 代理模式
    当然,以下是一个关于代理模式的Markdown文件,展示了C#的一个简单案例。代理模式(ProxyPattern)代理模式是一种设计模式,它为其他对象提供一种代理以控制对这个对象的访问。常见的代理类型包括远程代理(远程控制对象)、虚拟代理(延迟加载对象)和保护代理(控制对对象的访问权限)。结构......
  • 装饰模式
    以下是关于装饰模式的Markdown文件,其中包含C#示例代码:装饰模式(DecoratorPattern)装饰模式是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这个模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整的前提下,提供额外的功能。模式结构......
  • 设计模式:装饰模式(Decorator)
    设计模式:装饰模式(Decorator)设计模式:装饰模式(Decorator)模式动机模式定义模式结构时序图模式实现在单线程环境下的测试在多线程环境下的测试模式分析优缺点适用场景应用场景应用实例模式扩展参考设计模式:装饰模式(Decorator)装饰模式(Decorator)属于结构型模式(Structural......
  • uniapp实现PDA扫码(广播模式)
    1.进入开发者模式查看PDA的广播动作和广播标签2.在uni-app项目里新建一个公共组件就叫pda-scan吧,放到公共组件components中,目录:components/pda-scan/pda-scan.vue<template> <view> </view></template><scriptsetup>import{onShow,onHide,onLoad,onUnload}from......
  • 关于Visitor模式的一些看法
    访问者模式(Visitor)1.意图表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。2.适用性在下列情况下使用Visitor模式:一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。......
  • 设计模式——工厂三兄弟之简单工厂
    1.业务需求​大家好,我是菠菜。在介绍这期简单工厂设计模式前,我们先来看看这样的需求:制作一个简单的计算器,能够实现控制台输入俩个数以及运算符完成运算。2.初步实现实现第一版思路:​创建计算器类,控制台输入俩个数以及运算符,通过if条件输出运算结果。CalClient类:pu......
  • MySQL四种主要的存储引擎,约束条件null not null,严格模式,基本字段类型之整型,浮点型,
    ⅠMySQL之存储引擎【一】什么是存储引擎日常生活中文件格式有很多,并且针对不同的文件格式会有对应不同的存储方式和处理机制针对不同的数据应该有对应的不同的处理机制存储引擎就是不同的处理机制【二】MySQL四种主要的存储引擎【1】Innodb是MySQL5.5版本之后的默认存......