【平头哥RVB2601创意应用开发】第四篇 声音直方图
[复制链接]
本篇测评实验的内容是将声音播放和显示结合起来,播放声音的同时屏幕同时显示声音强度的直方图。
先上视频,再解释实现方法。
视频
4-1
本实验代码是基于Offline版本的musicplay例程开发的。
该例程是将嵌入程序的mp3声音数据(以数组形式保存)播放出来。
例如实验中使用的welcome_mp3声音数据就保存在include/welcome_mp3.h中。
数组里的数据完全是按照mp3文件格式排布的。比如前四个字节表示声音数据段的帧头。感兴趣的朋友可以自己研究一下mp3文件格式,对理解这个声音播放demo还是很有帮助的。
MP3声音数据是压缩过的数据,需要先解码成PCM后才能播放。Demo中mp3数据解码是使用pvmp3dec开源的mp3解码库来实现的。
解码后的数据,送到AV_AO_ALSA PCM输出驱动进行音频输出。
在花了N多小时的研究后,终于定位到了音频解码后数据所在。
Player.c文件中_ptask()任务函数中,调用ad_decode()对mp3数据进行解码。解码后数据存放在dframe数组中。
rc = ad_decode(ad, dframe, &got_frame, &pkt);
接下来对音频数据进行处理,提取出声音的强度。下面的处理只是简单的对PCM幅度值进行平均处理。
if(dframe->linesize[0] > 1024){
tempmaxvalue = 0;
for(uint8_t j=0;j<16;j++){
blocknumtemp[j] = 0;
temptotal = 0;
for(uint8_t i=0;i<32;i++){
temp = *(dframe->data[0]+1+j*64+i*2);
temp = temp << 8;
temp += *(dframe->data[0]+j*64+i*2);
temptotal += temp;
}
blocknumtemp[j] = temptotal;
if(blocknumtemp[j] > tempmaxvalue){
tempmaxvalue = blocknumtemp[j];
}
}
if(tempmaxvalue >0){
for(uint8_t j=0;j<16;j++){
blocknum[j] = (blocknumtemp[j] * 8)/tempmaxvalue;
}
}
}
下面是把这些代表声音强度的数据在在屏幕以直方图形式显示出来。
void draw_block(uint8_t x, uint8_t y)
{
for(uint8_t i = x; i >= x-4; i--){
for(uint8_t j=y; j<= y+7; j++){
buf[j] = 1;
}
}
for(uint8_t j=y; j<= y+7; j++){
buf[x-4][j] = 0;
}
for(uint8_t i = x; i >= x-3; i--){
buf[y] = 0;
buf[y+7] = 0;
}
}
void draw_blocks()
{
uint8_t block_row, block_col, blockrownum,x,y;
for(uint8_t i=0;i<64;i++){
for(uint8_t j=0;j<128;j++){
buf[j] = 0;
}
}
for(block_col=1;block_col<= BLOCKCOLNUM;block_col++){
for(block_row=1;block_row<= blocknum[block_col-1];block_row++){
x = 63 - (block_row -1)*5;
y = (block_col - 1)*8;
draw_block(x, y);
}
}
}
|