I have a math game with multiple choice questions. I have a bell sound for a right answer and an oink sound for a wrong answer. There is a timed play mode which encourages the player to enter answers rapidly. The sounds play fine if answer buttons are pressed slowly. But if in quick succession, a sound fails to play.
The two sounds are each a fraction of a second long.
In the method that handles correct answers I have ting.start();, and in the method for wrong answers I have oink.start();
One thing I tried was to forcibly stop both sounds and then start only the one I want (see below) but then the sounds don't play at all! Any suggestions?
private void handleWrongAnswer(int chosenID)
{
// Toast.makeText(getApplicationContext(), "Oops, try again.", Toast.LENGTH_SHORT).show();
Button checked_button = (Button) findViewById(chosenID);
checked_button.setEnabled(false);
checked_button.setClickable(false);
checked_button.setBackgroundColor(Color.rgb(255,100,100));
score = score - 1.0/3.0;
score_field.setText(String.format("%.2f", score));
ting.stop();
oink.stop();
oink.start();
}
Well I suppose that you are using Mediaplayer to play that sounds. If you want to play small audio clips and repeat them in small place of time you should use soundPool.
You should implement it this way:
private SoundPool soundPool;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 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.sound1, 1);
}
And then when you want to use it:
// Getting the user sound settings
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
float actualVolume = (float) audioManager
.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = (float) audioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = actualVolume / maxVolume;
// Is the sound loaded already?
if (loaded) {
soundPool.play(soundID, volume, volume, 1, 0, 1f);
}
Anyway you have a nice tutorial about this here.
Related
I have been integrating the YoutubePlayer API for with my Android project. The videos from the playlist are working well. What I am trying to do is have the audio start low and fade in over 30seconds.
What I have done so far, for some reason is doing somthing really weird. It set it to max volume and if you try to turn it down it turns it back up again really straight away.
The way I thought I could do it was to set the audio manager to a 0 volume and then on an ontick timer raise that by 1 until it got to the max volume.
The code below was my attempt, but like I said it is doing weird things.
Thanks for your help
youTubePlayer.loadPlaylist(playListTitle);
final AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// Add listeners to YouTubePlayer instance
youTubePlayer.setPlayerStateChangeListener(new YouTubePlayer.PlayerStateChangeListener() {
#Override
public void onLoaded(String arg0) {
youTubePlayer.play();
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
Integer volumeRaisingTime = 30000;
new CountDownTimer(volumeRaisingTime, 1000) {
Integer deviceMaxVolume = 20;
Integer devicevolume = 0;
public void onTick(long millisUntilFinished) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 20, 0);
if (devicevolume > deviceMaxVolume){
devicevolume++;
Log.d("Device Volume:", ""+devicevolume);
}
}
public void onFinish() {
}
}.start();
}
When i click button plays sound on my app, but keep clicking for a while doesn`t play anymore. Maybe it is memory issue? Could you solve me my issue? Here is implemented play sound via SoundPool: when i click button i called play method: and play method works background thread
private void play(int resId) {
soundPool = buildBeforeAPI21();//TODO: refactor with deprecated constructor
soundPool.load(activity, Integer.parseInt(resId), 1);
}
public SoundPool buildBeforeAPI21() {
if (soundPool == null) {
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f);
}
}
});
}
return soundPool;
}
Don't create a new SoundPool with each click. That is extremely wasteful. Do this instead:
1) Create the SoundPool just once
2) Load it with all the sounds you want to play, just once
3) Wait for all the sounds to load
4) Just call soundPool.play() with each click.
Maybe this answer cames too late; but here we go. The problem is in the line
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
That '2' number is the int maxStreams, following the documentation "the maximum number of simultaneous streams for this SoundPool object" (you can go deep on this here). Now change it and set it to 10, for example, and try again. And after that, you cand adjust it as your wishes. So:
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
Hope this helps (if it is still necessary).
I am having a bit of difficulty with my SoundPool. I have an ArrayList<Integer> of my soundIDs located in my res/raw folder. I'm creating the SoundPool like so in my ViewHolder class for my RecyclerView:
//create the SoundPool
sp = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
//create the AudioManager for managing volume
audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
//store the streamVolume in an int
streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
//set the load listener for my soundfiles
sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
loaded = true;
}
});
I am playing the sound on the click of an ImageView like so:
#Override
public void onClick(View v) {
if (v.equals(cardImg)) {
sp.load(context, cardData.getSoundId(), 1);
if (loaded) {
sp.play(cardData.getSoundId(), streamVolume, streamVolume, 1, 0, 1f);
}
}
}
And every time I click on the cardImg it gives me this error:
W/SoundPool﹕ sample 2130968609 not READY
Where the sample int changes depending on which card I click, like it should.
So I know that it's GETTING the proper soundID from my ArrayList (stored in CardData class), and it definitely sees that it's loaded, because it wouldn't try to play otherwise because loaded would never be true. My question is: Why are my sounds never ready?
My sounds are .m4a format which Android says is supported in the documentation. I've tried on an Android 5.0 device and an Android 4.4 device but nothing changes.
I have tried using a MediaPlayer but I am running into memory errors as I have many short clips that need to be able to be spammed and I read that a SoundPool was a much better way to manage this (?).
Any help would be appreciated! I am super vexxed here.
You're using the wrong id. SoundPool.load returns an id that is suppose to be passed in to SoundPool.play.
Hi I am working on an music app for Android.In that I want to change playback speed & reverb value for music dynamically.
In my view there will be two SeekBar for both playback speed & reverb value, so on changing SeekBar's value sound must change accordingly.
Currently I am using MediaPlayer but after search I found the MediaPlayer doesn't support functionality for changing playback speed.
Then I tried with SoundPool, with this I am able to changes the speed of track.But with SoundPool I am not able to use the big music files.
I want a way where I can change both speed & reverb value.
I am searching for weeks for solution but still I am not able to find it.
Please please help me...
EDIT
float playbackSpeed = 1.5f;
SoundPool soundPool;
int soundId;
void soundPooler()
{
soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
final int soundId = soundPool.load("/storage/sdcard0/Music/departed.mp3", 1);
AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
final float volume = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener()
{
#Override
public void onLoadComplete(SoundPool arg0, int arg1, int arg2)
{
soundPool.play(soundId, volume, volume, 1, 0, playbackSpeed);
}
});
}
This is the code I have tried.
Thanks..
My activity plays a specific sound effect once every second.
The following code works, however there is a bug: occasionally the sound is played TWICE every second. This only happens every once in a while (once every 10-20 attempts). When it happens, the double sound occurs for the entire run of the activity, start to finish. So, if I see the activity started without the bug, it stays that way for the entire run of the activity.
Here's the relevant code - what's the problem with it? Thank you!
private Handler mHandler = new Handler();
#Override
protected void onResume() {
super.onResume();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.post(mUpdateTimeTask);
}
#Override
protected void onPause() {
// Another activity is taking focus (this activity is about to be "paused").
mHandler.removeCallbacks(mUpdateTimeTask);
super.onPause();
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
PlayTick();
mHandler.removeCallbacks(this);
mHandler.postDelayed(this, 1000);
}
};
public void PlayTick() {
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
float actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = actualVolume / maxVolume;
soundPool.play(soundID, volume, volume, 1, 0, 1f);
}
Found a solution - seems it's a known SoundPool bug, it sometimes plays the effect twice. I used a .wav file; converting the file to .ogg seems to resolve the issue.