完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1.前言
本文为本学期一门课程的一次课程设计大作业,题目是《音乐合成器设计》,想着作业做也做了,不如写下这篇博客巩固一下学习所得,同时也给有需要的人分享经验。所做工作主要有一下几个:1.基于乐曲简谱和“十二平均律”,使用MATLAB分析不同单音节的频谱;2.基于STM32利用乐音频率实现完整音乐的合成和播放功能。 2.前置知识 十二平均律 十二平均律,亦称“十二等程律”,世界上通用的一组音(八度)分成十二个半音音程的律制,各相邻两律之间的振动数之比完全相等。十二平均律在交响乐队和键盘乐器中得到广泛使用,钢琴即是根据十二平均律来定音的。-——来源百度百科 划重点,十二平均律是组成一首音乐的基础,各相邻两律之间的振动数之比完全相等。换言之就是常见的Do Re Mi Fa So La Si Do和其他四个半音。 3.单音频谱分析 篇幅有限,笔者只录下7个常见单音。话不多说,立马翻出半途而废,尘封多年的吉他,用手机把7个单音逐个录了下来。 Do 2弦第1品、 Re 2弦第3品、Mi 1弦空弦、Fa 1弦第1品、So 1弦第3品、La 1弦第5品、Si 1弦第7品。——来自百度,笔者吉他水平实在太差 使用MATLAB对单音进行傅里叶变换(FFT),得到该音节的频谱图 MATLAB代码: close all; clear all; clc; figure; [filename,filepath]=uigetfile(‘.wav’,‘Open wav file’); [w,fs,bits]=wavread([filepath,filename]); %从电脑文件夹选择wav音频文件 sound(w,fs,bits); y=w(:,1); display(‘声音文件的大小为:’);size(w) subplot(211);plot(y);title(‘时域波形’); N=pow2(nextpow2(length(y))); Y=fft(y,N); subplot(212);plot(fs*[1:N]/N,abs(Y));title(‘幅度值’);grid; 注意有些手机录音机输出的是.m4a的MPEG-4音频文件,要使用转码软件转成.wav格式。 频谱如下: 1.Do:频率大约在380Hz 2.Re:436Hz 3.Mi:492Hz 4.Fa:522Hz 5.So:584Hz 6.La:654Hz 7.Si:734Hz 综上,Do:380Hz Re:436Hz Mi:492Hz Fa:522Hz So:584Hz La:654Hz Si:734Hz。 他们之间的频率差56Hz 56Hz 30Hz 62Hz 70Hz 80Hz。 除了Re 和Mi之间没有半度音,其他都有半度音,考虑到手机录音存在偏差,基本各音节的频率差为30,基本满足了“各相邻两律之间的振动数之比完全相等”。 十二平均律的频谱分析到此为止。 4.基于STM32电子琴设计 本实验使用的是STM32F103和一个无源蜂鸣器。由于无源蜂鸣器的工作频率是在2KHz~5KHz,而上面吉他所测得的频率都在1KHz以下,显然不能满足无源蜂鸣器的工作频率。于是笔者查到下表: 小字四组则是2KHz以上的十二平均律频率。 4.1 利用STM32内部定时器产生PWM输出信号 PWM就是脉冲宽度调制,由高电平和低电平来回跳变组成一组信号来驱动元件,其中有两个关键指标:频率和占空比。 1秒内,0.5秒开,0.5秒灭,占空比是50%对吧?那么,1毫秒内,0.5毫秒开,0.5毫秒灭,占空比也是50%,对吧?如果是1秒呢,频率就是1HZ,如果是1毫秒,频率就是1KHZ,显然,同样是50%占空比,如果频率是1HZ,那电机肯定是跳着走的,灯光肯定闪得可以跳舞,不具有调速和调光的意义。——@一个在奋斗路上前行的小菜鸟 笔者使用Tim3通道2输出一路PWM信号,定时器的参数由结构体TimeBaselnitTypeDef定义,主要包括预分频系数、时钟分割、计数器模式、计数溢出大小等。例如,要由TIM3(定时器3)产生一个时长为1 s的定时,首先,应进行系统时钟的设置,得到TIM3CLK=72MHz,然后进行定时器设置。其中,预分频系数为35 999,此时,TIM3时钟为72 MHz/36 000=2 kHz,无时钟分割。设置计数溢出大小为1 999,即每计2 000个数就产生一个更新事件,输出频率为2 kHz/2 000=1 Hz。设置如下: TIM_TimeBaseStructure.TIM_Period=2000-1; //自动装载周期值 TIM_TimeBaseStructure.TIM_Prescaler=36000-1; //预分频值 TIM_TimeBaseStructure.TIM_ClockDivision=0; //时钟分割 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式 4.2占空比 有如下含义:在一串理想的脉冲周期序列(如方波)中,正脉冲的持续时间与脉冲总周期的比值。 当TIM_Period为1 999时,若想得到占空比50%,则TIM_Pulse应设置为(1999+1)/2=1000。具体设置如下: TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2; //PWM模式2 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出极性高 4.3频率 音阶的产生依赖于PWM输出信号的频率。为了简化设计,我们令定时器的TIM_Period为1 999,且占空比始终为50%,根据式(1)则TIM_ Pulse为1000。此时,PWM输出信号频率仅与定时器预分频系数TIM_Prescaler有关,只需要调整该系数,即可得到所需信号频率。 TIM_Prescaler由下式得到: fsound为音阶对应的频率,如Do频率为2093 Hz。要产生该音频,TIM_Prescaler应为17。 4.4电路设计 4.5主要实现代码 beer.h #ifndef _beer_H #define _beer_H #include “stm32f10x.h” #include “delay.h” void TIM3_PWM_Init(u16 arr,u16 psc);//arr void music_note(u16 psc,u16 ms); #endif 1 2 3 4 5 6 7 8 9 10 beer.c #include “beer.h” void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能 PB,AFIO 端口时钟 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //部分重映射,到PB5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0--》PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度为 50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 GPIOB.5 TIM_TimeBaseStructure.TIM_Period=arr; //自动装载周期值 TIM_TimeBaseStructure.TIM_Prescaler=psc; //预分频值 TIM_TimeBaseStructure.TIM_ClockDivision=0; //时钟分割 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2; //PWM模式2 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出极性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能预装载寄存器 TIM_Cmd(TIM3, ENABLE);//使能TIM3 } void music_note(u16 psc,u16 ms) //单音节输出,包含预分频值和延迟时间 { TIM3_PWM_Init(2000-1,psc); TIM_SetCompare2(TIM3,1000); delay_ms(ms); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 main.c #include “stm32f10x.h” #include “delay.h” #include “beer.h” int main() { delay_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); while(1) { music_note(17,500); music_note(15,500); music_note(14,500); music_note(13,500); music_note(11,500); music_note(10,500); music_note(9,500); } } 实现效果:Do Re Mi Fa So La Si循环播放。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1750 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1608 浏览 1 评论
1049 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1665 浏览 2 评论
1924浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
710浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
559浏览 3评论
583浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
544浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 10:29 , Processed in 0.953101 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号