Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ $ sudo cp dtmf.py /usr/local/bin/dtmf
You have to give a wav file (you can try to convert it with `ffmpeg -i audio.mp3 audio.wav` for example).

```
Usage: dtmf [-h] [-v] [-l] [-r] [-d] [-t F] [-i T] file.wav
Usage: dtmf [-h] [-v] [-l] [-r] [-d] [-t F] [-i T] [-p] file.wav

optional arguments:
-h, --help show this help message and exit
Expand All @@ -29,6 +29,7 @@ optional arguments:
-d, --debug show graphs to debug
-t F acceptable frequency error (in hertz, 20 by default)
-i T process by T seconds intervals (0.05 by default)
-p, --processletters process keypad mapping (contigent on having a proper decode using the basic feature without --verbose mode)
```

## Examples
Expand All @@ -45,6 +46,13 @@ $ dtmf perfect-example.wav
```
As you can see it works perfectly, we have a classical French phone number.

```
$ dtmf -p perfect-example2.wav
62#74#23#43#81#93
Result: 62#74#23#43#81#93
Decoded result based on Keypad: NSCITY
```

#### The non-perfect case
```
$ dtmf not-perfect-example.wav
Expand Down
34 changes: 34 additions & 0 deletions dtmf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@
from scipy.io import wavfile
import argparse

keypad = {
"2": "ABC",
"3": "DEF",
"4": "GHI",
"5": "JKL",
"6": "MNO",
"7": "PQRS",
"8": "TUV",
"9": "WXYZ"
}

def decode_sequence(sequence: str) -> str:
parts = sequence.split("#")
decoded = []

for part in parts:
if len(part) != 2: # must be 2 digits
continue
digit, index = part[0], int(part[1])

if digit in keypad and 1 <= index <= len(keypad[digit]):
decoded.append(keypad[digit][index - 1])
else:
decoded.append("?")
return "".join(decoded)

dtmf = {(697, 1209): "1", (697, 1336): "2", (697, 1477): "3", (770, 1209): "4", (770, 1336): "5", (770, 1477): "6", (852, 1209): "7", (852, 1336): "8", (852, 1477): "9", (941, 1209): "*", (941, 1336): "0", (941, 1477): "#", (697, 1633): "A", (770, 1633): "B", (852, 1633): "C", (941, 1633): "D"}


Expand All @@ -15,6 +41,7 @@
parser.add_argument("-d", "--debug", help="show graphs to debug", action="store_true")
parser.add_argument("-t", type=int, metavar="F", help="acceptable frequency error (in hertz, 20 by default)", default=20)
parser.add_argument("-i", type=float, metavar='T', help="process by T seconds intervals (0.04 by default)", default=0.04)
parser.add_argument("-p", "--processletters", help="process keypad mapping", action="store_true")

parser.add_argument('file', type=argparse.FileType('r'))

Expand Down Expand Up @@ -63,6 +90,7 @@
debug = args.debug
verbose = args.verbose
c = ""
final_result = ""

if debug:
print("Warning:\nThe debug mode is very uncomfortable: you need to close each window to continue.\nFeel free to kill the process doing CTRL+C and then close the window.\n")
Expand Down Expand Up @@ -164,12 +192,18 @@
c = ""
elif dtmf[(lf,hf)] != c or verbose:
c = dtmf[(lf,hf)]
final_result = final_result + c
print(c, end='', flush=True)

if debug:
plt.show()

print()

print("Result: ", final_result)

if args.processletters:
print("Decoded result based on Keypad: ", decode_sequence(final_result))

except KeyboardInterrupt:
print("\nCTRL+C detected: exiting...")