Skip to content

Commit 4dcf9ec

Browse files
committed
Added modules to support cli.py modules
1 parent 25e0356 commit 4dcf9ec

File tree

10 files changed

+391
-99
lines changed

10 files changed

+391
-99
lines changed

src/cli.py

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
11
import argparse
2-
from service.commands import EnrollSpeakerCommand, RecognizeSpeakerCommand, ListSpeakersCommand, DeleteSpeakerCommand, CommandHandler
3-
from bst import BinarySearchTree
4-
5-
def main():
2+
import os
3+
4+
from service.commands import (
5+
EnrollSpeakerCommand,
6+
RecognizeSpeakerCommand,
7+
ListSpeakersCommand,
8+
DeleteSpeakerCommand,
9+
CommandHandler
10+
)
11+
from file_management.bst import BinarySearchTree
12+
from file_management.file_management import FileManagementInterface
13+
14+
def setup_environment(base_directory):
15+
# Ensure the base directory for models, audio files, and metadata exists
16+
if not os.path.exists(os.path.join(base_directory, "models")):
17+
os.makedirs(os.path.join(base_directory, "models"))
18+
if not os.path.exists(os.path.join(base_directory, "audio_files")):
19+
os.makedirs(os.path.join(base_directory, "audio_files"))
20+
if not os.path.exists(os.path.join(base_directory, "metadata")):
21+
os.makedirs(os.path.join(base_directory, "metadata"))
22+
print(f"Environment set up at {base_directory}")
23+
24+
def main(command_line_args=None):
625
"""CLI entry point."""
726
# Initialize Argument Parser
827
parser = argparse.ArgumentParser(description="Speaker Recognition CLI Tool")
@@ -27,6 +46,12 @@ def main():
2746
# Recognize Command
2847
recognize_parser = subparsers.add_parser('recognize', help='Recognize a speaker from an audio file')
2948
recognize_parser.add_argument('audio_file', type=str, help='Path to the audio file')
49+
recognize_parser.add_argument('--sample_rate', type=int, default=16000, help='Sample rate of the audio file')
50+
recognize_parser.add_argument('--frame_size', type=float, default=0.025, help='Frame size in seconds')
51+
recognize_parser.add_argument('--frame_step', type=float, default=0.01, help='Frame step (overlap) in seconds')
52+
recognize_parser.add_argument('--fft_size', type=int, default=512, help='FFT size for audio processing')
53+
recognize_parser.add_argument('--num_filters', type=int, default=26, help='Number of Mel filters')
54+
recognize_parser.add_argument('--num_ceps', type=int, default=13, help='Number of MFCC coefficients')
3055

3156
# List Speakers Command
3257
subparsers.add_parser('list_speakers', help='List all enrolled speakers')
@@ -36,14 +61,19 @@ def main():
3661
delete_parser.add_argument('speaker_name', type=str, help='Name of the speaker to delete')
3762

3863
# Parse the arguments
39-
args = parser.parse_args()
64+
args = parser.parse_args(command_line_args)
4065

4166
# Initialize the command handler
4267
handler = CommandHandler()
4368

44-
# Binary Search Tree and base directory
45-
bst = BinarySearchTree() # Placeholder for actual binary search tree
46-
base_directory = "models/" # Placeholder for actual base directory
69+
# Base directory setup
70+
base_directory = "test_environment" # Placeholder for the base directory
71+
72+
# Ensure environment setup
73+
setup_environment(base_directory)
74+
75+
# Initialize Binary Search Tree
76+
bst = BinarySearchTree() # Placeholder for actual binary search tree implementation
4777

4878
# Process the command based on the parsed arguments
4979
if args.command == 'enroll':
@@ -61,21 +91,60 @@ def main():
6191
n_mixtures=args.n_mixtures
6292
)
6393
handler.run(command)
94+
95+
# Serialize the BST before exiting the program
96+
bst.serialize_bst()
6497

6598
elif args.command == 'recognize':
66-
command = RecognizeSpeakerCommand(args.audio_file)
99+
command = RecognizeSpeakerCommand(
100+
bst=bst,
101+
audio_file=args.audio_file,
102+
base_directory=base_directory,
103+
sample_rate=args.sample_rate,
104+
frame_size=args.frame_size,
105+
frame_step=args.frame_step,
106+
fft_size=args.fft_size,
107+
num_filters=args.num_filters,
108+
num_ceps=args.num_ceps
109+
)
67110
handler.run(command)
68111

69112
elif args.command == 'list_speakers':
70-
command = ListSpeakersCommand()
113+
file_management = FileManagementInterface(bst=bst, base_directory=base_directory)
114+
command = ListSpeakersCommand(file_management)
71115
handler.run(command)
72116

73117
elif args.command == 'delete_speaker':
74-
command = DeleteSpeakerCommand(args.speaker_name)
118+
file_management = FileManagementInterface(bst=bst, base_directory=base_directory)
119+
command = DeleteSpeakerCommand(args.speaker_name, file_management)
75120
handler.run(command)
76121

77122
else:
78123
parser.print_help()
79124

80125
if __name__ == "__main__":
81-
main()
126+
#debug_args = [
127+
# 'enroll',
128+
# 'maria',
129+
# '/home/gena/PROJECTS/voice-recognition-engine/audio_files/maria.wav',
130+
# '--sample_rate', '16000',
131+
# '--num_filters', '40',
132+
# '--num_ceps', '13',
133+
# '--n_fft', '512',
134+
# '--frame_size', '0.025',
135+
# '--frame_step', '0.01',
136+
# '--n_mixtures', '8'
137+
#]
138+
139+
debug_args = [
140+
'recognize',
141+
'/home/gena/PROJECTS/voice-recognition-engine/audio_files/leah_recognize.wav',
142+
'--sample_rate', '16000',
143+
'--frame_size', '0.025',
144+
'--frame_step', '0.01',
145+
'--fft_size', '512',
146+
'--num_filters', '40',
147+
'--num_ceps', '13',
148+
]
149+
150+
main(debug_args)

src/feature_extraction/audio_feature_extractor.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import numpy as np
22
import matplotlib.pyplot as plt
33
import librosa
4-
from src.feature_extraction.pre_emphasis import PreEmphasisFilter
5-
from src.feature_extraction.framing import Framing
6-
from src.feature_extraction.hamming_window import HammingWindow
7-
from src.feature_extraction.fft import FFTProcessor
8-
from src.feature_extraction.mel_filterbank import MelScaleFilterbank
9-
from src.feature_extraction.dct_processor import DCTProcessor, LogarithmCompression
4+
from feature_extraction.pre_emphasis import PreEmphasisFilter
5+
from feature_extraction.framing import Framing
6+
from feature_extraction.hamming_window import HammingWindow
7+
from feature_extraction.fft import FFTProcessor
8+
from feature_extraction.mel_filterbank import MelScaleFilterbank
9+
from feature_extraction.dct_processor import DCTProcessor, LogarithmCompression
1010

1111
class AudioFeatureExtractor:
1212
def __init__(self, sample_rate=16000, frame_size=0.025, frame_step=0.01, fft_size=512, num_filters=26, num_ceps=13):

src/file_management/file_management.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import time
44
import hashlib
55

6-
import src.file_management.bst as bst
6+
import file_management.bst as bst
77

88

99
class FileManagementBase(ABC):

src/gmm/gmm_factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from src.gmm.gmm_gaussian import GMMGaussianModel
1+
from gmm.gmm_gaussian import GMMGaussianModel
22

33
"""
44
GMM Factory Module

src/gmm/gmm_gaussian.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from sklearn.mixture import GaussianMixture
33
import pickle
44

5-
from src.gmm.gmm_base import GMMModelBase
5+
from gmm.gmm_base import GMMModelBase
66

77
class GMMGaussianModel(GMMModelBase):
88
"""

src/main.py

Lines changed: 31 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,33 @@
1-
import time
2-
import pathlib
3-
import os
4-
import re
5-
import file_management.bst as bst
6-
7-
8-
# The program should generate 5 files with name that have file's uniq ID and time stamps
9-
10-
11-
def current_time():
12-
t = time.localtime()
13-
current_time = time.strftime("%Y_%m_%d_%H_%M_%s", t)
14-
return current_time
15-
16-
def read_files(target_directory):
17-
"""TBD"""
18-
files_data = {}
19-
for filename in os.listdir(target_directory):
20-
file_path = os.path.join(target_directory, filename)
21-
22-
if os.path.isfile(file_path) and filename.endswith(".txt"):
23-
with open(file_path, "r") as f:
24-
lines = f.readlines()
25-
# Extract file_id and timestamp from the lines
26-
file_id = int(lines[0].split(":")[1].strip())
27-
timestamp = lines[1].split(":")[1].strip()
28-
files_data[file_id] = timestamp
29-
return files_data
30-
31-
32-
def generate_files(number_of_files, target_directory):
33-
"""TBD"""
34-
file_info = {}
35-
36-
for i in range(number_of_files):
37-
file_info[i + 1] = current_time()
38-
39-
file_name = f"{i + 1}_{file_info[i + 1]}.txt"
40-
full_path = os.path.join(target_directory, file_name)
41-
with open(full_path, "w") as f:
42-
f.write("File ID: " + str(i + 1) )
43-
f.write("\n")
44-
f.write("File last modified: " + file_info[i + 1])
45-
time.sleep(1) # Wait for 1 second between files
1+
import sys
2+
from cli import main as cli_main # Import the CLI entry point
3+
from web_gui import app as web_app # Import the Flask app for the Web GUI
4+
import logging
5+
import json
6+
7+
def load_config():
8+
"""Load configuration settings (e.g., port, logging settings)."""
9+
with open('config.json', 'r') as config_file:
10+
config = json.load(config_file)
11+
return config
12+
13+
def setup_logging():
14+
"""Setup logging configuration."""
15+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16+
logging.info("Logging is set up.")
17+
18+
def main():
19+
"""Main entry point for the system."""
20+
# Load config and set up logging
21+
config = load_config()
22+
setup_logging()
23+
24+
# Determine execution mode (CLI or Web GUI)
25+
if len(sys.argv) > 1 and sys.argv[1] == 'cli':
26+
logging.info("Starting CLI interface...")
27+
cli_main() # Run the CLI
28+
else:
29+
logging.info("Starting Web GUI...")
30+
web_app.run(host='0.0.0.0', port=config.get("port", 5000), debug=True)
4631

4732
if __name__ == "__main__":
48-
49-
50-
#target_directory = "/home/gena/PROJECTS/ServerManagement/config_files"
51-
#number_of_files = 100
52-
#generate_files(number_of_files, target_directory)
53-
54-
# Create binary search tree and insert data
55-
56-
tree = bst.BinarySearchTree()
57-
config_files = read_files("/home/gena/PROJECTS/ServerManagement/config_files")
58-
print("Measure how long it take to insert one file to the BST")
59-
for file_id, file_timestamp in config_files.items():
60-
start_time = time.time()
61-
tree.insert(file_id, file_timestamp)
62-
end_time = time.time()
63-
print(f"Insertion of file ID {file_id} took {end_time - start_time:.6f} seconds")
64-
65-
print("Measure how long it take to delete a node form the BST")
66-
start_time = time.time()
67-
file_id = 57
68-
tree.delete_node(file_id)
69-
end_time = time.time()
70-
print(f"Deletion of file ID {file_id} took {end_time - start_time:.6f} seconds")
71-
72-
73-
74-
75-
76-
77-
33+
main()

src/service/commands.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Updated commands.py based on the provided details
2+
3+
# commands.py
4+
import os
5+
from service.speaker_enrollment import SpeakerEnrollment
6+
from service.speaker_recognition import SpeakerRecognition
7+
from file_management.file_management import FileManagementInterface
8+
9+
# Base Command class
10+
class Command:
11+
"""Base class for all commands."""
12+
def execute(self):
13+
raise NotImplementedError("Subclasses must implement the execute method.")
14+
15+
# Command for enrolling a speaker
16+
class EnrollSpeakerCommand(Command):
17+
def __init__(self, speaker_name, audio_file, bst, base_directory,
18+
sample_rate, num_filters, num_ceps, n_fft,
19+
frame_size, frame_step, n_mixtures):
20+
self.speaker_name = speaker_name
21+
self.audio_file = audio_file
22+
self.bst = bst
23+
self.base_directory = base_directory
24+
self.sample_rate = sample_rate
25+
self.num_filters = num_filters
26+
self.num_ceps = num_ceps
27+
self.n_fft = n_fft
28+
self.frame_size = frame_size
29+
self.frame_step = frame_step
30+
self.n_mixtures = n_mixtures
31+
32+
def execute(self):
33+
"""Execute the enroll command by enrolling a new speaker."""
34+
# Initialize SpeakerEnrollment with the provided parameters
35+
speaker_enrollment = SpeakerEnrollment(
36+
bst=self.bst,
37+
base_directory=self.base_directory,
38+
sample_rate=self.sample_rate,
39+
num_filters=self.num_filters,
40+
num_ceps=self.num_ceps,
41+
n_fft=self.n_fft,
42+
frame_size=self.frame_size,
43+
frame_step=self.frame_step,
44+
n_mixtures=self.n_mixtures
45+
)
46+
47+
# Enroll the speaker using the provided parameters
48+
success = speaker_enrollment.enroll_speaker(self.speaker_name, self.audio_file)
49+
if success:
50+
print(f"Speaker {self.speaker_name} enrolled successfully.")
51+
else:
52+
print(f"Failed to enroll speaker {self.speaker_name}.")
53+
54+
# Command for recognizing a speaker
55+
class RecognizeSpeakerCommand(Command):
56+
def __init__(self, bst, audio_file, base_directory, sample_rate, frame_size, frame_step, fft_size, num_filters, num_ceps):
57+
self.audio_file = audio_file
58+
self.recognizer = SpeakerRecognition(
59+
bst=bst,
60+
base_directory=base_directory,
61+
sample_rate=sample_rate,
62+
frame_size=frame_size,
63+
frame_step=frame_step,
64+
fft_size=fft_size,
65+
num_filters=num_filters,
66+
num_ceps=num_ceps
67+
)
68+
69+
def execute(self):
70+
"""Execute the recognize command to identify the speaker."""
71+
recognized_speaker = self.recognizer.recognize_speaker(self.audio_file)
72+
print(f"Recognized Speaker: {recognized_speaker}")
73+
74+
# Command for listing all enrolled speakers
75+
class ListSpeakersCommand(Command):
76+
def __init__(self, file_management):
77+
self.file_management = file_management
78+
79+
def execute(self):
80+
"""Execute the list speakers command to display all speakers."""
81+
speakers = self.file_management.list_all_files()
82+
print("Enrolled Speakers:")
83+
for speaker in speakers:
84+
print(f"- {speaker['file_id']}")
85+
86+
# Command for deleting a speaker
87+
class DeleteSpeakerCommand(Command):
88+
def __init__(self, speaker_name, file_management):
89+
self.speaker_name = speaker_name
90+
self.file_management = file_management
91+
92+
def execute(self):
93+
"""Execute the delete command to remove a speaker."""
94+
self.file_management.delete_file(self.speaker_name)
95+
print(f"Speaker {self.speaker_name} deleted successfully.")
96+
97+
# CommandHandler to execute the commands
98+
class CommandHandler:
99+
"""Handles the execution of commands."""
100+
101+
def run(self, command):
102+
"""Run the given command."""
103+
command.execute()

0 commit comments

Comments
 (0)