之前一直想用单片机的adc播放音乐,一直有这个念头,网上找了很多的代码都很复杂,就想自己写一个兼容性高的,一眼就能看懂的WAVE解析的代码。以前基本功太差,现在感觉天清了雨晴了,我又觉得我行了!(狗头)
熬了两宿,对着两幅图把之前立的flag给补上了一部分。今天真的是写的太烦了,下边付了一份自己写的代码,代码目前的状态也就是能用吧!不稳定,bug超多,file safe啥的也没做,以后闲的蛋疼的时候在慢慢改。
代码先奉上,讲解日后心情好的时候补上。
?
?
?wave.c
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#include "wave.h"
void printf_c(void * data,unsigned char num)
{
unsigned int i = 0;
char name[num];
memcpy(name,data,num);
for(i=0;i<num;i++)
printf("%c",name[i]);
printf("\n");
}
int wave_asf(wave *ral_wave)
{
unsigned int read_len = 0;
unsigned int read_len_sizeof = 0;
unsigned int ChunkID = 0;
unsigned int local_offset = 0;
unsigned char * extern_data;
Wave_RIFF *baseframe;
Wave_Base *miniframe;
Wave_FMT *wavefmt;
WAVE_DATA *wavedata;
baseframe = (Wave_RIFF*)calloc(sizeof(Wave_RIFF),sizeof(char));
miniframe = (Wave_Base*)calloc(sizeof(Wave_Base),sizeof(char));
wavefmt = (Wave_FMT*) calloc(sizeof(Wave_FMT),sizeof(char));
wavedata = (WAVE_DATA*)calloc(sizeof(WAVE_DATA),sizeof(char));
read_len = fread(baseframe, 1, sizeof(Wave_RIFF), ral_wave->fp);
if(read_len<sizeof(Wave_RIFF))
printf("read file false!\n");
local_offset = local_offset + read_len;
bit8to32(&ChunkID,baseframe->ChunkID);
if(ChunkID != RIFF_id)
printf("file no wave!\n");
while(TURE){
memset(miniframe,0,sizeof(Wave_Base));
ChunkID = 0;
// 获取chunk_id
read_len = fread(miniframe, 1, sizeof(Wave_Base), ral_wave->fp);
if(read_len<sizeof(Wave_Base))
printf("read file false!\n");
local_offset = local_offset + read_len;
bit8to32(&ChunkID,miniframe->ChunkID);
switch(ChunkID){
case fmt_id:
read_len = fread(&read_len_sizeof, 1,sizeof(int) , ral_wave->fp);
local_offset = local_offset + read_len;
read_len = fread(wavefmt, 1,read_len_sizeof , ral_wave->fp);
local_offset = local_offset + read_len;
ral_wave->AudioFormate = wavefmt->AudioFormate;
ral_wave->BitePerSample = wavefmt->BitePerSample;
ral_wave->BlockAilgn = wavefmt->BlockAilgn;
ral_wave->ByteRate = wavefmt->ByteRate;
ral_wave->NumChannels = wavefmt->NumChannels;
ral_wave->SampleRate = wavefmt->SampleRate;
ral_wave->ChunkSize = read_len_sizeof;
break;
case data_id:
read_len = fread(wavedata, 1,sizeof(WAVE_DATA) , ral_wave->fp);
local_offset = local_offset + read_len;
ral_wave->Subchunck2Size = wavedata->Subchunck2Size;
goto out_while;
default:
read_len = fread(&read_len_sizeof, 1,sizeof(int) , ral_wave->fp);
local_offset = local_offset + read_len;
extern_data = (unsigned char*)calloc(read_len_sizeof,sizeof(char));
read_len = fread(extern_data, 1,read_len_sizeof , ral_wave->fp);
local_offset = local_offset + read_len;
// 文件指针后移
free(extern_data);
break;
}
}
out_while:
free(baseframe);
free(miniframe);
free(wavefmt);
free(wavedata);
ral_wave->DataOffset = local_offset;
printf("ral_wave->DataOffset %x\n",ral_wave->DataOffset);
printf("hello world~\n");
return 0;
}
int channel_select(wave *ral_wave)
{
switch(ral_wave->AudioFormate){
case 1:
return 1;
break;
case 2:
// 不支持其他
break;
default:
// 不支持其他
break;
}
return 0;
}
// 声道,采样率分离
void channal_sbisample(wave *ral_wave)
{
unsigned int read_len;
// printf("ral_wave->ByteRate %d\n",ral_wave->ByteRate);
// printf("ral_wave->BitePerSample %d\n",ral_wave->BitePerSample);
// printf("ral_wave->BlockAilgn %d\n",ral_wave->BlockAilgn);
// printf("ral_wave->NumChannels %d\n",ral_wave->NumChannels);
// printf("ral_wave->SampleRate %d\n",ral_wave->SampleRate);
// ByteRate == SampleRate * NumChannels * BitsPerSample/8
// BlockAlign == NumChannels * BitsPerSample/8
if(ral_wave->NumChannels == 1){
switch(ral_wave->BitePerSample){
case 8:
printf("channel 1,8 bit\n");
break;
case 16:
printf("channel 1,16 bit\n");
break;
default:
printf("chanel 1 error!\n");
break;
}
}
else if(ral_wave->NumChannels == 2){
switch(ral_wave->BitePerSample){
case 8:
printf("channel 2,8 bit\n");
break;
case 16:
printf("channel 2,16 bit\n");
c2b16 loca_c2b16;
read_len = fread(&loca_c2b16, 1,sizeof(c2b16) , ral_wave->fp);
printf("%d %d read_len %d\n",sizeof(c2b16),sizeof(short),read_len);
printf("loca_c2b16.L_c2b16 %x,loca_c2b16.R_c2b16 %x\n",loca_c2b16.L_c2b16,loca_c2b16.R_c2b16);
ral_wave->DataOffset = ral_wave->DataOffset + read_len;
printf("ral_wave->DataOffset %x\n",ral_wave->DataOffset);
// 直接写道到DAC?
break;
default:
printf("chanel 2 error!\n");
break;
}
}
else{
printf("error!\n");
}
}
int main(void)
{
wave *do_wave;
do_wave = (wave*)calloc(sizeof(wave),sizeof(char));
do_wave->fp = fopen("D:\\wave\\test.wav", "r");
wave_asf(do_wave);
if(channel_select(do_wave)!=1)
return 0;
for(int i = 0;i<1000;i++)
channal_sbisample(do_wave);
fclose(do_wave->fp);
free(do_wave);
return 0;
}
?wave.h
/*
* wave.h
*
* Created on: 2021年7月22日
* Author: uida0349
*/
#ifndef WAVE_H_
#define WAVE_H_
#define TURE 1
#define FALSE 0
// 将四个8bit的拼接成32bit的
#define bit8to32(a,b) {*a = b[3];*a = ((*a)<<8)|b[2];*a = ((*a)<<8)|b[1];*a = ((*a)<<8)|b[0];}
/**
* 此处用于存储WAV的id信息
* */
enum WAV_ID{
RIFF_id = 0x46464952,
fmt_id = 0x20746d66,
data_id = 0x61746164,
};
typedef struct wave_base{
//char ExtentsID[4];
unsigned char ChunkID[4];
}Wave_Base;
typedef struct wave_riff{
//char ExtentsID[4];
unsigned char ChunkID[4];
unsigned int ChunkSize;
unsigned char Format[4];
}Wave_RIFF;
typedef struct wave_fmt{
// fmt Bolck
unsigned short AudioFormate;
unsigned short NumChannels;
unsigned int SampleRate;
unsigned int ByteRate;
unsigned short BlockAilgn;
unsigned short BitePerSample;
}Wave_FMT;
typedef struct wave_data{
// data Block
unsigned int Subchunck2Size;
}WAVE_DATA;
typedef struct wave_Extents{
char ExtentsID[4];
unsigned int ExtentsSize;
unsigned int ExtentsDataLength;
void * ExtentsData;
}Extents_data;
typedef struct wave_demo{
FILE *fp;
// RIFF Bolck
char ChunkID[4];
unsigned int ChunkSize;
char Format[4];
// fmt Bolck
char Subchunk1ID[4];
unsigned int Subchunk1Size;
unsigned short AudioFormate;
unsigned short NumChannels;
unsigned int SampleRate;
unsigned int ByteRate;
unsigned short BlockAilgn;
unsigned short BitePerSample;
// extents Block
Extents_data *ExtentsFrames;
// data Block
char Subchunck2ID[4];
unsigned int Subchunck2Size;
// data offset
unsigned int DataOffset;
}wave;
// 存储单声道8bit的数据
typedef unsigned char c1b8;
// 存储单声道16bit的数据
typedef unsigned short c1b16;
// 存储双声道8bit的数据
typedef struct {
unsigned char L_c2b8;
unsigned char R_c2b8;
}c2b8;
// 存储双声道16bit的数据
typedef struct {
unsigned short L_c2b16;
unsigned short R_c2b16;
}c2b16;
#endif /* WAVE_H_ */
下一步的计划,一直到单片机里边,再加个timer,调度啥的,争取早点实现单片机片上DAC播放WAVE的想法。
|