298 lines
8.3 KiB
Text
298 lines
8.3 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import struct\n",
|
|
"import random\n",
|
|
"import itertools\n",
|
|
"import datetime\n",
|
|
"import multiprocessing\n",
|
|
"from collections import defaultdict\n",
|
|
"import json\n",
|
|
"\n",
|
|
"from matplotlib import pyplot as plt\n",
|
|
"import matplotlib\n",
|
|
"import numpy as np\n",
|
|
"from scipy import signal as sig\n",
|
|
"from scipy import fftpack as fftpack\n",
|
|
"import ipywidgets\n",
|
|
"\n",
|
|
"import pydub\n",
|
|
"\n",
|
|
"from tqdm.notebook import tqdm\n",
|
|
"import colorednoise\n",
|
|
"\n",
|
|
"np.set_printoptions(linewidth=240)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%matplotlib widget"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# From https://github.com/mubeta06/python/blob/master/signal_processing/sp/gold.py\n",
|
|
"preferred_pairs = {5:[[2],[1,2,3]], 6:[[5],[1,4,5]], 7:[[4],[4,5,6]],\n",
|
|
" 8:[[1,2,3,6,7],[1,2,7]], 9:[[5],[3,5,6]], \n",
|
|
" 10:[[2,5,9],[3,4,6,8,9]], 11:[[9],[3,6,9]]}\n",
|
|
"\n",
|
|
"def gen_gold(seq1, seq2):\n",
|
|
" gold = [seq1, seq2]\n",
|
|
" for shift in range(len(seq1)):\n",
|
|
" gold.append(seq1 ^ np.roll(seq2, -shift))\n",
|
|
" return gold\n",
|
|
"\n",
|
|
"def gold(n):\n",
|
|
" n = int(n)\n",
|
|
" if not n in preferred_pairs:\n",
|
|
" raise KeyError('preferred pairs for %s bits unknown' % str(n))\n",
|
|
" t0, t1 = preferred_pairs[n]\n",
|
|
" (seq0, _st0), (seq1, _st1) = sig.max_len_seq(n, taps=t0), sig.max_len_seq(n, taps=t1)\n",
|
|
" return gen_gold(seq0, seq1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 49,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def modulate(data, nbits=5, pad=True):\n",
|
|
" # 0, 1 -> -1, 1\n",
|
|
" mask = np.array(gold(nbits))*2 - 1\n",
|
|
" \n",
|
|
" sel = mask[data>>1]\n",
|
|
" data_lsb_centered = ((data&1)*2 - 1)\n",
|
|
"\n",
|
|
" signal = (np.multiply(sel, np.tile(data_lsb_centered, (2**nbits-1, 1)).T).flatten() + 1) // 2\n",
|
|
" if pad:\n",
|
|
" return np.hstack([ np.zeros(len(mask)), signal, np.zeros(len(mask)) ])\n",
|
|
" else:\n",
|
|
" return signal"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 53,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generate_noisy_signal(\n",
|
|
" test_duration=32,\n",
|
|
" test_nbits=5,\n",
|
|
" test_decimation=10,\n",
|
|
" test_signal_amplitude=200e-3,\n",
|
|
" noise_level=10e-3):\n",
|
|
"\n",
|
|
" #test_data = np.random.RandomState(seed=0).randint(0, 2 * (2**test_nbits), test_duration)\n",
|
|
" #test_data = np.array([0, 1, 2, 3] * 50)\n",
|
|
" test_data = np.array(range(test_duration))\n",
|
|
" signal = np.repeat(modulate(test_data, test_nbits, pad=False) * 2.0 - 1, test_decimation) * test_signal_amplitude\n",
|
|
" noise = colorednoise.powerlaw_psd_gaussian(1, len(signal)*2) * noise_level\n",
|
|
" noise[-int(1.5*len(signal)):][:len(signal)] += signal\n",
|
|
"\n",
|
|
" return noise+50\n",
|
|
" #with open(f'mains_sim_signals/dsss_test_noisy_padded.bin', 'wb') as f:\n",
|
|
" # for e in noise:\n",
|
|
" # f.write(struct.pack('<f', e))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 54,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "c778037402024206b195a27591dc0b40",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[<matplotlib.lines.Line2D at 0x7f2ab8cabca0>]"
|
|
]
|
|
},
|
|
"execution_count": 54,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"fig, ax = plt.subplots()\n",
|
|
"ax.plot(generate_noisy_signal())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 58,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"with open('data/ref_sig_audio_test3.bin', 'wb') as f:\n",
|
|
" for x in generate_noisy_signal():\n",
|
|
" f.write(struct.pack('f', x))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def synthesize_sine(freqs, freqs_sampling_rate=10.0, output_sampling_rate=44100):\n",
|
|
" duration = len(freqs) / freqs_sampling_rate # seconds\n",
|
|
" afreq_out = np.interp(np.linspace(0, duration, int(duration*output_sampling_rate)), np.linspace(0, duration, len(freqs)), freqs)\n",
|
|
" return np.sin(np.cumsum(2*np.pi * afreq_out / output_sampling_rate))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"test_sig = synthesize_sine(generate_noisy_signal())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "5171d9dbbe5048e2b32c3cf7f7d03744",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[<matplotlib.lines.Line2D at 0x7f2a90476bb0>]"
|
|
]
|
|
},
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"fig, ax = plt.subplots()\n",
|
|
"ax.plot(test_sig[:44100])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 56,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def save_signal_flac(filename, signal, sampling_rate=44100):\n",
|
|
" signal -= np.min(signal)\n",
|
|
" signal /= np.max(signal)\n",
|
|
" signal -= 0.5\n",
|
|
" signal *= 2**16 - 1\n",
|
|
" le_bytes = signal.astype(np.int16).tobytes()\n",
|
|
" seg = pydub.AudioSegment(data=le_bytes, sample_width=2, frame_rate=sampling_rate, channels=1)\n",
|
|
" seg.export(filename, format='flac')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 57,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"save_signal_flac('synth_sig_test_0123_02.flac', synthesize_sine(generate_noisy_signal(), freqs_sampling_rate=10.0 * 100/128, output_sampling_rate=44100))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def emulate_adc_signal(adc_bits=12, adc_offset=0.4, adc_amplitude=0.25, freq_sampling_rate=10.0, output_sampling_rate=1000, **kwargs):\n",
|
|
" signal = synthesize_sine(generate_noisy_signal(), freq_sampling_rate, output_sampling_rate)\n",
|
|
" signal = signal*adc_amplitude + adc_offset\n",
|
|
" smin, smax = np.min(signal), np.max(signal)\n",
|
|
" if smin < 0.0 or smax > 1.0:\n",
|
|
" raise UserWarning('Amplitude or offset too large: Signal out of bounds with min/max [{smin}, {smax}] of ADC range')\n",
|
|
" signal *= 2**adc_bits -1\n",
|
|
" return signal"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def save_adc_signal(fn, signal, dtype=np.uint16):\n",
|
|
" with open(fn, 'wb') as f:\n",
|
|
" f.write(signal.astype(dtype).tobytes())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"save_adc_signal('emulated_adc_readings_01.bin', emulate_adc_signal(freq_sampling_rate=10.0 * 100/128))"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "labenv",
|
|
"language": "python",
|
|
"name": "labenv"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.8.3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|