-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsinyal.py
198 lines (151 loc) · 6.24 KB
/
sinyal.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import numpy as np
import wave
import matplotlib.pyplot as plt
DTMF_FREQS = {
'1': (1209, 697),
'2': (1336, 697),
'3': (1477, 697),
'4': (1209, 770),
'5': (1336, 770),
'6': (1477, 770),
'7': (1209, 852),
'8': (1336, 852),
'9': (1477, 852),
'0': (1336, 941),
'*': (1209, 941),
'#': (1477, 941),
}
# --------------------------------------------------------------------------------
def decode_dtmf(sig, Fs, window=0.05, ofset=10):
# Initialize empty list to store the decoded keys and frequencies found
keys = []
found_freqs = []
# Iterate through the signal in window-sized chunks
for i in range(0, len(sig), int(Fs*window)):
# Get the current chunk of the signal
cut_sig = sig[i:i+int(Fs*window)]
# Take the Fast Fourier Transform (FFT) of the current chunk
fft_sig = np.fft.fft(cut_sig, Fs)
# Take the absolute value of the FFT
fft_sig = np.abs(fft_sig)
# Set the first 500 elements of the FFT to 0 (removes DC component)
fft_sig[:500] = 0
# Only keep the first half of the FFT (removes negative frequencies)
fft_sig = fft_sig[:int(len(fft_sig)/2)]
# Set the lower bound to be 75% of the maximum value in the FFT
lower_bound = 0.75 * np.max(fft_sig)
# Initialize empty list to store the frequencies that pass the lower bound threshold
filtered_freqs = []
# Iterate through the FFT and store the indices of the frequencies that pass the lower bound threshold
for i, mag in enumerate(fft_sig):
if mag > lower_bound:
filtered_freqs.append(i)
# Iterate through the DTMF frequencies and check if any of the filtered frequencies fall within the expected range
for char, frequency_pair in DTMF_FREQS.items():
high_freq_range = range(
frequency_pair[0] - ofset, frequency_pair[0] + ofset + 1)
low_freq_range = range(
frequency_pair[1] - ofset, frequency_pair[1] + ofset + 1)
if any(freq in high_freq_range for freq in filtered_freqs) and any(freq in low_freq_range for freq in filtered_freqs):
# If a match is found, append the key and frequency pair to the lists
keys.append(char)
found_freqs.append(frequency_pair)
# Return the decoded keys and found frequencies
return keys, found_freqs
# --------------------------------------------------------------------------------
def synthesize_DTMF(phone_number, duration, silence_duration, Fs):
# Set the amplitude (A) of the sine waves
A = 0.5
# Create an empty list to store the DTMF tones
DTMF = []
# Iterate over the list of digits
for digit in phone_number:
# Get the frequencies for the digit
f1, f2 = DTMF_FREQS[digit]
# Generate the sine waves for the frequencies
sine1 = A * np.sin(2 * np.pi * f1 * np.linspace(0,
duration, int(duration * Fs), False))
sine2 = A * np.sin(2 * np.pi * f2 * np.linspace(0,
duration, int(duration * Fs), False))
# Add the sine waves together to create the DTMF tone
DTMF_tone = sine1 + sine2
# Add the DTMF tone to the list
DTMF.extend(DTMF_tone)
# Add a period of silence to the list
silence = np.zeros(int(silence_duration * Fs))
DTMF.extend(silence)
# Convert the DTMF signal to a 16-bit integer representation
DTMF = np.int16(DTMF / np.max(np.abs(DTMF)) * 32767)
# Open a wave file for writing
with wave.open("phone_number.wav", "w") as file:
# Set the parameters of the wave file
file.setparams((1, 2, Fs, 0, "NONE", "not compressed"))
# Write the DTMF signal to the wave file
file.writeframes(DTMF)
# --------------------------------------------------------------------------------
def analyze_audio(filename):
# Open the audio file
wave_file = wave.open(filename, 'r')
num_samples = wave_file.getnframes()
Fs = wave_file.getframerate()
data = wave_file.readframes(num_samples)
sample_width = wave_file.getsampwidth()
if sample_width == 1:
data = data = np.frombuffer(data, dtype=np.uint8)
elif sample_width == 2:
data = data = np.frombuffer(data, dtype=np.int16)
wave_file.close()
# Decode the DTMF tones
keys, found_freqs = decode_dtmf(data, Fs, duration + silence_duration)
# Print the detected digits
print(keys)
# Plot the waveform in the time domain
plt.figure()
plt.plot(data)
plt.xlabel('Sample index')
plt.ylabel('Amplitude')
plt.title('Waveform in the time domain')
# Plot the detected DTMF frequencies in the time domain
plt.figure()
for f1, f2 in found_freqs:
plt.stem([f1, f2], [1, 1], 'k')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('Detected DTMF frequencies in the time domain')
# Calculate the frequency spectrum
spectrum = np.abs(np.fft.fft(data))
freqs = np.fft.fftfreq(len(data), 1/Fs)
# Plot the frequency spectrum
plt.figure()
plt.plot(freqs, spectrum)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude')
plt.title('Frequency spectrum')
# Plot the detected DTMF frequencies in the frequency domain
plt.figure()
for f1, f2 in found_freqs:
idx1 = np.argmin(np.abs(freqs - f1))
idx2 = np.argmin(np.abs(freqs - f2))
plt.stem([freqs[idx1], freqs[idx2]], [
spectrum[idx1], spectrum[idx2]], 'k')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude')
plt.title('Detected DTMF frequencies in the frequency domain')
# Show the plots
plt.show()
# --------------------------------------------------------------------------------
# region main
# Define your phone number as a string of digits
phone_number = "05313133131"
# Set the sampling frequency (Fs) in Hz
Fs = 8000
# Set the duration of each DTMF tone in seconds
duration = 0.1
# Set the duration of silence between tones in seconds
silence_duration = 0.1
# Synthesize the DTMF signal
synthesize_DTMF(phone_number, duration, silence_duration, Fs)
# Analyze the synthesized audio file
analyze_audio("phone_number.wav")
analyze_audio("Ornek.wav")
# endregion