[SOLVED] Play the voice's MC based on their gender using Renpy's Automatic Voice function.

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Message
Author
alexei
Regular
Posts: 137
Joined: Mon Sep 09, 2019 10:31 am
Completed: re:shape, Monster Boys Doctor, Hearts and Hexes, The Prince's Heart, Dragon Gazer
Projects: Motifs, Longing for Change, The Sinking of the Dream Chaser, Town of the Damned, Monster Boy Wars
Organization: Funigami
itch: funigami
Discord: alexei#5190
Contact:

[SOLVED] Play the voice's MC based on their gender using Renpy's Automatic Voice function.

#1 Post by alexei »

Hi,

I'm using config.auto_voice support for automatically determining the voice file to play, making it possible to play back voice without having to put voice statements before each line of dialogue - https://www.renpy.org/doc/html/voice.ht ... atic-voice

However, in my current game the player can select their gender, so I have male/female voices depending on the player's gender. Any idea how to implement gendered voices with auto_voice? I'm at a dead end.
Last edited by alexei on Mon Jul 25, 2022 5:08 am, edited 1 time in total.

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Play voice's MC based on their gender.

#2 Post by m_from_space »

Code: Select all

define config.auto_voice = None

    This may be a string, a function, or None. If None, auto-voice is disabled.

    If a string, this is formatted with the id variable bound to the identifier of the current line of dialogue. If this gives an existing file, that file is played as voice audio.

    If a function, the function is called with a single argument, the identifier of the current line of dialogue. The function is expected to return a string. If this gives an existing file, that file is played as voice audio.

    See Automatic Voice for more details.
So I suggest setting config.auto_voice to a function. Inside the function (that has only 1 argument), you also read in the current gender and add it to the string you then return to renpy, so it can play the file.

I did not test this, but something like the following should work, assuming your voices are inside "voice/female/" and "voice/male/"

Code: Select all

default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        return "voice/{}/{}.ogg".format(gender, id)
    config.auto_voice = genderVoice # or maybe genderVoice()

alexei
Regular
Posts: 137
Joined: Mon Sep 09, 2019 10:31 am
Completed: re:shape, Monster Boys Doctor, Hearts and Hexes, The Prince's Heart, Dragon Gazer
Projects: Motifs, Longing for Change, The Sinking of the Dream Chaser, Town of the Damned, Monster Boy Wars
Organization: Funigami
itch: funigami
Discord: alexei#5190
Contact:

Re: Play voice's MC based on their gender.

#3 Post by alexei »

m_from_space wrote: Sun Jul 10, 2022 5:26 am

Code: Select all

define config.auto_voice = None

    This may be a string, a function, or None. If None, auto-voice is disabled.

    If a string, this is formatted with the id variable bound to the identifier of the current line of dialogue. If this gives an existing file, that file is played as voice audio.

    If a function, the function is called with a single argument, the identifier of the current line of dialogue. The function is expected to return a string. If this gives an existing file, that file is played as voice audio.

    See Automatic Voice for more details.
So I suggest setting config.auto_voice to a function. Inside the function (that has only 1 argument), you also read in the current gender and add it to the string you then return to renpy, so it can play the file.

I did not test this, but something like the following should work, assuming your voices are inside "voice/female/" and "voice/male/"

Code: Select all

default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        return "voice/{}/{}.ogg".format(gender, id)
    config.auto_voice = genderVoice # or maybe genderVoice()
Thanks for your help, I think it'll work. I have another question though. The above function could work for those two gendered options, but what about the rest of the cast?

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Play voice's MC based on their gender.

#4 Post by m_from_space »

Hm, you're right. Other characters should also work. XD

I didn't test it, since I never used voices, but maybe this works, assuming all other characters are inside "voice/*.ogg". You could of course make different return statements depending on all the characters. I'm not sure the _get_voice_info() function is working here though. It hopefully determines who is speaking at the moment.

Code: Select all

define mc = Character("Main Character", voice_tag="mc_voice")
default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        vi = _get_voice_info()
        if vi.tag == "mc_voice":
            return "voice/{}/{}.ogg".format(gender, id)
        return "voice/{}.ogg".format(id)
        
    config.auto_voice = genderVoice # or maybe genderVoice()

alexei
Regular
Posts: 137
Joined: Mon Sep 09, 2019 10:31 am
Completed: re:shape, Monster Boys Doctor, Hearts and Hexes, The Prince's Heart, Dragon Gazer
Projects: Motifs, Longing for Change, The Sinking of the Dream Chaser, Town of the Damned, Monster Boy Wars
Organization: Funigami
itch: funigami
Discord: alexei#5190
Contact:

Re: Play voice's MC based on their gender.

#5 Post by alexei »

Thanks! Will check it out and update if it worked.

Thanks again!

alexei
Regular
Posts: 137
Joined: Mon Sep 09, 2019 10:31 am
Completed: re:shape, Monster Boys Doctor, Hearts and Hexes, The Prince's Heart, Dragon Gazer
Projects: Motifs, Longing for Change, The Sinking of the Dream Chaser, Town of the Damned, Monster Boy Wars
Organization: Funigami
itch: funigami
Discord: alexei#5190
Contact:

Re: Play voice's MC based on their gender.

#6 Post by alexei »

m_from_space wrote: Tue Jul 12, 2022 2:36 am Hm, you're right. Other characters should also work. XD

I didn't test it, since I never used voices, but maybe this works, assuming all other characters are inside "voice/*.ogg". You could of course make different return statements depending on all the characters. I'm not sure the _get_voice_info() function is working here though. It hopefully determines who is speaking at the moment.

Code: Select all

define mc = Character("Main Character", voice_tag="mc_voice")
default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        vi = _get_voice_info()
        if vi.tag == "mc_voice":
            return "voice/{}/{}.ogg".format(gender, id)
        return "voice/{}.ogg".format(id)
        
    config.auto_voice = genderVoice # or maybe genderVoice()
So, I got the following error.

Image

Any idea what might be the problem?

alexei
Regular
Posts: 137
Joined: Mon Sep 09, 2019 10:31 am
Completed: re:shape, Monster Boys Doctor, Hearts and Hexes, The Prince's Heart, Dragon Gazer
Projects: Motifs, Longing for Change, The Sinking of the Dream Chaser, Town of the Damned, Monster Boy Wars
Organization: Funigami
itch: funigami
Discord: alexei#5190
Contact:

Re: Play voice's MC based on their gender.

#7 Post by alexei »

This function works thought

Code: Select all

default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        return "voice/{}/{}.ogg".format(gender, id)
    config.auto_voice = genderVoice # or maybe genderVoice()

alexei
Regular
Posts: 137
Joined: Mon Sep 09, 2019 10:31 am
Completed: re:shape, Monster Boys Doctor, Hearts and Hexes, The Prince's Heart, Dragon Gazer
Projects: Motifs, Longing for Change, The Sinking of the Dream Chaser, Town of the Damned, Monster Boy Wars
Organization: Funigami
itch: funigami
Discord: alexei#5190
Contact:

Re: Play voice's MC based on their gender.

#8 Post by alexei »

m_from_space wrote: Tue Jul 12, 2022 2:36 am Hm, you're right. Other characters should also work. XD

I didn't test it, since I never used voices, but maybe this works, assuming all other characters are inside "voice/*.ogg". You could of course make different return statements depending on all the characters. I'm not sure the _get_voice_info() function is working here though. It hopefully determines who is speaking at the moment.

Code: Select all

define mc = Character("Main Character", voice_tag="mc_voice")
default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        vi = _get_voice_info()
        if vi.tag == "mc_voice":
            return "voice/{}/{}.ogg".format(gender, id)
        return "voice/{}.ogg".format(id)
        
    config.auto_voice = genderVoice # or maybe genderVoice()
Following my previous messages, I think that the auto_voice function needs to be written in a way to not call _get_voice_info because in getting the voice info, Ren'Py will attempt to call auto voice, which tries to get the voice info, which causes Ren'Py to call the auto voice, which tries to get the voice info, etc.

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Play voice's MC based on their gender.

#9 Post by m_from_space »

Sorry, as I said, I didn't test it and didn't know the timing of those function calls and that _get_voice_info triggers a call of your own function.

So I don't really know what easy way there is to determine who is speaking at the moment. Maybe it's easy, but since I never used voices like this, I don't know.

Alouette
Newbie
Posts: 5
Joined: Tue Oct 08, 2013 7:40 pm
Location: Canada
Contact:

Re: Play voice's MC based on their gender.

#10 Post by Alouette »

I don't claim to be more than a novice at either python or ren'py, but if you want a quick solution you can access the voice tag directly. Building off of what you've already been working with:

Code: Select all

define mc = Character("Main Character", voice_tag="mc_voice")
default gender = "female" # or "male"

init python:
    def genderVoice(id):
        global gender
        voice_tag = _voice.tag
        if voice_tag == "mc_voice":
            return "voice/{}/{}.ogg".format(gender, id)
        return "voice/{}.ogg".format(id)
        
    config.auto_voice = genderVoice # or maybe genderVoice()
This seemed to work for me.

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Play voice's MC based on their gender.

#11 Post by m_from_space »

Alouette wrote: Wed Jul 20, 2022 10:16 pm I don't claim to be more than a novice at either python or ren'py, but if you want a quick solution you can access the voice tag directly. Building off of what you've already been working with:
Very interesting, but say, where is this _voice variable coming from? I can't find anything about it in the documentation. Have you sneaked into renpy's code for this? :)

Alouette
Newbie
Posts: 5
Joined: Tue Oct 08, 2013 7:40 pm
Location: Canada
Contact:

Re: Play voice's MC based on their gender.

#12 Post by Alouette »

m_from_space wrote: Thu Jul 21, 2022 12:51 am Very interesting, but say, where is this _voice variable coming from? I can't find anything about it in the documentation. Have you sneaked into renpy's code for this? :)
You caught me, I did! :lol:

I didn't see anything useful looking in documentation, so I went poking around to see what exactly _get_voice_info() was doing and where it got the voice tag.
_voice seems to be where the returned VoiceInfo gets it?
Here's a link if you're interested: https://github.com/renpy/renpy/blob/843 ... e.rpy#L320

But yeah, it's not in documentation, which is why I'm not sure if it's really a good idea to use or if it breaks best practices?

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Play voice's MC based on their gender.

#13 Post by m_from_space »

The fun thing about encountering a variable that starts with "_" in Python is, that there is this programmer's convention, that you don't use them out of their context. The underscore marks them as "private", although in Python you cannot really mark something as private (like in C++). :D

It's definitely not best practice. But I don't have another solution for the above problem, so there is that.

Alouette
Newbie
Posts: 5
Joined: Tue Oct 08, 2013 7:40 pm
Location: Canada
Contact:

Re: Play voice's MC based on their gender.

#14 Post by Alouette »

m_from_space wrote: Thu Jul 21, 2022 1:40 pm The fun thing about encountering a variable that starts with "_" in Python is, that there is this programmer's convention, that you don't use them out of their context. The underscore marks them as "private", although in Python you cannot really mark something as private (like in C++). :D
Oh, that's good to know! Thank you!!
I'm definitely a better C++ programmer than I am a python one :lol:

m_from_space wrote: Thu Jul 21, 2022 1:40 pm It's definitely not best practice. But I don't have another solution for the above problem, so there is that.
I actually did think of another idea-- what about using a character callback? Something like:

Code: Select all

default gender = "female" # or "male"

init python:
    config.auto_voice = "voice/{id}.ogg"  # auto-voice all characters
    
    def genderVoice(event, interact=True, **kwargs):
        if not interact:
            return
            
        if event == "begin":
            vi = _get_voice_info()
            
            # main character voice file is at "voice/{gender}/{id}" like before
            filename_list = vi.auto_filename.rsplit("/")
            filename = filename_list[0] + "/{}/".format(gender) + filename_list[1]
            
            voice(filename, vi.tag)

define mc = Character("Main Character", callback=genderVoice)

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Play voice's MC based on their gender.

#15 Post by m_from_space »

Alouette wrote: Thu Jul 21, 2022 6:43 pmI actually did think of another idea-- what about using a character callback? Something like:
I'm not sure. Isn't Renpy then trying to both play the auto-voice for MC and the genderVoice? I don't know about the timing of those events in callback in relation to playing a voice. But you may want to use a callback for determining who is speaking at the moment and save that in a global variable you then use in genderVoice. But as I said, I don't know if Renpy already tried to figure out what voice to play before event == 'begin' triggers.

I guess @alexei has to give feedback. (Or others that use voices.)

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot], Milkymalk