目录
一 算法原理
1 确定展示 音频采样在 X 轴一个点代表的 采样 周期,如 20ms
2 在 采样周期内确定一个最大值 和最小值
3 在坐标轴上 x 位置画一条直线, 从最小值 连到最大值
二 读取音频采样生成灰度图
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#define SAMPLE_HZ (48000)
#define PERIOD_MS (10)
#define PERIOD_SAMPLES (SAMPLE_HZ * 1ul * PERIOD_MS / 1000)
#define MAX_PIC_W (1280)
#define MAX_PIC_H (640)
void calc_peak(short *in, int num, int *max_peak, int *min_peak)
{
int i;
*min_peak = 32768;
*max_peak = -32768;
for(i = 0 ; i < num; ++i){
if (in[i] > *max_peak)
*max_peak = in[i];
if (in[i] < *min_peak)
*min_peak = in[i];
}
}
int draw_line(char *canvas, int max_w, int s_x, int s_y, int e_x, int e_y)
{
int deltax, deltay;
int draw_x, draw_y;
int step;
deltax = e_x - s_x;
deltay = e_y - s_y;
if (0 == deltax && 0 == deltay)
return 0;
if (abs(deltax) > abs(deltay)){
draw_x = s_x;
draw_y = s_y;
step = deltax > 0 ? 1 : -1;
while(draw_x != e_x){
draw_y = s_y + deltay * (draw_x - s_x) / deltax ;
canvas[draw_y * max_w + draw_x] = 255;
draw_x += step;
}
}else {
int step = deltay > 0 ? 1 : -1;
draw_x = s_x;
draw_y = s_y;
while(draw_y != e_y){
draw_x = s_x + deltax * (draw_y - s_y) / deltay;
canvas[draw_y * max_w + draw_x] = 255;
draw_y += step;
}
}
return 0;
}
int main(int ac, char *av[])
{
short buf_sample[PERIOD_SAMPLES];
char *buf_gray;
FILE *fp;
int ret;
int x;
int max_peak, min_peak;
int y_max, y_min;
if (ac < 3){
printf("usage : %s in_pcm , out.gray\n", av[0]);
return -1;
}
fp = fopen(av[1], "rb");
if (!fp)
return -1;
buf_gray = (char *)malloc(MAX_PIC_W * MAX_PIC_H);
memset(buf_gray, 0, MAX_PIC_W * MAX_PIC_H);
memset(buf_gray + (MAX_PIC_H / 2) * MAX_PIC_W, 128, MAX_PIC_W);
for(x = 0 ; x < MAX_PIC_W ; ++x){
ret = fread(buf_sample, sizeof(short), PERIOD_SAMPLES, fp);
if (ret != PERIOD_SAMPLES)
break;
calc_peak(buf_sample, PERIOD_SAMPLES, &max_peak, &min_peak);
y_min = (32768 - min_peak ) * MAX_PIC_H / 65536;
y_max = (32768 - max_peak ) * MAX_PIC_H / 65536;
draw_line(buf_gray, MAX_PIC_W, x, y_min, x , y_max);
}
fclose(fp);
fp = fopen(av[2], "wb");
printf("write resut to file %s\n", av[2]);
fwrite(buf_gray, 1, MAX_PIC_W * MAX_PIC_H, fp);
fclose(fp);
return 0;
}
效果如下:
三读取音频采样生成RGB彩色图
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#define SAMPLE_HZ (48000)
#define PERIOD_MS (2)
#define PERIOD_SAMPLES (SAMPLE_HZ * 1ul * PERIOD_MS / 1000)
#define MAX_PIC_W (1280)
#define MAX_PIC_H (640)
void calc_peak(short *in, int num, int *max_peak, int *min_peak)
{
int i;
*min_peak = 32768;
*max_peak = -32768;
for(i = 0 ; i < num; ++i){
if (in[i] > *max_peak)
*max_peak = in[i];
if (in[i] < *min_peak)
*min_peak = in[i];
}
}
int draw_line_rgb24(char *canvas, int max_w, int s_x, int s_y, int e_x, int e_y, char color_r, char color_g, char color_b)
{
int deltax, deltay;
int draw_x, draw_y;
int step;
deltax = e_x - s_x;
deltay = e_y - s_y;
if (0 == deltax && 0 == deltay)
return 0;
if (abs(deltax) > abs(deltay)){
draw_x = s_x;
draw_y = s_y;
step = deltax > 0 ? 1 : -1;
while(draw_x != e_x){
draw_y = s_y + deltay * (draw_x - s_x) / deltax ;
canvas[draw_y * max_w * 3 + draw_x * 3] = color_r;
canvas[draw_y * max_w * 3 + draw_x * 3 + 1] = color_g;
canvas[draw_y * max_w * 3 + draw_x * 3 + 2] = color_b;
draw_x += step;
}
}else {
int step = deltay > 0 ? 1 : -1;
draw_x = s_x;
draw_y = s_y;
while(draw_y != e_y){
draw_x = s_x + deltax * (draw_y - s_y) / deltay;
canvas[draw_y * max_w * 3 + draw_x * 3 ] = color_r;
canvas[draw_y * max_w * 3 + draw_x * 3 + 1] = color_g;
canvas[draw_y * max_w * 3 + draw_x * 3 + 2] = color_b;
draw_y += step;
}
}
return 0;
}
int main(int ac, char *av[])
{
short buf_sample[PERIOD_SAMPLES];
char *buf_rgb24;
FILE *fp;
int ret;
int x;
int max_peak, min_peak;
int y_max, y_min;
if (ac < 3){
printf("usage : %s in_pcm , out.rgb\n", av[0]);
return -1;
}
fp = fopen(av[1], "rb");
if (!fp)
return -1;
buf_rgb24 = (char *)malloc(MAX_PIC_W * MAX_PIC_H * 3);
memset(buf_rgb24, 0, MAX_PIC_W * MAX_PIC_H * 3);
memset(buf_rgb24 + (MAX_PIC_H / 2) * MAX_PIC_W * 3, 128, MAX_PIC_W * 3); // center line
for(x = 0 ; x < MAX_PIC_W ; ++x){
ret = fread(buf_sample, sizeof(short), PERIOD_SAMPLES, fp);
if (ret != PERIOD_SAMPLES)
break;
calc_peak(buf_sample, PERIOD_SAMPLES, &max_peak, &min_peak);
y_min = (32768 - min_peak ) * MAX_PIC_H / 65536;
y_max = (32768 - max_peak ) * MAX_PIC_H / 65536;
draw_line_rgb24(buf_rgb24, MAX_PIC_W, x, y_min, x , y_max, 0, 0, 255);
}
fclose(fp);
fp = fopen(av[2], "wb");
printf("write resut to file %s\n", av[2]);
fwrite(buf_rgb24, 1, MAX_PIC_W * MAX_PIC_H * 3, fp);
fclose(fp);
return 0;
}
效果如下: