PP600 PP600 - 6 months ago 36
Java Question

Access violation in JNI bindings for Pocketsphinx

I try to program a little VoiceRecognition with Pocketsphinx.

First I built sphinxbase and pocketsphinx. I am able to start pocketsphinx_continuous out of cmd. I want to use it only in inmic-mode.

Now I tried to rewrite the c-source so I have only the inmic-mode. I built a .dll out of this code and tried to run it in Eclipse.

This is my Java Source

public class Test {

private native Test Decoder_defaultConfig();
private native void recognize_from_mic();

public static void main(final String[] args) {

final Test test = new Test().Decoder_defaultConfig();
test.recognize_from_mic();

}
static {
System.loadLibrary("pocketsphinx_Test");
}
}


This is my c-Source. It's nearly the same like the pocketsphinx_continuous.c.

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <jni.h>
#include <sphinxbase\cmd_ln.h>

#include <windows.h>

#include <sphinxbase/err.h>
#include <sphinxbase/ad.h>

#include "pocketsphinx.h"

static ps_decoder_t *ps;
static cmd_ln_t *config;
static FILE *rawfd;

static const arg_t cont_args_def[] = {
POCKETSPHINX_OPTIONS,
/* Argument file. */
{ "-argfile",
ARG_STRING,
NULL,
"Argument file giving extra arguments." },
{ "-adcdev",
ARG_STRING,
NULL,
"Name of audio device to use for input." },
{ "-infile",
ARG_STRING,
NULL,
"Audio file to transcribe." },
{ "-inmic",
ARG_BOOLEAN,
"no",
"Transcribe audio from microphone." },
{ "-time",
ARG_BOOLEAN,
"no",
"Print word times in file transcription." },
CMDLN_EMPTY_OPTION
};

static void sleep_msec(int32 ms)
{
#if (defined(_WIN32) && !defined(GNUWINCE)) || defined(_WIN32_WCE)
Sleep(ms);
#else
/* ------------------- Unix ------------------ */
struct timeval tmo;

tmo.tv_sec = 0;
tmo.tv_usec = ms * 1000;

select(0, NULL, NULL, NULL, &tmo);
#endif
}

JNIEXPORT void JNICALL Java_Test_Decoder_1defaultConfig(JNIEnv *env, jobject obj)
{
char const *cfg;

config = cmd_ln_init(NULL, ps_args(), "-inmic", "yes", TRUE, NULL);

if (config == NULL || cmd_ln_boolean_r(config, "-inmic") == FALSE) {
E_INFO("Specify '-inmic yes' to recognize from microphone.\n");
cmd_ln_free_r(config);

}

ps_default_search_args(config);
ps = ps_init(config);
if (ps == NULL) {
cmd_ln_free_r(config);

}


}

JNIEXPORT void JNICALL Java_Test_recognize_1from_1mic(JNIEnv *env, jobject obj)
{
ad_rec_t *ad;
int16 adbuf[2048];
uint8 utt_started, in_speech;
int32 k;
char const *hyp;

if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),
(int)cmd_ln_float32_r(config,
"-samprate"))) == NULL)
E_FATAL("Failed to open audio device\n");
if (ad_start_rec(ad) < 0)
E_FATAL("Failed to start recording\n");

if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");

for (;;) {
if ((k = ad_read(ad, adbuf, 2048)) < 0)
E_FATAL("Failed to read audio\n");
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started) {
utt_started = TRUE;
E_INFO("Listening...\n");
}
if (!in_speech && utt_started) {
/* speech -> silence transition, time to start new utterance */
ps_end_utt(ps);
hyp = ps_get_hyp(ps, NULL);
if (hyp != NULL) {
printf("%s\n", hyp);
fflush(stdout);
}

if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
}
sleep_msec(100);
}
ad_close(ad);

ps_free(ps);
cmd_ln_free_r(config);

}


And the generated Header-File:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Test */

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Test
* Method: Decoder_defaultConfig
* Signature: ()LTest;
*/
JNIEXPORT jobject JNICALL Java_Test_Decoder_1defaultConfig
(JNIEnv *, jobject);

/*
* Class: Test
* Method: recognize_from_mic
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Test_recognize_1from_1mic
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


If I run the program in eclipse I get the following error:

# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000004f0cd0, pid=11388, tid=0x0000000000002774
#
# JRE version: OpenJDK Runtime Environment (8.0_74-b02) (build 1.8.0_74-b02)
# Java VM: OpenJDK 64-Bit Server VM (25.74-b02 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [sphinxbase.dll+0x20cd0]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\sde\workspaceAW_4.5\pocketsphinx\hs_err_pid11388.log
#


Does anybody know where my issue is and how I can fix this Problem? It says that the Problem is in the sphinxbase.dll-file, but I don't know what is wrong, because when I run it with cmd it works. Could it be any Problem with 32/64 Versions?

Answer

This part

   config = cmd_ln_init(NULL, ps_args(), "-inmic", "yes", TRUE, NULL);

    if (config == NULL || cmd_ln_boolean_r(config, "-inmic") == FALSE) {
        E_INFO("Specify '-inmic yes' to recognize from microphone.\n");
        cmd_ln_free_r(config);

    }

Is not quite correct. "-inmic" is an option of pocketsphinx_continuous, not an option of sphinxbase. It should be simply

    config = cmd_ln_init(NULL, ps_args(), TRUE, NULL);

Also, you need to exit the program after cmd_ln_free_r(config), not continue execution. When you free config and later try to use it you cause a memory violation.

Comments