Closed gerosyab closed 6 years ago
WaveReader::Error not a valid WAVE file is fired when the header of the file does not contain the correct headers information (although it has validated partial headers, e.g. the RIFF declaration, but not the WAVE declaration).
Are you using JavaUtilities.createSampleFromFile() or JavaUtilities.createSampleFromAsset() (as in the example activity?). These return boolean values to indicate file read success. If they return false, you will know setSample() will crash as an empty buffer is passed.
The questions is, how literal is the copy of your app in relation to the example application ? e.g. are you literally using the same .wav files, are they in the ./assets folder or elsewhere in the packaged .APK ? Does the example Activity build fine for you ?
I am using JavaUtilities.createSampleFromAsset() and it returns false.
I copied hihat.wav and clap.wav from example activity source (git cloned) and example activity building was fine for me too.
I check CRC checksum value and also check hex code value of the wav files.
They are same files as the example activity's, and they had correct header value (RIFF).
Here's my activity's loadWAVAsset() method.
private void loadWAVAsset( String assetName, String sampleName )
{
final Context ctx = getApplicationContext();
AssetManager assetMgr = getAssets();
try {
String[] list = assetMgr.list("/");
int length = list.length;
for(int i= 0; i < length; i++) {
Log.d("guitaroid", "loadWAVAsset() file #" + i + " : " + list[i]);
}
InputStream is = assetMgr.open("hat.wav");
InputStream is2 = assetMgr.open("clap.wav");
Log.d("guitaroid", "loadWAVAsset() hihat.wav available() " + is.available());
Log.d("guitaroid", "loadWAVAsset() clap.wav available() " + is2.available());
is.close();
is2.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.d("guitaroid", "loadWAVAsset("+ assetName + ", " + sampleName+ ")");
Log.d("guitaroid", "loadWAVAsset() - ctx.getAssets() : "+ ctx.getAssets() + ", ctx.getCacheDir() : " + ctx.getCacheDir() + ", ctx.getCacheDir().getAbsolutePath() : " + ctx.getCacheDir().getAbsolutePath() + ")");
boolean result = JavaUtilities.createSampleFromAsset(
sampleName, ctx.getAssets(), ctx.getCacheDir().getAbsolutePath(), assetName
);
Log.d("guitaroid", "loadWAVAsset() - JavaUtilities.createSampleFromAsset() : "+ result);
}
And here is my logcat message.
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #0 : AndroidManifest.xml
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #1 : META-INF
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #2 : SEC-INF
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #3 : assets
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #4 : classes.dex
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #5 : classes2.dex
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #6 : classes3.dex
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #7 : classes4.dex
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #8 : classes5.dex
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #9 : classes6.dex
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #10 : lib
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #11 : res
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #12 : resources.arsc
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() hihat.wav available() 45100
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() clap.wav available() 92590
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset(hat.wav, hat)
12-22 16:59:42.769 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() - ctx.getAssets() : android.content.res.AssetManager@61a9182, ctx.getCacheDir() : /data/user/0/net.gerosyab.guitaroid/cache, ctx.getCacheDir().getAbsolutePath() : /data/user/0/net.gerosyab.guitaroid/cache)
12-22 16:59:42.770 22828-23801/net.gerosyab.guitaroid I/AudioTrack: Skip ramp
12-22 16:59:42.773 22828-22828/net.gerosyab.guitaroid V/MWENGINE: WaveReader::Error not a valid WAVE file
12-22 16:59:42.773 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() - JavaUtilities.createSampleFromAsset() : false
12-22 16:59:42.775 22828-23801/net.gerosyab.guitaroid I/AudioTrack: Skip ramp
12-22 16:59:42.780 22828-23801/net.gerosyab.guitaroid I/AudioTrack: Skip ramp
12-22 16:59:42.785 22828-23801/net.gerosyab.guitaroid I/AudioTrack: Skip ramp
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #0 : AndroidManifest.xml
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #1 : META-INF
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #2 : SEC-INF
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #3 : assets
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #4 : classes.dex
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #5 : classes2.dex
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #6 : classes3.dex
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #7 : classes4.dex
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #8 : classes5.dex
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #9 : classes6.dex
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #10 : lib
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #11 : res
12-22 16:59:42.786 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() file #12 : resources.arsc
12-22 16:59:42.787 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() hihat.wav available() 45100
12-22 16:59:42.787 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() clap.wav available() 92590
12-22 16:59:42.787 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset(clap.wav, clap)
12-22 16:59:42.787 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() - ctx.getAssets() : android.content.res.AssetManager@61a9182, ctx.getCacheDir() : /data/user/0/net.gerosyab.guitaroid/cache, ctx.getCacheDir().getAbsolutePath() : /data/user/0/net.gerosyab.guitaroid/cache)
12-22 16:59:42.788 22828-22828/net.gerosyab.guitaroid V/MWENGINE: WaveReader::Error not a valid WAVE file
12-22 16:59:42.788 22828-22828/net.gerosyab.guitaroid D/guitaroid: loadWAVAsset() - JavaUtilities.createSampleFromAsset() : false
12-22 16:59:42.790 22828-23801/net.gerosyab.guitaroid I/AudioTrack: Skip ramp
12-22 16:59:42.791 22828-22828/net.gerosyab.guitaroid A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x4 in tid 22828 (osyab.guitaroid)
I think I can get the wav files by java method (AssetManager.open() ) but can't by native method.
Can you please tell me where I should look into more?
Thanks.
12-22 18:37:22.617 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset filename : clap.wav
12-22 18:37:22.617 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset tempFolder : /data/user/0/net.gerosyab.guitaroid/cache
12-22 18:37:22.618 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset length : 92590
12-22 18:37:22.618 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset remaining : 92590
12-22 18:37:22.618 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset Mb : 1024000
12-22 18:37:22.618 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset readUsingTempFile : true
12-22 18:37:22.618 10908-10908/net.gerosyab.guitaroid V/MWENGINE: WaveReader::Error not a valid WAVE file
12-22 18:37:22.618 10908-10908/net.gerosyab.guitaroid D/guitaroid: JavaUtilities::createSampleFromAsset sampleBuffer == NULL
I think it's about reading wav file (making temp file and read from it).
I debugged more and found something.
AudioBuffer* WaveReader::fileToBuffer( std::string inputFile )
{
FILE* fp;
AudioBuffer* out = 0;
fp = fopen( inputFile.c_str(), "rb" );
if ( fp )
{
char id[ 5 ];
unsigned long size;
short* sound_buffer;
short tag, amountOfChannels, blockAlign, bps;
unsigned int format, sampleRate, bytesPerSec, dataSize, i;
// first we'll check the necessary headers identifying the WAV file
fread( id, sizeof( char ), 4, fp );
id[ 4 ] = '\0';
__android_log_print(ANDROID_LOG_DEBUG, "guitaroid", "WaveReader::fileToBuffer id 1 : %s", id);
if ( !strcmp( id, "RIFF" ))
{
fread( &size, sizeof( unsigned long ), 1, fp );
fread( id, sizeof( unsigned char ), 4, fp );
id[ 4 ] = '\0';
__android_log_print(ANDROID_LOG_DEBUG, "guitaroid", "WaveReader::fileToBuffer id 2 : %s", id);
if ( !strcmp( id, "WAVE" ))
{
...
}
else
Debug::log( "WaveReader::Error not a valid WAVE file" );
}
else
Debug::log( "WaveReader::Error not a valid WAVE file (no RIFF header)" );
fclose( fp );
}
else {
Debug::log( "WaveReader::Error could not open file '%s'", inputFile.c_str() );
}
return out;
}
12-23 17:05:07.471 17173-17173/net.gerosyab.guitaroid D/guitaroid: WaveReader::fileToBuffer inputFile : /data/user/0/net.gerosyab.guitaroid/cache/tmp
12-23 17:05:07.471 17173-17173/net.gerosyab.guitaroid D/guitaroid: WaveReader::fileToBuffer id 1 : RIFF
12-23 17:05:07.471 17173-17173/net.gerosyab.guitaroid D/guitaroid: WaveReader::fileToBuffer id 2 : fmt
12-23 17:05:07.471 17173-17173/net.gerosyab.guitaroid V/MWENGINE: WaveReader::Error not a valid WAVE file
First header value is "RIFF" and second header value is "fmt ", not "WAVE".
Now same error occurs in the Example activity too, not like before.
I've re-installed and upgraded ADT, SDK, NDK and other tools recently, so I don't know when this error happens exactly...
That is interesting! To be honest I would not know why it doesn't occur for the current sample files that are in the repository (NDK/SDK versions shouldn't really matter here).
One question: for what architecture are you building/testing ? (e.g. ARM, x64, etc.) It might be related to a hardware specific issue (perhaps the sizes of unsigned long not being as I expect them to be here).
Built with multiple architecure (arm64-v8a, armeabi, armeabi-v7a, x86, x86_74) I think. I use galaxy s7 and depending on the logcat message, the architecture of testing device is ARM64.
12-23 17:05:07.627 17417-17417/? A/DEBUG: #00 pc 00000000000451c0 /data/app/net.gerosyab.guitaroid-2/lib/arm64/libmwengine.so (_ZN11SampleEvent9setSampleEP11AudioBuffer+36)
12-23 17:05:01.114 3739-3855/? I/PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /data/app/vmdl712199686.tmp/base.apk pkg=net.gerosyab.guitaroid isa=arm64 vmSafeMode=false debuggable=true target-filter=interpret-only oatDir = /data/app/vmdl712199686.tmp/oat sharedLibraries=null
12-23 17:05:02.371 3739-3855/? D/PackageManager: Abis for package[net.gerosyab.guitaroid] are primary=arm64-v8a secondary=null
// fread( &size, sizeof( unsigned long ), 1, fp );
fread( &size, sizeof( unsigned int ), 1, fp );
// fread( &format, sizeof( unsigned long ), 1, fp );
fread( &format, sizeof( unsigned int ), 1, fp );
// fread( &sampleRate, sizeof( unsigned long ), 1, fp );
fread( &sampleRate, sizeof( unsigned int ), 1, fp );
// fread( &bytesPerSec, sizeof( unsigned long ), 1, fp );
fread( &bytesPerSec, sizeof( unsigned int ), 1, fp );
// fread( &dataSize, sizeof( unsigned long ), 1, fp );
fread( &dataSize, sizeof( unsigned int ), 1, fp );
12-29 10:59:54.975 1436-1436/net.gerosyab.guitaroid D/guitaroid: sizeof(unsigned int) : 4
12-29 10:59:54.975 1436-1436/net.gerosyab.guitaroid D/guitaroid: sizeof(unsigned long) : 8
12-29 10:59:54.975 1436-1436/net.gerosyab.guitaroid D/guitaroid: WaveReader::fileToBuffer id 1 : RIFF
12-29 10:59:54.975 1436-1436/net.gerosyab.guitaroid D/guitaroid: WaveReader::fileToBuffer id 2 : WAVE
I changed all of "sizeof(unsigned long)" to "sizeof(unsigned int)" in the wavereader.cpp and problem solved.
I think the sizeof(unsigned long) is 8 bytes in 64bit architecture, so header parsing of wav file was not right.
Hi @gerosyab I expected something horrible like this, it's strange that for ARM64 the unsigned long data type is defined to be 32-bits, but for Linux 64-bit environments, unsigned long is 64-bits. Unclear how this affects certain devices in the Android ecosphere.
However, unsigned int should be the correct value as it should be interpreted to be 32-bit in length across all supported architectures. I have updated the code in the master branch accordingly.
Referenced pull request: https://github.com/igorski/MWEngine/pull/32
Hello, I'm trying to import mwengine to my project.
I copied c++ and java source as same directory structure and swig build script and build was successful.
When I try to start the activity from my app, it crashes.
The activity and asserts resources are almost same as sample. (MWEngineActivity.java, hihat.wav, clap.wav)
The logcat said
I added more information to logcat. And I think I found the occuring point.
Wav files are same as in the sample's asserts folder but don't know why the WaveReader says not a valid WAVE file.
Anyway the location is "Java_nl_igorski_lib_audio_mwengine_MWEngineCoreJNI_SampleEvent_1setSample()" in "java_interface_wrapper.cpp"
When setSample() method in SampleEvent.cpp is called, it crashed.
Could you give me any advice?