diff --git a/include/type.hpp b/include/type.hpp index 82f0aba..7905dfc 100644 --- a/include/type.hpp +++ b/include/type.hpp @@ -12,8 +12,6 @@ #include #include #endif - - #include #include #include diff --git a/include/wav.hpp b/include/wav.hpp new file mode 100644 index 0000000..3cb8730 --- /dev/null +++ b/include/wav.hpp @@ -0,0 +1,409 @@ +#ifndef wav_hpp +#define wav_hpp + +#include +#include + +using std::string; +using std::vector; + +FILE * readWAVInfo(void); + +struct WAV_Format{ + uint32_t ChunkID; /* "RIFF" */ + uint32_t ChunkSize; /* 36 + Subchunk2Size */ + uint32_t Format; /* "WAVE" */ +}; + +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. */ +}; + +struct WAV_CHUNK { + uint32_t SubchunkExID; + uint32_t SubchunkExSize; + uint32_t NumChannels; +}; + +struct CHUNK_INFO{ + uint32_t ChunkID; + uint32_t ChunkSize; +}; + +struct WAV_DATA{ + /* sub-chunk "data" */ + uint32_t Subchunk2ID; /* "data" */ + uint32_t Subchunk2Size; /* data size */ +}; + +struct process{ + uint32_t start,now,end,step; +}; + +struct Bit32 +{ + unsigned short da:16; + unsigned short db:16; +}; + +struct BitO16 +{ + unsigned short da:16; +}; + +struct Bit16 +{ + unsigned short da:8; + unsigned short db:8; +}; + +struct BitO8 +{ + unsigned short da:8; +}; + +class Data32{ +public: + bool active; + vector 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; + } + +}; + +class Data{ +public: + bool active; + uint32_t channels, bit_size; + vector bit32; + vector bito16; + vector bit16; + vector bito8; + vector color_data; + Color avg_color; + Data(uint32_t tchannels, uint32_t tbit_size,void *start, void *end):active(true),channels(tchannels),bit_size(tbit_size){ + 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); + } + } + 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); + } + } + } + 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; + } + 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; + + //printf("%d %d\n",bit.da,bit.db); + 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; + 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); + } + } + 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}); + } + } + } +}; + +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) throw -1; + + do{ + fread(&this->info, 1, sizeof(struct CHUNK_INFO), fp); + char *p_id = (char *)(&info.ChunkID); + + uint32_t temp; + char *p_tmp = (char *)(&temp); + 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); + 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); + /*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);*/ + 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; + } + 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; + } + } + + 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; + } + } + + 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; + } + + 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 */ diff --git a/src/graphs.cpp b/src/graphs.cpp new file mode 100644 index 0000000..999e6f8 --- /dev/null +++ b/src/graphs.cpp @@ -0,0 +1,23 @@ +// +// graphs.c +// Fields +// +// Created by 胡一兵 on 2018/12/13. +// Copyright © 2018年 Bakantu. All rights reserved. +// + +#include +#include +#include + +/* +extern int if_fresh, if_draw; +list Window::shapes; +map Window::menus; +extern vector fields; + +extern Window *p_nwd; +extern WAV twav; +extern Shape *p_avg; + */ + diff --git a/unix/main.cpp b/unix/main.cpp index 63f73ae..9e4392c 100644 --- a/unix/main.cpp +++ b/unix/main.cpp @@ -1,11 +1,3 @@ -// -// main.cpp -// Fields -// -// Created by 胡一兵 on 2018/12/13. -// Copyright © 2018年 Bakantu. All rights reserved. -// - #include #include #include @@ -28,6 +20,7 @@ int main(int argc, char * argv[]) { nwd.position({200,100}); twav.getInfo(); twav.setTimer(20); + int hw = sqrt(twav.m_pss.step); nwd.create("Fields"); p_avg->setRetangle({{0.98,-0.98},{0.85,-0.85}}); @@ -45,3 +38,51 @@ int main(int argc, char * argv[]) { nwd.show(); return 0; } + +void draw_fields(int signal){ + if (if_fresh == 1 && if_draw == 0){ + timeval timer_a, timer_b; + gettimeofday(&timer_a, NULL); + Data tmp_data = twav.getData(); + tmp_data.Data2Color(); + if(tmp_data.active == true){ + if_fresh = 0; + if_draw = 1; + int idx = 1; + for(auto i = tmp_data.color_data.begin(); i!= tmp_data.color_data.end(); i++){ + Color m_color = (*i); + //printf("%f %f %f\n",m_color.red, m_color.green, m_color.blue); + //m_color.brighter(); + if(idx>fields.size()-1) break; + fields[idx]->color.setColor(m_color); + idx++; + } + p_avg->setColor(tmp_data.avg_color); + } + else{ + for(auto i = fields.begin(); i!= fields.end(); i++){ + (*i)->color.setColor({0,0,0}); + } + p_avg->setColor({0,0,0}); + } + gettimeofday(&timer_b, NULL); + //printf("Draw Time: %ums\n",(timer_b.tv_usec-timer_a.tv_usec)/1000); + } + glutTimerFunc(DRAW_TIMER, draw_fields, 1); +} + +unsigned long fresh_screen(int signal){ + if(if_draw == 1 && if_fresh == 0){ + timeval timer_a, timer_b; + if_fresh = 1; + if_draw = 0; + gettimeofday(&timer_a, NULL); + p_nwd->displayEngine(); + gettimeofday(&timer_b, NULL); + double ms = (timer_b.tv_usec-timer_a.tv_usec)/1000.0; + if(ms - (unsigned long)ms > 0.65) ms = (unsigned long)ms + 1; + //printf("MS: %lf\n",ms); + return ms; + } + return -1; +}