File size: 8,948 Bytes
54d552b
e602a12
3e96922
 
6ff812d
e602a12
1c668c5
a686010
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491e7b3
493a19d
e602a12
 
493a19d
54d552b
e602a12
 
54d552b
9a12661
a686010
695d82a
a686010
 
491e7b3
38c6fd2
491e7b3
a686010
e602a12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c752b08
 
e602a12
c752b08
 
 
 
 
 
 
 
 
7fee0e0
e602a12
9a12661
7fee0e0
 
 
 
 
c752b08
7fee0e0
 
 
 
 
 
 
 
c752b08
 
 
 
7fee0e0
 
 
 
 
 
 
 
 
c752b08
7fee0e0
c752b08
e602a12
7fee0e0
9a12661
7fee0e0
e602a12
 
 
 
7fee0e0
 
 
 
 
 
c752b08
7fee0e0
 
 
 
c752b08
7fee0e0
 
 
 
 
 
 
 
 
 
 
 
c752b08
7fee0e0
c752b08
 
 
 
 
e602a12
 
c752b08
a686010
 
 
 
 
 
 
 
 
e602a12
 
 
 
6c7fe6c
695d82a
e602a12
695d82a
38c6fd2
9a12661
e602a12
a686010
 
695d82a
9a12661
a686010
9a12661
 
 
a686010
 
 
9a12661
 
e602a12
9a12661
 
a686010
 
e602a12
9a12661
e602a12
a686010
9a12661
 
 
a686010
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import sympy as sp
import gradio as gr
import speech_recognition as sr
from gtts import gTTS
import os
import re

def generate_tts(text, engine_choice="auto", output_file="response.mp3"):
    """
    Generate TTS audio using gTTS or pyttsx3.
    - If `engine_choice` is "gTTS", uses Google TTS (online).
    - If `engine_choice` is "pyttsx3", uses pyttsx3 (offline).
    - If `engine_choice` is "auto", tries gTTS first, then falls back to pyttsx3.
    
    Args:
    - text (str): The text to convert to speech.
    - engine_choice (str): "gTTS", "pyttsx3", or "auto".
    - output_file (str): Name of the output audio file.
    
    Returns:
    - str: Path to the saved audio file.
    """
    if engine_choice == "gTTS" or engine_choice == "auto":
        try:
            tts = gTTS(text, lang="en")
            tts.save(output_file)
            print(f"Audio generated using gTTS: {output_file}")
            return output_file
        except Exception as e:
            print(f"gTTS failed: {e}")
            if engine_choice == "gTTS":
                raise e  # Raise the error if gTTS is explicitly requested

    if engine_choice == "pyttsx3" or engine_choice == "auto":
        try:
            engine.save_to_file(text, output_file)
            engine.runAndWait()
            print(f"Audio generated using pyttsx3: {output_file}")
            return output_file
        except Exception as e:
            print(f"pyttsx3 failed: {e}")
            raise e  # Raise the error if pyttsx3 fails even in auto mode

    # Raise an error if no valid engine choice is provided
    raise ValueError("Invalid TTS engine choice. Use 'gTTS', 'pyttsx3', or 'auto'.")


def process_math(query, tts_engine="auto"):
    """
    Process the math query and convert the result into audio using the selected TTS engine.
    
    Args:
    - query (str): The math expression to evaluate.
    - tts_engine (str): The TTS engine to use ("gTTS", "pyttsx3", or "auto").
    
    Returns:
    - tuple: (result_text, audio_path)
    """
    try:
        # Clean up the input by removing unnecessary spaces
        query = query.replace(" ", "")  # Removing extra spaces around operators or parentheses
        
        # Try to process the query using sympy
        expr = sp.sympify(query)

        # Basic operations handled automatically by sympy
        result = expr

        # Generate TTS output
        result_text = f"The result is: {result}"
        audio_path = generate_tts(result_text, engine_choice=tts_engine)  # Pass the selected engine
        return result_text, audio_path
    except Exception as e:
        return f"Error: Unable to process the query. Please check the syntax. Error: {e}", None


# Function to handle voice input (speech-to-text)
def voice_to_text(audio):
    recognizer = sr.Recognizer()
    try:
        with sr.AudioFile(audio) as source:
            audio_data = recognizer.record(source)
            text = recognizer.recognize_google(audio_data)
            return text
    except Exception as e:
        return f"Error in voice recognition: {e}"

# Mapping words to their corresponding numerical values
word_to_num = {
    "one": 1, "two": 2, "three": 3, "four": 4, "five": 5,
    "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10,
    "eleven": 11, "twelve": 12, "thirteen": 13, "fourteen": 14,
    "fifteen": 15, "sixteen": 16, "seventeen": 17, "eighteen": 18,
    "nineteen": 19, "twenty": 20, "thirty": 30, "forty": 40,
    "fifty": 50, "sixty": 60, "seventy": 70, "eighty": 80, "ninety": 90,
    "hundred": 100, "thousand": 1000
}

import re

def convert_speech_to_math(text):
    """
    Converts natural language math queries into valid mathematical expressions.
    
    Args:
        text (str): The natural language input.
    
    Returns:
        str: The converted mathematical expression.
    """
    # Convert the input text to lowercase
    text = text.lower()

    # Arithmetic operations
    text = re.sub(r'add (\d+) and (\d+)', r'\1 + \2', text)
    text = re.sub(r'subtract (\d+) from (\d+)', r'\2 - \1', text)
    text = re.sub(r'multiply (\d+) by (\d+)', r'\1 * \2', text)
    text = re.sub(r'divide (\d+) by (\d+)', r'\1 / \2', text)

    # Exponentiation and roots
    text = re.sub(r'power of (\d+) to (\d+)', r'\1**\2', text)
    text = re.sub(r'square of (\d+)', r'\1**2', text)
    text = re.sub(r'cube of (\d+)', r'\1**3', text)
    text = re.sub(r'square root of (\d+)', r'sqrt(\1)', text)
    text = re.sub(r'cube root of (\d+)', r'cbrt(\1)', text)

    # Logarithmic operations
    text = re.sub(r'log of (\d+)', r'log(\1)', text)  # Convert "log of 100" to "log(100)"
    text = re.sub(r'log base (\d+) of (\d+)', r'log(\2, \1)', text)  # Handle "log base 2 of 8"
    text = re.sub(r'natural log of (\d+)', r'ln(\1)', text)  # Handle "natural log of 10"

    # Trigonometric operations
    text = re.sub(r'sine of (.+)', r'sin(\1)', text)
    text = re.sub(r'cosine of (.+)', r'cos(\1)', text)
    text = re.sub(r'tangent of (.+)', r'tan(\1)', text)

    # Inverse trigonometric operations
    text = re.sub(r'arc sine of (.+)', r'asin(\1)', text)
    text = re.sub(r'arc cosine of (.+)', r'acos(\1)', text)
    text = re.sub(r'arc tangent of (.+)', r'atan(\1)', text)

    # Factorials and combinatorics
    text = re.sub(r'factorial of (\w+)', lambda m: f'factorial({m.group(1)})', text)
    text = re.sub(r'permutation of (\d+), (\d+)', r'permutation(\1, \2)', text)
    text = re.sub(r'combination of (\d+), (\d+)', r'combinations(\1, \2)', text)

    # Calculus
    text = re.sub(r'differentiate (.+)', r'diff(\1, x)', text)
    text = re.sub(r'integrate (.+)', r'integrate(\1, x)', text)
    text = re.sub(r'limit of (.+)', r'limit(\1, x, 0)', text)

    # Matrices
    text = re.sub(r'matrix of (\[.*\])', r'Matrix(\1)', text)

    # Complex numbers
    text = re.sub(r'absolute value of (.+)', r'Abs(\1)', text)
    text = re.sub(r'conjugate of (.+)', r'conjugate(\1)', text)

    # Set operations
    text = re.sub(r'union of (.+) and (.+)', r'Union(\1, \2)', text)
    text = re.sub(r'intersection of (.+) and (.+)', r'Intersection(\1, \2)', text)
    text = re.sub(r'complement of (.+)', r'Complement(\1)', text)

    # Statistical operations
    text = re.sub(r'mean of (.+)', r'Mean(\1)', text)
    text = re.sub(r'median of (.+)', r'Median(\1)', text)
    text = re.sub(r'standard deviation of (.+)', r'std(\1)', text)
    text = re.sub(r'variance of (.+)', r'variance(\1)', text)

    # Custom math operations
    text = re.sub(r'absolute difference between (\d+) and (\d+)', r'Abs(\1 - \2)', text)
    text = re.sub(r'floor of (.+)', r'floor(\1)', text)
    text = re.sub(r'ceiling of (.+)', r'ceiling(\1)', text)

    # Miscellaneous formatting fixes
    text = re.sub(r'\s*\(', r'(', text)  # Remove spaces before parentheses
    text = re.sub(r'to the power of (\d+)', r'**\1', text)  # Handle "to the power of"

    # Handle additional edge cases
    text = re.sub(r'logof(\d+)', r'log(\1)', text)  # Correct misinterpreted "logof100"
    text = re.sub(r'sqrt(\d+)', r'sqrt(\1)', text)  # Ensure proper sqrt function

    return text


def calculator(audio=None, text_input=None, tts_engine="auto"):
    """
    Main function to handle input and process it for math calculation (text or voice).
    
    Args:
    - audio: Filepath to the audio input.
    - text_input: Math expression in text form.
    - tts_engine: Selected TTS engine ("gTTS", "pyttsx3", or "auto").
    """
    if audio:
        query = voice_to_text(audio)
        print(f"Voice Input Detected: {query}")  # Debugging: Print detected voice input
        query = convert_speech_to_math(query)  # Convert the voice input into valid math expression
    elif text_input:
        query = text_input
        print(f"Text Input: {query}")  # Debugging: Print detected text input
    else:
        return "No valid input provided.", None

    # Process the math problem
    return process_math(query, tts_engine)


def start_interface():
    # Gradio Interface with Voice Input, Text Input, and TTS Engine Choice
    interface = gr.Interface(
        fn=calculator,
        inputs=[
            gr.Audio(type="filepath", label="Speak a Math Expression (e.g., factorial(5), differentiate x squared, integrate sin(x), matrix([[1, 2], [3, 4]]) )"),
            gr.Textbox(label="Or Type a Math Expression (Optional)", placeholder="Type your math expression here..."),
            gr.Radio(choices=["auto", "gTTS", "pyttsx3"], value="auto", label="Select TTS Engine")
        ],
        outputs=[
            "text",  # Show the text result
            gr.Audio(label="Listen to the result")  # Provide the audio result
        ],
        title="Advanced Math Solver with Dual TTS",
        description="Solve math problems with both online (gTTS) and offline (pyttsx3) TTS support.",
        live=True
    )
    
    interface.launch(share=True)

if __name__ == "__main__":
    start_interface()