电子说
首先,微处理器被编程为80MHz Olimex PIC32,焊接到PIC32-PINGUINO-OTG开发板。(对于那些曾经使用Arduino板进行修改的人:它是相同的,只有更快的芯片和更少的内置库)算法必须以固定的时间间隔对输入信号进行采样,将此信号转换为频域,并可视化检测到的频率在16x16x5 LED矩阵上。
当然,在编写任何代码之前,我们必须弄清楚如何将输入样本转换为频率分布。通过对输入信号应用离散傅里叶变换(DFT),在信号处理中始终完成这一事情。给定以恒定频率采样的信号,DFT输出一组落在信号中的幅度或频带。例如,当您的信号主要由中间C(或Do)音调组成时,DFT将为频带分配相对较高的幅度并匹配相应的262 Hz频率。
然而,人耳以对数方式感知声音,这意味着声音信号的频率加倍仅被视为线性更高的音调。为了弥补这一点,我们使用了Constant Q变换(CQT)代替DFT。简而言之,在DFT返回频带f-2f-3f-4f-等的幅度的情况下,CQT与频带f-2f-4f-8f-etc一起工作。
因此,从理论角度来看,3DSA所需的算法非常简单:以规则的时间间隔对输入信号进行采样,对16个频带应用CQT计算幅度,并使16个LED列中的每一个适当地闪烁。鉴于Pinguino开发板支持C,我们假设实现这个算法不会那么难。但是,总会出现一些挑战:
第一个障碍:如果您只有一个线程,您如何定期采样信号?一个简单的解决方案是获取样本,计算CQT和可视化,让线程休眠直到某个时间段已经过去,然后再开始新的样本 - 计算 - 可视化循环。但是,我们希望我们的采样率为14 KHz,这在80 MHz微处理器上留下了课程,而不是样本之间的6k个时钟周期来计算CQT。这证明是不够的 - 最后我们为每个计算 - 可视化周期使用了~1M个时钟周期,因此我们必须弄清楚如何在进行CQT计算和旧样本的LED可视化时采集新样本。
在仔细阅读了许多Pinguino论坛之后,解决方案以中断的形式出现:一段比其他代码具有更高优先级的代码,并由处理器以指定的时间间隔执行。由于Pinguino开发人员没有为PIC32上的中断提供C库,因此我们必须通过将某些处理器位设置为正确值来手动实现此功能。成长为Java程序员后,我几乎可以感受到代码中的硅片
另一个大障碍是PIC32芯片不存在的浮点功能。在我们的CQT实现的内部循环中执行任何浮点运算会使代码减慢一个数量级,从而以幻灯片形式转换LED可视化(现在我知道如何使用旧GPU)。为了解决这个问题,我们使用了一个临时的定点数字格式,使用了10个小数位。这是一个复杂的乘法,但完成了工作。
全部0条评论
快来发表一下你的评论吧 !