Commit 95f008b9 authored by Stefan Westerfeld's avatar Stefan Westerfeld

Move key list loop into SyncFinder/BlockDecoder/ClipDecoder.

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 3949cd7d
......@@ -26,10 +26,10 @@ using std::vector;
using std::string;
using std::min;
void
vector<vector<SyncFinder::FrameBit>>
SyncFinder::init_up_down (const Key& key, const WavData& wav_data, Mode mode)
{
sync_bits.clear();
vector<vector<SyncFinder::FrameBit>> sync_bits;
// "long" blocks consist of two "normal" blocks, which means
// the sync bits pattern is repeated after the end of the first block
......@@ -76,6 +76,7 @@ SyncFinder::init_up_down (const Key& key, const WavData& wav_data, Mode mode)
std::sort (frame_bits.begin(), frame_bits.end(), [] (FrameBit& f1, FrameBit& f2) { return f1.frame < f2.frame; });
sync_bits.push_back (frame_bits);
}
return sync_bits;
}
/* safe to call from any thread */
......@@ -116,7 +117,8 @@ SyncFinder::bit_quality (float umag, float dmag, int bit)
}
double
SyncFinder::sync_decode (const WavData& wav_data, const size_t start_frame,
SyncFinder::sync_decode (const vector<vector<FrameBit>>& sync_bits,
const WavData& wav_data, const size_t start_frame,
const vector<float>& fft_out_db,
const vector<char>& have_frames,
ConvBlockType *block_type)
......@@ -179,12 +181,22 @@ SyncFinder::scan_silence (const WavData& wav_data)
wav_data_last--;
}
vector<SyncFinder::Score>
SyncFinder::search_approx (const WavData& wav_data, Mode mode)
vector<SyncFinder::KeyResult>
SyncFinder::search_approx (const std::vector<Key>& key_list, const WavData& wav_data, Mode mode)
{
vector<float> fft_db;
vector<char> have_frames;
vector<Score> sync_scores;
vector<KeyResult> key_results;
for (const auto& key : key_list)
{
KeyResult key_result;
key_result.key = key;
key_result.sync_bits = init_up_down (key, wav_data, mode);
key_results.push_back (key_result);
}
// compute multiple time-shifted fft vectors
size_t n_bands = Params::max_band - Params::min_band + 1;
......@@ -198,16 +210,21 @@ SyncFinder::search_approx (const WavData& wav_data, Mode mode)
{
const size_t sync_index = start_frame * Params::frame_size + sync_shift;
if ((start_frame + total_frame_count) * wav_data.n_channels() * n_bands < fft_db.size())
{
for (auto& key_result : key_results)
{
ConvBlockType block_type;
double quality = sync_decode (wav_data, start_frame, fft_db, have_frames, &block_type);
double quality = sync_decode (key_result.sync_bits, wav_data, start_frame, fft_db, have_frames, &block_type);
// printf ("%zd %f\n", sync_index, quality);
sync_scores.emplace_back (Score { sync_index, quality, block_type });
key_result.sync_scores.emplace_back (Score { sync_index, quality, block_type });
}
}
}
sort (sync_scores.begin(), sync_scores.end(), [] (const Score& a, const Score &b) { return a.index < b.index; });
return sync_scores;
}
for (auto& key_result : key_results)
sort (key_result.sync_scores.begin(), key_result.sync_scores.end(), [] (const Score& a, const Score &b) { return a.index < b.index; });
return key_results;
}
void
......@@ -255,12 +272,12 @@ SyncFinder::sync_select_n_best (vector<Score>& sync_scores, size_t n)
}
void
SyncFinder::search_refine (const Key& key, const WavData& wav_data, Mode mode, vector<Score>& sync_scores)
SyncFinder::search_refine (const WavData& wav_data, Mode mode, KeyResult& key_result)
{
vector<float> fft_db;
vector<char> have_frames;
vector<Score> result_scores;
BitPosGen bit_pos_gen (key);
BitPosGen bit_pos_gen (key_result.key);
int total_frame_count = mark_sync_frame_count() + mark_data_frame_count();
const int first_block_end = total_frame_count;
......@@ -275,7 +292,7 @@ SyncFinder::search_refine (const Key& key, const WavData& wav_data, Mode mode, v
want_frames[first_block_end + bit_pos_gen.sync_frame (f)] = 1;
}
for (const auto& score : sync_scores)
for (const auto& score : key_result.sync_scores)
{
//printf ("%zd %s %f", score.index, find_closest_sync (score.index).c_str(), score.quality);
......@@ -292,7 +309,7 @@ SyncFinder::search_refine (const Key& key, const WavData& wav_data, Mode mode, v
if (fft_db.size())
{
ConvBlockType block_type;
double q = sync_decode (wav_data, 0, fft_db, have_frames, &block_type);
double q = sync_decode (key_result.sync_bits, wav_data, 0, fft_db, have_frames, &block_type);
if (q > best_quality)
{
......@@ -305,11 +322,11 @@ SyncFinder::search_refine (const Key& key, const WavData& wav_data, Mode mode, v
if (best_quality > Params::sync_threshold2)
result_scores.push_back (Score { best_index, best_quality, best_block_type });
}
sync_scores = result_scores;
key_result.sync_scores = result_scores;
}
vector<SyncFinder::Score>
SyncFinder::fake_sync (const WavData& wav_data, Mode mode)
vector<SyncFinder::KeyResult>
SyncFinder::fake_sync (const vector<Key>& key_list, const WavData& wav_data, Mode mode)
{
vector<Score> result_scores;
......@@ -324,16 +341,22 @@ SyncFinder::fake_sync (const WavData& wav_data, Mode mode)
result_scores.push_back (Score { expect_index, 1.0, (ab++ & 1) ? ConvBlockType::b : ConvBlockType::a });
}
return result_scores;
vector<KeyResult> key_results;
for (auto key : key_list)
{
KeyResult key_result;
key_result.key = key;
key_result.sync_scores = result_scores;
key_results.push_back (key_result);
}
return key_results;
}
vector<SyncFinder::Score>
SyncFinder::search (const Key& key, const WavData& wav_data, Mode mode)
vector<SyncFinder::KeyResult>
SyncFinder::search (const vector<Key>& key_list, const WavData& wav_data, Mode mode)
{
if (Params::test_no_sync)
return fake_sync (wav_data, mode);
init_up_down (key, wav_data, mode);
return fake_sync (key_list, wav_data, mode);
if (mode == Mode::CLIP)
{
......@@ -346,22 +369,25 @@ SyncFinder::search (const Key& key, const WavData& wav_data, Mode mode)
wav_data_first = 0;
wav_data_last = wav_data.samples().size();
}
vector<Score> sync_scores = search_approx (wav_data, mode);
sync_select_by_threshold (sync_scores);
vector<KeyResult> key_results = search_approx (key_list, wav_data, mode);
for (auto& key_result : key_results)
{
/* find local maxima, select by threshold */
sync_select_by_threshold (key_result.sync_scores);
if (mode == Mode::CLIP)
sync_select_n_best (sync_scores, 5);
sync_select_n_best (key_result.sync_scores, 5);
search_refine (key, wav_data, mode, sync_scores);
search_refine (wav_data, mode, key_result);
}
return sync_scores;
return key_results;
}
vector<vector<SyncFinder::FrameBit>>
SyncFinder::get_sync_bits (const Key& key, const WavData& wav_data, Mode mode)
{
init_up_down (key, wav_data, mode);
return sync_bits;
return init_up_down (key, wav_data, mode);
}
void
......
......@@ -78,26 +78,33 @@ public:
std::vector<int> up;
std::vector<int> down;
};
private:
struct KeyResult
{
Key key;
std::vector<std::vector<FrameBit>> sync_bits;
std::vector<Score> sync_scores;
};
private:
std::vector<std::vector<FrameBit>> init_up_down (const Key& key, const WavData& wav_data, Mode mode);
void init_up_down (const Key& key, const WavData& wav_data, Mode mode);
double sync_decode (const WavData& wav_data, const size_t start_frame,
double sync_decode (const std::vector<std::vector<FrameBit>>& sync_bits,
const WavData& wav_data, const size_t start_frame,
const std::vector<float>& fft_out_db,
const std::vector<char>& have_frames,
ConvBlockType *block_type);
void scan_silence (const WavData& wav_data);
std::vector<Score> search_approx (const WavData& wav_data, Mode mode);
std::vector<KeyResult> search_approx (const std::vector<Key>& key_list, const WavData& wav_data, Mode mode);
void sync_select_by_threshold (std::vector<Score>& sync_scores);
void sync_select_n_best (std::vector<Score>& sync_scores, size_t n);
void search_refine (const Key& key, const WavData& wav_data, Mode mode, std::vector<Score>& sync_scores);
std::vector<Score> fake_sync (const WavData& wav_data, Mode mode);
void search_refine (const WavData& wav_data, Mode mode, KeyResult& key_result);
std::vector<KeyResult> fake_sync (const std::vector<Key>& key_list, const WavData& wav_data, Mode mode);
// non-zero sample range: [wav_data_first, wav_data_last)
size_t wav_data_first = 0;
size_t wav_data_last = 0;
public:
std::vector<Score> search (const Key& key, const WavData& wav_data, Mode mode);
std::vector<KeyResult> search (const std::vector<Key>& key_list, const WavData& wav_data, Mode mode);
std::vector<std::vector<FrameBit>> get_sync_bits (const Key& key, const WavData& wav_data, Mode mode);
static double bit_quality (float umag, float dmag, int bit);
......
......@@ -307,27 +307,30 @@ public:
class BlockDecoder
{
int debug_sync_frame_count = 0;
vector<SyncFinder::Score> sync_scores; // stored here for sync debugging
vector<SyncFinder::KeyResult> key_results; // stored here for sync debugging
public:
void
run (const Key& key, const WavData& wav_data, ResultSet& result_set)
run (const vector<Key>& key_list, const WavData& wav_data, ResultSet& result_set)
{
int total_count = 0;
SyncFinder sync_finder;
sync_scores = sync_finder.search (key, wav_data, SyncFinder::Mode::BLOCK);
FFTAnalyzer fft_analyzer (wav_data.n_channels());
key_results = sync_finder.search (key_list, wav_data, SyncFinder::Mode::BLOCK);
for (const auto& key_result : key_results)
{
int total_count = 0;
vector<float> raw_bit_vec_all (code_size (ConvBlockType::ab, Params::payload_size));
vector<int> raw_bit_vec_norm (2);
const Key& key = key_result.key;
SyncFinder::Score score_all { 0, 0 };
SyncFinder::Score score_ab { 0, 0, ConvBlockType::ab };
ConvBlockType last_block_type = ConvBlockType::b;
vector<vector<float>> ab_raw_bit_vec (2);
vector<float> ab_quality (2);
FFTAnalyzer fft_analyzer (wav_data.n_channels());
for (auto sync_score : sync_scores)
for (auto sync_score : key_result.sync_scores)
{
const size_t count = mark_sync_frame_count() + mark_data_frame_count();
const size_t index = sync_score.index;
......@@ -408,12 +411,19 @@ public:
if (!bit_vec.empty())
result_set.add_pattern (/* time */ 0.0, score_all, bit_vec, decode_error, ResultSet::Type::ALL);
}
}
debug_sync_frame_count = frame_count (wav_data);
}
void
print_debug_sync()
{
/* this is really only useful for debugging, and should be used with exactly one key */
if (key_results.size() != 1)
return;
const auto& sync_scores = key_results[0].sync_scores;
/* search sync markers at typical positions */
const int expect0 = Params::frames_pad_start * Params::frame_size;
const int expect_step = (mark_sync_frame_count() + mark_data_frame_count()) * Params::frame_size;
......@@ -475,13 +485,16 @@ class ClipDecoder
return linear_decode (key, fft_out, n_channels);
}
void
run_padded (const Key& key, const WavData& wav_data, ResultSet& result_set, double time_offset_sec)
run_padded (const vector<Key>& key_list, const WavData& wav_data, ResultSet& result_set, double time_offset_sec)
{
SyncFinder sync_finder;
vector<SyncFinder::Score> sync_scores = sync_finder.search (key, wav_data, SyncFinder::Mode::CLIP);
vector<SyncFinder::KeyResult> key_results = sync_finder.search (key_list, wav_data, SyncFinder::Mode::CLIP);
FFTAnalyzer fft_analyzer (wav_data.n_channels());
for (auto sync_score : sync_scores)
for (const auto& key_result : key_results)
{
const Key& key = key_result.key;
for (const auto& sync_score : key_result.sync_scores)
{
const size_t count = mark_sync_frame_count() + mark_data_frame_count();
const size_t index = sync_score.index;
......@@ -518,9 +531,10 @@ class ClipDecoder
}
}
}
}
enum class Pos { START, END };
void
run_block (const Key& key, const WavData& wav_data, ResultSet& result_set, Pos pos)
run_block (const vector<Key>& key_list, const WavData& wav_data, ResultSet& result_set, Pos pos)
{
const size_t n = (frames_per_block + 5) * Params::frame_size * wav_data.n_channels();
......@@ -562,7 +576,7 @@ class ClipDecoder
ext_samples.insert (ext_samples.end(), pad_samples_end, 0);
WavData l_wav_data (ext_samples, wav_data.n_channels(), wav_data.sample_rate(), wav_data.bit_depth());
run_padded (key, l_wav_data, result_set, time_offset);
run_padded (key_list, l_wav_data, result_set, time_offset);
}
public:
ClipDecoder() :
......@@ -570,13 +584,13 @@ public:
{
}
void
run (const Key& key, const WavData& wav_data, ResultSet& result_set)
run (const vector<Key>& key_list, const WavData& wav_data, ResultSet& result_set)
{
const int wav_frames = wav_data.n_values() / (Params::frame_size * wav_data.n_channels());
if (wav_frames < frames_per_block * 3.1) /* clip decoder is only used for small wavs */
{
run_block (key, wav_data, result_set, Pos::START);
run_block (key, wav_data, result_set, Pos::END);
run_block (key_list, wav_data, result_set, Pos::START);
run_block (key_list, wav_data, result_set, Pos::END);
}
}
};
......@@ -614,20 +628,20 @@ decode_and_report (const vector<Key>& key_list, const WavData& wav_data, const v
result_set.set_speed_pattern (true);
BlockDecoder block_decoder;
block_decoder.run (key, wav_data_speed, result_set);
block_decoder.run ({ key }, wav_data_speed, result_set);
ClipDecoder clip_decoder;
clip_decoder.run (key, wav_data_speed, result_set);
clip_decoder.run ({ key }, wav_data_speed, result_set);
result_set.set_speed_pattern (false);
}
}
}
BlockDecoder block_decoder;
block_decoder.run (key, wav_data, result_set);
block_decoder.run (key_list, wav_data, result_set);
ClipDecoder clip_decoder;
clip_decoder.run (key, wav_data, result_set);
}
clip_decoder.run (key_list, wav_data, result_set);
result_set.sort_by_time();
......@@ -641,7 +655,7 @@ decode_and_report (const vector<Key>& key_list, const WavData& wav_data, const v
{
int match_count = result_set.print_match_count (orig_bits);
// block_decoder.print_debug_sync(); FIXME
block_decoder.print_debug_sync();
if (Params::expect_matches >= 0)
{
......
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