music-field/include/wav.hpp

540 lines
17 KiB
C++
Raw Normal View History

2018-12-25 14:06:28 +00:00
#ifndef wav_hpp
#define wav_hpp
/*********************************************************************
*
*
*
*********************************************************************/
2018-12-25 14:06:28 +00:00
#include <type.hpp>
#include <graphs.hpp>
2018-12-26 06:31:21 +00:00
#include <hsv.hpp>
2018-12-25 14:06:28 +00:00
//需要用到的容器类
2018-12-25 14:06:28 +00:00
using std::string;
using std::vector;
/*********************************************************************
*
*
*
*********************************************************************/
//读取WAV文件的相关信息现已废弃
extern FILE * readWAVInfo(void);
//根据该工程的特点初始化WAV方法类
extern int init_test_wav(int);
/*********************************************************************
*
*
*
*********************************************************************/
2018-12-25 14:06:28 +00:00
/**
WAV头12个字节的信息
*/
2018-12-25 14:06:28 +00:00
struct WAV_Format{
// “RIFF”
uint32_t ChunkID;
// 文件大小相关
uint32_t ChunkSize;
// “WAVE”
uint32_t Format;
2018-12-25 14:06:28 +00:00
};
/**
fmt数据块信息体
*/
2018-12-25 14:06:28 +00:00
struct WAV_FMT {
// PCM = 1
uint16_t AudioFormat;
// Mono = 1, Stereo = 2, etc.
uint16_t NumChannels;
// 8000, 44100, etc.
uint32_t SampleRate;
// = SampleRate * NumChannels * BitsPerSample/8
uint32_t ByteRate;
// = NumChannels * BitsPerSample/8
uint16_t BlockAlign;
// 8bits, 16bits, etc.
uint16_t BitsPerSample;
2018-12-25 14:06:28 +00:00
};
/**
CHUNK
*/
2018-12-25 14:06:28 +00:00
struct WAV_CHUNK {
uint32_t SubchunkExID;
uint32_t SubchunkExSize;
uint32_t NumChannels;
};
/**
CHUNK的说明信息
*/
2018-12-25 14:06:28 +00:00
struct CHUNK_INFO{
uint32_t ChunkID;
uint32_t ChunkSize;
};
/**
data数据块的说明信息
*/
2018-12-25 14:06:28 +00:00
struct WAV_DATA{
/* sub-chunk "data" */
uint32_t Subchunk2ID; /* "data" */
uint32_t Subchunk2Size; /* data size */
};
/**
*/
2018-12-25 14:06:28 +00:00
struct process{
uint32_t start,now,end,step;
};
/*********************************************************************
*
*
*
*********************************************************************/
/**
16dadb两个域
*/
2018-12-25 14:06:28 +00:00
struct Bit32
{
unsigned short da:16;
unsigned short db:16;
};
/**
16
*/
2018-12-25 14:06:28 +00:00
struct BitO16
{
unsigned short da:16;
};
/**
8dadb两个域
*/
2018-12-25 14:06:28 +00:00
struct Bit16
{
unsigned short da:8;
unsigned short db:8;
};
/**
8
*/
2018-12-25 14:06:28 +00:00
struct BitO8
{
unsigned short da:8;
};
/*********************************************************************
*
*
*
*********************************************************************/
/************************************************
32
***/
2018-12-25 14:06:28 +00:00
class Data32{
public:
bool active;
vector<struct Bit32> bit;
Data32(uint32_t *start, uint32_t *end):active(true){
for(auto i = start;i != end; i++){
struct Bit32 temp;
memcpy(&temp, i, sizeof(struct Bit32));
bit.push_back(temp);
}
}
Data32(const Data32 &tmp){
active = tmp.active;
bit = tmp.bit;
}
};
/************************************************
***/
2018-12-25 14:06:28 +00:00
class Data{
public:
// 数据包是否可用
2018-12-25 14:06:28 +00:00
bool active;
// 声道信息,每次采样的数据大小信息
2018-12-25 14:06:28 +00:00
uint32_t channels, bit_size;
// 16位双声道容器
2018-12-25 14:06:28 +00:00
vector<struct Bit32> bit32;
// 16位单声道容器
2018-12-25 14:06:28 +00:00
vector<struct BitO16> bito16;
// 8位双声道容器
2018-12-25 14:06:28 +00:00
vector<struct Bit16> bit16;
// 8位单声道容器
2018-12-25 14:06:28 +00:00
vector<struct BitO8> bito8;
// 计算后的颜色数据储存容器
2018-12-25 14:06:28 +00:00
vector<Color> color_data;
// 根据数据包内部颜色信息所计算出的平均颜色
2018-12-25 14:06:28 +00:00
Color avg_color;
/**
WAV类在创建数据包时传值
@param tchannels
@param tbit_size
@param start
@param end
*/
2018-12-25 14:06:28 +00:00
Data(uint32_t tchannels, uint32_t tbit_size,void *start, void *end):active(true),channels(tchannels),bit_size(tbit_size){
// 当每次采样的数据大小为32bit时
2018-12-25 14:06:28 +00:00
if (bit_size == 32){
uint32_t *m_s = (uint32_t *)start, *m_e = (uint32_t *)end;
for(auto i = m_s;i != m_e; i++){
struct Bit32 temp;
// 内存拷贝,解决强制类型转化无法完成的问题
2018-12-25 14:06:28 +00:00
memcpy(&temp, i, sizeof(struct Bit32));
// 选用适当的容器储存
2018-12-25 14:06:28 +00:00
bit32.push_back(temp);
}
}
else if(bit_size == 16){
uint16_t *m_s = (uint16_t *)start, *m_e = (uint16_t *)end;
if(channels == 2)
for(auto i = m_s;i != m_e; i++){
struct Bit16 temp;
memcpy(&temp, i, sizeof(struct Bit16));
bit16.push_back(temp);
}
else{
for(auto i = m_s;i != m_e; i++){
struct BitO16 temp;
memcpy(&temp, i, sizeof(struct BitO16));
bito16.push_back(temp);
}
}
}
else if(bit_size == 8){
uint8_t *m_s = (uint8_t *)start, *m_e = (uint8_t *)end;
for(auto i = m_s;i != m_e; i++){
struct BitO8 temp;
memcpy(&temp, i, sizeof(struct BitO8));
bito8.push_back(temp);
}
}
}
2018-12-25 14:06:28 +00:00
Data(const Data &tmp){
bit_size = tmp.bit_size;
channels = tmp.channels;
active = tmp.active;
bit32 = tmp.bit32;
bito16 = tmp.bito16;
bit16 = tmp.bit16;
bito8 = tmp.bito8;
}
/**
*/
2018-12-25 14:06:28 +00:00
void Data2Color(void){
if(channels == 2){
if(bit_size == 32){
double sumr = 0 ,sumb = 0, sumg = 0;
//printf("BLOCKS\n");
for(auto i = bit32.begin(); i != bit32.end(); i++){
Bit32 bit = (*i);
if(i != bit32.begin()){
Color m_color;
double cb = log2(sqrt(bit.da + bit.db)+1)*18.5, cg = log2(sqrt(abs(bit.db - (*(i-1)).db))+1)*42, cr = log2(sqrt(abs(bit.da - (*(i-1)).da))+1)*42;
2018-12-26 06:31:21 +00:00
rgb crgb;
hsv chsv;
crgb.r = 1.0*cr/255;
crgb.g = 1.0*cg/255;
crgb.b = 1.0*cb/255;
chsv = rgb2hsv(crgb);
//addsaturation(chsv);
chsv.s += 0.5;
chsv.s > 1 ? 1 : 1;
crgb = hsv2rgb(chsv);
cr = 255 * crgb.r;
cg = 255 * crgb.g;
cb = 255 * crgb.b;
2018-12-25 14:06:28 +00:00
cr = cr>255?255:cr;
cg = cg>255?255:cg;
cb = cb>255?255:cb;
sumr += cr;
sumb += cb;
sumg += cg;
2018-12-26 06:31:21 +00:00
2018-12-25 14:06:28 +00:00
m_color.setColor({cr,cb,cg});
color_data.push_back(m_color);
}
}
sumr/=(bit32.size()-1);
sumb/=(bit32.size()-1);
sumg/=(bit32.size()-1);
avg_color.setColor({sumr,sumb,sumg});
}
else{
double sumr = 0 ,sumb = 0, sumg = 0;
for(auto i = bit16.begin(); i != bit16.end(); i++){
Bit16 bit = (*i);
if(i != bit16.begin()){
Color m_color;
double cb = log2(bit.da + bit.db + 1)*18.5, cg = log2(abs(bit.db - (*(i-1)).db)+1)*22.5, cr = log2(abs(bit.da - (*(i-1)).da)+1)*22.5;
cr = cr>255?255:cr;
cg = cg>255?255:cg;
cb = cb>255?255:cb;
sumr += cr;
sumb += cb;
sumg += cg;
m_color.setColor({cr,cb,cg});
color_data.push_back(m_color);
}
}
avg_color.setColor({sumr,sumb,sumg});
}
}
else{
if(bit_size == 16){
double sumr = 0 ,sumg = 0;
for(auto i = bito16.begin(); i != bito16.end(); i++){
BitO16 bit = (*i);
if(i != bito16.begin()){
Color m_color;
double cg = log2(bit.da + 1)*18.5, cr = log2(abs(bit.da - (*(i-1)).da)+1)*22.5;
cr = cr>255?255:cr;
cg = cg>255?255:cg;
sumr += cr;
sumg += cg;
m_color.setColor({cr,cg,0});
color_data.push_back(m_color);
}
}
avg_color.setColor({sumr,sumg,0});
}
else{
double sumr = 0 ,sumb = 0;
for(auto i = bito8.begin(); i != bito8.end(); i++){
BitO8 bit = (*i);
if(i != bito8.begin()){
Color m_color;
double cb = log2(bit.da + 1)*18.5, cr = log2(abs(bit.da - (*(i-1)).da)+1)*22.5;
cr = cr>255?255:cr;
cb = cb>255?255:cb;
sumr += cr;
sumb += cb;
m_color.setColor({cr,cb,0});
color_data.push_back(m_color);
}
}
avg_color.setColor({sumr,sumb,0});
}
}
}
};
/************************************************
WAV文件的抽象
***/
2018-12-25 14:06:28 +00:00
class WAV{
public:
//文件头信息储存相关变量
2018-12-25 14:06:28 +00:00
struct WAV_Format format;
struct WAV_FMT fmt;
struct WAV_DATA data;
struct WAV_CHUNK fact;
struct WAV_CHUNK list;
struct CHUNK_INFO info;
// 计算出的文件大小储存
2018-12-25 14:06:28 +00:00
uint32_t file_size;
// 判断文件是否合法的相关变量
2018-12-25 14:06:28 +00:00
bool active,if_fmt;
// 文件指针,指向所读取的文件的操作结构
2018-12-25 14:06:28 +00:00
FILE *fp;
// 文件原始音频数据储存的相关容器
2018-12-25 14:06:28 +00:00
vector<uint32_t> data32;
vector<uint16_t> data16;
vector<uint8_t> data8;
// 文件音频持续时间
2018-12-25 14:06:28 +00:00
uint32_t seconds;
// 数据包取用状态记录变量
2018-12-25 14:06:28 +00:00
struct process m_pss;
2018-12-25 14:06:28 +00:00
WAV(string path):active(false),if_fmt(false){
fp = fopen(path.data(), "rb");
2018-12-26 07:07:19 +00:00
if(fp == NULL){
printf("Can't open target file.\n");
throw -1;
}
2018-12-25 14:06:28 +00:00
do{
fread(&this->info, 1, sizeof(struct CHUNK_INFO), fp);
char *p_id = (char *)(&info.ChunkID);
uint32_t temp;
char *p_tmp = (char *)(&temp);
// 判断本次所读入的数据是否为RIFF
2018-12-25 14:06:28 +00:00
if(*p_id=='R' && *(p_id+1)=='I' && *(p_id+2)=='F' && *(p_id+3)=='F'){
format.ChunkID = info.ChunkID;
format.ChunkSize = info.ChunkSize;
file_size = info.ChunkSize+8;
fread(&temp, 1, sizeof(uint32_t), fp);
// 判断本次所读入的数据是否为WAVE
2018-12-25 14:06:28 +00:00
if(*p_tmp=='W' && *(p_tmp+1)=='A' && *(p_tmp+2)=='V' && *(p_tmp+3)=='E'){
active = true;
format.Format = temp;
}
else{
active = false;
throw -1;
}
}
else if(*p_id=='L' && *(p_id+1)=='I' && *(p_id+2)=='S' && *(p_id+3)=='T'){
fseek(fp, info.ChunkSize, SEEK_CUR);
}
else if(*p_id=='f' && *(p_id+1)=='m' && *(p_id+2)=='t'){
if_fmt = true;
fread(&this->fmt, 1, sizeof(WAV_FMT), fp);
}
else if(*p_id=='f' && *(p_id+1)=='a' && *(p_id+2)=='c' && *(p_id+3)=='t'){
fseek(fp, info.ChunkSize, SEEK_CUR);
}
else if(*p_id=='d' && *(p_id+1)=='a' && *(p_id+2)=='t' && *(p_id+3)=='a'){
if(if_fmt == false) throw -1;
else if(fmt.AudioFormat != 1) throw -1;
else{
data.Subchunk2ID = info.ChunkID;
data.Subchunk2Size = info.ChunkSize;
break;
}
}
}while(!feof(fp) && active == true);
// 读入WAV文件中储存的音频数据
2018-12-25 14:06:28 +00:00
if(fmt.BlockAlign == 4){
uint32_t t_data32, count = data.Subchunk2Size/sizeof(uint32_t);
while(fread(&t_data32, 1, sizeof(uint32_t), fp) && ~count){
data32.push_back(t_data32);
count--;
}
}
else if(fmt.BlockAlign == 2){
uint16_t t_data16;
uint32_t count = data.Subchunk2Size/sizeof(uint16_t);
while(fread(&t_data16, 1, sizeof(uint16_t), fp) && ~count){
data16.push_back(t_data16);
count--;
}
}
else if(fmt.BlockAlign == 1){
uint8_t t_data8;
uint32_t count = data.Subchunk2Size/sizeof(uint8_t);
while(fread(&t_data8, 1, sizeof(uint8_t), fp) && ~count){
data8.push_back(t_data8);
count--;
}
}
seconds = data.Subchunk2Size/fmt.ByteRate;
}
/**
@param ms ms
*/
2018-12-25 14:06:28 +00:00
void setTimer(int ms){
if(ms <= 1000){
m_pss.step = (((double)ms/seconds)*((data.Subchunk2Size/1000.0)/(double)fmt.BlockAlign));
m_pss.end = data.Subchunk2Size/(double)fmt.BlockAlign;
m_pss.start = 0;
m_pss.now = 0;
}
}
/**
32bits大的数据包
*/
2018-12-25 14:06:28 +00:00
Data32 getData32(void){
if(m_pss.now < m_pss.end && m_pss.now + m_pss.step < m_pss.end){
Data32 m_data(&(data32[m_pss.now]),
&(data32[m_pss.now + m_pss.step]));
m_pss.now += m_pss.step;
return m_data;
}
else{
Data32 m_data(NULL,NULL);
m_data.active = false;
return m_data;
}
}
/**
*/
2018-12-25 14:06:28 +00:00
Data getData(void){
if(m_pss.now < m_pss.end && m_pss.now + m_pss.step < m_pss.end){
if(fmt.NumChannels == 2){
if(fmt.BlockAlign == 4){
Data m_data(fmt.NumChannels,fmt.BlockAlign*8,&data32[m_pss.now],
&data32[m_pss.now + m_pss.step]);
m_pss.now += m_pss.step;
return m_data;
}
else if(fmt.BlockAlign == 2){
Data m_data(fmt.NumChannels,fmt.BlockAlign*8,&data16[m_pss.now],
&data16[m_pss.now + m_pss.step]);
m_pss.now += m_pss.step;
return m_data;
}
}
else{
if(fmt.BlockAlign == 2){
Data m_data(fmt.NumChannels,fmt.BlockAlign*8,&data16[m_pss.now],
&data16[m_pss.now + m_pss.step]);
m_pss.now += m_pss.step;
return m_data;
}
else if(fmt.BlockAlign == 1){
Data m_data(fmt.NumChannels,fmt.BlockAlign*8,&data8[m_pss.now],
&data8[m_pss.now + m_pss.step]);
m_pss.now += m_pss.step;
return m_data;
}
}
}
Data m_data(0,0,NULL,NULL);
m_data.active = false;
return m_data;
}
/**
WAV文件的相关主要信息
*/
2018-12-25 14:06:28 +00:00
void getInfo(void){
printf("ChunkID \t%x\n", format.ChunkID);
printf("ChunkSize \t%d\n", format.ChunkSize);
printf("Format \t\t%d\n", format.Format);
printf("AudioFormat \t%d\n", fmt.AudioFormat);
printf("NumChannels \t%d\n", fmt.NumChannels);
printf("SampleRate \t%d\n", fmt.SampleRate);
printf("ByteRate \t%d\n", fmt.ByteRate);
printf("BlockAlign \t%d\n", fmt.BlockAlign);
printf("BitsPerSample \t%d\n", fmt.BitsPerSample);
printf("Subchunk2ID \t%x\n", data.Subchunk2ID);
printf("Subchunk2Size \t%d\n", data.Subchunk2Size);
}
};
#endif /* wav_hpp */