2017-10-17 11 views
-1

J'essaie de calculer des coefficients MFCC à partir de fichiers wav stockés sur la carte SD. J'utilise la bibliothèque: https://github.com/dspavankumar/compute-mfccAlternative pour ifstream (C++) en essayant de lire un fichier .wav dans android

L'entrée est le chemin du fichier wav utilisant ifstream. Je dois pouvoir accéder à différents fichiers pcm séparés d'un seul fichier wav en fonction des segments de temps et calculer le MFCC pour chaque segment. J'ai du mal à trouver un moyen d'obtenir ces données (données pcm brutes) dans le tampon montré dans la méthode ci-dessous de la classe java. (Avec 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; 
} 

`

Il semble que je ne peux pas accéder au fichier wav sur la carte SD directement à partir de la bibliothèque C++. Donc, je l'ai essayé dans un passage jbytearray et la convertir en char * en utilisant:

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); 
} 

mais cela a échoué. Des suggestions sur la façon dont je peux accomplir cela?

+0

Note: j'ai modifié les paramètres pour que mfccComputer soit (const * char wavBytes) – user2654207

+0

* Il semble que je ne peux pas accéder au fichier wav sur la carte SD * Note: nous avons 2017 et l'Android 6 a été introduit en 2015, donc vous avez eu 2 ans pour savoir ce qui a été changé. C'est évidemment problème avec les permissions pas avec ifstreams – Selvin

+0

C'est la première fois que j'utilise Android. C'est juste pour un but précis im im apprendre – user2654207

Répondre

0

Jetez un oeil ici:

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

pour se familiariser avec les tableaux de passage entre Java et C.

En ce qui concerne jbyte - ce type dépend de la machine. Typiquement, ce sera "signé char". Je suggère de transmettre vos données à C, puis de lancer le tableau en char *. Ça devrait marcher.

Mais! Assurez-vous de vérifier comment jbyte est déclaré dans le cas de votre système cible. Vous pouvez le trouver ici: $ YOUR_PLATFORM_NAME/jni_md.h

+0

_ "Comme pour jbyte - ce type dépend de la machine." _ Il ne devrait pas être. Oracle le spécifie comme _signed 8 bits_: http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html – Michael

+0

De jni.h -/* jni_md.h contient la machine- typedefs dépendants pour jbyte, jint et jlong ​​* / – mko