I am trying to implement a musical keyboard application that will play string sounds. String sounds are needed to be played till the user releases the key.
I am using a small sample of 1 second with the idea of looping the sample using SoundPool on
MotionEvent.ACTION_DOWN,
and stopping it as
ACTION_UP
gets called. But looping does not seem to work. I can put a "long enough" sound sample assuming no user would keep the button pressed for that long, but that is not quite the way I want the app work.
What should I do?
Try this code:
inside onCreate()
mp=MediaPlayer.create(MainActivity.this,R.raw.beep);
b.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mp.setLooping(true);
mp.start();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
mp.stop();
mp=MediaPlayer.create(MainActivity.this,R.raw.beep);
}
return false;
}
});
Related
im trying to do a Soundboard for a school proyect, but I have problems when I pulse the buttons, If I pulse a button twice, the sound does not reproduce again, and, even if the condition fullfills, the audio doesnt loop. I have different buttons, and all of they call a method (each one with different parameters on the call
btn1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
reproducir(mp1, motionEvent, btn1, colorin);
return false;
}
});
public void reproducir(MediaPlayer mp, MotionEvent motionEvent, Button btn, String colorin ){
switch(motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
mp.start();
btn.setBackgroundColor(getResources().getColor(R.color.Blanco));
if(instrumento.getText().equals("piano")) {
mp.setLooping(true);
}
break;
case MotionEvent.ACTION_UP:
mp.stop();
ponerColor(colorin);
}
}
The last line calls to a method to put again the original color of the button, thanks a lot
Your Code is Fine Only One tiny Mistake:
You should replace mp.stop(); with mp.pause();
That's All.
Better to it Like this though:
if (mp.isPlaying()){
mp.pause();
}
....
if (!mp.isPlaying()){
mp.start();
}
...
if (!mp.isLooping()){
mp.setLooping(true);
}
I should also let you know that mp.stop() Stops the media, it's Good, But Stop is only to be used in case You want the Whole MediaPlayer Forget what song is being played and we just wanna change The Audio, reset MEdia player and start another Audio.
Hope you find this useful
I'm trying to have a SoundPool play while a view object is being clicked.
I have successfully implemented it but found out that the sound of the click will lag.
I've been researching on StackOverFlow and on the internet for solutions and the best solution seems to be to have the SoundPool on a separate Thread.
I'm very new to the whole Thread thing and so I don't really know what to do at the moment.
I have followed THIS guide on creating a SoundPool thread, however, I don't know how to access it, or even to assign the clips that I wished to play.
Can someone please give me an example of how I should call the SoundPool thread to play my clip while an object in the view is being clicked.
Please find my onClick code below:
#Override
public boolean onTouch(View v, MotionEvent event) {
int actionPerformed = event.getAction();
switch(actionPerformed) {
case MotionEvent.ACTION_DOWN: {
if (Math.pow((event.getX() - a_Ball.getX()),2)
+ Math.pow((event.getY() - a_Ball.getY()), 2)
<= Math.pow(a_Ball.getDiameter(),2)) {
//pCheck = !pCheck;
if (pauseBall == false) {
SoundPool soundPool = new SoundPool(1,AudioManager.STREAM_MUSIC,1);
clickSound = soundPool.load(MainActivity.this, R.raw.click, 1);
/*soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
soundPool.play(clickSound,1.0f, 1.0f, 0, 0, 1.0f);
}
});*/
//Increase Ball Speed
sIncrease = true;
}
} else {
if (pauseBall == false) {
//set minus health when not touch on ball
health--;
TextView txtHealth = (TextView)findViewById(R.id.health);
String tempHealth = txtHealth.getText().toString();
tempHealth = getResources().getString(R.string.health) + String.valueOf(health);
txtHealth.setText(tempHealth);
}
}
break;
}
default:
return false;
}
return true;
} //onTouch end
Thanks in advance.
You don't need threads to make sounds without lag. The lag comes from the loading of the sound file, try create the SoundPool and load the sound (soundPool.load) in advance (e.g. onCreate), then just call soundPool.play in your onTouch method.
Ok, so instead of doing it in another class, I decided to do it in one class and created a new thread by myself. Seems to be working well enough.
I'll mark this thread as answer.
I'm creating a sampler app for school. I've wrote code which plays a sample when I press and hold a button and stops when I release it. My problem is that it has too much latency. It takes too long after I press the button to play the sound.
My audio files are mp3's.
Here's my code:
smpl1.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View arg0, MotionEvent theMotion)
{
switch (theMotion.getAction())
{
case MotionEvent.ACTION_DOWN:
sample = MediaPlayer.create(MainActivity.this, R.raw.bassdrum);
smpl1.setText("ON");
smpl1.setTextColor(Color.GREEN);
sample.start();
break;
case MotionEvent.ACTION_UP:
smpl1.setText("OFF");
smpl1.setTextColor(Color.RED);
sample.stop();
break;
}
return true;
}
Create the sample object before the button press, then just use the start / stop functionality in your handler code.
I have a button called " micro" , when I click on my sound is played , and when I click on again it must stop
I tried the code below but when I click on my button for the second time , the music is played again and again without stopping:
Button micro=(Button)findViewById(R.id.micro);
micro.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
MediaPlayer mp = MediaPlayer.create(getBaseContext(),
R.raw.mymusic);
mp.start();
}
if(event.getAction() == MotionEvent.ACTION_UP){
MediaPlayer mp = MediaPlayer.create(getBaseContext(),
R.raw.mymusic);
mp.stop();
}
return true;
}
});
You are creating separate MediaPlayer objects. You should just create one that you tell to start and stop as necessary.
Right now you're telling one to start, and then later telling a different one to stop.
I have seen couple of similar problems with solutions, but I couldn't find one that would work in my situation.
I am making VolumePreference (extending DialogPreference) that let's user choose volume level for some alarm.
In other preference user chooses desired ringtone that is played during alarm. It is also played while user is choosing volume in VolumePreference, so he knows how it actually sounds.
In yet another preference user chooses if alarm should "override" phone's media volume level when playing - I do that, so if user wants to have fixed volume level for alarm, then it shouldn't be affected by changes made by volume keys and so on.
If user chooses to do that, before starting to play alarm in AlarmActivity, I set volume to max level with AudioManager and intercept all keyDown events of volume keys, restoring volume level after alarm finishes.
Problem is, I can't block volume keys within my VolumePreference as there is no onKeyDown method.
After some checking, I found registerMediaButtonEventReceiver method of AudioManager that "Register a component to be the sole receiver of MEDIA_BUTTON intents.", which I believe could help in my situation (making some empty receiver), and even make volume locking more universal (register when I want to start lock, unregister after unlock), but it is working from API8, while I am making app for API7 - which still hold over 10% of market from what I read, so I would like to stick to it.
Any ideas on how one could block volume changes in PreferenceDialog?
After some thinking solution proved to be really simple - one can override onKeyDown method of View created in onCreateDialogView of DialogPreference or set onKeyListener of that View.
First example:
LinearLayout layout = new LinearLayout(mContext)
{
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP) return true;
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP) return true;
return super.onKeyUp(keyCode, event);
}
};
Second example (mDialogView is saved reference to layout from first example):
mDialogView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP)
return true;
return false;
}
});
I have chosen second solution, as I think it is more flexible for two reasons at least
I can just remove listener to stop blocking volume keys, while in first method I can't
in first solution I need to decide if I want to block keys input while creating View - not much use if VolumePreference is extending some other Preference that shouldn't block keys input