67 lines
2.2 KiB
Markdown
67 lines
2.2 KiB
Markdown
# Short Term Fuel Trim - misc
|
|
|
|
The data is a list of _129*1380_ complex numbers
|
|
```
|
|
# STFT shape: complex64 (129, 1380)
|
|
(0.000000000000000000e+00+0.000000000000000000e+00j)
|
|
(0.000000000000000000e+00+0.000000000000000000e+00j)
|
|
(-1.484999775886535645e+00+0.000000000000000000e+00j)
|
|
(2.873720169067382812e+00+0.000000000000000000e+00j)
|
|
(9.447572708129882812e+00+0.000000000000000000e+00j)
|
|
(8.104647827148437500e+01+0.000000000000000000e+00j)
|
|
(1.316259765625000000e+01+0.000000000000000000e+00j)
|
|
(-3.101673889160156250e+02+0.000000000000000000e+00j)
|
|
(-4.186026916503906250e+02+0.000000000000000000e+00j)
|
|
(-5.818300781250000000e+02+0.000000000000000000e+00j)
|
|
(2.119775390625000000e+02+0.000000000000000000e+00j)
|
|
(-1.738154602050781250e+02+0.000000000000000000e+00j)
|
|
(-2.650747985839843750e+02+0.000000000000000000e+00j)
|
|
(-3.873171691894531250e+02+0.000000000000000000e+00j)
|
|
(-4.193124389648437500e+02+0.000000000000000000e+00j)
|
|
(-1.984837646484375000e+02+0.000000000000000000e+00j)
|
|
(-1.092494659423828125e+02+0.000000000000000000e+00j)
|
|
|
|
```
|
|
STFT stands for [short time Fourier transform](https://en.wikipedia.org/wiki/Short-time_Fourier_transform).
|
|
The data is actually the STFT of an audio signal.
|
|
|
|
Using [scipy.signal.istft](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.istft.html),
|
|
we performed the inverse transform and reconstructed the audio signal
|
|
```python
|
|
|
|
with open("numbers.txt", "r") as f:
|
|
lines = f.readlines()
|
|
|
|
shape = (129, 1380)
|
|
|
|
nums = np.array([complex(l.strip()) for l in lines[1:]])
|
|
arr = nums.reshape(*shape)
|
|
|
|
|
|
sampling_rate_hz = 44100
|
|
|
|
t, z = istft(arr, fs=sampling_rate_hz)
|
|
|
|
from scipy.io import wavfile
|
|
|
|
def time_series_to_wav(arr, sample_rate=44100):
|
|
#sample_rate = 44100 # Hz — set correctly
|
|
#samples = samples.astype(np.float32)
|
|
|
|
arr_mean = arr.mean()
|
|
arr_ptp = arr.max() - arr.min()
|
|
|
|
samples = (arr - arr_mean)*2/arr_ptp
|
|
|
|
# Normalize if float in [-1,1], convert to 16-bit:
|
|
scaled = (samples * 32767).astype(np.int16)
|
|
|
|
wavfile.write("out.wav", sample_rate, scaled)
|
|
|
|
time_series_to_wav(z, sample_rate=44100)
|
|
```
|
|
|
|
The flag is spoken text, and can be transcribed from the wav file.
|
|
|
|
|
|
The flag is `gigem{fft_is_50_0p}`
|