text
[RRG-proxmark3.git] / client / pyscripts / theremin.py
blob790fc6bf850d3eaa2bbb92c5fafd4e6006cb83da
1 #!/usr/bin/python3
3 ### Parameters
4 # Sound output parameters
5 volume = 1.0
6 sample_buf_size = 44
7 sampling_freq = 44100 #Hz
9 # Frequency generator parameters
10 min_freq = 200 #Hz
11 max_freq = 2000 #Hz
13 # Proxmark3 parameters
14 pm3_client="/usr/local/bin/proxmark3"
15 pm3_reader_dev_file="/dev/ttyACM0"
16 pm3_tune_cmd="hf tune"
19 ### Modules
20 import numpy
21 import pyaudio
22 from select import select
23 from subprocess import Popen, DEVNULL, PIPE
26 ### Main program
27 p = pyaudio.PyAudio()
29 # For paFloat32 sample values must be in range [-1.0, 1.0]
30 stream = p.open(format=pyaudio.paFloat32,
31 channels=1,
32 rate=sampling_freq,
33 output=True)
35 # Initial voltage to frequency values
36 min_v = 100.0
37 max_v = 0.0
38 v = 0
39 out_freq = min_freq
41 # Spawn the Proxmark3 client
42 pm3_proc = Popen([pm3_client, pm3_reader_dev_file, "-c", pm3_tune_cmd], bufsize=0, env={}, stdin=DEVNULL, stdout=PIPE, stderr=DEVNULL)
43 mv_recbuf = ""
45 # Read voltages from the Proxmark3, generate the sine wave, output to soundcard
46 sample_buf = [0.0 for x in range(0, sample_buf_size)]
47 i = 0
48 sinev = 0
49 while True:
51 # Read Proxmark3 client's stdout and extract voltage values
52 if(select([pm3_proc.stdout], [], [], 0)[0]):
54 b = pm3_proc.stdout.read(256).decode("ascii")
55 if "Done" in b:
56 break;
57 for c in b:
58 if c in "0123456789 mV":
59 mv_recbuf += c
60 else:
61 mv_recbuf = ""
62 if mv_recbuf[-3:] == " mV":
63 v = int(mv_recbuf[:-3]) / 1000
64 if v < min_v:
65 min_v = v - 0.001
66 if v > max_v:
67 max_v = v
69 # Recalculate the audio frequency to generate
70 out_freq = (max_freq - min_freq) * (max_v - v) / (max_v - min_v) \
71 + min_freq
73 # Generate the samples and write them to the soundcard
74 sinevs = out_freq / sampling_freq * numpy.pi * 2
75 sample_buf[i] = sinev
76 sinev += sinevs
77 sinev = sinev if sinev < numpy.pi * 2 else sinev - numpy.pi * 2
78 i = (i + 1) % sample_buf_size
79 if not i:
80 stream.write((numpy.sin(sample_buf) * volume).
81 astype(numpy.float32).tobytes())