[d2t] Data to Tones

Onion Courier <[email protected]>
Newsgroups alt.cypherpunks
Organization dizum.com - The Internet Problem Provider
Message-ID <[email protected]>
https://jmp.sh/ELTus4hj
(download and decode with Python3 code below)

import argparse
import math
import numpy as np
import struct
import sys
from scipy.fftpack import fft

SAMPLE_RATE = 44100
DURATION = 0.2
FFT_SIZE = 8820
AMPLITUDE_8BIT = 127
AMPLITUDE_16BIT = 32760
BASE_FREQ = 440.0
FREQ_STEP = 25.0  # Larger step size since we only need 16 values

def generate_tone_buffer(freq, use_16bit):
    num_samples = int(SAMPLE_RATE * DURATION)
    amplitude = AMPLITUDE_16BIT if use_16bit else AMPLITUDE_8BIT
    bytes_per_sample = 2 if use_16bit else 1
    buf = bytearray(num_samples * bytes_per_sample)

    for i in range(num_samples):
        t = i / SAMPLE_RATE
        window = 0.5 * (1 - math.cos(2 * math.pi * i / (num_samples - 1)))
        sample = int(amplitude * math.sin(2 * math.pi * freq * t) * window)

        if use_16bit:
            struct.pack_into('>h', buf, i * 2, sample)
        else:
            buf[i] = sample + AMPLITUDE_8BIT

    return buf

def write_au_header(use_16bit):
    encoding = 0x03 if use_16bit else 0x02
    header = bytearray([
        0x2e, 0x73, 0x6e, 0x64,
        0x00, 0x00, 0x00, 0x20,
        0xff, 0xff, 0xff, 0xff,
        0x00, 0x00, 0x00, encoding,
        0x00, 0x00, 0xac, 0x44,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    ])
    sys.stdout.buffer.write(header)

def encode_tones(data, use_16bit, tone_buffers):
    write_au_header(use_16bit)
    hex_str = data.hex()

    for c in hex_str:
        index = int(c, 16)
        sys.stdout.buffer.write(tone_buffers[index])

def detect_frequency(samples):
    windowed_samples = samples * np.hanning(len(samples))
    spectrum = fft(windowed_samples)
    magnitude = np.abs(spectrum[:len(spectrum) // 2])
    peak_index = np.argmax(magnitude)
    freq = peak_index * SAMPLE_RATE / FFT_SIZE

    if peak_index > 0 and peak_index < FFT_SIZE // 2 - 1:
        alpha = magnitude[peak_index - 1]
        beta = magnitude[peak_index]
        gamma = magnitude[peak_index + 1]
        correction = 0.5 * (alpha - gamma) / (alpha - 2 * beta + gamma)
        freq += correction * SAMPLE_RATE / FFT_SIZE

    return freq

def freq_to_hex(freq):
    index = round((freq - BASE_FREQ) / FREQ_STEP)
    if 0 <= index < 16:
        return format(index, 'x')
    return None

def decode_tones(input_data, use_16bit):
    bytes_per_sample = 2 if use_16bit else 1
    input_data = input_data[24:]
    num_samples = len(input_data) // bytes_per_sample

    if use_16bit:
        samples = np.frombuffer(input_data, dtype='>i2').astype(np.float64) / AMPLITUDE_16BIT
    else:
        samples = (np.frombuffer(input_data, dtype=np.uint8).astype(np.float64) - AMPLITUDE_8BIT) / AMPLITUDE_8BIT

    hex_output = []
    for i in range(0, num_samples, FFT_SIZE):
        if i + FFT_SIZE > num_samples:
            break
        window = samples[i:i + FFT_SIZE]
        freq = detect_frequency(window)
        digit = freq_to_hex(freq)
        if digit is not None:
            hex_output.append(digit)

    decoded_data = bytes.fromhex(''.join(hex_output))
    sys.stdout.buffer.write(decoded_data)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--decode', action='store_true', help='Decode mode')
    parser.add_argument('-16', '--use16bit', action='store_true', help='Use 16-bit audio (default: 8-bit)')
    args = parser.parse_args()

    tone_buffers = [
        generate_tone_buffer(BASE_FREQ + i * FREQ_STEP, args.use16bit)
        for i in range(16)
    ]

    input_data = sys.stdin.buffer.read()

    if args.decode:
        decode_tones(input_data, args.use16bit)
    else:
        encode_tones(input_data, args.use16bit, tone_buffers)

if __name__ == '__main__':
    main()
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.