查看: 2035|回复: 1

[经验] 【我的毕设作品】数字语音存储回放系统

[复制链接]
  • TA的每日心情
    擦汗
    2019-7-25 08:15
  • 签到天数: 4 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2019-6-25 15:13:43 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 fx283 于 2019-6-25 17:38 编辑

            其实这并不是我的毕设作品,为了参与这个活动才加上的标签。但是作品还是有必要分享一下。
            一道全国大学生电子设计竞赛的题目:1999年的数字语音存储回放系统


    一、题目要求   
            先来简单看一下题目要求
    Screenshot_1.png


        基本部分
    Screenshot_2.png

        发挥部分
    Screenshot_3.png

            题目整体的结构比较简单,制作的思路也比较清晰。就直接给出详细的设计方案:

    二、硬件部分

    • 拾音器

            使用普通的咪头就可以完成采集,电阻分压,电容隔直。
    Screenshot_4.png

    • 放大器1

            题目要求放大倍数为46dB,也就是200倍的放大倍数,一级放大可能不太行,采用两级如下图所示的放大器电路串联。
    Screenshot_5.png

    • 滤波器1


            滤波器要求的通频带是300Hz~3400Hz。使用TI的在线滤波器设计工具Webench来进行设计,之后使用洞洞板来焊接。由于此处设计比较简单,就不再贴出具体的电路图了
    Screenshot_6.png

            如果对这个在线工具感兴趣先要简单学习一下,这里有简易的教学视频

    • 加法器


            因为单片机不能采集0V以下的电压,所以需要将信号抬升到0V以上,这里就使用一个加法器电压,调节前级电路使得信号的峰峰值最大不超过3.3V,这里将信号抬升1.65V,这样采集到的音频信号就会在0V~3.3V之间了。
    Screenshot_7.png

    • 限幅器


            为了防止某一时刻突然的一个大的声响导致信号电平激增,意外烧坏单片机,所以出于安全的考虑使用一个限幅器电路,将信号电平保持在3.3V以下。
    Screenshot_8.png

    • 滤波器2

            由于此处的滤波器要求的通频带和滤波器1相同,所以使用和滤波器1相同的电路。

    • 放大器2

            此处要求的放大倍数为43dB,为100倍,一级放大已经可以满足要求,故此处使用一级放大电路
    Screenshot_5.png

    • 功放

            因为题目要求的是接一个耳机,那么可以不需要接功率放大电路,只将耳机接在放大器的后面就可以,但是演示效果不好,所以这里使用功率放大电路驱动喇叭去播放录音。使用的是功率放大器模块,PAM8403
    Screenshot_9.png

    • 系统整体图片

    Screenshot_12.png

    三、软件部分

    • 说明:

            基于正点原子战舰V3开发板的触摸屏实验进行修改,硬件测试平台为太极M3开发板,引脚基本兼容战舰V3开发板,显示屏(触摸)引脚、TF卡引脚完全兼容

    • 程序操作方法:

            1、插入TF卡
            2、打开电源,点击显示屏上对用的区域即可执行相应的功能


    • 程序设计思路:

            1、使用定时器产生8KHz的中断,在中断中获取数据,存储到Buffer中
            2、存储512个字节后,就在主函数中将数据存入TF卡中的一个Page内
            3、当结束录音时,就记录当前的Page数,并写入第一个Page中,作为录音文件的信息
            4、DA出来时,同样使用这个定时器
            5、直通模式,在定时器中边采集变输出
            6、自动音量控制需要分析整个录音文件的均值,根据一定的关系式计算出一个因子
            7、提高信噪比,将信号电平与一个门限值比较,若小于门限,则判定为噪声信号,将其置0
            7、数据压缩:使用QuickLZ压缩算法,实时进行数据的压缩与解压
            8、矫正:使用SINC插值滤波的方法进行矫正
    • 主函数文件中的主要内容
    1. ……
    2. #include "AUDIO.h"
    3. #include "sdio_sdcard.h"
    4. #include "quicklz.h"

    5. /*
    6.         全局变量
    7. */
    8. //模式Sample、Play、Cross最多只能有一个为1,Info模式一直为1进行显示
    9. extern u8 Now_Mode[4];
    10. extern u8 Info_Mode[3];
    11. ……
    12.         
    13. qlz_state_compress state_compress;
    14. qlz_state_decompress state_decompress;
    15. extern size_t QuickLZ_Size ;

    16. int main(void)
    17. {

    18.         
    19. ……//一堆的初始化

    20.         //初始化UI界面,随意触发一下界面绘制
    21.         MODE_Scan_DISP(0 , 300 );
    22.         
    23.         
    24.         while(1)
    25.         {
    26.                 tp_dev.scan(0);
    27.                 if(tp_dev.sta&TP_PRES_DOWN)                        //触摸屏被按下
    28.                 {
    29.                          if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
    30.                         {
    31.                                 //扫描触摸屏,获得对应的函数
    32.                                 switch (MODE_Scan_DISP( tp_dev.x[0] , tp_dev.y[0] ) )//主要就是做界面的显示
    33.                                 {
    34.                                         case MODE_Sample:
    35.                                         if(Now_Mode[0])
    36.                                                 MODE_Sample_ON_Function();
    37.                                         else if( !Now_Mode[0] )
    38.                                                 MODE_Sample_OFF_Function();
    39.                                         break;
    40. ……
    41.                                         default:break;
    42.                                 }
    43.                         }
    44.                 }
    45.                
    46.                 //写入操作移出中断
    47.                 if(ADC_FINISH_FLAG)
    48.                 {
    49.                         ADC_FINISH_FLAG = 0;

    50.                         if( QuickLZ_Flag )
    51.                         {
    52.                                 QuickLZ_Size = qlz_compress(ADC_BUFF,(char*)DATA_BUFF,512, &state_compress);
    53.                                 SD_WriteDisk(DATA_BUFF,TF_Page_Count,1);
    54.                         }
    55.                         else
    56.                                 SD_WriteDisk(ADC_BUFF,TF_Page_Count,1);
    57.                         
    58.                         TF_Page_Count++;
    59.                         time_count++;
    60.                         sprintf(str,"%7.1f",(float)time_count*0.064);
    61.                        ……………………
    62.                         
    63.                 }
    64.                
    65.                 //读出操作移出中断
    66.                 if(DAC_FINISH_FLAG)
    67.                 {
    68.                         DAC_FINISH_FLAG = 0;
    69.                         
    70.                         if( QuickLZ_Flag )
    71.                         {
    72.                                 while(SD_ReadDisk(DATA_BUFF,TF_Page_Count,1)!=0);
    73.                                 if(TF_Page_Count != TF_End_Page)
    74.                                         qlz_decompress((char*)DATA_BUFF, DAC_BUFF , &state_decompress);
    75.                                 else
    76.                                         for(i=0;i<512;i++)
    77.                                                 DAC_BUFF[i] = DATA_BUFF[i];
    78.                         }
    79.                         else
    80.                                 while(SD_ReadDisk(DAC_BUFF,TF_Page_Count,1)!=0);
    81.                         
    82.                         ……………………
    83.                         
    84.                         if( TF_Page_Count > TF_End_Page )//播放完毕,自动触发结束函数
    85.                         {
    86.                                 
    87.                                 TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
    88.                                 TIM_ITConfig(TIM4,TIM_IT_Update,DISABLE);
    89.                                 
    90.                                 if(SINC_Flag)
    91.                                         MODE_Scan_DISP( 200 , 250 );
    92.                                 else
    93.                                         MODE_Scan_DISP( 50 , 100 );

    94.                                 INFO_SINC_Function_OFF();
    95.                                 MODE_Play_OFF_Function();

    96.                         }
    97.                 }

    98.         }
    99. }
    复制代码
           所有与音频采集处理、界面显示有关的函数全部都放在了这个Audio文件中,方便移植

    Screenshot_10.png



            程序最终实现的效果如下图所示:

    Screenshot_11.png


    四、功能设计

    • 存储

            因为单片机是串行操作,读取ADC的值和存储ADC的值不能同时进行,只要存储器写入一个字节的速度小于1/8K的时间,那么存储就不是问题,否则就会出现采集得快、存储得慢等,数据丢失等一系列问题。实际测试时发现,使用大容量存储介质SD卡的时候,需要一次写入512个字节。写入读出的速度测试如下:

    clipboard.png

            大于1/8K的125us,所以不可避免会出现在写入数据时数据丢失的问题,所以计划采用乒乓操作的思想进行处理,详细原理不再赘述。

    • 自动音量控制

            自动音量控制(AVC)是输出限幅装置的一种,其作用是将不同强度的语声调整到最适听取的水平。例如:在不调节电视机音量的情况下,有的电视节目声音很大,有的电视节目又声音很小。使用AVC功能后,电视机可以根据节目输入的音量水平,自动调节输出音量水平,保持声音的稳定,减少或消除爆音,同时放大较小的声音至适宜的范围。
    软件中首先将所有的音频数据统一处理,计算其平均功率,之后根据一定的计算规则生成一个比例因子,将此比例因子与音频数据相乘,控制数据的大小,使得信号得以实现自动音量控制。


    • 压缩算法

            QuickLZ是世界上速度最快的压缩库,每个核心达到308 Mbyte / s。易于使用且易于集成。其C语言版本的代码,可以在无障碍得在各种平台快速移植。如Windows上的Visual Studio,Linux上的gcc,ARM等。软件中使用此压缩算法QuickLZ V1.5.0。
            算法处理512个数据的速度测试:


    clipboard.png

            但是它有个最大的缺点:太占用资源,STM32F103ZET6一共64KB的RAM,它自己占用了56KB,下图中最后两个是此算法压缩和解压的结构体变量:

    clipboard.png

    • sinc函数矫正

            通过提高ADC的采样率可以使得信号的失真度降低。如果AD的采样率一定,那么就可以使用插值滤波器对信号进行处理。软件中另外开启一个32KHz的定时器,使得其DAC的速率变为32KHz,在每两个原采样点之间插入了3个零值。从频域的角度来说,并没有改变信号的单周期频谱,但是却将频谱进行了细化,具体的原理在数字信号处理教材中有讲解,此处不再赘述。

    五、系统测试

            最后附上系统整体测试的视频








    回复

    使用道具 举报

  • TA的每日心情
    开心
    2019-7-6 12:57
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2019-7-6 12:59:31 | 显示全部楼层
    不错,挺有帮助的,我最近准备电赛也在做这个题目,方案很有参考价值
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-19 08:44 , Processed in 0.125401 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.