AlignMark / util.py
2026anonymous
Initial commit
b9deace
Raw
History Blame Contribute Delete
2.23 kB
import base64
import struct
from typing import List
import numpy as np
import torch
def hamming_distance(preds, message):
return (preds != message).sum().item()
def random_message(nbits: int, batch_size: int) -> torch.Tensor:
if nbits == 0:
return torch.tensor([])
return torch.randint(0, 2, (batch_size, nbits))
def bits_to_chunks(bits: torch.Tensor, nchunk_size: int) -> List[torch.Tensor]:
batch_size, nbits = bits.shape
nchunks = nbits // nchunk_size
chunk_values = []
for i in range(nchunks):
chunk_bits = bits[:, i * nchunk_size : (i + 1) * nchunk_size]
chunk_val = torch.zeros(batch_size, dtype=torch.long, device=bits.device)
for bit_idx in range(nchunk_size):
chunk_val += (chunk_bits[:, bit_idx].long() << bit_idx)
chunk_values.append(chunk_val)
return chunk_values
def chunks_to_bits(chunk_values: List[torch.Tensor], nchunk_size: int) -> torch.Tensor:
bit_chunks = []
for chunk_val in chunk_values:
chunk_bits = []
for bit_idx in range(nchunk_size):
bit = (chunk_val >> bit_idx) & 1
chunk_bits.append(bit.unsqueeze(-1))
bit_chunks.append(torch.cat(chunk_bits, dim=-1))
bits = torch.cat(bit_chunks, dim=-1)
return bits
def tensor_to_base64(audio_tensor, sample_rate=16000):
audio_tensor = audio_tensor.cpu()
if audio_tensor.dim() == 2:
audio_tensor = audio_tensor.squeeze(0)
audio_numpy = audio_tensor.numpy()
audio_numpy = np.clip(audio_numpy, -1.0, 1.0)
audio_int16 = (audio_numpy * 32767).astype(np.int16)
channels = 1
bits_per_sample = 16
byte_rate = sample_rate * channels * bits_per_sample // 8
block_align = channels * bits_per_sample // 8
header = struct.pack(
"<4sI4s4sIHHIIHH4sI",
b"RIFF",
36 + len(audio_int16.tobytes()),
b"WAVE",
b"fmt ",
16,
1,
channels,
sample_rate,
byte_rate,
block_align,
bits_per_sample,
b"data",
len(audio_int16.tobytes()),
)
wav_data = header + audio_int16.tobytes()
base64_str = base64.b64encode(wav_data).decode("utf-8")
return base64_str