音频(八)——I2S 输出正弦波

I2S 输出正弦波

  • PC 端:生成一个频率为 1KHz 的正弦波 C 语言数组
  • MCU 端:将正弦波数组使用 I2S 输出
  • AP 端:接收从 MCU I2S 端口出来的正弦波数据并测量 THD+N 等数据

PC 端生成正弦波数组

原理

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

  • A 表示幅值
  • w 表示角速度 w = 2 Π f w=2Πf w=f T = 2 Π / w T = {2Π}/w T=/w T = 1 / f T = 1/f T=1/f

代码实现

源码

#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

波形

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

音频(八)——I2S 输出正弦波_第1张图片

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

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

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

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

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

基本思路:

  • 采样频率和需要的采样点控制步长
  • 采样位数控制幅值
    • char 型数据,即 8 位采样位数的取值范围 − 2 7 —— 2 7 − 1 -2^7——2^7-1 27——271
    • short 型数据,即 16 位采样位数的取值范围 − 2 15 —— 2 15 − 1 -2^{15}——2^{15}-1 215——2151
    • int 型数据, 即 32 位采样位数的取值范围 − 2 31 —— 2 31 − 1 -2^{31}——2^{31}-1 231——2311

源码实现

#include 
#include 
#include 

#define SAMPLE_POINT_NUM        (48)        /* 需要生成的点的个数 */
#define SAMPLE_BIT              (16)        /* 采样位数 */

#define PI                      (3.1415926) /* 数学中的常量:Π */
#define POINT_BUFFER_LEN        (128)

int generate_data[POINT_BUFFER_LEN];        /* 生成的数据放在此数组中 */

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;

    sin_max_data = get_sin_max(SAMPLE_BIT - 1);

    for (int i = 0; i < point; i++)
    {
        data = sin_max_data * sin(2 * PI * (1.0 / point) * 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——2311

波形

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

音频(八)——I2S 输出正弦波_第2张图片

I2S 输出

数据通路

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

AP 仪器测试

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

波形测试

音频(八)——I2S 输出正弦波_第3张图片

FFT 测试

音频(八)——I2S 输出正弦波_第4张图片

THD+N 测试

测试数据
音频(八)——I2S 输出正弦波_第5张图片

频率测试

测试数据
音频(八)——I2S 输出正弦波_第6张图片

你可能感兴趣的:(音频,正弦波数组,I2S,AP,THD+N,采样频率和采样位数)