How to remove background Noise in Audio Track? - android

I am developing VOIP kind of application. Sending the voice is perfect but when i receive the same voice from the webserver, i am playing back that using AudioTrack API.
I am calling at.play() and at.write in a Thread so that i should get all the voice which is recorded and sent from the other device.
But, now the problem here i m facing is, if there is no voice than its still playing like some bullet sound, i mean there is a continuos background sound when i try to play .
I m using this following function in a Thread:
if (at != null) {
if (at.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
at.play();
} else {
if (playing == true) {
System.out.println("BEFORE WRITE");
at.write(playShortData, 0,
playShortData.length);
System.out.println("AFTER WRITE");
at.flush();
playing = false;
}
}
}
How can i remove the background noise if there no voice is send from other device.

I think its playing Junk value when none of them is speaking on other sides, its just sending junk values ..

Related

How do I determine when Google maps is Speaking in Android

I'm trying to modify my application to pause audio playback when Google maps is announcing a turn by turn direction.
I've added the following code (shown below) to my application. The audio focus listener is called when applications like Pandora Radio or Spotify request audio focus in order to play music but it's not called when Google maps announces a turn by turn direction. Is there another intent I should be listening for in order to detect this behavior?
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(
new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(new AudioManager.OnAudioFocusChangeListener() {
#Override
public void onAudioFocusChange(int focusChange) {
// This is called by Pandora Radio and Spotify
Log.d("Focus change:", " Event is: " + focusChange);
}
}).build());
You will need AudioManager's AudioPlaybackCallback updates.
This only works on Android O and above.
To do this you have to access the audio manager -
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
And then add the listener like this -
Handler handler = new Handler();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
audioManager.registerAudioPlaybackCallback(new AudioManager.AudioPlaybackCallback() {
#Override
public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
super.onPlaybackConfigChanged(configs);
// This will be called when navigation audio state on google maps changes
Log.d("audio active", String.valueOf(audioManager.isMusicActive()));
}
}, handler);
}
The List<AudioPlaybackConfiguration> configs returned in the callback has a AudioAttribute object which contains a string describing the audio playing. For Google maps navigation the String constant value is USAGE_ASSISTANCE_NAVIGATION_GUIDANCE which you can compare to be sure that it is Google Maps announcing the navigation direction.
Programatically you can get it like this
// Loop through the configs to see the media's usage data
configs.get(0).getAudioAttributes().getUsage();
For Android O, the missing navigation duck focus change notifications were only received after I explicitly set my player's AudioAttributes and content type to speech (as I am playing podcast mp3 files, didn't test with other content types):
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
AudioAttributes.Builder aab = new AudioAttributes.Builder();
aab.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH);
aab.setUsage(USAGE_MEDIA);
player.setAudioAttributes(aab.build());
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mPlayOnAudioFocus && !isPlaying()) {
play();
} else if (isPlaying()) {
setVolume(MEDIA_VOLUME_DEFAULT);
}
mPlayOnAudioFocus = false;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
setVolume(MEDIA_VOLUME_DUCK);
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (isPlaying()) {
mPlayOnAudioFocus = true;
pause();
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
mAudioManager.abandonAudioFocus(this);
mPlayOnAudioFocus = false;
stop();
break;
}
}
}
The following code snippet contains an implementation of this interface for an app that plays audio. And it handles ducking for transient audio focus loss. It also handles audio focus change due to the user pausing playback, vs another app (like the Google Assistant) causing transient audio focus loss
does your app temporarily need audio focus (with the option to duck), since it needs to play an audio notification, or a turn by turn spoken direction, or it needs to record audio from the user for a short period of time? This is
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.
Ducking vs pausing on transient audio focus loss
You can choose to pause playback or temporarily reduce the volume of your audio playback in the OnAudioFocusChangeListener, depending on what UX your app needs to deliver. Android O supports auto ducking, where the system will reduce the volume of your app automatically without you having to write any extra code. In your OnAudioFocusChangeListener, just ignore the AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK event.
In Android N and earlier, you have to implement ducking yourself (as shown in the code snippet above).
for Detail visit :https://medium.com/androiddevelopers/audio-focus-3-cdc09da9c122
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
added in API level 8
public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Used to indicate a temporary request of audio focus, anticipated to last a short amount of time, and where it is acceptable for other audio applications to keep playing after having lowered their output level (also referred to as "ducking"). Examples of temporary changes are the playback of driving directions where playback of music in the background is acceptable.
You should use "AudioManager.AUDIOFOCUS_GAIN_TRANSIENT", according to the documentation:
AUDIOFOCUS_GAIN_TRANSIENT
Used to indicate a temporary gain or request of audio focus, anticipated to last a short amount of time. Examples of temporary changes are the playback of driving directions, or an event notification.

Android interrupt media player with ringtone manager

I have used ringtonemanager previously in android studio and it seemed to lower the volume of any music that was playing in a different app to play the alert i was trying to play, then once my alert had completed the background music would then come back to normal volume (as the default alarm/notification would do) But now a year or so later im trying to implement this again but my alert cannot be heard over the music playing in Google Play Music.
Is this a change that now requires additional parameters to function as it used to?
Im using:
Uri notification =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
myRM = RingtoneManager.getRingtone(this.getContext(), notification);
myRM.play();
Many Thanks
Handling Changes in Audio Output seems what fits your need.
In short, you need to request audio focus before starting playing.
...
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.requestAudioFocus(null, mStreamType, AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
mRingtone.play();
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Used to indicate a temporary request of audio focus, anticipated to
last a short amount of time, and where it is acceptable for other
audio applications to keep playing after having lowered their output
level (also referred to as "ducking").
Remember to release audio focus when finishing..
if (mRingtone != null && mRingtone.isPlaying()) {
mRingtone.stop();
}
mRingtone = null;
if (mAudioManager != null) {
mAudioManager.abandonAudioFocus(null);
}

Android - How to change sound output while playing sound?

I have an app that plays a list of soundtracks. It works great, however changing the sound output to internal speakers or vice versa, has no effect. It stops the current one, and then plays the next on the new mode.
I've read in android documentation of MediaPlayer that I can't change the sound output using setAudioStreamType() method. So this is the problem, but can't find a solution!
Here's the code for the toggle when the track is playing:
if (this.audioManager.isSpeakerphoneOn() || this.getCurrent() == 1) {
this.audioManager.setMode(AudioManager.MODE_IN_CALL);
this.audioManager.setSpeakerphoneOn(false);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
} else if (this.getCurrent() != 0) {
this.audioManager.setMode(AudioManager.MODE_NORMAL);
this.audioManager.setSpeakerphoneOn(true);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
Thanks in advance!

How to stop Media Player when you have more that one sound being played?

My app is a music pad, which allows the user to create their own music by pressing buttons that will play a specific sound, and if the users presses more than one button there will be more sounds being played at the same time.
I want to stop all sounds when the onPause() gets called. But I realized that if I have more than one sound being played by the same Media player Object it only stops the last sound that was attributed to it, and the others stay on playing.
It would be very unpleasant for the user to receive a call and having my app sounds still on playing :p
Any help would be appreciated.
#Override
protected void onPause() {
super.onPause();
try {
while (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
}catch (IllegalStateException e){
//Do nothing
}
}
EDIT
I tried to implement SoundPool API but since my app is very dynamic (users can upload their samples and also record using mic). And I have everything already implemented and working well, it would be a mess to change it now to another API rather than MediaPlayer. Is there any way to stop all sounds that were attributed to the MediaPlayer object and that are currently being played? maybe accessing to some other classes and using other methods to stop all the sounds?
I would suggest you look into the SoundPool API. It looks like that would be well suited for your task. It allows you to preload sound files and play them independently.
The SoundPool class manages and plays audio resources for applications.
A SoundPool is a collection of samples that can be loaded into memory from a resource inside the APK or from a file in the file system. The SoundPool library uses the MediaPlayer service to decode the audio into a raw 16-bit PCM mono or stereo stream. This allows applications to ship with compressed streams without having to suffer the CPU load and latency of decompressing during playback.
After a few research and trial and error there is no way that I discovered to stop all sounds being played by the same MediaPlayer Object, you can only control the last sound being attributed to it, all the other will continue until they end or the app gets destroyed.
Ok so what I did was:
I created an object for each key sound of my music pad, and Override the onPause() with the following code:
#Override
protected void onPause() {
super.onPause();
if (mAudioManager.isMusicActive()){
for (MediaPlayer aMMediaPlayer : mMediaPlayer) {
if (aMMediaPlayer != null) {
try {
if (aMMediaPlayer.isPlaying()) {
aMMediaPlayer.stop();
aMMediaPlayer.release();
}
} catch (IllegalStateException e) {
//Do nothing
}
}
}
}
}

Adding a delay to android sound output

So I wrote this piece for an Android App. The idea is simple:
Detect whether sound is playing and if yes open the BluethoothSCO Channel so the audio gets played there.
I want to use it to "route" the navigation direction infos to my car speaker. It works nearly like expected.
There is a 'huge' delay of around 1 second between the audio recognition and the bluethoothsco connection being ready. This results in a loss of nearly half the navigation information.
My Idea was to add a delay or pause the playback for a second.
NOW: Sound is detected -> BluethootSCO opening (sound keeps playing here) -> sound over car speaker
IDEA: Sound is detected -> pause/delay for 1 sec ->BluethootSCO opening -> resume playback -> sound over car speaker
I thought about recording it and playing it afterwards but that would be to late for some informations like "turn left NOW".
A short delay would be ok, but I have no idea on to implement this :(
Since the app is only for myself using root would be ok.
Maybe there is an possibility direct at the AudioFlinger?
public void checkSound() {
AudioManager localAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
Visualizer localVisualizer = new Visualizer(0);
localVisualizer.setEnabled(true);
Visualizer.MeasurementPeakRms localPeak = new Visualizer.MeasurementPeakRms();
boolean wasPlayingBefore=false;
while (keeprunning) //Loop to detect changes on the Media Audio Stream
{
localVisualizer.getMeasurementPeakRms(localPeak);
if(localPeak.mPeak > -8500 && !wasPlayingBefore)
{
//There is some audio output
wasPlayingBefore=true;
localAudioManager.setBluetoothScoOn(true);
localAudioManager.startBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
android.os.SystemClock.sleep(5000); //Route to BT Headset will exist min. 5 seconds ...
}
if(localPeak.mPeak <= -8500 && wasPlayingBefore)
{
//output (temporary) gone
android.os.SystemClock.sleep(2000);//... plus this 2 seconds
//check again
localVisualizer.getMeasurementPeakRms(localPeak);
}
if(localPeak.mPeak <= -8500 && wasPlayingBefore)
{
//Audio didn't get back in last 2 seconds...
wasPlayingBefore=false;
localAudioManager.setBluetoothScoOn(false);
localAudioManager.stopBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_NORMAL);
}
android.os.SystemClock.sleep(100); //Slow down the loop
Log.d("Peak", String.valueOf(localPeak.mPeak));//Debug info - Audio peak -9600 = Silent, 0 = MAX Output
}
localVisualizer.release();
}

Categories

Resources