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();
}
Related
public class AndroidSound implements Sound {
int soundId;
SoundPool soundPool;
public AndroidSound(SoundPool soundPool, int soundId) {
this.soundId = soundId;
this.soundPool = soundPool;
}
#Override
public void play(float volume) {
soundPool.play(soundId, volume, volume, 0, 0, 1);
}
#Override
public void dispose() {
soundPool.unload(soundId);
}}
public class Assets{
public Music theme;
public static Sound sound;
public static void load(Game game) {
theme = game.getAudio().createMusic("theme.mp3");
theme.setLooping(true);
theme.setVolume(0.85f);
theme.play();
sound = game.getAudio().createSound("death.wav");
}
}
Then I play this sound in different class by calling play() on it, but it plays with really huge delay, something around 500ms. Why is that? I tried looking for solution, but there is tons of people with that problem and I haven't found any answer that actually worked. Most of topics was bit old tho, maybe there is a simple solution for this already, counting on your help.
public class AndroidAudio implements Audio {
AssetManager assets;
SoundPool soundPool;
public AndroidAudio(Activity activity) {
activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
this.assets = activity.getAssets();
this.soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
}
#Override
public Sound createSound(String filename) {
try {
AssetFileDescriptor assetDescriptor = assets.openFd(filename);
int soundId = soundPool.load(assetDescriptor, 0);
return new AndroidSound(soundPool, soundId);
} catch (IOException e) {
throw new RuntimeException("Couldn't load sound '" + filename + "'");
}
}
}
I don't know if this will be helpful now but also answering.
Use of SoundPool
1)First load your audio as required in the levels in the beginning of application initialization.Suppose you need 5 sound in the level load them in the beginning and keep the soundID's handy.
2) Now on any event just call play with the soundID.
3) This plays with a very less delay while I debugged from SoundPool play till HAL layer.Around 10-15 ms in my device.
For more info on SoundPool implementation follow my github thread:
https://github.com/sauravpradhan/Basic-Audio-Routing
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.
I am trying to program a sound app where on button click I would like to play 3-4 sound files one after the other. How can this be done? Also I would like to increase the time of play of the files. Is this where the loop variable in play function used??
Here is part of code I have done with SoundPool. However the files all play simultaneously :(
public void onClick(View v){
//check for scan button
if(v.getId()==R.id.playbutton){
queueSound(1000);
sound.changePitchfile3(R.raw.a0);
queueSound(5000);
sound.changePitchfile2(R.raw.a1);
queueSound(10000);
sound.changePitchfile3(R.raw.a3);
}
}
});
}
private void queueSound(final long delay) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
}}, delay);
public void changePitchfile1(int res1) {
int soundId = (Integer) mSounds.get(res1);
this.myPlayer.play(soundId, 1, 1, 0, 0,1.125f);
}
If I play a single sound, it runs fine.
Adding a second sound causes it to crash.
Anyone know what is causing the problem?
private SoundManager mSoundManager;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sos);
mSoundManager = new SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(1,R.raw.dit);
mSoundManager.addSound(1,R.raw.dah);
Button SoundButton = (Button)findViewById(R.id.SoundButton);
SoundButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mSoundManager.playSound(1);
mSoundManager.playSound(2);
}
});
}
mSoundManager.addSound(1,R.raw.dit);
mSoundManager.addSound(1,R.raw.dah);
You need to change the second line to:
mSoundManager.addSound(2,R.raw.dah);
In order to play multiple sounds at once, first you need to let the SoundPool know that. In the declaration of SoundPool notice that I specified 20 streams. I have many guns and bad guys making noise in my game, and each has a very short sound loop, < 3000ms. Notice when I add a sound below I keep track of the specified index in a vector called, "mAvailibleSounds", this way my game can try and play sounds for items that dont exist and carry on without crashing. Each Index in this case corresponds to a sprite id. Just so you understand how I map particular sounds to specific sprites.
Next we queue up sounds, with playSound(). Each time this happens a soundId is dropped into a stack, which I then pop whenever my timeout occurs. This allows me to kill a stream after it has played, and reuse it again. I choose 20 streams because my game is very noisy. After that the sounds get washed out, so each application will require a magic number.
I found this source here, and added the runnable & kill queue myself.
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
private Vector<Integer> mAvailibleSounds = new Vector<Integer>();
private Vector<Integer> mKillSoundQueue = new Vector<Integer>();
private Handler mHandler = new Handler();
public SoundManager(){}
public void initSounds(Context theContext) {
mContext = theContext;
mSoundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int Index, int SoundID)
{
mAvailibleSounds.add(Index);
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
// dont have a sound for this obj, return.
if(mAvailibleSounds.contains(index)){
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int soundId = mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
mKillSoundQueue.add(soundId);
// schedule the current sound to stop after set milliseconds
mHandler.postDelayed(new Runnable() {
public void run() {
if(!mKillSoundQueue.isEmpty()){
mSoundPool.stop(mKillSoundQueue.firstElement());
}
}
}, 3000);
}
}
How do I set up an audiofile to play when a user touches an image.
Where should I store the audio file and what code should I use to actually play the file?
I don't want to bring up the MediaPlayer interface or anything like that.
I was thinking of doing it like this:
foo = (ImageView)this.findViewById(R.id.foo);
foo.setOnClickListener(this);
public void onClick(View v) {
if (foo.isTouched()) {
playAudioFile();
}
}
Thanks
This won't create a bring up the MediaPlayer interface... it will just play the sound you want.
Button boton = (Button) findViewById(R.id.boton);
boton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(TestSonido.this, R.raw.slayer);
mp.start();
}
});
In this case, R.raw.slayer represents an audio file called slayer.mp3 that is stored in the res/raw/ folder and once you click the button the droid will rock you...
You can also achieve the same using SoundPool.
MediaPlayer first loads the whole sound data in memory then play, so it produces some lag when we switch among sounds frequently.
SoundPool is a better option with small size sound file and produces better result with .ogg media file.
SoundPool pl = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
// 5 indicates the maximum number of simultaneous streams for this SoundPool object
pl.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
// The onLoadComplet method is called when a sound has completed loading.
soundPool.play(sampleId, 1f, 1f, 0, 0, 1);
// second and third parameters indicates left and right value (range = 0.0 to 1.0)
}
});
Button btn = findViewById(R.id.boton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int sound = pl.load(this, R.raw.sound_01, 0);
}
});
public void aud_play(View view) {
if (!mp.isPlaying()) { //If media player is not playing it.
mp = MediaPlayer.create(this, R.raw.audio_name);
mp.start();
} else {// Toast of Already playing ...
}
}