diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/fields.o b/bin/Debug/music-field.build/Objects-normal/x86_64/fields.o index 03a04e1..5714e78 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/fields.o and b/bin/Debug/music-field.build/Objects-normal/x86_64/fields.o differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.dia b/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.dia index 7d1a737..ac18785 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.dia and b/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.dia differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.o b/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.o index 6f8a297..9cb0bab 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.o and b/bin/Debug/music-field.build/Objects-normal/x86_64/graphs.o differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/hsv.o b/bin/Debug/music-field.build/Objects-normal/x86_64/hsv.o index 6b832d1..161ce34 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/hsv.o and b/bin/Debug/music-field.build/Objects-normal/x86_64/hsv.o differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/main.dia b/bin/Debug/music-field.build/Objects-normal/x86_64/main.dia index 508d862..5ff8a49 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/main.dia and b/bin/Debug/music-field.build/Objects-normal/x86_64/main.dia differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/main.o b/bin/Debug/music-field.build/Objects-normal/x86_64/main.o index 08e851d..13ea2f8 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/main.o and b/bin/Debug/music-field.build/Objects-normal/x86_64/main.o differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/wav.dia b/bin/Debug/music-field.build/Objects-normal/x86_64/wav.dia index 6993865..5117ab0 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/wav.dia and b/bin/Debug/music-field.build/Objects-normal/x86_64/wav.dia differ diff --git a/bin/Debug/music-field.build/Objects-normal/x86_64/wav.o b/bin/Debug/music-field.build/Objects-normal/x86_64/wav.o index 00c8928..f3bb5f0 100644 Binary files a/bin/Debug/music-field.build/Objects-normal/x86_64/wav.o and b/bin/Debug/music-field.build/Objects-normal/x86_64/wav.o differ diff --git a/document/数据部分.md b/document/数据部分.md index a8e0b47..e863140 100644 --- a/document/数据部分.md +++ b/document/数据部分.md @@ -1,5 +1,20 @@ # 设计内容(数据部分) +## 对于相关数据结构体的分析 +1. WAV_Format结构体用来储存WAV文件最开始的12个字节的信息,识别读取的文件是否为WAV格式。 +2. WAV_FMT结构体用来储存WAV文件头的fmt数据块的信息,包括是否为PCM格式数据,比特率等。 +3. CHUNK_INFO结构体用来读入一个CHUNK结构头8个字节的描述信息。 +3. WAV_DATA结构体用来读入data数据块的头8个字节的描述信息,包括CHUNK标签(用来识别是否为data数据块)、数据块的大小等。 +4. process结构体,用来记录数据包的取用相关的进度信息和取用步长信息。 + +## 对于相关位域的分析 +1. Bit32用来储存16位双声道二进制音频数据,分为da,db两个域。分别是左声道,右声道的数据。 +2. Bit16用来储存8位双声道二进制音频数据,分为da,db两个域。分别是左声道,右声道的数据。 +3. BitO16用来储存16位单声道的二进制音频数据。 +4. BitO8用来储存8位单声道的二进制音频数据。 + ## 对于WAV类的分析 1. 传入需要读入的WAV格式文件的路径,而后对于WAV格式的文件头进行通过二进制模式读取操作。为了提高程序的鲁棒性,程序通过while循环来读入,根据读入的标签的特点来进行下一步操作。这样,能够在处理少部分不和主流形式一致文件头的情况下,仍然能够正确读取文件中必要信息与相关数据。在读取data标签前,会对fmt标签是否已读入进行检查。在读取fmt标签时会检查文件数据是否为PCM格式。 2. 数据储存上,利用stdint.h中定义的uint32_t来保证一次读入4个字节,来符合标准规范。由于WAV文件头中包含很多个小节,针对这些小节及其特点建立了相关的结构体。用来一次性读入相关信息,确保读入的稳定性与安全性。 -3. 在音频数据的处理上,由于PCM格式的音频输入含有16位双声道,8位双声道,16位单声道,8位单声道。对于这几种不同的类型,实际的处理方式会不同。在工程定义时,定义了4个不同的位域,用来分割不同类型下的音频数据。并且对于这四种不同的位域,给它们配置了4中不同的容器来容纳。所以该类在识别音频文件后,会自动选择合适的容器来存放。 +3. 在音频数据的处理上,由于PCM格式的音频输入含有16位双声道,8位双声道,16位单声道,8位单声道。对于这几种不同的类型,实际的处理方式会不同。在工程定义时,定义了4个不同的位域,用来分割不同类型下的二进制音频数据。并且对于这四种不同的位域,给它们配置了4中不同的容器来容纳。所以该类在识别音频文件后,会自动选择合适的容器(vector)来存放。 +4. 对于WAV文件的数据的取用上,需要先通过setTimer方法来指定所取用的音频数据的持续时间,单位是ms,且要求小于1000ms。然后通过getData方法来进行数据包(抽象为Data类)的一次取用。该类通过process结构体储存当前数据包取用进度,返回储存正确位置数据的数据包。在取用数据包时,数据包会自动根据音频数据的类型来进行调整,降低用户手动操作的操作复杂度。用户可以根据返回的数据包内部的active变量来得知获取数据操作是否到了文件尾部。 +5. 通过getInfo方法,程序可以直接打印WAV文件的相关主要信息。 diff --git a/include/graphs.hpp b/include/graphs.hpp index ddcca32..5c4c890 100644 --- a/include/graphs.hpp +++ b/include/graphs.hpp @@ -11,6 +11,12 @@ using std::map; class Field; +/********************************************************************* + * + *函数声明 + * + *********************************************************************/ + //绘图函数声明 unsigned long fresh_screen(int signal); //计算函数声明 @@ -18,6 +24,12 @@ void draw_fields(int signal); int create_fields(int hw); +/********************************************************************* + * + *图形操作类声明 + * + *********************************************************************/ + /************************************************ 颜色的抽象 ***/ diff --git a/include/type.hpp b/include/type.hpp index f642110..6db2707 100644 --- a/include/type.hpp +++ b/include/type.hpp @@ -1,12 +1,18 @@ #ifndef type_h #define type_h - +/********************************************************************* + * + *需要使用的库头文件的包含 + * + *********************************************************************/ +//C++标准库 #include #include #include #include +//苹果操作系统 #ifdef __APPLE__ #include #include @@ -15,22 +21,33 @@ #define _CRT_SECURE_NO_WARNINGS #endif +//Windows操作系统 #ifdef WIN32 #include #include #pragma warning(disable:4996) #endif - +//容器类头文件包含 #include #include #include +/********************************************************************* + * + *编译相关常量的定义 + * + *********************************************************************/ //计算函数执行时间间隔 #define DRAW_TIMER 1 //绘图函数执行时间间隔 #define FRESH_TIMER 20 +/********************************************************************* + * + *需要使用的自定义变量 + * + *********************************************************************/ typedef std::pair Size; typedef std::pair Point; typedef std::vector Point3; diff --git a/include/wav.hpp b/include/wav.hpp index 7b34c24..6d1b1cf 100644 --- a/include/wav.hpp +++ b/include/wav.hpp @@ -1,78 +1,150 @@ #ifndef wav_hpp #define wav_hpp - +/********************************************************************* + * + *相关头文件与命名空间的包含或引用 + * + *********************************************************************/ #include #include #include +//需要用到的容器类 using std::string; using std::vector; -FILE * readWAVInfo(void); -int init_test_wav(int); +/********************************************************************* + * + *函数声明 + * + *********************************************************************/ +//读取WAV文件的相关信息,现已废弃 +extern FILE * readWAVInfo(void); +//根据该工程的特点,初始化WAV方法类 +extern int init_test_wav(int); + +/********************************************************************* + * + *数据储结构体声明 + * + *********************************************************************/ + +/** + 储存WAV头12个字节的信息 + */ struct WAV_Format{ - uint32_t ChunkID; /* "RIFF" */ - uint32_t ChunkSize; /* 36 + Subchunk2Size */ - uint32_t Format; /* "WAVE" */ +// “RIFF” + uint32_t ChunkID; +// 文件大小相关 + uint32_t ChunkSize; +// “WAVE” + uint32_t Format; }; + +/** + 储存fmt数据块信息体 + */ struct WAV_FMT { - /* "fmt " */ - //uint32_t Subchunk1ID; - /* 16 for PCM */ - //uint32_t Subchunk1Size; - uint16_t AudioFormat; /* PCM = 1*/ - uint16_t NumChannels; /* Mono = 1, Stereo = 2, etc. */ - uint32_t SampleRate; /* 8000, 44100, etc. */ - uint32_t ByteRate; /* = SampleRate * NumChannels * BitsPerSample/8 */ - uint16_t BlockAlign; /* = NumChannels * BitsPerSample/8 */ - uint16_t BitsPerSample; /* 8bits, 16bits, etc. */ +// 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; }; + +/** + 储存一个CHUNK(数据块) + */ struct WAV_CHUNK { uint32_t SubchunkExID; uint32_t SubchunkExSize; uint32_t NumChannels; }; +/** + 储存一个CHUNK的说明信息 + */ struct CHUNK_INFO{ uint32_t ChunkID; uint32_t ChunkSize; }; +/** + 储存data数据块的说明信息 + */ struct WAV_DATA{ /* sub-chunk "data" */ uint32_t Subchunk2ID; /* "data" */ uint32_t Subchunk2Size; /* data size */ }; + +/** + 储存数据包取用进度和步长 + */ struct process{ uint32_t start,now,end,step; }; +/********************************************************************* + * + *数据储存位域声明 + * + *********************************************************************/ + +/** + 储存16位双声道二进制音频数据,分为da,db两个域。分别是左声道,右声道的数据 + */ struct Bit32 { unsigned short da:16; unsigned short db:16; }; +/** + 储存16位单声道的二进制音频数据 + */ struct BitO16 { unsigned short da:16; }; +/** + 储存8位双声道二进制音频数据,分为da,db两个域。分别是左声道,右声道的数据 + */ struct Bit16 { unsigned short da:8; unsigned short db:8; }; +/** + 储存8位单声道的二进制音频数据 + */ struct BitO8 { unsigned short da:8; }; +/********************************************************************* + * + *数据操作类声明 + * + *********************************************************************/ + +/************************************************ + 32位数据包的抽象,已废弃不用。 + ***/ class Data32{ public: bool active; @@ -92,22 +164,45 @@ public: }; +/************************************************ + 数据包的抽象 + ***/ class Data{ public: +// 数据包是否可用 bool active; +// 声道信息,每次采样的数据大小信息 uint32_t channels, bit_size; +// 16位双声道容器 vector bit32; +// 16位单声道容器 vector bito16; +// 8位双声道容器 vector bit16; +// 8位单声道容器 vector bito8; +// 计算后的颜色数据储存容器 vector color_data; +// 根据数据包内部颜色信息所计算出的平均颜色 Color avg_color; + + /** + 构造函数,一般由WAV类在创建数据包时传值 + + @param tchannels 声道 + @param tbit_size 每次采样的数据大小 + @param start 指向这段数据在数据容器中数据容器开始部分的指针 + @param end 指向这段数据在数据容器中数据容器结束部分的指针 + */ Data(uint32_t tchannels, uint32_t tbit_size,void *start, void *end):active(true),channels(tchannels),bit_size(tbit_size){ +// 当每次采样的数据大小为32bit时 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; +// 内存拷贝,解决强制类型转化无法完成的问题 memcpy(&temp, i, sizeof(struct Bit32)); +// 选用适当的容器储存 bit32.push_back(temp); } } @@ -136,6 +231,7 @@ public: } } } + Data(const Data &tmp){ bit_size = tmp.bit_size; channels = tmp.channels; @@ -145,6 +241,10 @@ public: bit16 = tmp.bit16; bito8 = tmp.bito8; } + + /** + 将储存的声音数据计算转化成颜色数据 + */ void Data2Color(void){ if(channels == 2){ if(bit_size == 32){ @@ -244,22 +344,33 @@ public: } }; +/************************************************ + WAV文件的抽象 + ***/ class WAV{ public: +//文件头信息储存相关变量 struct WAV_Format format; struct WAV_FMT fmt; struct WAV_DATA data; struct WAV_CHUNK fact; struct WAV_CHUNK list; struct CHUNK_INFO info; +// 计算出的文件大小储存 uint32_t file_size; +// 判断文件是否合法的相关变量 bool active,if_fmt; +// 文件指针,指向所读取的文件的操作结构 FILE *fp; +// 文件原始音频数据储存的相关容器 vector data32; vector data16; vector data8; +// 文件音频持续时间 uint32_t seconds; +// 数据包取用状态记录变量 struct process m_pss; + WAV(string path):active(false),if_fmt(false){ fp = fopen(path.data(), "rb"); if(fp == NULL){ @@ -272,11 +383,13 @@ public: uint32_t temp; char *p_tmp = (char *)(&temp); +// 判断本次所读入的数据是否为RIFF 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 if(*p_tmp=='W' && *(p_tmp+1)=='A' && *(p_tmp+2)=='V' && *(p_tmp+3)=='E'){ active = true; format.Format = temp; @@ -308,20 +421,7 @@ public: } }while(!feof(fp) && active == true); - /*fread (&this->format, 1, sizeof(struct WAV_Format), fp); - fread (&this->fmt, 1, sizeof(struct WAV_FMT), fp); - char if_fact[5]; - do{ - fread (&if_fact, 1, sizeof(uint32_t), fp); - if_fact[4] = '\0'; - if(!strcmp(if_fact, "fact")) - fread(&this->fact, 1, sizeof(struct WAV_CHUNK), fp); - else if (!strcmp(if_fact, "LIST")) - fread(&this->list, 1, sizeof(struct WAV_CHUNK), fp); - fseek(fp, -sizeof(uint32_t), SEEK_CUR); - - }while(strcmp(if_fact, "data")); - fread(&this->data, 1, sizeof(struct WAV_DATA), fp);*/ +// 读入WAV文件中储存的音频数据 if(fmt.BlockAlign == 4){ uint32_t t_data32, count = data.Subchunk2Size/sizeof(uint32_t); while(fread(&t_data32, 1, sizeof(uint32_t), fp) && ~count){ @@ -347,6 +447,12 @@ public: } seconds = data.Subchunk2Size/fmt.ByteRate; } + + /** + 设置数据包所存音频数据的长度 + + @param ms 以ms(毫秒)为单位 + */ void setTimer(int ms){ if(ms <= 1000){ m_pss.step = (((double)ms/seconds)*((data.Subchunk2Size/1000.0)/(double)fmt.BlockAlign)); @@ -356,6 +462,9 @@ public: } } + /** + 获得一个32bits大的数据包,现在已经废弃 + */ 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]), @@ -370,6 +479,10 @@ public: } } + + /** + 获得一个数据包 + */ Data getData(void){ if(m_pss.now < m_pss.end && m_pss.now + m_pss.step < m_pss.end){ if(fmt.NumChannels == 2){ @@ -406,6 +519,9 @@ public: return m_data; } + /** + 打印WAV文件的相关主要信息 + */ void getInfo(void){ printf("ChunkID \t%x\n", format.ChunkID); printf("ChunkSize \t%d\n", format.ChunkSize); @@ -420,7 +536,4 @@ public: printf("Subchunk2Size \t%d\n", data.Subchunk2Size); } }; - - - #endif /* wav_hpp */