Я пишу программу, которая эмулирует функциональность следующей Java-программы:
public class MFCC {
public static void main(String[] args) throws IOException, InterruptedException, Exception {
System.out.println("MFCC Coefficient Extractor");
// Executables
String sox = "/usr/bin/sox";
String x2x = "/usr/local/bin/x2x";
String frame = "/usr/local/bin/frame";
String window = "/usr/local/bin/window";
String mcep = "/usr/local/bin/mcep";
String swab = "/usr/local/bin/swab";
// Command Line Options
String WavFile = "/output/audio.wav";
String RawFile = WavFile + ".raw";
String frameLength = "400";
String frameLengthOutput = "512";
String framePeriod = "80";
String mgcOrder = "24";
String mfccFile = WavFile + ".mfc";
String soxcmd = sox + " " + WavFile + " " + RawFile;
launchProc(soxcmd, "sox", WavFile);
// MFCC
String mfcccmd = x2x + " +sf " + WavFile + " | " + frame + " -l " + frameLength + " -p " + framePeriod + " | " + window
+ " -l " + frameLength + " -L " + frameLengthOutput + " -w 1 -n 1 | " + mcep + " -a 0.42 -m " + mgcOrder
+ " -l " + frameLengthOutput + " | " + swab + " +f > " + mfccFile;
launchBatchProc(mfcccmd, "getSptkMfcc", WavFile);
int numFrames;
DataInputStream mfcData = null;
Vector<Float> mfc = new Vector<Float>();
mfcData = new DataInputStream(new BufferedInputStream(new FileInputStream(mfccFile)));
try {
while (true) {
mfc.add(mfcData.readFloat());
}
} catch (EOFException e) {
}
mfcData.close();
System.out.println("Coefficient vector length: " + mfc.size());
System.out.println("The coefficients are: " + mfc);
}
}
(Запустите ее путем клонирования этого репозитория и запуска docker build -t javamfcc:latest . && docker run --name javamfcc --rm -v $PWD/output:/output javamfcc:latest
)
Основная суть этой программы - запустить аудиофайл через список каналов исполняемых файлов, предоставленных проектом SPTK , и проанализировать окончательный результат, прочитав 4 байта как число с плавающей запятой и добавив тезначения в один вектор.
Я более или менее имею хорошее представление о том, как получить каналы, но у меня возникают проблемы с выяснением того, как я могу пройти через последний * io.Reader и читать каждые 4 байта какfloat (как это сделано в Java.io.DataInputStream.readFloat()
) выполняется с помощью следующего кода:
package main
import "fmt"
func main() {
fileName := "/output/audio.wav"
frameLength := 400
frameLengthOutput := 512
framePeriod := 80
mgcOrder := 24
mfcc := exec.Command("mfcc.sh", "/output/"+fileheader.Filename, strconv.Itoa(frameLength), strconv.Itoa(frameLengthOutput), strconv.Itoa(framePeriod), strconv.Itoa(mgcOrder))
mfccout, mfccerr := mfcc.Output()
if mfccerr != nil {
log.Println("Error executing mfcc.sh")
panic(mfccerr)
}
b := bytes.NewReader(mfcc)
}
mfcc.sh
#!/bin/bash
filename=$1
frameLength=$2
frameLengthOutput=$3
framePeriod=$4
mgcOrder=$5
echo "filename: "$filename
echo "frameLength: "$frameLength
echo "frameLengthOutput: "$frameLengthOutput
echo "framePeriod: "$framePeriod
echo "mgcOrder: "$mgcOrder
x2x +sf $filename | frame -l $frameLength -p $framePeriod | window -l $frameLength -L $frameLengthOutput -w 1 -n 1 | mcep -a 0.42 -m $mgcOrder -l $frameLengthOutput | swab +f