2017-10-17 274 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