Ogg optimises.
This commit is contained in:
parent
d11050db34
commit
3f66afff24
5 changed files with 601 additions and 24 deletions
214
lib/bitstream.cpp
Normal file
214
lib/bitstream.cpp
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
#include"bitstream.h"
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
#include<iostream>
|
||||||
|
|
||||||
|
namespace Utils{
|
||||||
|
bitstream::bitstream(){
|
||||||
|
data = NULL;
|
||||||
|
offset = 0;
|
||||||
|
dataSize = 0;
|
||||||
|
bufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bitstream::checkBufferSize(unsigned int size){
|
||||||
|
if (size > bufferSize){
|
||||||
|
void* temp = realloc(data, size);
|
||||||
|
if (temp){
|
||||||
|
data = (char*) temp;
|
||||||
|
bufferSize = size;
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstream::append(char* input, size_t bytes){
|
||||||
|
if (checkBufferSize(dataSize+bytes)){
|
||||||
|
memcpy(data+dataSize, input, bytes);
|
||||||
|
dataSize += bytes;
|
||||||
|
}
|
||||||
|
//std::cout << std::hex << std::string(data, dataSize) << std::dec << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstream::append(std::string input){
|
||||||
|
append((char*)input.c_str(), input.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bitstream::peekOffset(size_t peekOffset){
|
||||||
|
peekOffset += offset;
|
||||||
|
return ((data[peekOffset >> 3]) >> (7 - (peekOffset & 7))) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::peek(size_t count){
|
||||||
|
if (count > 64){
|
||||||
|
std::cerr << "Utils::bitstream: Warning; Can not read "<< count <<" bits into a long long unsigned int!" << std::endl;
|
||||||
|
//return 0;
|
||||||
|
}
|
||||||
|
if (count > size()){
|
||||||
|
std::cerr << "Utils::bitstream: not enough bits left in stream. Left: " << size() << " requested: " << count << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
long long unsigned int retval = 0;
|
||||||
|
size_t curPlace = 0;
|
||||||
|
size_t readSize;
|
||||||
|
size_t readOff;
|
||||||
|
char readBuff;
|
||||||
|
while (curPlace < count){
|
||||||
|
readBuff = data[(int)((offset+curPlace)/8)];
|
||||||
|
readSize = 8;
|
||||||
|
readOff = (offset + curPlace) % 8; //the reading offset within the byte
|
||||||
|
if (readOff != 0){
|
||||||
|
//if we start our read not on the start of a byte
|
||||||
|
//curplace and retval should both be 0
|
||||||
|
//this should be the first read that aligns reading to bytes, if we read over the end of read byte
|
||||||
|
//we cut the MSb off of the buffer by bit mask
|
||||||
|
readSize -= readOff;//defining starting bit
|
||||||
|
readBuff = readBuff & ((1 << readSize) - 1);//bitmasking
|
||||||
|
}
|
||||||
|
//up until here we assume we read to the end of the byte
|
||||||
|
if (count - curPlace < readSize){//if we do not read to the end of the byte
|
||||||
|
//we cut off the LSb off of the read buffer by bitshift
|
||||||
|
readSize = count - curPlace;
|
||||||
|
readBuff = readBuff >> (8 - readSize - readOff);
|
||||||
|
}
|
||||||
|
retval = (retval << readSize) + readBuff;
|
||||||
|
curPlace += readSize;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::get(size_t count){
|
||||||
|
if(count <= size()){
|
||||||
|
long long unsigned int retVal;
|
||||||
|
retVal = peek(count);
|
||||||
|
skip(count);
|
||||||
|
return retVal;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstream::skip(size_t count){
|
||||||
|
if(count <= size()){
|
||||||
|
offset += count;
|
||||||
|
}else{
|
||||||
|
offset = dataSize*8;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::size(){
|
||||||
|
return (dataSize * 8) - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstream::clear(){
|
||||||
|
dataSize = 0;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstream::flush(){
|
||||||
|
memmove(data, data + (offset/8), dataSize - (offset/8));
|
||||||
|
dataSize -= offset / 8;
|
||||||
|
offset %= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::golombPeeker(){
|
||||||
|
for (size_t i = 0; i < 64 && i < size(); i++){
|
||||||
|
if (peekOffset(i)){
|
||||||
|
return peek((i * 2) + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::golombGetter(){
|
||||||
|
for (size_t i = 0; i < 64 && i < size(); i++){
|
||||||
|
if (peekOffset(i)){
|
||||||
|
return get((i * 2) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long int bitstream::getExpGolomb(){
|
||||||
|
long long unsigned int temp = golombGetter();
|
||||||
|
return (temp >> 1) * (1 - ((temp & 1) << 1)); //Is actually return (temp / 2) * (1 - (temp & 1) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::getUExpGolomb(){
|
||||||
|
return golombGetter() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long int bitstream::peekExpGolomb(){
|
||||||
|
long long unsigned int temp = golombPeeker();
|
||||||
|
return (temp >> 1) * (1 - ((temp & 1) << 1)); //Is actually return (temp / 2) * (1 - (temp & 1) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstream::peekUExpGolomb(){
|
||||||
|
return golombPeeker() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Note: other bitstream here
|
||||||
|
bitstreamLSBF::bitstreamLSBF(){
|
||||||
|
readBufferOffset = 0;
|
||||||
|
readBuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstreamLSBF::append (char* input, size_t bytes){
|
||||||
|
append(std::string(input,bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstreamLSBF::append (std::string input){
|
||||||
|
data += input;
|
||||||
|
fixData();
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstreamLSBF::size(){
|
||||||
|
return data.size() * 8 + readBufferOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstreamLSBF::get(size_t count){
|
||||||
|
if (count <= 32 && count <= readBufferOffset){
|
||||||
|
long long unsigned int retval = readBuffer & (((long long unsigned int)1 << count) - 1);
|
||||||
|
readBuffer = readBuffer >> count;
|
||||||
|
readBufferOffset -= count;
|
||||||
|
fixData();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstreamLSBF::skip(size_t count){
|
||||||
|
if (count <= 32 && count <= readBufferOffset){
|
||||||
|
readBuffer = readBuffer >> count;
|
||||||
|
readBufferOffset -= count;
|
||||||
|
fixData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long long unsigned int bitstreamLSBF::peek(size_t count){
|
||||||
|
if (count <= 32 && count <= readBufferOffset){
|
||||||
|
return readBuffer & ((1 << count) - 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstreamLSBF::clear(){
|
||||||
|
data = "";
|
||||||
|
readBufferOffset = 0;
|
||||||
|
readBuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitstreamLSBF::fixData(){
|
||||||
|
while (readBufferOffset <= 32 && data.size() != 0){
|
||||||
|
//readBuffer = readBuffer & ((1 << readBufferOffset) - 1) | (data[0] << readBufferOffset);
|
||||||
|
readBuffer |= (((long long unsigned int)data[0]) << readBufferOffset);
|
||||||
|
data = data.substr(1);
|
||||||
|
readBufferOffset += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
lib/bitstream.h
Normal file
56
lib/bitstream.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include<string>
|
||||||
|
|
||||||
|
namespace Utils{
|
||||||
|
class bitstream{
|
||||||
|
public:
|
||||||
|
bitstream();
|
||||||
|
bitstream& operator<< (std::string input){
|
||||||
|
append(input);
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
void append (char* input, size_t bytes);
|
||||||
|
void append (std::string input);
|
||||||
|
long long unsigned int size();
|
||||||
|
void skip(size_t count);
|
||||||
|
long long unsigned int get(size_t count);
|
||||||
|
long long unsigned int peek(size_t count);
|
||||||
|
bool peekOffset(size_t peekOffset);
|
||||||
|
void flush();
|
||||||
|
void clear();
|
||||||
|
long long int getExpGolomb();
|
||||||
|
long long unsigned int getUExpGolomb();
|
||||||
|
long long int peekExpGolomb();
|
||||||
|
long long unsigned int peekUExpGolomb();
|
||||||
|
private:
|
||||||
|
bool checkBufferSize(unsigned int size);
|
||||||
|
long long unsigned int golombGetter();
|
||||||
|
long long unsigned int golombPeeker();
|
||||||
|
char* data;
|
||||||
|
size_t offset;
|
||||||
|
size_t dataSize;
|
||||||
|
size_t bufferSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class bitstreamLSBF{
|
||||||
|
public:
|
||||||
|
bitstreamLSBF();
|
||||||
|
bitstreamLSBF& operator<< (std::string input){
|
||||||
|
append(input);
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
void append (char* input, size_t bytes);
|
||||||
|
void append (std::string input);
|
||||||
|
long long unsigned int size();
|
||||||
|
void skip(size_t count);
|
||||||
|
long long unsigned int get(size_t count);
|
||||||
|
long long unsigned int peek(size_t count);
|
||||||
|
void clear();
|
||||||
|
std::string data;
|
||||||
|
private:
|
||||||
|
long long unsigned int readBuffer;
|
||||||
|
int readBufferOffset;
|
||||||
|
void fixData();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,9 @@ namespace OGG{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Page::setPageSegments(char newVal){
|
inline void Page::setPageSegments(char newVal){
|
||||||
data[26] = newVal;
|
if(checkDataSize(26)){
|
||||||
|
data[26] = newVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Page::getSegmentTable(){
|
char* Page::getSegmentTable(){
|
||||||
|
@ -432,7 +434,7 @@ namespace OGG{
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Page::checkDataSize(unsigned int size){
|
inline bool Page::checkDataSize(unsigned int size){
|
||||||
if (size > datasize){
|
if (size > datasize){
|
||||||
void* tmp = realloc(data,size);
|
void* tmp = realloc(data,size);
|
||||||
if (tmp){
|
if (tmp){
|
||||||
|
|
312
lib/vorbis.cpp
312
lib/vorbis.cpp
|
@ -1,10 +1,27 @@
|
||||||
#include"vorbis.h"
|
#include "vorbis.h"
|
||||||
#include<stdlib.h>
|
#include <stdlib.h>
|
||||||
#include<string.h>
|
#include <string.h>
|
||||||
#include<sstream>
|
#include <sstream>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include "bitstream.h"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace vorbis{
|
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(){
|
header::header(){
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
@ -66,7 +83,7 @@ namespace vorbis{
|
||||||
|
|
||||||
char header::getBlockSize0(){
|
char header::getBlockSize0(){
|
||||||
if (getHeaderType() == 1){
|
if (getHeaderType() == 1){
|
||||||
return (data[28]>>4) & 0x0F;
|
return data[28] & 0x0F;
|
||||||
}else{
|
}else{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -74,12 +91,13 @@ namespace vorbis{
|
||||||
|
|
||||||
char header::getBlockSize1(){
|
char header::getBlockSize1(){
|
||||||
if (getHeaderType() == 1){
|
if (getHeaderType() == 1){
|
||||||
return data[28] & 0x0F;
|
return (data[28]>>4) & 0x0F;
|
||||||
}else{
|
}else{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char header::getFramingFlag(){
|
char header::getFramingFlag(){
|
||||||
if (getHeaderType() == 1){
|
if (getHeaderType() == 1){
|
||||||
return data[29];
|
return data[29];
|
||||||
|
@ -140,9 +158,6 @@ namespace vorbis{
|
||||||
if (length < 7){
|
if (length < 7){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/*if (! (newData[0] & 0x80)){
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
if(memcmp(newData+1, "vorbis", 6)!=0){
|
if(memcmp(newData+1, "vorbis", 6)!=0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +170,266 @@ namespace vorbis{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::deque<mode> 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 << ", " <<codebook_entries << std::dec<< std::endl;
|
||||||
|
bool orderedFlag = stream.get(1);
|
||||||
|
//std::cerr << " Ordered Flag: " << orderedFlag << std::endl;
|
||||||
|
if (!orderedFlag){
|
||||||
|
bool sparseFlag = stream.get(1);
|
||||||
|
//std::cerr << " Sparse Flag: " << sparseFlag << std::endl;
|
||||||
|
if (sparseFlag){//sparse flag
|
||||||
|
//sparse handling
|
||||||
|
for (int o = 0; o < codebook_entries; o++){
|
||||||
|
if (stream.get(1)){
|
||||||
|
//long long unsigned int length = stream.get(5)+1;
|
||||||
|
//std::cerr << " codeword length: "<< length <<std::endl;
|
||||||
|
stream.skip(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//exit(1);
|
||||||
|
}else{
|
||||||
|
for (int o = 0; o < codebook_entries; o++){
|
||||||
|
//long long unsigned int length = stream.get(5)+1;
|
||||||
|
//std::cerr << " codeword length: "<< length <<std::endl;
|
||||||
|
stream.skip(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//ordered handling
|
||||||
|
//std::cerr << "WARNING: Ordered codebook decoding in vorbis setup header NOT tested!" << std::endl;
|
||||||
|
long long unsigned int length = stream.get(5) + 1;
|
||||||
|
for (int o = 0; o < codebook_entries; o++){
|
||||||
|
int readnow = (std::log(codebook_entries-o))/(std::log(2))+1;
|
||||||
|
//std::cerr << " Read amount of bits: " << readnow << ";" << codebook_entries-o << std::endl;
|
||||||
|
o+=stream.get(readnow);
|
||||||
|
|
||||||
|
}
|
||||||
|
//exit(2);
|
||||||
|
}
|
||||||
|
char codebook_lookup_type = stream.get(4);
|
||||||
|
//std::cerr << " codebook_lookup_type: " <<std::hex<< (int)codebook_lookup_type <<std::dec << std::endl;
|
||||||
|
if (codebook_lookup_type != 0){
|
||||||
|
stream.skip(32);
|
||||||
|
stream.skip(32);
|
||||||
|
char codebook_value_bits = stream.get(4) + 1;
|
||||||
|
//std::cerr << " codebook_value_bits: " << (int)codebook_value_bits << std::endl;
|
||||||
|
bool codebook_sequence_flag = stream.get(1);
|
||||||
|
unsigned int codebook_lookup_value;
|
||||||
|
if (codebook_lookup_type == 1){
|
||||||
|
codebook_lookup_value = std::pow(codebook_entries, (1.0/codebook_dimensions));
|
||||||
|
//std::cerr << " std::pow(" << codebook_entries << ", (1/" << codebook_dimensions << ")) =";
|
||||||
|
}else{
|
||||||
|
codebook_lookup_value = codebook_entries * codebook_dimensions;
|
||||||
|
//std::cerr << " " << codebook_entries << " * " << codebook_dimensions << " = ";
|
||||||
|
}
|
||||||
|
//std::cerr << " codebook_lookup_value: " << codebook_lookup_value << std::endl << " ";
|
||||||
|
for (int i = 0; i < codebook_lookup_value; i++){
|
||||||
|
//(int)stream.get(codebook_value_bits) << " ";
|
||||||
|
stream.skip(codebook_value_bits);
|
||||||
|
}
|
||||||
|
//std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end of codebooks
|
||||||
|
//std::cerr << "bits in to time domain transforms: " << (beginsize-stream.size()) << ", " << stream.size() << std::endl;
|
||||||
|
//time domain transforms
|
||||||
|
long long unsigned int TDT = stream.get(6) + 1;
|
||||||
|
//std::cerr << "Time domain Transforms: " << TDT << std::endl;
|
||||||
|
for (int i = 0; i < TDT; i++){
|
||||||
|
stream.skip(16);
|
||||||
|
}
|
||||||
|
//std::cerr << "bits in to floors: " << (beginsize-stream.size()) << ", " << stream.size() << std::endl;
|
||||||
|
//Floors
|
||||||
|
long long unsigned int floors = stream.get(6) + 1;
|
||||||
|
//std::cerr << "Floors: " << floors << std::endl;
|
||||||
|
for (int i = 0; i < floors; i++){
|
||||||
|
long long unsigned int floorType = stream.get(16);
|
||||||
|
//std::cerr << "FloorType: " << floorType << std::endl;
|
||||||
|
switch(floorType){
|
||||||
|
case 0:{
|
||||||
|
std::cerr << "WARNING: FloorType 0 in vorbis setup header not tested!" << std::endl;
|
||||||
|
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 (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::cerr << " floorPartitions: " << floorPartitions << std::endl;
|
||||||
|
std::deque<int> 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<int> 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<<class_subclass); p++){
|
||||||
|
stream.skip(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.skip(2);//floor1_multiplier
|
||||||
|
int rangebits = stream.get(4);//rangebits
|
||||||
|
//std::cerr << " rangebits: " << rangebits << std::endl;
|
||||||
|
long long unsigned int count = 0;
|
||||||
|
long long unsigned int skipper = 0;
|
||||||
|
for (int o = 0; o < floorPartitions; o++){
|
||||||
|
count += class_dimensions[(partition_class[o])];
|
||||||
|
//std::cerr << " count: " << count << std::endl << " ";
|
||||||
|
while (skipper < count){
|
||||||
|
stream.skip(rangebits);
|
||||||
|
skipper ++;
|
||||||
|
}
|
||||||
|
//std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std::cerr << "bits in to Residues: " << (beginsize-stream.size()) << ", " << stream.size() << std::endl;
|
||||||
|
|
||||||
|
//Residues
|
||||||
|
long long unsigned int residues = stream.get(6) + 1;
|
||||||
|
//std::cerr << "Residue count: " << residues << std::endl;
|
||||||
|
for(int i = 0; i < residues; i++){
|
||||||
|
std::deque<char> 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; o<coupling_steps; o++){
|
||||||
|
int temp = (std::log((audioChannels-o)-1))/(std::log(2)) + 1;
|
||||||
|
//std::cerr << " ilogAudioChannels: " << temp << std::endl;
|
||||||
|
if (temp>0){
|
||||||
|
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<mode> 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){
|
uint32_t header::getInt32(size_t index){
|
||||||
if (datasize >= (index + 3)){
|
if (datasize >= (index + 3)){
|
||||||
|
@ -180,8 +454,24 @@ namespace vorbis{
|
||||||
|
|
||||||
std::string header::toPrettyString(size_t indent){
|
std::string header::toPrettyString(size_t indent){
|
||||||
std::stringstream r;
|
std::stringstream r;
|
||||||
r << "Testing vorbis Pretty string" << std::endl;
|
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();
|
return r.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
21
lib/vorbis.h
21
lib/vorbis.h
|
@ -1,9 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include<sys/types.h>
|
#include <cmath>
|
||||||
#include<stdint.h>
|
#include <sys/types.h>
|
||||||
#include<string>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
namespace vorbis{
|
namespace vorbis{
|
||||||
|
struct mode{
|
||||||
|
bool blockFlag;
|
||||||
|
unsigned short windowType;
|
||||||
|
unsigned short transformType;
|
||||||
|
char mapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline unsigned int ilog(unsigned int input){
|
||||||
|
return (std::log(input))/(std::log(2))+1;
|
||||||
|
}
|
||||||
|
|
||||||
class header{
|
class header{
|
||||||
public:
|
public:
|
||||||
header();
|
header();
|
||||||
|
@ -19,11 +32,13 @@ namespace vorbis{
|
||||||
char getBlockSize1();
|
char getBlockSize1();
|
||||||
char getFramingFlag();
|
char getFramingFlag();
|
||||||
std::string toPrettyString(size_t indent = 0);
|
std::string toPrettyString(size_t indent = 0);
|
||||||
|
std::deque<mode> readModeDeque(char audioChannels);
|
||||||
protected:
|
protected:
|
||||||
uint32_t getInt32(size_t index);
|
uint32_t getInt32(size_t index);
|
||||||
uint32_t getInt24(size_t index);
|
uint32_t getInt24(size_t index);
|
||||||
uint16_t getInt16(size_t index);
|
uint16_t getInt16(size_t index);
|
||||||
private:
|
private:
|
||||||
|
std::deque<mode> modes;
|
||||||
char* data;
|
char* data;
|
||||||
unsigned int datasize;
|
unsigned int datasize;
|
||||||
bool checkDataSize(unsigned int size);
|
bool checkDataSize(unsigned int size);
|
||||||
|
|
Loading…
Add table
Reference in a new issue