How to add volume gain to MediaPlayer? - android

I made an Android app to record and play wildlife sounds. It also shows a waveform of the volume of the recording as it records, and when you load a song it also shows you the waveform. I did this reading the bytes[] of the WAVE file, translating to shorts[], and showing the graph. Works as expected.
The problem with wildlife sounds is that they are usually very quiet. Of course, the device volume at play time is at its max, but even at max the volume is usually still too low. So I implemented a gain control at recording time: it just multiplies the shorts[] from AudioRecord (taking care of clipping) while printing the waveform, and then saves them to the WAVE file. Again, it works as expected.
But now I am thinking that I am doing everything wrong: why to apply gain before saving? This may introduce clipping ruining the capture. Much better is to implement gain at play time.
But I do not know how to do this. I reproduce the sound with MediaPlayer, and although it has a setVolume(float,float) control, this does not actually increase the volume.
How can I send a stream with gain to MediaPlayer?
If this cannot be done, how can I add volume gain at play time? Maybe AudioTrack? Never used it...

Related

AudioRecord while also playing audio - accessing output playback data

I'm messing around in my app with a custom model for speech commands - I have it working fine recording and processing input audio from an AudioRecord, and I give feedback to the user through text to speech.
One issue I have is that I'd like this to work even when audio is playing - either through my own text to speech or through something else playing in the background (music for instance). I realize this is going to be a non trivial problem, but if I could get access in some way to the audio output data (what the phone is playing) and match that up with my microphone input data, I think I can at least adjust my model for this + improve my results.
However, based on Android - Can I get the audio data for playback from the audio mixer? , it sounds like that is impossible.
Two questions:
1) Is there any way that I'm missing to get access to expected audio output/playback data through the android api, or any options the android api provides for dealing with this issue (the feedback loop between audio output and input)?
2) Outside of stopping all other playback or waiting for other playback to finish - is there any other approach to solve this problem? I would assume some calling apps have a way of dealing with this if the user is on speaker phone, I'm just missing how to do it myself
Thanks
Answers to 1 & 2: You want AcousticEchoCanceler.
A short lecture on why "deleting the speaker audio from the microphone input" input is a non-trivial task that takes substantial signal processing knowledge: It's more complicated than just time-shifting the speaker audio a little bit and subtracting it from the mic input. The fact is, the spectrum of the audio changes drastically even as it leaves the speaker (most tiny speakers have a very peaky response centered around 3-4KHz). The audio may bounce off multiple objects (walls, etc.) before it gets back to the mic (multipath interference). Different frequency components interfere at the microphone in different, impossible to predict ways, vastly changing the spectrum of the audio. And by the way -- if anything in the room moves, say, if you put your hand near the phone -- everything changes. That is why you don't want to try to write your own echo cancellation filter. Android has provided one for you, so you can write cool speakerphone apps and such.

Play audio in background without interrupting mediaplayer

How can I play background audio, in Android, without interrupting the MediaPlayer playback, by either using MediaPlayer (preferred) or OpenSL ES?
I know SoundPool is able to play sound effects without interrupting any MediaPlayer playback, but the size is limited to 1M per effect, which is way to less. Not requesting audio focus, via AudioManager doesn't seem to work either, audio doesn't play at all in this case.
And in the case of OpenSL ES, all audio generally stops when I start to play a longer asset file. It's similar to the behaviour of SoundPool described above.
Edit from the comments:
I don't want to interrupt other music players, it's the background
audio of a game, which shall play without interrupting the, for
example, music of a player. Games like Subway Surfer, Clash Royale and
such seem to have this achieved somehow, but I could not achieve it
via OpenSL ES, or MediaPlayer.
In order to play sound in background you can use SoundPool, AudioTracks and OpenSlES.
Soundpool: Use small files and make a sequence. In my last project i use 148 sound files (all small) in different scenarios and played using soundpool. Make a list and play one by one or in parallel. Also in games usually you have a small set of sound for particular scenario and it loops. Best is soundpool for that. You can also perform some effects like rate change. Also ogg files are way small, so use them.
AudioTrack: You can use RAW PCM data in audio track. If you want you can extract pcm data using MediaExtractor from almost all formats and use it. But it will be a little work for you in your case, but it is really good (supports huge data, even live streaming).
OpenSLES: Apparently android uses opensles in background for all its purpose. So using it will help you a lot. But it's not easy to get everything done on it. You need to learn more for lesser work.
I have been deeply working on OpenSlES for about 20 days and still i will say for small purpose use soundpool, medium to high level implementation use AudioTracks and for kickass implementation use OpenSLES.
PS: It will be bad effect on your user if you play game sound in background while they are playing their music or their call. Personal experience.

MediaPlayer -- how to separate a narration track?

I'm working on an android app that plays video (using video view). the video is meant to have both music (left and right) and narration, but I want to selectively be able to turn off the narration track in the MediaPlayer.
Is the way to do this correctly to encode by mp4 video file with 3 audio tracks (right left and narration) and then turn off the naration audio track with deselectTrack()?
Not clear to me from the documentation that MediaPlayer can handle more than 2 audio tracks.
If the audio tracks are limited to 2, would it make sense to run two media player simultaneously (synching them up with seekTo())when I want the narration track to play?
Thanks.
Sorry to burst your bubble, but...
1) You have a misunderstanding about what a "track" denotes. A track can have multiple channels (e.g., a stereo track has left and right channels). As I understand it, stereo is the extent of the Android AudioTrack implementation at present. I haven't yet checked if the OpenSL implementation is more extensive than the Java API.
2) Only 1 audio track can be selected at a time, so you wouldn't be able to have background and narration simultaneously in the way you were thinking.
3) Audio tracks can only be selected in the prepared state (i.e., not after playback has started). The documentation mentions this limitation is not ideal, so it will probably change in the future. If not for this problem, your goal could be accomplished with two audio tracks encoded in the stream, one with both background & narration, the other just background.
You will probably find it difficult to synchronize two MediaPlayers, but I haven't tried. Maybe this approach would be acceptable for your situation, although be forewarned the seekTo method isn't accurate. It depends on the encoding of the files.
Something I would try if I were you is to have two complete encoded videos, one with narration, the other without. Use two MediaPlayers and keep them both prepared. When you want to switch use seekTo to put the correct one at (or near) the desired location. That way you don't have to worry about synchronization. If the video is large, this method could use significantly more resources, though.

Can I set volume beyond AudioManager.getStreamMaxVolume?

I am making a birding app with playback to call birds. Many of the songs recorded are quite bad, some with very low volume. I know how to set max volume of music with
AudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
but this may not be enough for many songs; my Galaxy Note has quite bad speakers, and even with headphones max is low...
Would it be possible to add gain over this max for low volume songs, in order to be played at a decent volume?
This may sound like a silly question, but mplayer for Linux/Maemo has this option, called gain, that allowed me to play some songs higher than max in a Nokia N800.
Thanks!!
instead of using mediaplayer use audiotrack to play the filese. for the the work flow will be following
read from the files as byte or short array
to add a gain just multiply the sample by some fraction
(related question Android - how to add gain control when recording)
now write the samples to audiotrack
then play it.

Reduce the background noise when recording in android

I have developed a app which record the sound & play at same time approximate 100ms delay by using audio track & audio record class in android. But the played audio have lot of background noise. So there is any way in android to reduce the background noise while playing.
Please don't tell me used to Audacity Software for reduce the noise because i am not saving the recorded audio. I am just save it in a buffer & play this buffer by audio track.Cab be implemented a filter to reduce the background noise in android using NDK.
The simple thing to do is play the audio back using the voice setting. It will filter out most of the "hum" noise. AudioManager.STREAM_VOICE_CALL. You can use the NoiseSupression filter if available. NoiseSuppressor.create(device.getAudioSessionId());
You can use ClearRecord application. It is free. You can play audio with noise reduction on. While playing audio, the background noise gets eliminated and clear one can hear clear sound.

Categories

Resources