Seef
Seef

Reputation: 324

MediaPlayer only plays certain WAV files

So the app I'm writing is hitting an API and getting base64 encoded WAV voicemails. Decoding and creating the WAV file works but some will crash when calling setDataSource. I can pull the WAV files from my phones storage and play them on Mac so I know the file is being saved okay.

The Base64 I'm decoding looks different and I can tell whether MediaPlayer will play it or not based on looking at it. I have read that WAV file bitrates behave differently with MediaPlayer so I think that may be the issue? The Base64 that doesn't play is much shorter than the Base64 that does even with the same audio duration.

    try {
        val fileInputStream = FileInputStream(voicemailFile)

        if (audioManager == null) {
            audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager?
        }

        audioManager?.let { audioManager ->
            audioManager.isSpeakerphoneOn = isSpeakerPhoneOn
            audioManager.mode = AudioManager.MODE_IN_CALL
        }

        mediaPlayer.setAudioAttributes(AudioAttributes
                .Builder()
                .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
                .build())

        mediaPlayer.setDataSource(fileInputStream.fd)
        mediaPlayer.setOnCompletionListener {
            finishPlayingVoicemail()
        }

        mediaPlayer.prepare()

        currentProgress?.let { currentProgress ->
            mediaPlayer.seekTo(currentProgress)
        }

        mediaPlayer.start()

        shouldResumePlaying = true

        fileInputStream.close()
    } catch (e: Exception) {
        e.printStackTrace()
    }

Crash -

E/GenericSource: initFromDataSource, cannot create extractor!
E/GenericSource: Failed to init from data source!
E/MediaPlayerNative: error (1, -2147483648)
W/System.err: java.io.IOException: Prepare failed.: status=0x1
W/System.err: at android.media.MediaPlayer.prepare(MediaPlayer.java:1274)

Examples of the Base64 that plays vs not plays (Just shorter snippets of them)

UklGRi96AABXQVZFZm10IBQAAAARAAEAQB8AANcPAAAAAQQAAgD5AWZhY3QEAAAAoPAAAGRhdGH7eQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwACqAA1CwyADYA2wQEgDeupwoNzQiub6tCiE1JYHJvLsYRDQSqMysiTBEM9QAGQCozLsKMDYkgcnLqxhTQxKozLuJQTQjktrbmikyNSKozLuLQDQkgrq9

^^ Does not play

UklGRqTvAwBXQVZFZm10IBAAAAABAAEAgD4AAAB9AAACABAAZGF0YYDvAwD//wAAAAD/////AAD/////AAAAAP///f/+/wEAAgD///z/+v/6//3//v/+//3//v/9//3//v8BAAEA/v/6//j//P8CAAAA9//1//v//P/4//f//P/+//z/9//0//j//v8AAPv/+f/7//z/+v/5//v//P/8//v/+f/6/////P/1//b//f/9//f/9f/6//3/+//4//b/+v8CAAAA9//0//r//f/8//v//f/+//3/+v/5//v///8AAP7//f8AAP///P/7//3//v/8//v//P///wIAAAD7//

^^ Does play

Upvotes: 1

Views: 1169

Answers (3)

Seef
Seef

Reputation: 324

msbit's answer led me to looking at ways to play IMA ADPCM wav files on Android. I decided to try swapping out MediaPlayer for ExoPlayer. ExoPlayer seems to be playing the files MediaPlayer couldn't.

Upvotes: 1

msbit
msbit

Reputation: 4320

First sample is:

RIFF (little-endian) data, WAVE audio, IMA ADPCM, mono 8000 Hz

second is:

RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 16000 Hz

As per Supported media formats, under the details for PCM/WAVE:

8- and 16-bit linear PCM (rates up to limit of hardware). Sampling rates for raw PCM recordings at 8000, 16000 and 44100 Hz.

In determining whether those files are linear PCM or not, from my reading of Pulse-code modulation, the second is linear PCM, whereas the former is adaptive differential PCM (ADPCM) so it may not be supported, hence what you are seeing.

Upvotes: 2

Sumanta Mandal
Sumanta Mandal

Reputation: 81

Let's try to play one .wav file. Let's say the name of your .wav file is test.wav and it is in res.raw folder in your android project. Please try the following lines of code and let me know.

Media mPlayer;
private Context mContext;
mPlayer = MediaPlayer.create(mContext, R.raw.test);
mPlayer.start();

Upvotes: 0

Related Questions