Friday 7 September 2012

Jade Sound

I have now implemented a JadeSound class that seems to be working very well. There WAS a hitch in the use of MediaPlayer. I kind of assumed that when you called MediaPlayer.release(), the instance of Media Player would be set to null. Not so. Although a failed create set mp to null, if I reset and released the mp, and then didn't create a new one, the next time I entered the method, mp would still have the value of the released mp and a new reset() caused a fault.
package uk.co.amazonsystems.jade;
import java.util.ArrayList;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.media.AudioManager;

public class JadeSound 
{
 // This class handles all sounds. There are two sound sources. Use soundpool for short
 // transient sounds. A single soundpool does all the sounds.
 // For background music and ambient sound, Use MediaPlayer. Each sound is a new mediaplayer.
 // Only one sound can be running at a time. All such sounds are looped.
 public static final int OK_SOUND = 0;
 public static final int BAD_SOUND = 1;
 public static final int NOSUCH_SOUND = 2;
 public static final int BAD_PLAY = 3;
 
 private SoundPool soundpool = null;
 private static int CHANNS = 4;  // Sound Channels
 private String soundName; // current ambient sound name
 private int [] SFX = new int[CHANNS];  // Stream IDs
 private int priority = 1;
 private int soundid[];  // Sound IDs
 private Context thiscontext;
 private MediaPlayer mp;
 private ArrayList  soundfiles;
 private int buggins;
 private boolean soundstate = true;
 
 // Initialise
 public JadeSound(Context JadeContext, ArrayList  SFXFiles)
 {
  thiscontext = JadeContext;
  soundfiles = SFXFiles;
  if (soundpool != null) soundpool.release();
  soundpool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
  int temp = soundfiles.size();
  soundid = new int [temp]; 
  for (int ii = 0; ii < temp; ii++)
  {
   int resid = getRaw(thiscontext, soundfiles.get(ii)); 
   if (resid == 0) 
    {
    soundid[ii] = 0;
    }
   else
    {
    soundid[ii] = soundpool.load(thiscontext, resid, priority);
    }
  }
  for (int ii = 0; ii < CHANNS; ii++)
  {
   SFX[ii] = -1;
  }
  buggins = 0;
 }
 public int playSFX(String name)
 {
  return playSFX(name, 0);
 }
 public int playSFX(String name, int Loop)
 {
  int index = soundfiles.indexOf(name);
  if (index == -1)
  {
   return NOSUCH_SOUND;
  }
  else
  {
   soundpool.stop(SFX[buggins]);
   if (soundid[index] != 0)
   {
    int reply = soundpool.play(soundid[index], 1, 1, priority, Loop, 1);
    if (reply == 0) return BAD_PLAY;
    SFX[buggins] = reply; 
    buggins++;
    if (buggins >= CHANNS)
    {
     buggins = 0;
    }
   }
   else return BAD_SOUND;
  }
  return OK_SOUND;
 }
 public int playAmbient(String name)
 {
  // if the same sound name, just exit immediately
  // we use the same mp we used last time, and keep playing the same song
  if (soundName != null)
  {
   if (soundName.equals(name))
   {
    return OK_SOUND;
   }
  }
  // if the media player still in use, reset it, release it and null it
        if (mp != null) 
        {
            mp.reset();
            mp.release();
            mp = null;
        }
        // remember the new sound name for next call
        soundName = name;
        // find the sound file in raw
        int resid = getRaw(thiscontext, name);
        // if it's not there, return
        if (resid == 0) 
         {
         return BAD_SOUND;
         }
        // Finally, create a media player
        mp = MediaPlayer.create(thiscontext, resid);
        // if it doesn't work, return
        if (mp == null) return BAD_SOUND;
        // Ambient always loops
        mp.setLooping(true);
        // start the playback
        mp.start();
        // if the song flag is false, pause it
        // we may have to start it later
        if (!getSoundState())
         pauseAmbient();
        return OK_SOUND;
 }
 public void pauseAmbient()
 {
  if (mp != null)
  {
   mp.pause();
  }
 }
 public void resumeAmbient()
 {
  if (getSoundState())
  {
   if (mp != null)
   {
    mp.start();
   }
  }
 }
 public void pauseAll()
 {
  if (soundpool != null) soundpool.autoPause();
  pauseAmbient();
 }
 public void resumeAll()
 {
  if (soundpool != null) soundpool.autoResume();
  resumeAmbient();
 }
 public void closeSound()
 {
  if (soundpool != null)
  {
   soundpool.release();
   soundpool = null;
  }
        if (mp != null) 
        {
            mp.reset();
            mp.release();
            mp = null;
        }
 }
 public void setSoundState(boolean state)
 {
  soundstate = state;
 }
 public boolean getSoundState()
 {
  return soundstate;
 }
 // Helper method that translates a filename in res/raw to a resource id
 public static int getRaw(Context context, String name)
 {

     return context.getResources().getIdentifier(name,
             "raw", context.getPackageName());
 }

}

No comments: