diablo2-web/tests/fixtures/audio-fixture-generator.cpp

99 lines
3.8 KiB
C++

#include <iostream>
#include <fstream>
#include <vector>
#include <cstdint>
#include <string>
#include <iomanip>
#include "stormlib_src/huffman/huff.h"
#include "stormlib_src/adpcm/adpcm.h"
using namespace std;
ofstream out;
void dumpHex(const string& name, const vector<uint8_t>& data) {
out << "export const " << name << " = new Uint8Array([\n";
for(size_t i=0; i<data.size(); ++i) {
out << "0x" << hex << setfill('0') << setw(2) << (int)data[i];
if (i < data.size() - 1) out << ", ";
if ((i + 1) % 16 == 0) out << "\n";
}
out << "\n]);\n\n";
}
int main() {
out.open("/usr/local/google/home/taodao/d2w-wg3/tests/fixtures/audio.ts");
// 1. Huffman inputs
// We want a highly competitive input that causes many weight swaps to catch any minor weight deviation
vector<uint8_t> huff_input;
for (int rep=0; rep<12; rep++) {
for (int i=0; i<256; i++) {
huff_input.push_back(i);
}
}
// Also include some repeating blocks
for (int rep=0; rep<10; rep++) {
for (int i=0; i<256; i++) {
huff_input.push_back((i * 17) % 256);
}
}
dumpHex("huff_uncompressed", huff_input);
for (int type = 0; type <= 8; type++) {
THuffmannTree tree(true);
vector<uint8_t> compressed(16384, 0);
TOutputStream os(compressed.data(), compressed.size());
int encSize = tree.Compress(&os, huff_input.data(), huff_input.size(), type);
compressed.resize(encSize);
dumpHex("huff_compressed_type_" + to_string(type), compressed);
}
// 2. ADPCM
// We want a vector that pushes differences up and down to trigger clamping and dynamic shift
vector<int16_t> pcm_mono = {0, 100, 200, 300, 1000, 5000, 10000, 20000, 32767, -32768, -20000, -10000, 0, 0, 10, -10};
vector<int16_t> pcm_stereo = {0, 10, 100, -100, 500, -500, 32767, -32768, 20000, -20000, 0, 10};
// Pad them a bit to make them longer
for(int i=0; i<300; i++) { pcm_mono.push_back((i*113) % 20000); pcm_stereo.push_back((i*97) % 20000); }
dumpHex("adpcm_mono_uncompressed", vector<uint8_t>((uint8_t*)pcm_mono.data(), (uint8_t*)pcm_mono.data() + pcm_mono.size() * 2));
dumpHex("adpcm_stereo_uncompressed", vector<uint8_t>((uint8_t*)pcm_stereo.data(), (uint8_t*)pcm_stereo.data() + pcm_stereo.size() * 2));
for (int cmpType = 4; cmpType <= 6; cmpType++) {
vector<uint8_t> comp_mono(2048, 0);
int mSize = CompressADPCM(comp_mono.data(), comp_mono.size(), (void*)pcm_mono.data(), pcm_mono.size() * 2, 1, cmpType);
comp_mono.resize(mSize);
dumpHex("adpcm_mono_compressed_" + to_string(cmpType), comp_mono);
vector<uint8_t> dec_mono(2048, 0);
int decSize = DecompressADPCM(dec_mono.data(), dec_mono.size(), comp_mono.data(), comp_mono.size(), 1);
dec_mono.resize(decSize);
dumpHex("adpcm_mono_expected_" + to_string(cmpType), dec_mono);
}
for (int cmpType = 4; cmpType <= 6; cmpType++) {
vector<uint8_t> comp_stereo(2048, 0);
int sSize = CompressADPCM(comp_stereo.data(), comp_stereo.size(), (void*)pcm_stereo.data(), pcm_stereo.size() * 2, 2, cmpType);
comp_stereo.resize(sSize);
dumpHex("adpcm_stereo_compressed_" + to_string(cmpType), comp_stereo);
vector<uint8_t> dec_stereo(2048, 0);
int decSize = DecompressADPCM(dec_stereo.data(), dec_stereo.size(), comp_stereo.data(), comp_stereo.size(), 2);
dec_stereo.resize(decSize);
dumpHex("adpcm_stereo_expected_" + to_string(cmpType), dec_stereo);
}
out.close();
return 0;
}
/*
To regenerate the audio.ts fixtures, place StormLib's C sources alongside this file
and compile and execute it using g++:
g++ -o gen_vectors audio-fixture-generator.cpp stormlib_src/huffman/huff.cpp stormlib_src/adpcm/adpcm.cpp
./gen_vectors
*/