Route voice buffer from mic to speaker in Android - android

I need to increase voice, recorder from microphone on Android device.
I try to read buffer from AudioRecord and then write it to AudioTrack... It works, but with delay, because min buffer size, returned bu method AudioRecord.getMinBufferSize with frequency like 44100 is 4480 bytes.
Any ideas?
Thanks.

I have this code
AudioRecord and AudioTrack latency
But it happens to that there is a 20ms delay, and I need to solve it,
The code above seems that plays something but there is no mic input, does it work?
Thanks!

I noticed there is no threading code. I would recommend trying to thread the recording and playback aspects and see if that better avoids the latency. Fill the buffer in from the mic one thread, and read it out to the speaker in the other. Avoid buffer overflows and underruns by handling those situations with some action (e.g. clearing the buffer for overflows). In theory, one should keep up with the other.

package org.example.audio;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class AudioDemo extends Activity implements OnClickListener {
private static final String TAG = "AudioDemo";
private static final String isPlaying = "Media is Playing";
private static final String notPlaying = "Media has stopped Playing";
MediaPlayer player;
Button playerButton;
public void onClick(View v) {
Log.d(TAG, "onClick: " + v);
if (v.getId() == R.id.play) {
playPause();
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//player = MediaPlayer.create(this, R.raw.robotrock);
player.setLooping(false); // Set looping
// Get the button from the view
playerButton = (Button) this.findViewById(R.id.play);
playerButton.setText(R.string.stop_label);
playerButton.setOnClickListener(this);
// Begin playing selected media
demoPlay();
// Release media instance to system
player.release();
}
#Override
public void onPause() {
super.onPause();
player.pause();
}
// Initiate media player pause
private void demoPause(){
player.pause();
playerButton.setText(R.string.play_label);
Toast.makeText(this, notPlaying, Toast.LENGTH_LONG).show();
Log.d(TAG, notPlaying);
}
// Initiate playing the media player
private void demoPlay(){
player.start();
playerButton.setText(R.string.stop_label);
Toast.makeText(this, isPlaying, Toast.LENGTH_LONG).show();
Log.d(TAG, isPlaying);
}
// Toggle between the play and pause
private void playPause() {
if(player.isPlaying()) {
demoPause();
} else {
demoPlay();
}
}
}

Related

Keep music playing while changing orientation

I'm making music player app for Android and i have problem with keeping music playing while i change orientation of phone.
package nori.beta.musicplayer;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import nori.beta.musicplayer.Class.BlurBuilder;
import nori.beta.musicplayer.Fragment.Playlist;
import nori.beta.musicplayer.Fragment.Utilities;
public class MainActivity extends Activity {
private ImageView bg; // blured backgroud of size of screen
private ImageView cover; // small image in center of activity that plays song
private BlurBuilder blured; // class to blur image for background
private SeekBar
progressBar; // Creating seekbar that show progress of song and allow us scroll and rewind song
private ImageButton
play_pause_stopButton; //on click do 1.play/2.paues/3.stop for all change icon
private MediaPlayer player; // Player that play music
private Handler mHandler = new Handler(); //Handler that help with refreshing progressBar
private Utilities utils; //Change seconds into min + sec
ArrayList<File> mySongs; // list of music file
ArrayList<Song> songsInfo; //list of music file with extract information about them
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// init all GUI staff
initGUI();
setButtons();
}
#Override
protected void onResume() {
super.onResume();
// init Database and rest of gui staff that need database
// Here have u data of all file and chosen song and can u make to play song
}
private void initGUI() {
// Image Part
bg = (ImageView) findViewById(R.id.main_background);
cover = (ImageView) findViewById(R.id.cover_image);
blured = new BlurBuilder();
//Buttons
play_pause_stopButton = (ImageButton) findViewById(R.id.play_pause_stop_button);
progressBar = (SeekBar) findViewById(R.id.progressBar);
player = new MediaPlayer();
utils = new Utilities();
mySongs = findSongs(Environment.getExternalStorageDirectory());
songsInfo = new ArrayList<Song>();
for (File f : mySongs) {
songsInfo.add(new Song(f));
}
//progressBar.setOnSeekBarChangeListener(this);
}
private ArrayList<File> findSongs(File root) {
ArrayList<File> al = new ArrayList<File>();
File[] files = root.listFiles();
/**
* findSongs Search for music file in memory
*
* for each file in memory
* 1.if is that file a folder , then take all file then give it in method findSongs
* and with requrency
* 2.Else if that file end with .mp3 or .wav ,then add to list
*/
for (File singleFile : files) {
if (singleFile.isDirectory() && !singleFile.isHidden()) {
al.addAll(findSongs(singleFile));
//Log.e("findsongs","Folder");
} else {
if (singleFile.getName().endsWith(".mp3") || singleFile.getName().endsWith(".wav")) {
al.add(singleFile);
Log.e("FileInfo.GetSong", singleFile.getName().toString());
}
}
}
return al;
}
private void setButtons() {
play_pause_stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Play/Pause song button clicked
playSong(0);
}
});
progressBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { //Using progress bar to scrolling song
#Override
public void onStopTrackingTouch(SeekBar progressBar) {
}
#Override
public void onStartTrackingTouch(SeekBar progressBar) {
}
#Override
public void onProgressChanged(SeekBar progressBar, int progress, boolean fromUser) { //When user move progress bar song go to moment that user choosed
if (player != null && fromUser) {
player.seekTo(progress * 1000);
}
}
});
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer player) { //When song ended playing
playSong(0);
}
});
}
public void updateProgressBar() {
mHandler.postDelayed(mUpdateTimeTask, 100); //Updating progressBar every 100ms
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() { //Updating time of song and progressbar
long totalDuration = player.getDuration();
long currentDuration = player.getCurrentPosition();
// Updating progress bar
int mCurrentPosition = player.getCurrentPosition() / 1000;
progressBar.setProgress(mCurrentPosition);
// Running this thread after 100 milliseconds
mHandler.postDelayed(this, 100);
}
};
// set it in all changes of the privius songs <#-- Krzysiek -->
private void setBackground(int i) {
//setting the back image and cover image to the chosen song
if (songsInfo.get(i).getBackground() != null) {
bg.setImageBitmap(blured.blur(this, songsInfo.get(i).getBackground()));
cover.setImageBitmap(songsInfo.get(i).getBackground());
Log.i("FileInfo.SetCover", "Set cover of " + songsInfo.get(i).getName());
}
}
public void playSong(int index) {
try {
player.reset();
player.setDataSource(songsInfo.get(index).getPath()); //Getting song with proper index from list
player.prepare();
player.start(); //Playing prepared song
// Displaying Song title
String songTitle = songsInfo.get(index).getTitle();
String songArtist = songsInfo.get(index).getArtist();
setBackground(index);
// Changing Button Image to pause image
play_pause_stopButton.setImageResource(R.drawable.pause);
// set Progress bar values
progressBar.setProgress(0);
progressBar.setMax(player.getDuration() / 1000);
// Updating progress bar
updateProgressBar();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I tried with
android:configChanges="orientation|screenSize"
in manifest and it work but only for 1st change from vertical to horizontal orientation. When i change again from horizontal to vertical, same song start from beggining while old is still playing so i have 2 songs played at same moment. Can anyone help me with it?
keep the config changes and add an override to the onconfig...
#Override
public void onConfigurationChanged(Configuration newConfig) {
}
when the orientation changes the oncreate is called by default , you need to override it like this example or maybe use a singleton as a mediaplayer so it won't create two of them
It was just stupid but i just make player static. It helped and now it dont create additional instances
When you orientate your device, it redraw your layouts and that's why activity restarts (calls onConCreate()). You can save your instance with overriding this method:
#Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
}
and restore instance with overriding this method:
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
I created source in github about this topic, saving instances and restoring. Maybe it'll help you in some circumstances. Orientation Mode

Play Audio from raw folder in Android

I tried to play an audio file from res/raw folder, here is the code, which I used to play the file, this is not generating any error and my device volume is max, but not getting any sound. I tried MP3 and WAV files.
public void btnPlay(View v) {
MediaPlayer mPlayer = MediaPlayer.create(con, R.raw.horse);
try {
mPlayer.start();
}catch (Exception e) {
e.printStackTrace();
Toast.makeText(con,e.toString(),Toast.LENGTH_SHORT).show();
}
}
I'm getting following message on LogCat after start
02-07 17:50:42.331: I/MediaPlayer(16345): Don't send intent. msg.arg1 = 0, msg.arg2 = 0
Help me to resolve this issue and it will be appreciated.
int resID = getResources().getIdentifier("name of sound" , "name of folder", getPackageName());
MediaPlayer mediaPlayer = MediaPlayer.create(getBaseContext(), resID);
mediaPlayer.start();
If you want an easy way to play audio from the raw folder, try this code:
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
public class Main2Activity extends AppCompatActivity {
MediaPlayer mplayer;
public void play(View view) {
mplayer.start();
}
public void pause(View view) {
mplayer.pause();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mplayer =MediaPlayer.create(this, R.raw.ab);
}
}

mute and unmute the sound of my active application

i build an app , and i want to mute and unmute just the sound of this app..
i found this code to mute the sound:
AudioManager aManager=(AudioManager)getSystemService(AUDIO_SERVICE);
aManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
It mutes all the sound of the device and disables the setting of the device to set the sound, not just the sound of the app..
And i found this code to unmute the sound:
AudioManager aManager=(AudioManager)getSystemService(AUDIO_SERVICE);
aManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
When i have muted the sound, and i clicked the button that contains this code, this code is not running and the sound setting of my device is still disabled..
I just want to mute and unmute the sound of my app, not my device.. Any correction?
Try this code:
import android.support.v7.app.ActionBarActivity;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
Button play, mute, data, max;
private boolean VolIsMute;
AudioManager manager;
int currentVolume;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
VolIsMute = false;
init();
}
public void isMute() {
if (VolIsMute) {
manager.setStreamMute(AudioManager.STREAM_MUSIC, false);
VolIsMute = false;
} else {
manager.setStreamMute(AudioManager.STREAM_MUSIC, true);
VolIsMute = true;
}
}
public void init() {
max = (Button) findViewById(R.id.max);
play = (Button) findViewById(R.id.start);
mute = (Button) findViewById(R.id.mute);
play.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
MediaPlayer mp = MediaPlayer.create(
getApplicationContext(), R.raw.abc);
mp.start();
} catch (NullPointerException e) {
e.printStackTrace();
Log.d("WTF", "error: " + e);
}
}
});
}
public void mute(View view) {
currentVolume = manager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (currentVolume == 0) {
Toast.makeText(getApplicationContext(),
" Volume is " + currentVolume +"Press unmute", Toast.LENGTH_SHORT).show();
} else {
isMute();
}
}
public void checvol(View view) {
currentVolume = manager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (currentVolume != 0) {
Toast.makeText(getApplicationContext(),
"Press unmute", Toast.LENGTH_SHORT).show();
} else {
isMute();
}
}
}
I used two buttons one for mute and other for unmute.
Check the current volume first and then do appropriately with if -else.
For those who simplify this,don't forget to post the code.

wake lock does not work [duplicate]

This question already has answers here:
WakeLock not working
(2 answers)
Closed 8 years ago.
I have posted this question before and no one could answer it so I am trying again as this issue makes my app worthless. I need the sound to keep playing when the screen times out or the user taps the power button. I have read almost every online post about wake locks that I can find and i can not get it to work. below is one of the .Java files that plays a sound based on the user selected input. Everything works great except that when the screen goes dark the sound stops playing. Just a note, I am very new to this so if this code is sloppy or redundant please let me know.
package com.androidsleepmachine.gamble;
import android.app.Activity;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
public class Ship extends Activity implements View.OnClickListener {
public static final Integer[] TIME_IN_MINUTES = { 30, 45, 60, 180, 360 };
public MediaPlayer mediaPlayer;
public Handler handler = new Handler();
public Button button2;
public Spinner spinner2;
public PowerManager.WakeLock wl;
// Initialize the activity
#Override
public void onCreate(Bundle savedInstanceState) {
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"Playwhenoff");
super.onCreate(savedInstanceState);
wl.acquire();
setContentView(R.layout.ship);
button2 = (Button) findViewById(R.id.btn2);
button2.setOnClickListener(this);
spinner2 = (Spinner) findViewById(R.id.spinner2);
ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this,
android.R.layout.simple_spinner_item, TIME_IN_MINUTES);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner2.setAdapter(adapter);
}
// Play the sound and start the timer
private void playSound(int resourceId) {
// Cleanup any previous sound files
cleanup();
// Create a new media player instance and start it
mediaPlayer = MediaPlayer.create(this, resourceId);
mediaPlayer.start();
// Create the timer to stop the sound after x number of milliseconds
int selectedTime = TIME_IN_MINUTES[spinner2.getSelectedItemPosition()];
handler.postDelayed(runnable, selectedTime * 60 * 1000);
}
// Handle button callback
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn2:
playSound(R.raw.ocean_ship);
break;
}
}
protected void onStop() {
cleanup();
super.onStop();
}
// Stop the sound and cleanup the media player
public void cleanup() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
wl.release();
}
// Cancel any previously running tasks
handler.removeCallbacks(runnable);
}
// Runnable task used by the handler to stop the sound
public Runnable runnable = new Runnable() {
public void run() {
cleanup();
}
};
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
wl.release();
}
}
This probably has nothing to do with the WakeLock. Your activity is probably being called with onStop() when the screen turns off.
Audio players usually use a service for the audio playback, so the playback can run independently of UI concerns like this.
You are releasing your wakeLock onPause ->
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
wl.release(); // -> This is the line where you release the wakelock
}
When your device "goes to sleep", it goes like onPause -> onStop.
If you release your wakelock onPause, you will not be able to play your music with your screen off, because the system will not keep your CPU awaked.
Release it somewhere else (perhaps onDestroy?) and it should work.

Android Programming - How to play a SoundPool sound from a broadcastreceiver?

I'm very new to Android development and would like to know how to play a SoundPool sound within a broadcastreceiver?
I read somewhere that using SoundPool is the way go play the sound but I don't know how to set it up properly.
I have some sound files such as wave and mp3 files in my Eclipse res\raw folder. I would like to play a file called half.wav
Can you show example code I need to place into my broadcastreceiver?
Here is a first attempt at the code but I do get an error stating that soundID = soundPool.load(this, R.raw.half, 1);
"The Method Load(Context, Int, Int) In The Type SoundPool Is Not Applicable..."
Here is the code for the class:
package ChimeMe.BigBen;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import android.os.Bundle;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.SoundPool.OnLoadCompleteListener;
public class AlarmReceiver extends BroadcastReceiver {
private SoundPool soundPool;
private int soundID;
boolean loaded = false;
#Override
public void onReceive(Context context, Intent intent) {
try {
// Load the sound
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
loaded = true;
}
});
soundID = soundPool.load(this, R.raw.half, 1);
Toast.makeText(context, "This is the alarm.", Toast.LENGTH_SHORT)
.show();
} catch (Exception e) {
Toast.makeText(
context,
"There was an error somewhere, but we still received an alarm",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
Thanks in advance.
Truly,
Emad
If it is just one sound you want to play I think using the MediaPlayer would be quicker and easier...
This is the code from an app of mine that plays a beep every 30 minutes when this Broadcastreceiver runs
public class Gameloop extends BroadcastReceiver {
MediaPlayer mp = null;// Here
private static final String TAG = "VPET";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Loop running");
if (Pet.isAlive == true) {
mp = MediaPlayer.create(context, R.raw.beep);//Onreceive gives you context
mp.start();// and this to play it
} else {
}
}
}
}

Categories

Resources