Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds FeatureExtractor and corresponding test class; #37

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions sphinx4-core/src/main/java/edu/cmu/sphinx/api/FeatureExtractor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package edu.cmu.sphinx.api;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import edu.cmu.sphinx.frontend.Data;
import edu.cmu.sphinx.frontend.DataEndSignal;
import edu.cmu.sphinx.frontend.DataProcessingException;
import edu.cmu.sphinx.frontend.DoubleData;
import edu.cmu.sphinx.frontend.FloatData;
import edu.cmu.sphinx.frontend.FrontEnd;

/**
* Extracts features from input stream
*
* @author Vladisav Jelisavcic
*
*/
class FeatureExtractor {

private FrontEnd frontEnd;
private int featureLength = -1;

/**
* Constructs a FeatureExtractor.
*
* @param cm
* the configuration manager
* @param frontEndName
* the name for the frontEnd to be used
* @param inputStream
* data stream
*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The javadoc params don't match the actual parameters.

* @throws IOException
* if error occurred
*/
public FeatureExtractor(InputStream inputStream, int sampleRate)
throws IOException {
Configuration configuration = new Configuration();

configuration.setAcousticModelPath("resource:/edu/cmu/sphinx/models/en-us/en-us");
configuration.setDictionaryPath("resource:/edu/cmu/sphinx/models/en-us/cmudict-en-us.dict");
configuration.setLanguageModelPath("resource:/edu/cmu/sphinx/models/en-us/en-us.lm.bin");

Context ctx = new Context(configuration);
ctx.setSampleRate(sampleRate);
ctx.setSpeechSource(inputStream);

frontEnd = (FrontEnd) ctx.getInstance(FrontEnd.class);
}

/**
* Extracts all features from the supplied InputStream.
*
* @return float[][] when called first time, null otherwise
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type was changed to a List. The javadoc should be updated.

*
* @throws DataProcessinException
* if error occurred
*/
public List<float[]> getAllFeatures() throws DataProcessingException {
List<float[]> featureList = new ArrayList<float[]>();

Data feature = frontEnd.getData();
if (feature == null)
return null;

while (!(feature instanceof DataEndSignal)) {
if (feature instanceof DoubleData) {
double[] featureData = ((DoubleData) feature).getValues();
if (featureLength < 0) {
featureLength = featureData.length;
}
float[] convertedData = new float[featureData.length];
for (int i = 0; i < featureData.length; i++) {
convertedData[i] = (float) featureData[i];
}
featureList.add(convertedData);
} else if (feature instanceof FloatData) {
float[] featureData = ((FloatData) feature).getValues();
if (featureLength < 0) {
featureLength = featureData.length;
}
featureList.add(featureData);
}
feature = frontEnd.getData();
}

return featureList;
}

/**
* Extracts a single feature frame from the supplied InputStream.
*
* @return float[] or null if end of stream reached
*
* @throws DataProcessinException
* if error occurred
*/
public float[] getNextFeatureFrame() throws DataProcessingException {
Data feature = frontEnd.getData();
if (feature == null)
return null;

while (!(feature instanceof DoubleData || feature instanceof FloatData)) {
feature = frontEnd.getData();
if (feature == null)
return null;
}

if (feature instanceof DoubleData) {
double[] featureData = ((DoubleData) feature).getValues();
if (featureLength < 0) {
featureLength = featureData.length;
}
float[] convertedData = new float[featureData.length];
for (int i = 0; i < featureData.length; i++) {
convertedData[i] = (float) featureData[i];
}

return convertedData;
} else if (feature instanceof FloatData) {
float[] featureData = ((FloatData) feature).getValues();
if (featureLength < 0) {
featureLength = featureData.length;
}

return featureData;
}

return null;
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
*
*/
package edu.cmu.sphinx.api;

import static org.testng.AssertJUnit.assertEquals;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Scanner;

import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

/**
* @author Vladisav Jelisavcic
*
*/
public class FeatureExtractorTest {

static final String FRONTEND_NAME = "cepstraFrontEnd";
private float[] features;
final int sampleRate = 16000;

@BeforeTest
public void setUp() {
InputStream asciiStream = FeatureExtractorTest.class
.getResourceAsStream("/edu/cmu/sphinx/api/10001-90210-01803.features");
Scanner sc = new Scanner(asciiStream);
int numDataPoints = sc.nextInt();

features = new float[numDataPoints];
int i = 0;
while (sc.hasNextFloat()) {
features[i++] = sc.nextFloat();
}
sc.close();
}

@AfterTest
public void tearDown() {

}

/**
* Test method for
* {@link edu.cmu.sphinx.api.FeatureExtractor#getAllFeatures()}.
*
* @throws IOException
*/
@Test
public void testGetAllFeatures() throws IOException {
InputStream audioStream = FeatureExtractorTest.class
.getResourceAsStream("/edu/cmu/sphinx/tools/bandwidth/10001-90210-01803.wav");

FeatureExtractor fe = new FeatureExtractor(audioStream, sampleRate);
List<float[]> data = fe.getAllFeatures();

int numSamples = data.size();
int numFeatures = data.get(0).length;

int numDataPoints = numSamples * numFeatures;

assertEquals(features.length, numDataPoints); // check if all data
// points are loaded
for (int i = 0; i < numSamples; i++) {
for (int j = 0; j < numFeatures; j++) {
assertEquals(features[i * numFeatures + j], data.get(i)[j]);
}
}
}

/**
* Test method for
* {@link edu.cmu.sphinx.api.FeatureExtractor#getNextFeatureFrame()}.
*
* @throws IOException
*/
@Test
public void testGetNextFeatureFrame() throws IOException {
InputStream audioStream = FeatureExtractorTest.class
.getResourceAsStream("/edu/cmu/sphinx/tools/bandwidth/10001-90210-01803.wav");

FeatureExtractor fe = new FeatureExtractor(audioStream, sampleRate);

int numDataPoints = 0;
float[] data;
while ((data = fe.getNextFeatureFrame()) != null) {
for (int i = 0; i < data.length; i++) {
assertEquals(features[i + numDataPoints], data[i]);
}
numDataPoints += data.length;
}

assertEquals(features.length, numDataPoints); // check if all data points are loaded
}

}

Large diffs are not rendered by default.