#include "bitstream.h" #include "defines.h" #include "vorbis.h" #include #include #include #include #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(char *newData, unsigned int length){ data = newData; datasize = length; } header::~header(){} 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 ntohl(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 isHeader(const char *newData, unsigned int length){ if (length < 7){return false;} if (memcmp(newData + 1, "vorbis", 6) != 0){return false;} return true; } bool header::isHeader(){return ::vorbis::isHeader(data, datasize);} /* bool header::read(const 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); stream.skip(28); // skipping common header part stream.skip(28); // skipping common header part char codebook_count = stream.get(8) + 1; for (int i = 0; i < codebook_count; i++){ long long unsigned int CMN = stream.get(24); if (CMN != 0x564342){ WARN_MSG("Is dit het? VCB != %c%c%c", (char)(CMN >> 16), (char)(CMN >> 8), (char)CMN); exit(1); } unsigned short codebook_dimensions = stream.get(16); unsigned int codebook_entries = stream.get(24); bool orderedFlag = stream.get(1); if (!orderedFlag){ bool sparseFlag = stream.get(1); if (sparseFlag){// sparse flag // sparse handling for (unsigned int o = 0; o < codebook_entries; o++){ if (stream.get(1)){stream.skip(5);} } }else{ for (unsigned int o = 0; o < codebook_entries; o++){stream.skip(5);} } }else{ // ordered handling stream.skip(5); for (unsigned int o = 0; o < codebook_entries; o++){ int readnow = (std::log(codebook_entries - o)) / (std::log(2)) + 1; o += stream.get(readnow); } } char codebook_lookup_type = stream.get(4); if (codebook_lookup_type != 0){ stream.skip(32); stream.skip(32); char codebook_value_bits = stream.get(4) + 1; stream.skip(1); unsigned int codebook_lookup_value; if (codebook_lookup_type == 1){ codebook_lookup_value = std::pow(codebook_entries, (1.0 / codebook_dimensions)); }else{ codebook_lookup_value = codebook_entries * codebook_dimensions; } for (unsigned int i = 0; i < codebook_lookup_value; i++){ stream.skip(codebook_value_bits); } } } // end of codebooks // time domain transforms long long unsigned int TDT = stream.get(6) + 1; for (unsigned int i = 0; i < TDT; i++){stream.skip(16);} // Floors long long unsigned int floors = stream.get(6) + 1; for (unsigned int i = 0; i < floors; i++){ long long unsigned int floorType = stream.get(16); switch (floorType){ case 0:{ WARN_MSG("FloorType 0 in vorbis setup header not tested!"); stream.skip(8); // order stream.skip(16); // rate stream.skip(16); // bark_map_size stream.skip(6); // amplitude bits stream.skip(8); // amplitude offset long long unsigned int numberOfBooks = stream.get(4) + 1; for (unsigned int o = 0; o < numberOfBooks; o++){ stream.skip(8); // book list array } break; } case 1:{ long long unsigned int floorPartitions = stream.get(5); long long int max = -1; std::deque partition_class; for (unsigned int o = 0; o < floorPartitions; o++){ long long int temp = stream.get(4); partition_class.push_back(temp); if (temp > max) max = temp; } std::deque class_dimensions; for (int o = 0; o <= max; o++){ class_dimensions.push_back(stream.get(3) + 1); // class dimensions PUT IN ARRAY! int class_subclass = stream.get(2); if (class_subclass != 0){ stream.skip(8); // class_master_books } for (int p = 0; p < (1 << class_subclass); p++){stream.skip(8);} } stream.skip(2); // floor1_multiplier int rangebits = stream.get(4); // rangebits long long unsigned int count = 0; long long unsigned int skipper = 0; for (unsigned int o = 0; o < floorPartitions; o++){ count += class_dimensions[(partition_class[o])]; while (skipper < count){ stream.skip(rangebits); skipper++; } } break; } default: exit(0); } } // Residues long long unsigned int residues = stream.get(6) + 1; for (unsigned int i = 0; i < residues; i++){ std::deque residueCascade; long long unsigned int residueType = stream.get(16); 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 stream.skip(8); // residue classbook for (unsigned int o = 0; o < residueClass; o++){ char temp = stream.get(3); // low bits bool bitFlag = stream.get(1); if (bitFlag){temp += stream.get(5) << 3;} residueCascade.push_back(temp); } for (unsigned int o = 0; o < residueClass; o++){ for (unsigned int p = 0; p < 7; p++){ if (((residueCascade[o] >> p) & 1) == 1){ stream.skip(8); }else{ } } } }else{ exit(0); } } // Mappings long long unsigned int mappings = stream.get(6) + 1; for (unsigned int i = 0; i < mappings; i++){ long long unsigned int mapType = stream.get(16); 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; for (unsigned int o = 0; o < coupling_steps; o++){ int temp = (std::log((audioChannels - o) - 1)) / (std::log(2)) + 1; if (temp > 0){ stream.skip(temp); // mapping magnitude stream.skip(temp); // mapping angle } } } char meh = stream.get(2); if (meh != 0){ ERROR_MSG("Sanity check ==0 : %i", (int)meh); exit(0); } 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 long long unsigned int modes = stream.get(6) + 1; std::deque retVal; for (unsigned int i = 0; i < modes; i++){ mode temp; temp.blockFlag = stream.get(1); temp.windowType = stream.get(16); temp.transformType = stream.get(16); temp.mapping = stream.get(8); retVal.push_back(temp); } stream.skip(1); 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(); } }// namespace vorbis