59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
import numpy as np
|
|
|
|
ALPHABET = (
|
|
list('abcdefghijklmnopqrstuvwxyz') +
|
|
list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') +
|
|
list('0123456789') +
|
|
[' ', '.']
|
|
)
|
|
|
|
def get_hadamard(n):
|
|
assert (n & (n - 1) == 0), "Hadamard order must be power of 2"
|
|
H = np.array([[1]])
|
|
while H.shape[0] < n:
|
|
H = np.block([
|
|
[ H, H],
|
|
[ H, -H]
|
|
])
|
|
return H
|
|
|
|
def decode_signal(signal, alphabet=ALPHABET):
|
|
code_length = 64
|
|
n_chars = len(signal) // code_length
|
|
H = get_hadamard(64)
|
|
scale = 1 / np.sqrt(code_length)
|
|
codebook = H * scale
|
|
|
|
decoded = []
|
|
for i in range(n_chars):
|
|
y = signal[i*code_length : (i+1)*code_length]
|
|
# The channel may have applied sqrt(10) gain to odds or evens
|
|
# We don't know which, so try both options and pick best
|
|
y_even = np.array(y)
|
|
y_even[::2] /= np.sqrt(10)
|
|
y_odd = np.array(y)
|
|
y_odd[1::2] /= np.sqrt(10)
|
|
# Try decoding both hypotheses
|
|
scores_even = codebook @ y_even
|
|
scores_odd = codebook @ y_odd
|
|
idx_even = np.argmax(scores_even)
|
|
idx_odd = np.argmax(scores_odd)
|
|
score_even = np.max(scores_even)
|
|
score_odd = np.max(scores_odd)
|
|
idx_best = idx_even if score_even > score_odd else idx_odd
|
|
decoded.append(alphabet[idx_best])
|
|
return ''.join(decoded)
|
|
|
|
def main():
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description="Receiver: decode y.txt to recovered message for PDC Project.")
|
|
parser.add_argument('--input_file', type=str, required=True, help="Received y.txt from channel/server")
|
|
parser.add_argument('--output_file', type=str, required=True, help="Text file for the decoded message")
|
|
args = parser.parse_args()
|
|
y = np.loadtxt(args.input_file)
|
|
decoded = decode_signal(y)
|
|
with open(args.output_file, 'w') as f:
|
|
f.write(decoded)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|