#include "vorbis.h" #include #include #include #include #include "bitstream.h" #include #include #include namespace vorbis{ long long unsigned int reverseByte16(long long unsigned int input){ return ((input & 0xFF00) >> 8) | ((input & 0xFF) << 8); } long long unsigned int reverseByte24(long long unsigned int input){ return ((input & 0xFF0000) >> 16)| (input & 0xFF00) | ((input & 0xFF) << 16); } long long unsigned int reverseByte32(long long unsigned int input){ return ((input & 0xFF000000) >> 24)| ((input & 0xFF0000) >> 8) | ((input & 0xFF00) << 8) | ((input & 0xFF) << 24); } header::header(){ data = NULL; datasize = 0; } int header::getHeaderType(){ return (int)(data[0]); } long unsigned int header::getVorbisVersion(){ if (getHeaderType() == 1){ return getInt32(7); }else{ return 0; } } char header::getAudioChannels(){ if (getHeaderType() == 1){ return data[11]; }else{ return 0; } } long unsigned int header::getAudioSampleRate(){ if (getHeaderType() == 1){ return getInt32(12); }else{ return 0; } } long unsigned int header::getBitrateMaximum(){ if (getHeaderType() == 1){ return getInt32(16); }else{ return 0; } } long unsigned int header::getBitrateNominal(){ if (getHeaderType() == 1){ return getInt32(20); }else{ return 0; } } long unsigned int header::getBitrateMinimum(){ if (getHeaderType() == 1){ return getInt32(24); }else{ return 0; } } char header::getBlockSize0(){ if (getHeaderType() == 1){ return data[28] & 0x0F; }else{ return 0; } } char header::getBlockSize1(){ if (getHeaderType() == 1){ return (data[28]>>4) & 0x0F; }else{ return 0; } } char header::getFramingFlag(){ if (getHeaderType() == 1){ return data[29]; }else{ return 0; } } bool header::checkDataSize(unsigned int size){ if (size > datasize){ void* tmp = realloc(data,size); if (tmp){ data = (char*)tmp; datasize = size; return true; }else{ return false; } }else{ return true; } } bool header::validate(){ switch(getHeaderType()){ case 1://ID header if (datasize!=30){ return false; } if (getVorbisVersion()!=0){ return false; } if (getAudioChannels()<=0){ return false; }; if (getAudioSampleRate()<=0) { return false; } if (getBlockSize0()>getBlockSize1()){ return false; }; if (getFramingFlag()!=1){ return false; }; break; case 3://comment header break; case 5://init header break; default: return false; break; } return true; } bool header::read(char* newData, unsigned int length){ if (length < 7){ return false; } if(memcmp(newData+1, "vorbis", 6)!=0){ return false; } if (checkDataSize(length)){ memcpy(data, newData, length); }else{ return false; } return true; } std::deque header::readModeDeque(char audioChannels){ Utils::bitstreamLSBF stream; stream.append(data,datasize); long long unsigned int beginsize = stream.size(); stream.skip(28); //skipping common header part stream.skip(28); //skipping common header part char codebook_count = stream.get(8) + 1; //std::cerr << "Codebook Count: " << (int)codebook_count << std::endl; for (int i = 0; i < codebook_count; i++){ //std::cerr << "codebook entry: " << i << std::endl; long long unsigned int CMN = stream.get(24); //std::cerr << " Codebook magic number: " << std::hex << CMN << std::dec << std::endl; if (CMN != 0x564342){ exit(1); } unsigned short codebook_dimensions = stream.get(16); unsigned int codebook_entries = stream.get(24); //std::cerr << " Codebook_dimensions, entries: "<< std::hex << codebook_dimensions << ", " < partition_class; for (int o = 0; o < floorPartitions; o++){ long long int temp = stream.get(4); partition_class.push_back(temp); //std::cerr << " partition_class: " << temp << std::endl; if (temp>max) max = temp; } std::deque class_dimensions; //std::cerr << " Max: " << max << std::endl; for (int o = 0; o <= max; o++){ class_dimensions.push_back(stream.get(3)+1);//class dimensions PUT IN ARRAY! //std::cerr << " class dimension: " << class_dimensions.back() << std::endl; int class_subclass = stream.get(2); if (class_subclass !=0){ stream.skip(8);//class_master_books } for (int p = 0; p < (1< residueCascade; long long unsigned int residueType = stream.get(16); //std::cerr << "ResidueType: " << residueType << std::endl; if(residueType<=2){ stream.skip(24);//residue begin stream.skip(24);//residue end stream.skip(24);//residue partition size long long unsigned int residueClass = stream.get(6)+1;//residue classifications //std::cerr<< " ResidueCLassification: " << residueClass << std::endl; stream.skip(8);//residue classbook for (int o = 0; o < residueClass; o++){ char temp = stream.get(3);//low bits bool bitFlag = stream.get(1); //std::cerr << " bitFlag: " << bitFlag << std::endl; if (bitFlag){ temp += stream.get(5) << 3; } //std::cerr << " temp: " << (int)temp << std::endl; residueCascade.push_back(temp); } for (int o = 0; o < residueClass; o++){ //std::cerr << " "; for (int p = 0; p < 7; p++){ if (((residueCascade[o] >> p) & 1) == 1){ //std::cerr << "1"; stream.skip(8); }else{ //std::cerr << "0"; } } //std::cerr << std::endl; } }else{ exit(0); } } //std::cerr << "bits in to Mappings: " << (beginsize-stream.size()) << ", " << stream.size() << std::endl; //Mappings long long unsigned int mappings = stream.get(6) + 1; //std::cerr << "Mapping count: " << mappings << std::endl; for(int i = 0; i < mappings; i++){ long long unsigned int mapType = stream.get(16); //std::cerr << "MapType: " << mapType << std::endl; if (mapType == 0){ char mappingSubmaps = 1; if (stream.get(1)==1){ mappingSubmaps = stream.get(4);//vorbis mapping submaps } long long unsigned int coupling_steps = 0; if (stream.get(1)==1){ coupling_steps = stream.get(8)+1; //std::cerr << " coupling steps: " << coupling_steps << std::endl; //std::cerr << " AudioChannels: " << (int)audioChannels << std::endl; for (int o = 0; o0){ stream.skip(temp);//mapping magnitude stream.skip(temp);//mapping angle } } } char meh = stream.get(2); if (meh != 0){ std::cerr << " Sanity Check ==0 : " << (int)meh << std::endl; exit(0); } //std::cerr << " Mapping Submaps: " << mappingSubmaps << std::endl; if (mappingSubmaps > 1){ for (int o = 0; o < audioChannels; o++){ stream.skip(4); } } for (int o = 0; o < mappingSubmaps; o++){ stream.skip(8);//placeholder stream.skip(8);//vorbis Mapping subfloor stream.skip(8);//vorbis mapping submap residue } }else{ exit(0); } } //Modes //std::cerr << "bits in to Modes: " << (beginsize-stream.size()) << ", " << stream.size() << std::endl; long long unsigned int modes = stream.get(6) + 1; //std::cerr << "Mode count: " << modes << std::endl; std::deque retVal; for (int i = 0; i < modes; i++){ mode temp; temp.blockFlag = stream.get(1); //std::cerr << " blockFlag: " << temp.blockFlag << std::endl; temp.windowType = stream.get(16); //std::cerr << " windowType: " << temp.windowType << std::endl; temp.transformType = stream.get(16); //std::cerr << " transformType: " << temp.transformType << std::endl; temp.mapping = stream.get(8); //std::cerr << " mapping: " << (int)temp.mapping << std::endl; retVal.push_back(temp); } //std::cerr << "Ending Bitflag (!=0): " << stream.get(1) << std::endl; stream.skip(1); //std::cerr << "bits left: " << (beginsize-stream.size()) << ", " << stream.size() << std::endl; return retVal; } uint32_t header::getInt32(size_t index){ if (datasize >= (index + 3)){ return (data[index] << 24) + (data[index + 1] << 16) + (data[index + 2] << 8) + data[index + 3]; } return 0; } uint32_t header::getInt24(size_t index){ if (datasize >= (index + 2)){ return 0 + (data[index] << 16) + (data[index + 1] << 8) + data[index + 2]; } return 0; } uint16_t header::getInt16(size_t index){ if (datasize >= (index + 1)){ return 0 + (data[index] << 8) + data[index + 1]; } return 0; } std::string header::toPrettyString(size_t indent){ std::stringstream r; r << std::string(indent+1,' ') << "Vorbis Header" << std::endl; r << std::string(indent+2,' ') << "Magic Number: " << std::string(data + 1,6) << std::endl; r << std::string(indent+2,' ') << "Header Type: " << getHeaderType() << std::endl; if (getHeaderType() == 1){ r << std::string(indent+2,' ') << "ID Header" << std::endl; r << std::string(indent+2,' ') << "VorbisVersion: " << getVorbisVersion() << std::endl; r << std::string(indent+2,' ') << "AudioChannels: " << (int)getAudioChannels() << std::endl; r << std::string(indent+2,' ') << "BitrateMaximum: " << std::hex << getBitrateMaximum() << std::dec << std::endl; r << std::string(indent+2,' ') << "BitrateNominal: " << std::hex << getBitrateNominal() << std::dec << std::endl; r << std::string(indent+2,' ') << "BitrateMinimum: " << std::hex << getBitrateMinimum() << std::dec << std::endl; r << std::string(indent+2,' ') << "BlockSize0: " << (int)getBlockSize0() << std::endl; r << std::string(indent+2,' ') << "BlockSize1: " << (int)getBlockSize1() << std::endl; r << std::string(indent+2,' ') << "FramingFlag: " << (int)getFramingFlag() << std::endl; } else if (getHeaderType() == 3){ r << std::string(indent+2,' ') << "Comment Header" << std::endl; } else if (getHeaderType() == 5){ r << std::string(indent+2,' ') << "Setup Header" << std::endl; } return r.str(); } }