首页 >> 大全

音频(八)——C语言生成正弦波并用 I2S 输出

2023-06-24 大全 47 作者:考证青年

文章目录 固定采样率下的正弦波数组 I2S 输出 USB 麦克风 AP 仪器测试

I2S 输出正弦波 PC 端 C 语言生成正弦波数组 原理

三角函数的公式 y = A s i n w x y = y=

代码实现 源码

#include 
#include 
#include #define SAMPLE_POINT_NUM            (64)        /* 需要生成的点的个数 */
#define SINE_MAX                    (512)       /* sin 函数幅值 */
#define PI                          (3.1415926) /* 数学中的常量:Π */
#define POINT_BUFFER_LEN            (128)int generate_data[POINT_BUFFER_LEN]; /* 生成的数据放在此数组中 */void get_sin_data(unsigned int point)
{unsigned int i = 0;float step = 0.0;float data = 0.0;int tem = 0;step = 2 * PI / point; /* 将 sin 函数从 [0-2Π] 等分为 N 个点,则每个点的步长为 2Π/point_num */for (i = 0; i < point; i++){data = SINE_MAX * sin(step * i);tem = (int)data;generate_data[i] = tem;}
}int main(int argc, char *argv[])
{get_sin_data(SAMPLE_POINT_NUM);for (int i = 0; i < SAMPLE_POINT_NUM; i++){printf("%d ", generate_data[i]);}printf("\r\n");return 0;
}

编译

gcc generate_sin_data.c -lm

需要用到数学库中的函数 sin ,所以链接的时候需要加上 lm 参数

运行结果

0 50 99 148 195 241 284 324 362 395 425 451 473 489 502 509 512 509 502 489 473 451 425 395 362 324 284 241 195 148 99 50 0 -50 -99 -148 -195 -241 -284 -324 -362 -395 -425 -451 -473 -489 -502 -509 -512 -509 -502 -489 -473 -451 -425 -395 -362 -324 -284 -241 -195 -148 -99 -50

从生成的数据中可以看出,数据的最大最小值分别为 512 和 -512

波形

将上述数据用散点图绘制出来如下图

固定采样率下的正弦波数组

上一节生成的正弦波数组 幅值 及 step 步长并没有考虑实际频率

实际音频输出是需要考虑:采样位数,采样频率,声道数详见音频(一)——基本概念及硬件拓扑

采样位数对应到正弦波中即为幅值

采样频率对应到正弦波中即为频率

基本思路:

源码实现

#include 
#include 
#include #define SAMPLE_POINT_NUM    (48)        /* 需要生成的点的个数,即每 ms 有多少个点,48000Hz - 48个点/ms; 16000 - 16个点/ms*/
#define SAMPLE_BIT          (16)        /* 采样位数 决定幅值 */
#define PI                  (3.1415926) /* 数学中的常量:Π */int generate_data[512]; /* 生成的数据放在此数组中 */int get_sin_max(int sample_bit)
{int value = 2;for (int i = 0; i < sample_bit - 1; i++){value = value * 2;}return value - 1;
}void get_sin_data(unsigned int point)
{float data = 0.0;int sin_max_data;float step = 0.0;sin_max_data = get_sin_max(SAMPLE_BIT - 1);step = 2 * PI / SAMPLE_POINT_NUM;for (int i = 0; i < point; i++){data = sin_max_data * sin(step * i);generate_data[i] = (int)data;}
}int main(int argc, char *argv[])
{get_sin_data(SAMPLE_POINT_NUM);for (int i = 0; i < SAMPLE_POINT_NUM; i++){printf("%d, ", generate_data[i]);}printf("\r\n");return 0;
}

编译

gcc generate_sin_data.c -lm

需要用到数学库中的函数 sin ,所以链接的时候需要加上 lm 参数

运行结果

0, 4276, 8480, 12539, 16383, 19947, 23169, 25995, 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272, 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276, 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995, -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272, -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276,

从生成的数据中可以看出,数据的最大最小值分别为 32767 和 -32767,16 位音频数据的取值范围为 − 2 31 —— 2 31 − 1 -2^{31}——2^{31}-1 −231——231−1

波形

将上述数据用散点图绘制出来如下图

I2S 输出 数据通路

sram/flash -> I2S master SDATAO -> AP SDATAI

USB 麦克风

对于 USB 麦克风,如果采样率为 16KHz,那么 1s 内有 16000 个点,1ms 内有 16 个点,其他采样率类似,如果是双声道,数据量需要乘以 2 。

对于全速设备的等时端点来说,1ms 来一次中断,所以将对应采样率的点数通过 USB 等时端点发送给主机即可。

short buf_mono_16KHz[] = {0, 12539, 23169, 30272, 32767, 30272, 23169, 12539, 0, -12539, -23169, -30272, -32767, -30272, -23169, -12539};
short buf_mono_32KHz[] = {0, 6392, 12539, 18204, 23169, 27244, 30272, 32137, 32767, 32137, 30272, 27244, 23169, 18204, 12539, 6392, 0, -6392, -12539, -18204, -23169, -27244, -30272, -32137, -32767, -32137, -30272, -27244, -23169, -18204, -12539, -6392, };
short buf_mono_48KHz[] = {0, 4276, 8480, 12539, 16383, 19947, 23169, 25995, 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272, 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276, 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995, -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272, -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276,};
short buf_mono_96KHz[] = {0, 2143, 4276, 6392, 8480, 10532, 12539, 14492, 16383, 18204, 19947, 21604, 23169, 24635, 25995, 27244, 28377, 29387, 30272, 31028, 31650, 32137, 32486, 32696, 32767, 32696, 32486, 32137, 31650, 31028, 30272, 29387, 28377, 27244, 25995, 24635, 23169, 21604, 19947, 18204, 16383, 14492, 12539, 10532, 8480, 6392, 4276, 2143, 0, -2143, -4276, -6392, -8480, -10532, -12539, -14492, -16383, -18204, -19947, -21604, -23169, -24635, -25995, -27244, -28377, -29387, -30272, -31028, -31650, -32137, -32486, -32696, -32767, -32696, -32486, -32137, -31650, -31028, -30272, -29387, -28377, -27244, -25995, -24635, -23169, -21604, -19947, -18204, -16383, -14492, -12539, -10532, -8480, -6392, -4276, -2143, };

软件测试 波形测试

频谱分析

上述代码中,将数组的幅值修改为 − 2 15 -2^{15} −215

得到的正弦波数组为

short test_buf_96_1db[] = {0, 1071, 2138, 3196, 4240, 5266, 6269, 7246, 8191, 9101, 9973, 10802, 11584, 12317, 12997, 13621, 14188, 14693, 15135, 15513, 15824, 16068, 16242, 16347, 16383, 16347, 16242, 16068, 15824, 15513, 15135, 14693, 14188, 13621, 12997, 12317, 11584, 10802, 9973, 9101, 8191, 7246, 6269, 5266, 4240, 3196, 2138, 1071, 0, -1071, -2138, -3196, -4240, -5266, -6269, -7246, -8191, -9101, -9973, -10802, -11584, -12317, -12997, -13621, -14188, -14693, -15135, -15513, -15824, -16068, -16242, -16347, -16383, -16347, -16242, -16068, -15824, -15513, -15135, -14693, -14188, -13621, -12997, -12317, -11584, -10802, -9973, -9101, -8191, -7246, -6269, -5266, -4240, -3196, -2138, -1071, };

该正弦波数组对应的 FFT 为

对于数字音频,根据 dBFS 的计算公式为:理解dB

d B = 20 ∗ l o g 10 s a m p l e 65535 dB = 20 * log_{10}{\frac{}{65535}} dB=20∗log10​​

由上公式可以算出两者相差 6dB。

对比两次频谱分析,差值也为 6dB( − 8 − − 2 {-8 - -2} −8−−2)。

通过测量二者的 RMS 也可以看出二者相差 6dB。

AP 仪器测试

AP 一起测试时,输入源选择数字音频接口即 I2S,并配置 AP 端 I2S 格式和 MCU 端格式一致

波形测试

FFT 测试

THD+N 测试

测试数据

频率测试

测试数据

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了