T13: NativeMixer mirror server pipeline (track gain/pan constant-power + brickwall limiter tanh, wired VST2/VST3 bridge, golden test 0.0001dB)
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// native_mixer_test.cpp — golden test driver cho NativeMixer (T13).
|
||||
//
|
||||
// Đọc input raw float32 interleaved stereo, áp NativeMixer (track gain/pan +
|
||||
// master limiter) theo argv, ghi output raw float32 interleaved. Python
|
||||
// (test_native_mixer_golden.py) so RMS/peak với reference server pipeline.
|
||||
//
|
||||
// Usage: native_mixer_test.exe <in.raw> <out.raw> <gainDb> <pan> <limActive> <thresholdDb>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "NativeMixer.h"
|
||||
|
||||
using sonicforge::int32;
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
if (argc < 7)
|
||||
{
|
||||
std::fprintf (stderr, "usage: native_mixer_test in.raw out.raw gainDb pan limActive thresholdDb\n");
|
||||
return 2;
|
||||
}
|
||||
const char* inPath = argv[1];
|
||||
const char* outPath = argv[2];
|
||||
const float gainDb = static_cast<float> (std::atof (argv[3]));
|
||||
const float pan = static_cast<float> (std::atof (argv[4]));
|
||||
const int32 limActive = std::atoi (argv[5]);
|
||||
const float thresholdDb = static_cast<float> (std::atof (argv[6]));
|
||||
|
||||
FILE* f = std::fopen (inPath, "rb");
|
||||
if (!f)
|
||||
{
|
||||
std::fprintf (stderr, "cannot open %s\n", inPath);
|
||||
return 2;
|
||||
}
|
||||
std::fseek (f, 0, SEEK_END);
|
||||
const long nBytes = std::ftell (f);
|
||||
std::fseek (f, 0, SEEK_SET);
|
||||
if (nBytes <= 0 || (nBytes % 8) != 0)
|
||||
{
|
||||
std::fprintf (stderr, "bad input size %ld\n", nBytes);
|
||||
std::fclose (f);
|
||||
return 2;
|
||||
}
|
||||
std::vector<float> buf (static_cast<size_t> (nBytes) / sizeof (float));
|
||||
if (std::fread (buf.data (), sizeof (float), buf.size (), f) != buf.size ())
|
||||
{
|
||||
std::fprintf (stderr, "short read\n");
|
||||
std::fclose (f);
|
||||
return 2;
|
||||
}
|
||||
std::fclose (f);
|
||||
|
||||
const int32 frames = static_cast<int32> (buf.size () / 2);
|
||||
std::vector<float> inL (static_cast<size_t> (frames));
|
||||
std::vector<float> inR (static_cast<size_t> (frames));
|
||||
for (int32 i = 0; i < frames; ++i)
|
||||
{
|
||||
inL[static_cast<size_t> (i)] = buf[static_cast<size_t> (2 * i)];
|
||||
inR[static_cast<size_t> (i)] = buf[static_cast<size_t> (2 * i + 1)];
|
||||
}
|
||||
|
||||
sonicforge::NativeMixer mixer;
|
||||
mixer.setTrack (sonicforge::TrackGainPan::fromDbPan (gainDb, pan));
|
||||
mixer.setLimiter (limActive != 0, thresholdDb);
|
||||
mixer.processInPlace (inL.data (), inR.data (), frames);
|
||||
|
||||
for (int32 i = 0; i < frames; ++i)
|
||||
{
|
||||
buf[static_cast<size_t> (2 * i)] = inL[static_cast<size_t> (i)];
|
||||
buf[static_cast<size_t> (2 * i + 1)] = inR[static_cast<size_t> (i)];
|
||||
}
|
||||
|
||||
FILE* g = std::fopen (outPath, "wb");
|
||||
if (!g)
|
||||
{
|
||||
std::fprintf (stderr, "cannot write %s\n", outPath);
|
||||
return 2;
|
||||
}
|
||||
std::fwrite (buf.data (), sizeof (float), buf.size (), g);
|
||||
std::fclose (g);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user