2017-10-17 106 views
-1

我正试图从存储在SD卡上的wav文件中计算MFCC系数。我正在使用库:https://github.com/dspavankumar/compute-mfcc替代ifstream(C++),同时尝试读取Android中的.wav文件

输入是使用ifstream的wav文件路径。我需要能够根据时间段访问从单个wav文件拆分的不同pcm文件,并计算每个段的MFCC。我无法找到一种方法将这些数据(原始pcm数据)从java类中下载到下面的方法中显示的缓冲区中。 (使用JNI)

int process (std::ifstream &wavFp, std::ofstream &mfcFp) { 
    // Read the wav header  
    wavHeader hdr; 
    int headerSize = sizeof(wavHeader); 

    wavFp.read((char *) &hdr, headerSize); 

    // Check audio format 
    if (hdr.AudioFormat != 1 || hdr.bitsPerSample != 16) { 
     std::cerr << "Unsupported audio format, use 16 bit PCM Wave" << 
    std::endl; 
     return 1; 
    } 
    // Check sampling rate 
    if (hdr.SamplesPerSec != fs) { 
     std::cerr << "Sampling rate mismatch: Found " << hdr.SamplesPerSec << " instead of " << fs <<std::endl; 
     return 1; 
    } 

    // Initialise buffer 
    uint16_t bufferLength = winLengthSamples-frameShiftSamples; 
    int16_t* buffer = new int16_t[bufferLength]; 
    int bufferBPS = (sizeof buffer[0]); 

    // Read and set the initial samples   
    wavFp.read((char *) buffer, bufferLength*bufferBPS); 
    for (int i=0; i<bufferLength; i++) 
     prevsamples[i] = buffer[i];   
    delete [] buffer; 

    // Recalculate buffer size 
    bufferLength = frameShiftSamples; 
    buffer = new int16_t[bufferLength]; 

    // Read data and process each frame 
    wavFp.read((char *) buffer, bufferLength*bufferBPS); 
    while (wavFp.gcount() == bufferLength*bufferBPS && !wavFp.eof()) { 
     mfcFp << processFrame(buffer, bufferLength); 
     wavFp.read((char *) buffer, bufferLength*bufferBPS); 
    } 
    delete [] buffer; 
    buffer = nullptr; 
    return 0; 
} 

`

好像我不能直接从C++库访问SD卡上的wav文件。所以我试图通过一个jbytearray并将其转换为char *使用:

extern "C" 
JNIEXPORT void JNICALL 
Java_com_example_nikhar_mst04v10_RecordActivity_doMFCC(JNIEnv *env, jobject 
instance, 
                jbyteArray wavBytes_) { 
int len = env ->GetArrayLength(wavBytes_); 
char* buf = new char[len]; 
env->GetByteArrayRegion(wavBytes_,0,len, reinterpret_cast<jbyte *>(buf)); 

// TODO 

/* env->ReleaseStringUTFChars(wavPath_, wavPath); 
env->ReleaseStringUTFChars(mfccPath_, mfccPath);*/ 
// Assign variables 
int numCepstra = 12; 
int numFilters = 40; 
int samplingRate = 16000; 
int winLength = 25; 
int frameShift = 10; 
int lowFreq = 50; 
int highFreq = samplingRate/2; 

// Initialise MFCC class instance 
MFCC mfccComputer (samplingRate, numCepstra, winLength, frameShift, 
numFilters, lowFreq, highFreq); 
mfccComputer.process(buf); 
} 

但这已失败。任何建议,以我如何可以实现这一目标?

+0

注意:我已经修改了mfccComputer的参数为(const * char wavBytes) – user2654207

+0

*好像我无法访问sd卡上的wav文件*注意:我们在2017年推出了Android 6,并于2015年推出了Android 6,所以您有2年时间才能了解发生了什么变化。这显然是权限问题,而不是ifstreams – Selvin

+0

这是我第一次使用android。它只是为了一个特定的目的,所以即时学习即时通讯 – user2654207

回答

0

到这里看看:

http://jnicookbook.owsiak.org/recipe-No-012/

让熟悉Java和C

至于jbyte之间传递阵列 - 这种类型是依赖于机器。通常情况下,它将是“签名字符”。我建议将您的数据传递给C,然后将数组强制转换为char *。它应该工作。

但是!确保在目标系统的情况下再次检查jbyte是如何声明的。你可以在这里找到它:$ YOUR_PLATFORM_NAME/jni_md.h

+0

_“至于jbyte - 这种类型是依赖于机器的。”_不应该。 Oracle将其指定为_signed 8 bits_:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html – Michael

+0

从jni.h -/* jni_md.h包含machine- jbyte,jint和jlong​​的依赖typedef * / – mko