3

I'm using pocketsphinx in Android. And I've been able to import rules in one .gram file to another .gram file, and I've been able to use rules by specifying a String, but can't seem to be able to combine the two. That is, I can't import a file-based grammar from a string-based grammar; I keep getting Failed to find grammar errors.

When specifying the grammar as a string with:

private SpeechRecognizer mPsRecognizer;

//...

final StringGrammar sg = settings.getStringGrammar();
mPsRecognizer.getDecoder().setJsgfString(sg.getName(), sg.getString());

Where the string is something like:

name: "initial_grammar",

string: "#JSGF V1.0;\n"
    + "\n"
    + "grammar initial_grammar;\n"
    + "\n"
    + "import <digits.digits>;\n"
    + "import <actions.r_actions>;\n"
    + "import <help.r_help>;\n"
    + "\n"
    + "public <initial_grammar>\n"
    + "    = <r_actions>\n"
    + "    | <r_help>\n"
    + "    ;");

I get

com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar digits.gram
com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar actions.gram
com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar help.gram
com.sample.vr.commands I/cmusphinx: INFO: jsgf.c(691): Defined rule: PUBLIC <initial_step.initial_grammar>
com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 338: Undefined rule in RHS: <initial_step.digits>

Which is somehow expected since there is no base file to search relative to.

What I've tried: 1) using the full package name and 2) using the full path (what I get from pocketsphinx's own Asset sync utility).

Using package names If I change the import paths to

    //...
    + "import <com.sample.vr.commands/files/sync/actions.r_actions>;\n"
    + "import <com.sample.vr.commands/files/sync/help.r_help>;\n"
    //...

I get

com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar com/sample/vr/commands/files/sync/help.gram
com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar com/sample/vr/commands/files/sync/actions.gram

with full paths

#JSGF V1.0;

grammar initial_step;

import </storage/emulated/0/Android/data/com.sample.vr.commands/files/sync/actions.r_actions>;
import </storage/emulated/0/Android/data/com.sample.vr.commands/files/sync/help.r_help>;
public <initial_grammar>
    = <r_actions>
    | <r_help>
    ;

I get the following error (note the package part was converted to separate directories):

com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar /storage/emulated/0/Android/data/com/sample/vr/commands/files/sync/help.gram
com.sample.vr.commands E/cmusphinx: ERROR: "jsgf.c", line 775: Failed to find grammar /storage/emulated/0/Android/data/com/sample/vr/commands/files/sync/actions.gram
com.sample.vr.commands I/cmusphinx: INFO: jsgf.c(691): Defined rule: PUBLIC <initial_step.initial_grammar>

in pocketsphinx's source I see that they are replacing dots for slashes:

/* Construct a filename. */
for (c = path; *c; ++c)
    if (*c == '.')
        *c = '/';
strcat(path, ".gram");
newpath = path_list_search(jsgf->searchpath, path);
if (newpath == NULL) {
    E_ERROR("Failed to find grammar %s\n", path);
    ckd_free(path);
    return NULL;
}

What can I do to let pocketsphinx-android know where to find the files that I'm trying to import? I haven't found a function in SpeechRecognizer nor in Decoder. I'm thinking that there's perhaps a way to specify in the configuration where to look for grammar files, but I can't seem to find it. Add some parameter to SpeechRecognizerSetup or Config? Or is there a command line parameter in pocketsphinx that I can add as a string parameter to the Config/Setup object?

frozenkoi
  • 3,228
  • 22
  • 33

1 Answers1

0

In JSGF syntax package name maps to a location as coded, that means that if you write

 import com.package.name;

the corresponding grammar must be in folder com/package relative to the main grammar folder. Same as java packages. So, the layout must be:

main.jsgf
com
  package
    name.jsgf

In case JSGF is loaded from string, a current path is searched for imports. Search path is also configured by JSGF_PATH environment variable. However, it is not easy to set either current working folder or environment variables in Android in Java. For that reason it is better to recompile pocketsphinx-android with hardcoded changes you need or load jsgf from file instead of a string.

Nikolay Shmyrev
  • 24,897
  • 5
  • 43
  • 87
  • What is the 'main grammar folder' for an Android application using pocketsphinx-android? Do I have to configure it? If so, how? – frozenkoi Jan 26 '16 at 21:48
  • When you call `recognizer.addGrammarSearch(SEARCH_NAME, new File(/path/main.jsgf));` it loads the jsgf from the folder path. This path is the main grammar folder. – Nikolay Shmyrev Jan 26 '16 at 21:58
  • Correct, the issue is that adding the grammar by `String` instead of `File` it has to be done with `recognizer.getDecoder().setJsgfString(SEARCH_NAME, searchAsString` , which doesn't provide the context of what the main grammar folder is. – frozenkoi Jan 26 '16 at 22:02
  • Ok, I see the problem now. In that case it uses current working folder which you can get with `getAbsolutePath(".")`. However, there is no easy way to modify that on Android. I think if you need this functionality it is better to recompile pocketsphinx-android with the changes you need or load jsgf from file instead of a string. – Nikolay Shmyrev Jan 26 '16 at 22:57
  • Unfortunately `File defaultDir = new File("."); String defaultDirstring = defaultDir.getAbsolutePath();` yields `/.` And since the directory has dots in the name, it's impossible to reach those files with absolute paths. I.e. trying to use `/storage/emulated/0/Android/data/com.sample.vr/files/sync/help.r_help` results in PS trying to find this file `/storage/emulated/0/Android/data/com/sample/vr/files/sync/help.gram` and the problem is Android's folder for the app which is a package itself (com.sample.vr), separated by dots. I think I'll resort to saving the string to a file and using that. – frozenkoi Jan 27 '16 at 03:32