Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
audiowmark
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Stefan Westerfeld
audiowmark
Commits
eee2cc79
Commit
eee2cc79
authored
Feb 10, 2019
by
Stefan Westerfeld
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Suppoort different block types: a, b, and ab for convolution codes.
Signed-off-by:
Stefan Westerfeld
<
stefan@space.twc.de
>
parent
1e1a673c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
64 additions
and
29 deletions
+64
-29
audiowmark.cc
src/audiowmark.cc
+5
-5
convcode.cc
src/convcode.cc
+43
-10
convcode.hh
src/convcode.hh
+6
-4
testconvcode.cc
src/testconvcode.cc
+10
-10
No files found.
src/audiowmark.cc
View file @
eee2cc79
...
...
@@ -382,7 +382,7 @@ mark_bit_linear (int f, const vector<complex<float>>& fft_out, vector<complex<fl
size_t
mark_data_frame_count
()
{
return
conv_code_size
(
Params
::
payload_size
)
*
Params
::
frames_per_bit
;
return
conv_code_size
(
ConvBlockType
::
a
,
Params
::
payload_size
)
*
Params
::
frames_per_bit
;
}
struct
MixEntry
...
...
@@ -608,7 +608,7 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
printf
(
"Strength: %.6g
\n\n
"
,
Params
::
water_delta
*
1000
);
/* add forward error correction, bitvec will now be a lot larger */
bitvec
=
randomize_bit_order
(
conv_encode
(
bitvec
),
/* encode */
true
);
bitvec
=
randomize_bit_order
(
conv_encode
(
ConvBlockType
::
a
,
bitvec
),
/* encode */
true
);
/* pad with zeros to match block_size */
bitvec
.
resize
(
mark_data_frame_count
()
/
Params
::
frames_per_bit
);
...
...
@@ -1116,12 +1116,12 @@ decode_and_report (const WavData& wav_data, const string& orig_pattern)
auto
decode_single
=
[
&
]
(
const
vector
<
float
>&
raw_bit_vec
,
SyncFinder
::
Score
sync_score
)
{
assert
(
raw_bit_vec
.
size
()
==
conv_code_size
(
Params
::
payload_size
));
assert
(
raw_bit_vec
.
size
()
==
conv_code_size
(
ConvBlockType
::
a
,
Params
::
payload_size
));
vector
<
float
>
soft_bit_vec
=
normalize_soft_bits
(
raw_bit_vec
);
float
decode_error
=
0
;
vector
<
int
>
bit_vec
=
conv_decode_soft
(
randomize_bit_order
(
soft_bit_vec
,
/* encode */
false
),
&
decode_error
);
vector
<
int
>
bit_vec
=
conv_decode_soft
(
ConvBlockType
::
a
,
randomize_bit_order
(
soft_bit_vec
,
/* encode */
false
),
&
decode_error
);
if
(
sync_score
.
index
)
{
...
...
@@ -1148,7 +1148,7 @@ decode_and_report (const WavData& wav_data, const string& orig_pattern)
total_count
++
;
};
vector
<
float
>
raw_bit_vec_all
(
conv_code_size
(
Params
::
payload_size
));
vector
<
float
>
raw_bit_vec_all
(
conv_code_size
(
ConvBlockType
::
a
,
Params
::
payload_size
));
SyncFinder
::
Score
score_all
{
0
,
0
};
for
(
auto
sync_score
:
sync_scores
)
...
...
src/convcode.cc
View file @
eee2cc79
...
...
@@ -24,9 +24,9 @@ parity (unsigned int v)
// rate 1/6 code generator poynomial from "In search of a 2dB Coding Gain", Yuen and Vo
// minimum free distance 56
constexpr
unsigned
int
rate
=
6
;
constexpr
unsigned
int
order
=
15
;
constexpr
auto
generators
=
std
::
array
<
unsigned
,
6
>
{
046321
,
051271
,
070535
,
063667
,
073277
,
076531
}
;
constexpr
auto
ab_generators
=
std
::
array
<
unsigned
,
6
>
{
046321
,
051271
,
070535
,
063667
,
073277
,
076531
}
;
constexpr
unsigned
int
ab_rate
=
ab_generators
.
size
()
;
constexpr
unsigned
int
order
=
15
;
/*
constexpr unsigned int order = 9;
...
...
@@ -43,14 +43,45 @@ constexpr unsigned int state_count = (1 << order);
constexpr
unsigned
int
state_mask
=
(
1
<<
order
)
-
1
;
size_t
conv_code_size
(
size_t
msg_size
)
conv_code_size
(
ConvBlockType
block_type
,
size_t
msg_size
)
{
return
(
msg_size
+
order
)
*
rate
;
switch
(
block_type
)
{
case
ConvBlockType
:
:
a
:
case
ConvBlockType
:
:
b
:
return
(
msg_size
+
order
)
*
ab_rate
/
2
;
case
ConvBlockType
:
:
ab
:
return
(
msg_size
+
order
)
*
ab_rate
;
default:
assert
(
false
);
}
}
vector
<
unsigned
>
get_block_type_generators
(
ConvBlockType
block_type
)
{
vector
<
unsigned
>
generators
;
if
(
block_type
==
ConvBlockType
::
a
)
{
for
(
unsigned
int
i
=
0
;
i
<
ab_rate
/
2
;
i
++
)
generators
.
push_back
(
ab_generators
[
i
*
2
]);
}
else
if
(
block_type
==
ConvBlockType
::
b
)
{
for
(
unsigned
int
i
=
0
;
i
<
ab_rate
/
2
;
i
++
)
generators
.
push_back
(
ab_generators
[
i
*
2
+
1
]);
}
else
{
assert
(
block_type
==
ConvBlockType
::
ab
);
generators
.
assign
(
ab_generators
.
begin
(),
ab_generators
.
end
());
}
return
generators
;
}
vector
<
int
>
conv_encode
(
const
vector
<
int
>&
in_bits
)
conv_encode
(
ConvBlockType
block_type
,
const
vector
<
int
>&
in_bits
)
{
auto
generators
=
get_block_type_generators
(
block_type
);
vector
<
int
>
out_vec
;
vector
<
int
>
vec
=
in_bits
;
...
...
@@ -75,8 +106,10 @@ conv_encode (const vector<int>& in_bits)
/* decode using viterbi algorithm */
vector
<
int
>
conv_decode_soft
(
const
vector
<
float
>&
coded_bits
,
float
*
error_out
)
conv_decode_soft
(
ConvBlockType
block_type
,
const
vector
<
float
>&
coded_bits
,
float
*
error_out
)
{
auto
generators
=
get_block_type_generators
(
block_type
);
unsigned
int
rate
=
generators
.
size
();
vector
<
int
>
decoded_bits
;
assert
(
coded_bits
.
size
()
%
rate
==
0
);
...
...
@@ -121,7 +154,7 @@ conv_decode_soft (const vector<float>& coded_bits, float *error_out)
float
delta
=
old_table
[
state
].
delta
;
int
sbit_pos
=
new_state
*
rate
;
for
(
size_t
p
=
0
;
p
<
generators
.
size
()
;
p
++
)
for
(
size_t
p
=
0
;
p
<
rate
;
p
++
)
{
const
float
cbit
=
coded_bits
[
i
+
p
];
const
float
sbit
=
state2bits
[
sbit_pos
+
p
];
...
...
@@ -160,7 +193,7 @@ conv_decode_soft (const vector<float>& coded_bits, float *error_out)
}
vector
<
int
>
conv_decode_hard
(
const
vector
<
int
>&
coded_bits
)
conv_decode_hard
(
ConvBlockType
block_type
,
const
vector
<
int
>&
coded_bits
)
{
/* for the final application, we always want soft decoding, so we don't
* special case hard decoding here, so this will be a little slower than
...
...
@@ -170,5 +203,5 @@ conv_decode_hard (const vector<int>& coded_bits)
for
(
auto
b
:
coded_bits
)
soft_bits
.
push_back
(
b
?
1.0
f
:
0.0
f
);
return
conv_decode_soft
(
soft_bits
);
return
conv_decode_soft
(
block_type
,
soft_bits
);
}
src/convcode.hh
View file @
eee2cc79
...
...
@@ -4,9 +4,11 @@
#include <vector>
#include <string>
size_t
conv_code_size
(
size_t
msg_size
);
std
::
vector
<
int
>
conv_encode
(
const
std
::
vector
<
int
>&
in_bits
);
std
::
vector
<
int
>
conv_decode_hard
(
const
std
::
vector
<
int
>&
coded_bits
);
std
::
vector
<
int
>
conv_decode_soft
(
const
std
::
vector
<
float
>&
coded_bits
,
float
*
error_out
=
nullptr
);
enum
class
ConvBlockType
{
a
,
b
,
ab
};
size_t
conv_code_size
(
ConvBlockType
block_type
,
size_t
msg_size
);
std
::
vector
<
int
>
conv_encode
(
ConvBlockType
block_type
,
const
std
::
vector
<
int
>&
in_bits
);
std
::
vector
<
int
>
conv_decode_hard
(
ConvBlockType
block_type
,
const
std
::
vector
<
int
>&
coded_bits
);
std
::
vector
<
int
>
conv_decode_soft
(
ConvBlockType
block_type
,
const
std
::
vector
<
float
>&
coded_bits
,
float
*
error_out
=
nullptr
);
#endif
/* AUDIOWMARK_CONV_CODE_HH */
src/testconvcode.cc
View file @
eee2cc79
...
...
@@ -46,16 +46,16 @@ main (int argc, char **argv)
printf
(
"%d"
,
b
);
printf
(
"
\n
"
);
vector
<
int
>
coded_bits
=
conv_encode
(
in_bits
);
vector
<
int
>
coded_bits
=
conv_encode
(
ConvBlockType
::
a
,
in_bits
);
printf
(
"coded vector (n=%zd): "
,
coded_bits
.
size
());
for
(
auto
b
:
coded_bits
)
printf
(
"%d"
,
b
);
printf
(
"
\n
"
);
printf
(
"coded hex: %s
\n
"
,
bit_vec_to_str
(
coded_bits
).
c_str
());
assert
(
coded_bits
.
size
()
==
conv_code_size
(
in_bits
.
size
()));
assert
(
coded_bits
.
size
()
==
conv_code_size
(
ConvBlockType
::
a
,
in_bits
.
size
()));
vector
<
int
>
decoded_bits
=
conv_decode_hard
(
coded_bits
);
vector
<
int
>
decoded_bits
=
conv_decode_hard
(
ConvBlockType
::
a
,
coded_bits
);
printf
(
"output vector (k=%zd): "
,
decoded_bits
.
size
());
for
(
auto
b
:
decoded_bits
)
printf
(
"%d"
,
b
);
...
...
@@ -70,7 +70,7 @@ main (int argc, char **argv)
}
if
(
argc
==
2
&&
string
(
argv
[
1
])
==
"error"
)
{
size_t
max_bit_errors
=
conv_code_size
(
128
)
*
0.5
;
size_t
max_bit_errors
=
conv_code_size
(
ConvBlockType
::
a
,
128
)
*
0.5
;
for
(
size_t
bit_errors
=
0
;
bit_errors
<
max_bit_errors
;
bit_errors
++
)
{
...
...
@@ -84,14 +84,14 @@ main (int argc, char **argv)
while
(
in_bits
.
size
()
!=
128
)
in_bits
.
push_back
(
rand
()
&
1
);
vector
<
int
>
coded_bits
=
conv_encode
(
in_bits
);
vector
<
int
>
coded_bits
=
conv_encode
(
ConvBlockType
::
a
,
in_bits
);
coded_bit_count
=
coded_bits
.
size
();
vector
<
int
>
error_bits
=
generate_error_vector
(
coded_bits
.
size
(),
bit_errors
);
for
(
size_t
pos
=
0
;
pos
<
coded_bits
.
size
();
pos
++
)
coded_bits
[
pos
]
^=
error_bits
[
pos
];
vector
<
int
>
decoded_bits
=
conv_decode_hard
(
coded_bits
);
vector
<
int
>
decoded_bits
=
conv_decode_hard
(
ConvBlockType
::
a
,
coded_bits
);
assert
(
decoded_bits
.
size
()
==
128
);
...
...
@@ -120,7 +120,7 @@ main (int argc, char **argv)
while
(
in_bits
.
size
()
!=
128
)
in_bits
.
push_back
(
rand
()
&
1
);
vector
<
int
>
coded_bits
=
conv_encode
(
in_bits
);
vector
<
int
>
coded_bits
=
conv_encode
(
ConvBlockType
::
a
,
in_bits
);
coded_bit_count
=
coded_bits
.
size
();
std
::
default_random_engine
generator
;
...
...
@@ -130,7 +130,7 @@ main (int argc, char **argv)
for
(
auto
b
:
coded_bits
)
recv_bits
.
push_back
(
b
+
dist
(
generator
));
vector
<
int
>
decoded_bits1
=
conv_decode_soft
(
recv_bits
);
vector
<
int
>
decoded_bits1
=
conv_decode_soft
(
ConvBlockType
::
a
,
recv_bits
);
vector
<
int
>
recv_hard_bits
;
for
(
auto
b
:
recv_bits
)
...
...
@@ -139,7 +139,7 @@ main (int argc, char **argv)
for
(
size_t
x
=
0
;
x
<
recv_hard_bits
.
size
();
x
++
)
local_be
+=
coded_bits
[
x
]
^
recv_hard_bits
[
x
];
vector
<
int
>
decoded_bits2
=
conv_decode_hard
(
recv_hard_bits
);
vector
<
int
>
decoded_bits2
=
conv_decode_hard
(
ConvBlockType
::
a
,
recv_hard_bits
);
assert
(
decoded_bits1
.
size
()
==
128
);
assert
(
decoded_bits2
.
size
()
==
128
);
...
...
@@ -171,7 +171,7 @@ main (int argc, char **argv)
const
size_t
runs
=
20
;
for
(
size_t
i
=
0
;
i
<
runs
;
i
++
)
{
vector
<
int
>
out_bits
=
conv_decode_hard
(
conv_encode
(
in_bits
));
vector
<
int
>
out_bits
=
conv_decode_hard
(
ConvBlockType
::
a
,
conv_encode
(
ConvBlockType
::
a
,
in_bits
));
assert
(
out_bits
==
in_bits
);
}
printf
(
"%.1f ms/block
\n
"
,
(
gettime
()
-
start_t
)
/
runs
*
1000.0
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment