🎯要点
- 声音和信号处理:🎯乐器数字接口MIDI协议:🖊输入输出 | 🖊双重和三重跟踪 🖊自动生成三和弦 🖊琶音器 🖊循环踏板 | 🖊特雷门琴 | 🖊气鼓 | 🖊灯光秀控制 | 🖊逻辑门控制电机供电顺序 | 🖊MIDI 信号驱动播放器 | 🖊MIDI吉他 | 🖊Arduino开源声音控制音乐多媒体 | 🖊MIDI 混沌摆 | 🖊MIDI 脚踏开关键盘或控制器。🎯信号:🖊声音取样和播放 | 🖊音效 | 🖊傅里叶滤波 | 🖊Karplus强算法数字信号处理。🎯射频控制:🖊制作通用继电器控制的音序器 | 🖊制作波束控制器,设置天线波束并将其旋转到特定航向 | 🖊定向瓦特和驻波比表 | 🖊频率计数器测量并显示变频振荡器频率 | 🖊直接数字合成变频振荡器 | 🖊LoRa点对点通讯、网关、连接RESTful 和MQTT 服务器、 GPS跟踪。
- 🎯项目:🖊无线网络和蓝牙监控生物波反馈身体健康 | 🖊可穿戴身体和环境状态检测外套 | 🖊高频语音收发
- 🎯Python控制Arduino音频
🍇Arduino使用算法频谱分析语音信号
大多数处理数字信号的设备都使用离散傅里叶变换。 当我们谈论数字信号时,指的是音频信号、图像信号等。因此,这意味着您的电视、计算机和收音机在幕后进行离散傅里叶变换。
现在你知道了这件事的重要性,让我们看看它是如何运作的。请记住,这里提出的概念是基本概念,它只能被视为傅里叶理论的一般概述。
在数字信号处理中,我们处理的所有信号都是模拟信号。 我们的世界是一个模拟世界。 模拟信号就是时间连续信号,但是,计算机却是数字的。 因此,如果我们要处理所有模拟信号,就必须将其转换为数字信号。 这就是离散傅里叶变换发挥作用的时候,它将模拟信号转换为数字信号。
我不会太深入地讨论这个主题,因为它非常难以理解,所以让我们保持简单。 可以这么说,离散傅里叶变换可以将模拟信号(A)转换为数字信号(B),然后我们可以使用计算机或DSP对其进行处理(C),最后重建原始信号(D) 。
此算法是一种极其有效的离散傅里叶变换方法。 这种计算方法与其他离散傅里叶变换方法的主要区别在于,它在每次迭代中使用单个实值系数。 该分析的缺点是与快速傅里叶变换相比,其复杂度更高。 然而,对于少数频率,该算法在效率方面优于同类算法。 请记住,我们是在 Arduino 中实现该软件,因此硬件限制是一个重要问题。
我不会解释该算法背后的所有数学原理。我们将看看它在实际应用中是如何工作的。为了使用该算法,我们需要首先执行以下步骤:
- 确定采样率。
- 选择块大小N。
- 预先计算一个余弦项和一个正弦项。
- 预先计算一个系数。
我们需要计算对模拟信号进行采样的频率。 为此,我们需要将微控制器的时钟除以 2 以获得最大采样频率,因为这是奈奎斯特-香农采样定理中规定的。 我们需要实现的公式如下:
ω
0
=
2
π
k
N
k
∈
{
0
,
1
,
2
,
…
,
N
−
1
}
y
[
N
]
=
∑
n
=
0
N
x
[
n
]
e
−
j
2
π
n
k
N
\begin{aligned} & \omega_0=2 \pi \frac{k}{N} \\ & k \in\{0,1,2, \ldots, N-1\} \\ & y[N]=\sum_{n=0}^N x[n] e^{-j 2 \pi \frac{n k}{N}} \end{aligned}
ω0=2πNkk∈{0,1,2,…,N−1}y[N]=n=0∑Nx[n]e−j2πNnk
请记住,您可以修改此项目,以便它也可以识别特定的音频模式甚至单词。所以,该函数将如下所示:
void inico(){
while(true){
Goel gl = Goel(4000, N, SAMPLING_FREQUENCY);
gl.sample(A0);
float ligar = gl.detect();
if(ligar>900){
digitalWrite(led2, LOW);
for (int i = 0; i < 8; i++)
{
lc.setRow(0,i,invader1a[i]);
}
delay(3000);
ligarAudio();
break;
}
}
}
void ResetGoel(void)
{
Q2 = 0;
Q1 = 0;
}
void ProcessSample(byte sample)
{
float Q0;
Q0 = coeff * Q1 - Q2 + (float) sample;
Q2 = Q1;
Q1 = Q0;
}
void GetRealImag(float *realPart, float *imagPart)
{
*realPart = (Q1 - Q2 * cosine);
*imagPart = (Q2 * sine);
}
void sample(int sensorPin)
{
for (int index = 0; index < N; index++)
{
testData[index] = (byte) analogRead(0);
}
}
float detect()
{
int index;
float magnitudeSquared;
float magnitude;
float real;
float imag;
for (index = 0; index < N; index++)
{
ProcessSample(testData[index]);
}
GetRealImag(&real, &imag);
magnitudeSquared = real*real + imag*imag;
magnitude = (sqrt(magnitudeSquared)/2);
ResetGoertzel();
return magnitude;
}
void setup(){
pinMode(led2, OUTPUT);
pinMode(relay, OUTPUT);
pinMode(A0, INPUT);
//Serial.begin(9600);
lc.shutdown(0,false);
lc.setIntensity(0,5);
lc.clearDisplay(0);
digitalWrite(led2, HIGH);
digitalWrite(relay, LOW);
inicio();
}
char normalizacao(float valor){
char retorno = 0;
if(valor>200){
retorno += 1;
}
if(valor>210){
retorno += 2;
}
if(valor>220){
retorno += 4;
}
if(valor>260){
retorno += 8;
}
if(valor>300){
retorno += 16;
}
if(valor>350){
retorno += 32;
}
if(valor>380){
retorno += 64;
}
if(valor>400){
retorno += 128;
}
return retorno;
}