I have a Text-To-Speech program that will ask the user to input text, convert it to speech and then output that speech from within Pygame by loading the file into memory, getting Pygame to play the file, closing Pygame, closing the file and then deleting the file, ready for the next input. It will then ask the user if they want to convert more text into speech or if they want to exit the program. For the past few days I've just been focusing on getting it working. Now that it finally works, I'm sure that it has many parts that can be improved upon, especially:def wait_for_it(audio_length, greater_than, less_than, time_to_wait):    if (audio_length) >= (greater_than) and (audio_length) < (less_than):        time.sleep((audio_length) + (time_to_wait))wait_for_it(audio_length, 0, 15, 1)wait_for_it(audio_length, 15, 30, 2)wait_for_it(audio_length, 30, 45, 3)wait_for_it(audio_length, 45, 60, 4)wait_for_it(audio_length, 60, 75, 5)wait_for_it(audio_length, 75, 90, 6)wait_for_it(audio_length, 90, 105, 7)wait_for_it(audio_length, 105, 120, 8)wait_for_it(audio_length, 120, 135, 9)wait_for_it(audio_length, 135, 150, 10)wait_for_it(audio_length, 150, 165, 11)wait_for_it(audio_length, 165, 180, 12)if audio_length >= 180:    time.sleep((audio_length) + 15)and answer = input(\nDo you want to repeat? ).strip().lower()if answer in [n, no, nah, nay, course not, don't, dont, not] or no in answer or nah in answer or nay in answer or course not in answer or don't in answer or dont in answer or not in answer:    exiting()elif answer in [y, yes, yeah, course, ye, yea, yh, do] or yes in answer or yeah in answer or course in answer or ye in answer or yea in answer or yh in answer or do in answer:    input_for_tts(\nPlease input something for the program to say: )Full code:import osimport timeimport sysimport getpassimport pipimport mmapimport impfrom contextlib import contextmanagermy_file = Text To Speech.mp3username = getpass.getuser()@contextmanagerdef suppress_output():    with open(os.devnull, w) as devnull:        old_stdout = sys.stdout        sys.stdout = devnull        try:              yield        finally:            sys.stdout = old_stdoutdef check_and_remove_file():    active = pygame.mixer.get_init()    if active != None:        pygame.mixer.music.stop()        pygame.mixer.quit()        pygame.quit()    if os.path.isfile(my_file):        os.remove(my_file)def wait_for_it(audio_length, greater_than, less_than, time_to_wait):    if (audio_length) >= (greater_than) and (audio_length) < (less_than):        time.sleep((audio_length) + (time_to_wait))def exiting():    check_and_remove_file()    print(\nGoodbye!)    sys.exit()def input_for_tts(message):    try:        tts = gTTS(text = input(message))        tts.save('Text To Speech.mp3')        with open(my_file) as f:            m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)        audio = MP3(my_file)        audio_length = audio.info.length        try:            pygame.mixer.init()        except pygame.error:            print(\nSorry, no audio device was detected. The code cannot complete.)            exiting()        pygame.mixer.music.load(m)        pygame.mixer.music.play()        wait_for_it(audio_length, 0, 15, 1)        wait_for_it(audio_length, 15, 30, 2)        wait_for_it(audio_length, 30, 45, 3)        wait_for_it(audio_length, 45, 60, 4)        wait_for_it(audio_length, 60, 75, 5)        wait_for_it(audio_length, 75, 90, 6)        wait_for_it(audio_length, 90, 105, 7)        wait_for_it(audio_length, 105, 120, 8)        wait_for_it(audio_length, 120, 135, 9)        wait_for_it(audio_length, 135, 150, 10)        wait_for_it(audio_length, 150, 165, 11)        wait_for_it(audio_length, 165, 180, 12)        if audio_length >= 180:            time.sleep((audio_length) + 15)        try:            m.close()            check_and_remove_file()        except PermissionError:            imp.reload(pygame)            check_and_remove_file()    except KeyboardInterrupt:        exiting()with suppress_output():    pkgs = ['mutagen', 'gTTS', 'pygame']    for package in pkgs:        if package not in pip.get_installed_distributions():            pip.main(['install', package])import pygamefrom pygame.locals import *from gtts import gTTSfrom mutagen.mp3 import MP3check_and_remove_file()input_for_tts(Hello there  + username + . This program is\nused to output the user's input as speech.\nPlease input something for the program to say: )while True:    try:        answer = input(\nDo you want to repeat? ).strip().lower()        if answer in [n, no, nah, nay, course not, don't, dont, not] or no in answer or nah in answer or nay in answer or course not in answer or don't in answer or dont in answer or not in answer:            exiting()        elif answer in [y, yes, yeah, course, ye, yea, yh, do] or yes in answer or yeah in answer or course in answer or ye in answer or yea in answer or yh in answer or do in answer:            input_for_tts(\nPlease input something for the program to say: )        else:            print(\nSorry, I didn't understand that. Please try again with yes or no.)    except KeyboardInterrupt:        exiting()
Optimizing a Text-To-Speech program with a lot of repetition
python;python 3.x;pygame;audio;modules
Not a full review, only answering the repetitive bits here.The relationship between the length of the speech and the length of the pause is given by a duration of the speech for each second of the pause. You should define all those upper bounds in a container and use a for loop combined to enumerate to examine all possibilities and know the pause duration. Something like:SPEECH_LENGTH_PER_SECOND_OF_PAUSE = range(15, 181, 15)  # [15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180]def get_pause_duration(audio_length, default_duration=15):    for pause_duration, upper_bound in enumerate(SPEECH_LENGTH_PER_SECOND_OF_PAUSE, 1):        if audio_length <= upper_bound:            return pause_duration    return default_durationAnd you can then replace all your wait_for_it by a singletime.sleep(audio_length + get_pause_duration(audio_length))However, you seem to use a very simple pattern to determine the length of the pause: each 15 seconds of audio gets you 1 second of pause, up to 15 seconds of pause This is easily computable:def get_pause_duration(audio_length, maximum_duration=15):    default_pause, correction = divmod(audio_length, 15)  # <-- you should probably define a constant to give a name to this 15    return min(default_pause + bool(correction), maximum_duration)