添加了wav.hpp注释,完成了数据部分的文档。

This commit is contained in:
Saturneic 2018-12-27 12:18:52 +08:00
parent bab388b4b5
commit af236970aa
12 changed files with 193 additions and 36 deletions

View File

@ -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位双声道二进制音频数据分为dadb两个域。分别是左声道右声道的数据。
2. Bit16用来储存8位双声道二进制音频数据分为dadb两个域。分别是左声道右声道的数据。
3. BitO16用来储存16位单声道的二进制音频数据。
4. BitO8用来储存8位单声道的二进制音频数据。
## 对于WAV类的分析 ## 对于WAV类的分析
1. 传入需要读入的WAV格式文件的路径而后对于WAV格式的文件头进行通过二进制模式读取操作。为了提高程序的鲁棒性程序通过while循环来读入根据读入的标签的特点来进行下一步操作。这样能够在处理少部分不和主流形式一致文件头的情况下仍然能够正确读取文件中必要信息与相关数据。在读取data标签前会对fmt标签是否已读入进行检查。在读取fmt标签时会检查文件数据是否为PCM格式。 1. 传入需要读入的WAV格式文件的路径而后对于WAV格式的文件头进行通过二进制模式读取操作。为了提高程序的鲁棒性程序通过while循环来读入根据读入的标签的特点来进行下一步操作。这样能够在处理少部分不和主流形式一致文件头的情况下仍然能够正确读取文件中必要信息与相关数据。在读取data标签前会对fmt标签是否已读入进行检查。在读取fmt标签时会检查文件数据是否为PCM格式。
2. 数据储存上利用stdint.h中定义的uint32_t来保证一次读入4个字节来符合标准规范。由于WAV文件头中包含很多个小节针对这些小节及其特点建立了相关的结构体。用来一次性读入相关信息确保读入的稳定性与安全性。 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文件的相关主要信息。

View File

@ -11,6 +11,12 @@ using std::map;
class Field; class Field;
/*********************************************************************
*
*
*
*********************************************************************/
//绘图函数声明 //绘图函数声明
unsigned long fresh_screen(int signal); unsigned long fresh_screen(int signal);
//计算函数声明 //计算函数声明
@ -18,6 +24,12 @@ void draw_fields(int signal);
int create_fields(int hw); int create_fields(int hw);
/*********************************************************************
*
*
*
*********************************************************************/
/************************************************ /************************************************
***/ ***/

View File

@ -1,12 +1,18 @@
#ifndef type_h #ifndef type_h
#define type_h #define type_h
/*********************************************************************
*
*使
*
*********************************************************************/
//C++标准库
#include <iostream> #include <iostream>
#include <stdint.h> #include <stdint.h>
#include <cmath> #include <cmath>
#include <time.h> #include <time.h>
//苹果操作系统
#ifdef __APPLE__ #ifdef __APPLE__
#include <OpenGL/OpenGL.h> #include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h> #include <GLUT/GLUT.h>
@ -15,22 +21,33 @@
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#endif #endif
//Windows操作系统
#ifdef WIN32 #ifdef WIN32
#include <Windows.h> #include <Windows.h>
#include <glut.h> #include <glut.h>
#pragma warning(disable:4996) #pragma warning(disable:4996)
#endif #endif
//容器类头文件包含
#include <vector> #include <vector>
#include <list> #include <list>
#include <map> #include <map>
/*********************************************************************
*
*
*
*********************************************************************/
//计算函数执行时间间隔 //计算函数执行时间间隔
#define DRAW_TIMER 1 #define DRAW_TIMER 1
//绘图函数执行时间间隔 //绘图函数执行时间间隔
#define FRESH_TIMER 20 #define FRESH_TIMER 20
/*********************************************************************
*
*使
*
*********************************************************************/
typedef std::pair<double, double> Size; typedef std::pair<double, double> Size;
typedef std::pair<double, double> Point; typedef std::pair<double, double> Point;
typedef std::vector<double> Point3; typedef std::vector<double> Point3;

View File

@ -1,78 +1,150 @@
#ifndef wav_hpp #ifndef wav_hpp
#define wav_hpp #define wav_hpp
/*********************************************************************
*
*
*
*********************************************************************/
#include <type.hpp> #include <type.hpp>
#include <graphs.hpp> #include <graphs.hpp>
#include <hsv.hpp> #include <hsv.hpp>
//需要用到的容器类
using std::string; using std::string;
using std::vector; 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{ struct WAV_Format{
uint32_t ChunkID; /* "RIFF" */ // “RIFF”
uint32_t ChunkSize; /* 36 + Subchunk2Size */ uint32_t ChunkID;
uint32_t Format; /* "WAVE" */ // 文件大小相关
uint32_t ChunkSize;
// “WAVE”
uint32_t Format;
}; };
/**
fmt数据块信息体
*/
struct WAV_FMT { struct WAV_FMT {
/* "fmt " */ // PCM = 1
//uint32_t Subchunk1ID; uint16_t AudioFormat;
/* 16 for PCM */ // Mono = 1, Stereo = 2, etc.
//uint32_t Subchunk1Size; uint16_t NumChannels;
uint16_t AudioFormat; /* PCM = 1*/ // 8000, 44100, etc.
uint16_t NumChannels; /* Mono = 1, Stereo = 2, etc. */ uint32_t SampleRate;
uint32_t SampleRate; /* 8000, 44100, etc. */ // = SampleRate * NumChannels * BitsPerSample/8
uint32_t ByteRate; /* = SampleRate * NumChannels * BitsPerSample/8 */ uint32_t ByteRate;
uint16_t BlockAlign; /* = NumChannels * BitsPerSample/8 */ // = NumChannels * BitsPerSample/8
uint16_t BitsPerSample; /* 8bits, 16bits, etc. */ uint16_t BlockAlign;
// 8bits, 16bits, etc.
uint16_t BitsPerSample;
}; };
/**
CHUNK
*/
struct WAV_CHUNK { struct WAV_CHUNK {
uint32_t SubchunkExID; uint32_t SubchunkExID;
uint32_t SubchunkExSize; uint32_t SubchunkExSize;
uint32_t NumChannels; uint32_t NumChannels;
}; };
/**
CHUNK的说明信息
*/
struct CHUNK_INFO{ struct CHUNK_INFO{
uint32_t ChunkID; uint32_t ChunkID;
uint32_t ChunkSize; uint32_t ChunkSize;
}; };
/**
data数据块的说明信息
*/
struct WAV_DATA{ struct WAV_DATA{
/* sub-chunk "data" */ /* sub-chunk "data" */
uint32_t Subchunk2ID; /* "data" */ uint32_t Subchunk2ID; /* "data" */
uint32_t Subchunk2Size; /* data size */ uint32_t Subchunk2Size; /* data size */
}; };
/**
*/
struct process{ struct process{
uint32_t start,now,end,step; uint32_t start,now,end,step;
}; };
/*********************************************************************
*
*
*
*********************************************************************/
/**
16dadb两个域
*/
struct Bit32 struct Bit32
{ {
unsigned short da:16; unsigned short da:16;
unsigned short db:16; unsigned short db:16;
}; };
/**
16
*/
struct BitO16 struct BitO16
{ {
unsigned short da:16; unsigned short da:16;
}; };
/**
8dadb两个域
*/
struct Bit16 struct Bit16
{ {
unsigned short da:8; unsigned short da:8;
unsigned short db:8; unsigned short db:8;
}; };
/**
8
*/
struct BitO8 struct BitO8
{ {
unsigned short da:8; unsigned short da:8;
}; };
/*********************************************************************
*
*
*
*********************************************************************/
/************************************************
32
***/
class Data32{ class Data32{
public: public:
bool active; bool active;
@ -92,22 +164,45 @@ public:
}; };
/************************************************
***/
class Data{ class Data{
public: public:
// 数据包是否可用
bool active; bool active;
// 声道信息,每次采样的数据大小信息
uint32_t channels, bit_size; uint32_t channels, bit_size;
// 16位双声道容器
vector<struct Bit32> bit32; vector<struct Bit32> bit32;
// 16位单声道容器
vector<struct BitO16> bito16; vector<struct BitO16> bito16;
// 8位双声道容器
vector<struct Bit16> bit16; vector<struct Bit16> bit16;
// 8位单声道容器
vector<struct BitO8> bito8; vector<struct BitO8> bito8;
// 计算后的颜色数据储存容器
vector<Color> color_data; vector<Color> color_data;
// 根据数据包内部颜色信息所计算出的平均颜色
Color avg_color; 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){ 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){ if (bit_size == 32){
uint32_t *m_s = (uint32_t *)start, *m_e = (uint32_t *)end; uint32_t *m_s = (uint32_t *)start, *m_e = (uint32_t *)end;
for(auto i = m_s;i != m_e; i++){ for(auto i = m_s;i != m_e; i++){
struct Bit32 temp; struct Bit32 temp;
// 内存拷贝,解决强制类型转化无法完成的问题
memcpy(&temp, i, sizeof(struct Bit32)); memcpy(&temp, i, sizeof(struct Bit32));
// 选用适当的容器储存
bit32.push_back(temp); bit32.push_back(temp);
} }
} }
@ -136,6 +231,7 @@ public:
} }
} }
} }
Data(const Data &tmp){ Data(const Data &tmp){
bit_size = tmp.bit_size; bit_size = tmp.bit_size;
channels = tmp.channels; channels = tmp.channels;
@ -145,6 +241,10 @@ public:
bit16 = tmp.bit16; bit16 = tmp.bit16;
bito8 = tmp.bito8; bito8 = tmp.bito8;
} }
/**
*/
void Data2Color(void){ void Data2Color(void){
if(channels == 2){ if(channels == 2){
if(bit_size == 32){ if(bit_size == 32){
@ -244,22 +344,33 @@ public:
} }
}; };
/************************************************
WAV文件的抽象
***/
class WAV{ class WAV{
public: public:
//文件头信息储存相关变量
struct WAV_Format format; struct WAV_Format format;
struct WAV_FMT fmt; struct WAV_FMT fmt;
struct WAV_DATA data; struct WAV_DATA data;
struct WAV_CHUNK fact; struct WAV_CHUNK fact;
struct WAV_CHUNK list; struct WAV_CHUNK list;
struct CHUNK_INFO info; struct CHUNK_INFO info;
// 计算出的文件大小储存
uint32_t file_size; uint32_t file_size;
// 判断文件是否合法的相关变量
bool active,if_fmt; bool active,if_fmt;
// 文件指针,指向所读取的文件的操作结构
FILE *fp; FILE *fp;
// 文件原始音频数据储存的相关容器
vector<uint32_t> data32; vector<uint32_t> data32;
vector<uint16_t> data16; vector<uint16_t> data16;
vector<uint8_t> data8; vector<uint8_t> data8;
// 文件音频持续时间
uint32_t seconds; uint32_t seconds;
// 数据包取用状态记录变量
struct process m_pss; struct process m_pss;
WAV(string path):active(false),if_fmt(false){ WAV(string path):active(false),if_fmt(false){
fp = fopen(path.data(), "rb"); fp = fopen(path.data(), "rb");
if(fp == NULL){ if(fp == NULL){
@ -272,11 +383,13 @@ public:
uint32_t temp; uint32_t temp;
char *p_tmp = (char *)(&temp); char *p_tmp = (char *)(&temp);
// 判断本次所读入的数据是否为RIFF
if(*p_id=='R' && *(p_id+1)=='I' && *(p_id+2)=='F' && *(p_id+3)=='F'){ if(*p_id=='R' && *(p_id+1)=='I' && *(p_id+2)=='F' && *(p_id+3)=='F'){
format.ChunkID = info.ChunkID; format.ChunkID = info.ChunkID;
format.ChunkSize = info.ChunkSize; format.ChunkSize = info.ChunkSize;
file_size = info.ChunkSize+8; file_size = info.ChunkSize+8;
fread(&temp, 1, sizeof(uint32_t), fp); fread(&temp, 1, sizeof(uint32_t), fp);
// 判断本次所读入的数据是否为WAVE
if(*p_tmp=='W' && *(p_tmp+1)=='A' && *(p_tmp+2)=='V' && *(p_tmp+3)=='E'){ if(*p_tmp=='W' && *(p_tmp+1)=='A' && *(p_tmp+2)=='V' && *(p_tmp+3)=='E'){
active = true; active = true;
format.Format = temp; format.Format = temp;
@ -308,20 +421,7 @@ public:
} }
}while(!feof(fp) && active == true); }while(!feof(fp) && active == true);
/*fread (&this->format, 1, sizeof(struct WAV_Format), fp); // 读入WAV文件中储存的音频数据
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);*/
if(fmt.BlockAlign == 4){ if(fmt.BlockAlign == 4){
uint32_t t_data32, count = data.Subchunk2Size/sizeof(uint32_t); uint32_t t_data32, count = data.Subchunk2Size/sizeof(uint32_t);
while(fread(&t_data32, 1, sizeof(uint32_t), fp) && ~count){ while(fread(&t_data32, 1, sizeof(uint32_t), fp) && ~count){
@ -347,6 +447,12 @@ public:
} }
seconds = data.Subchunk2Size/fmt.ByteRate; seconds = data.Subchunk2Size/fmt.ByteRate;
} }
/**
@param ms ms
*/
void setTimer(int ms){ void setTimer(int ms){
if(ms <= 1000){ if(ms <= 1000){
m_pss.step = (((double)ms/seconds)*((data.Subchunk2Size/1000.0)/(double)fmt.BlockAlign)); m_pss.step = (((double)ms/seconds)*((data.Subchunk2Size/1000.0)/(double)fmt.BlockAlign));
@ -356,6 +462,9 @@ public:
} }
} }
/**
32bits大的数据包
*/
Data32 getData32(void){ Data32 getData32(void){
if(m_pss.now < m_pss.end && m_pss.now + m_pss.step < m_pss.end){ 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_data(&(data32[m_pss.now]),
@ -370,6 +479,10 @@ public:
} }
} }
/**
*/
Data getData(void){ Data getData(void){
if(m_pss.now < m_pss.end && m_pss.now + m_pss.step < m_pss.end){ if(m_pss.now < m_pss.end && m_pss.now + m_pss.step < m_pss.end){
if(fmt.NumChannels == 2){ if(fmt.NumChannels == 2){
@ -406,6 +519,9 @@ public:
return m_data; return m_data;
} }
/**
WAV文件的相关主要信息
*/
void getInfo(void){ void getInfo(void){
printf("ChunkID \t%x\n", format.ChunkID); printf("ChunkID \t%x\n", format.ChunkID);
printf("ChunkSize \t%d\n", format.ChunkSize); printf("ChunkSize \t%d\n", format.ChunkSize);
@ -420,7 +536,4 @@ public:
printf("Subchunk2Size \t%d\n", data.Subchunk2Size); printf("Subchunk2Size \t%d\n", data.Subchunk2Size);
} }
}; };
#endif /* wav_hpp */ #endif /* wav_hpp */