I have soundpool that will load file from sd-card and I used mstreamID to stop it and I use mstreamID in OnLoadCompleteListener so the files can load. I use 2 buttons to play soundpool diffrent sounds. But when I click first button and while it plays 1 sound I click second button and it stops the sound from first button.
Here is my code:
public class MainActivity extends Settings {
SoundPool mSoundPool;
int mSoundId;
int mStreamId = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
mSoundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
mSoundPool
.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
public void onLoadComplete(SoundPool soundPool,
int sampleId, int status) {
mStreamId = soundPool.play(sampleId, 1, 1, 1, 0, 1f);
}
});
}
//OnClick
public void button1(View view) {
if (mStreamId != 0) {
mSoundPool.stop(mStreamId);
}
// et1 is extended from Settings.java
String path = getFullFilePath(getApplicationContext(), et1.getText()
.toString());
mSoundId = mSoundPool.load(path, 1);
}
public void button2(View view) {
if (mStreamId != 0) {
mSoundPool.stop(mStreamId);
}
String path = getFullFilePath(getApplicationContext(), et2.getText()
.toString());
mSoundId = mSoundPool.load(path, 1);
}
Read doc please, and what is the thing you want to say?
do not load same file more than one time if you not unload it.
load all sound at start when use SoundPool.
streamId is increasing all the time, you never get same streamId.
Related
Actually, I want to play all the sounds in raw folder in sequence. When I click the button only the first one is played. I will be grateful for your help . This is my code:
public class MainActivity extends AppCompatActivity {
private SoundPool soundPool;
private int sound1, sound2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(2)
.setAudioAttributes(audioAttributes)
.build();
} else {
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
}
sound1 = soundPool.load(this, R.raw.a, 1);
sound2 = soundPool.load(this, R.raw.d, 1);
}
public void playSound(View v) {
soundPool.play(sound1, 1, 1, 0, 0, 1);
soundPool.play(sound2, 1, 1, 0, 0, 1);
}
#Override
protected void onDestroy() {
super.onDestroy();
soundPool.release();
soundPool = null;
}
}
I used Howard Liu's SoundPoolPlayer class, a wrapper around the SoundPool that calculates the duration of the audio file playing (using the MediaPlayer) and calls the custom OnCompletionListener event after the playback is finished using postDelayed.
In the handling of the OnCompletionListener event, you just need to start playing the next audio file.
hy,,im newbie for android,i have error
AudioFlinger could not create track, status: -12 when running my application. i read for use release() method for fix it, but i don't know how to implement on my code, please help me ?? this is my code,please fix it :)
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.talempong);
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
spool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundID = spool.load(this, R.raw.doo, 1);
ImageButton Button = (ImageButton)findViewById(R.id.imagebutton1);
Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Sound();
}
});
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
spool2 = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundID2 = spool2.load(this, R.raw.re, 1);
ImageButton Button2 = (ImageButton)findViewById(R.id.imagebutton2);
Button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Sound2();
}
});
Is your sound greater that 1MB? SoudPool doesn't plays sounds that are greater that that.
If it isn't you can use the release after playing the sound.
// your code:
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
spool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundID = spool.load(this, R.raw.doo, 1);
//after this you have to:
spool.setOnLoadCompleteListener(new OnLoadCompleteListener(){
#Override
public void onLoadComplete(SoundPool sound,int sampleId,int status){
spool.play(teste, 20,20, 1, 0, 1);
new Thread(new Runnable(){
#Override
public void run(){
try {
Thread.sleep(2000);
spool.release();
} catch (InterruptedException e) { e.printStackTrace(); }
}
}).start();
}
});
// in the Thread.sleep put the value in millisecs of the time of your music this is a sample os 2 seconds
Basically, in a short explanation, I am making a sound board. Once I run the initial activity, it adds all sound clips to the soundpool. I then have two other activities that are to organize the sound clips, and I would like to use the previously loaded soundpool so that there isn't move load time when switching between activities. I am fairly new to this Android coding, so please make things in simple terms!
EDIT: Also, does anybody know how to stop the playback on a second button click? Not as in clicking a different button, I understand that, but if the same button is clicked, it will stop it?
My main activity:
private SoundManager mSoundManager;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
mSoundManager = new SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(0, R.raw.stop_playing);
mSoundManager.addSound(1, R.raw.sound1);
mSoundManager.addSound(2, R.raw.sound2);
mSoundManager.addSound(3, R.raw.sound3);
Dealing with soundpool stuff:
public void initSounds(Context theContext) {
mContext = theContext;
mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int Index,int SoundID)
{
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public void pauseSound(){
mSoundPool.autoPause();
}
public void stopSound(){
mSoundPool.stop(playingNumber);
}
public int playSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int soundId = mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
playingNumber = index;
return playingNumber;
}
}
Alwade create Application class, and create static SoundManager instance in the your application class, and add needed sounds to SoundManager in the Initial activity. Then you can use current Soundmanager in other activities. Change SoundManager class to static class.
For example:
public class MyApplication extends Application {
public static SoundManager soundManager;
public static SoundManager getSoundManager() {
return soundManager;
}
public static void setSoundManager(SoundManager soundManagerIns) {
soundManager = soundManagerIns;
}
}
and in the initial activity create instance and set it to :
mSoundManager = new SoundManager();
mSoundManager.initSounds(getApplicationContext);
mSoundManager.addSound(0, R.raw.stop_playing);
mSoundManager.addSound(1, R.raw.choo_choo);
mSoundManager.addSound(2, R.raw.all);
mSoundManager.addSound(3, R.raw.hearts);
MyApplication.setSoundManager(mSoundManager);
Then you can get this SoundManager in the other activities:
SoundManager sManager = MyApplication.getSoundManager();
This is my example project: SoundPoolExample
I have three sound files in raw folder. I want to play them one after another with no delay between them. I tried them playing with below code but all three files are playing together, not one after another. All three files are less then 50 kb. I also want to change their playback rate, that's why I am using SoundPool instead of MediaPlayer.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
final int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPoolMap.put(1, mSoundPool.load(this, R.raw.nancy, 1));
mSoundPoolMap.put(2, mSoundPool.load(this, R.raw.cymbal, 1));
mSoundPoolMap.put(3, mSoundPool.load(this, R.raw.njs, 1));
Button SoundButton = (Button)findViewById(R.id.Button);
SoundButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mSoundPool.play(mSoundPoolMap.get(1), streamVolume, streamVolume, 1, 0, 1f);
mSoundPool.play(mSoundPoolMap.get(2), streamVolume, streamVolume, 1, 0, 1f);
mSoundPool.play(mSoundPoolMap.get(3), streamVolume, streamVolume, 1, 0, 1f);
}
});
In order to do what you're trying to do, you'll probably have to create your own custom AsyncTask that takes in an array of SoundPool objects (or perhaps a HashMap), the implementation along the lines of:
private class SoundPoolTask extends AsyncTask <Soundpool, String, String>
{
#Override
protected String doInBackground(SoundPool... params) {
try {
//For each SoundPool object
// int soundLength = however long the SoundPool object is
// Play the sound
// Thread.sleep(soundLength);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {}
#Override
protected void onPostExecute(String result) {
//Clean up your class objects
}
}
You'll probably have to do some sort of calculation with the original length of the sound and the playrate to determine how long each sound is. I hope this helps!
I got same problem, so I create my own logic. Her it is:-
I have three audio file in my raw folder. I want to run these three file in sequence. To do this I follow this flow:-
Step1:- On clicking Button a thread will be generated.
Step2:- Thread will start a timer of 20 milliseconds.
Step3:- In timer it will check if media player is not playing.
If media player is not playing it will call a function to start media player.
Step4:- In function which will start the media player have switch logic which will decide which audio
file will be ON ( with help of a variable v).
Here is my code:-
public class MainActivity extends Activity {
int v=0;
TimerTask time;
MediaPlayer mp ;
Button btn;
void playmp(int a)
{
switch (a)
{
case 0:
{
mp = MediaPlayer.create(this,R.raw.a);
mp.start();
v++;
break;
}
case 1:
{
mp = MediaPlayer.create(this,R.raw.b);
mp.start();
v++;
break;
}
case 2:
{
mp = MediaPlayer.create(this,R.raw.c);
mp.start();
v++;
break;
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn= (Button) findViewById(R.id.button1);
mp = MediaPlayer.create(this,R.raw.a);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//Creating Thread
Thread thread = new Thread()
{
#Override
public void run() {
try {
sleep(1);
// Body Of Timer
time = new TimerTask() {
#Override
public void run() {
//Perform background work here
if(!mp.isPlaying())
{
playmp(v);
}
}
};
//Starting Timer
Timer timer = new Timer();
timer.schedule(time, 10, 20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
});
}
where "a","b"and "c" are my audio file name . If you want repeat audio after completing all three , replace this:-
case 2:
{
mp = MediaPlayer.create(this,R.raw.c);
mp.start();
v++;
break;
}
by this
case 2:
{
mp = MediaPlayer.create(this,R.raw.c);
mp.start();
v=0;
break;
}
As far as I can tell, my app runs fine but I notice this error from the SoundPool being reporting often in the logcat.
E/SoundPool(28182): 2 mChannels.erase can not get the lock
Any ideas as to what would cause this? I tried removing my thread synchronization code but I am still receiving the error.
This was observed using a Galaxy S2 (SC-02C) running Android 2.3.6.
Another solution that I propose for you :
Create an instance of SoundPool by sound with maxStreams = 1
Set volume 0 to only one streamID returned by play() method
This solution is not very clean I agree...
public class Sound {
public final static int STREAM = AudioManager.STREAM_SYSTEM;
private SoundPool pool;
private int soundID;
private int streamID;
public Sound(Context context, int resID) {
pool = new SoundPool(1, STREAM, 0);
soundID = pool.load(context, resID, 1);
}
public final void play() {
streamID = pool.play(soundID, 1, 1, 1, 0, 1);
}
public final void stop() {
pool.setVolume(streamID, 0, 0);
}
}
public class MyActivity extends Activity {
public static Sound alarm1;
public static Sound alarm2;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
setVolumeControlStream(Sound.STREAM);
if(alarm1 == null) alarm1 = new Sound(this, R.raw.alarm1);
if(alarm2 == null) alarm2 = new Sound(this, R.raw.alarm2);
findViewById(R.id.play_1).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm1.play(); }
});
findViewById(R.id.stop_1).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm1.stop(); }
});
findViewById(R.id.play_2).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm2.play(); }
});
findViewById(R.id.stop_2).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm2.stop(); }
});
}
}
And to manage all your sounds, we can imagine a library like this :
public class Soundlib {
private Context context;
private HashMap<Integer, Sound> library;
public Soundlib(Context context) {
this.context = context;
library = new HashMap<Integer, Sound>();
}
public final void add(int... rawID) {
for(int id : rawID) library.put(id, new Sound(context, id));
}
public final void play(int... rawID) {
for(int id : rawID) library.get(id).play();
}
public final void stop(int... rawID) {
for(int id : rawID) library.get(id).stop();
}
public final void stopAll() {
for(int id : library.keySet()) stop(id);
}
}
// to initilize sound library
if(soundlib == null) soundlib = new Soundlib(this){{
// to add one or more sounds
add(R.raw.alarm1, R.raw.alarm2);
}};
// to play one or more sounds
soundlib.play(R.raw.alarm1);
// to stop one or more sounds
soundlib.stop(R.raw.alarm1);
// to stop all sounds
soundlib.stopAll();
I think this error log is caused by the play() / stop() method of your SoundPool instance.
Do you try to play / stop an audio stream?