Commit a896c01d authored by Stefan Westerfeld's avatar Stefan Westerfeld

Implement simple shuffle algorithm.

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 912304b3
......@@ -27,6 +27,7 @@ namespace Params
static int min_band = 20;
static double water_delta = 0.015; // strength of the watermark
static double pre_scale = 0.95; // rescale the signal to avoid clipping after watermark is added
static bool shuffle = false;
}
void
......@@ -140,6 +141,10 @@ parse_options (int *argc_p,
{
Params::block = atoi (opt_arg);
}
else if (check_arg (argc, argv, &i, "--shuffle"))
{
Params::shuffle = true;
}
else if (check_arg (argc, argv, &i, "--water-delta", &opt_arg))
{
Params::water_delta = atof (opt_arg);
......@@ -246,6 +251,27 @@ get_up_down (int f, vector<int>& up, vector<int>& down)
choose_bands (down);
}
vector<int>
gen_shuffle (size_t size, int seed)
{
vector<int> result (size);
std::mt19937_64 rng;
// should use cryptographically secure generator, properly seeded
rng.seed (seed);
for (size_t i = 0; i < result.size(); i++)
result[i] = i;
// Fisher–Yates shuffle
for (size_t i = 0; i < result.size() - 1; i++)
{
size_t j = i + rng() % (result.size() - i);
std::swap (result[i], result[j]);
}
return result;
}
static unsigned char
from_hex_nibble (char c)
{
......@@ -408,7 +434,11 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
{
for (int ch = 0; ch < wav_data.n_channels(); ch++)
{
vector<float> frame = get_frame (wav_data, f, ch);
const int f_offset = f - f % (Params::block * Params::frames_per_bit);
vector<int> shuffle = gen_shuffle (Params::block * Params::frames_per_bit, f / (Params::block * Params::frames_per_bit));
const int f_shuffle = Params::shuffle ? f_offset + shuffle[f % (Params::block * Params::frames_per_bit)] : f;
vector<float> frame = get_frame (wav_data, f_shuffle, ch);
vector<float> new_frame;
if (frame.size() == Params::frame_size)
......@@ -422,7 +452,7 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
new_frame = frame;
}
for (size_t i = 0; i < new_frame.size(); i++)
out_signal[(f * Params::frame_size + i) * wav_data.n_channels() + ch] = new_frame[i] * Params::pre_scale;
out_signal[(f_shuffle * Params::frame_size + i) * wav_data.n_channels() + ch] = new_frame[i] * Params::pre_scale;
}
}
......@@ -461,7 +491,9 @@ get_watermark (const string& infile, const string& orig_pattern)
{
for (int ch = 0; ch < wav_data.n_channels(); ch++)
{
vector<float> frame = get_frame (wav_data, f, ch);
const int f_offset = f - f % (Params::block * Params::frames_per_bit);
vector<int> shuffle = gen_shuffle (Params::block * Params::frames_per_bit, f / (Params::block * Params::frames_per_bit));
vector<float> frame = get_frame (wav_data, Params::shuffle ? f_offset + shuffle[f % (Params::block * Params::frames_per_bit)] : f, ch);
if (frame.size() == Params::frame_size)
{
/* windowing */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment