Example resolution USES Java to implement the basic audio player writing points

  • 2020-04-01 04:36:45
  • OfStack

  Java audio playback, because must rely on the local environment, so Java in the audio processing advantage is not big, or since the development of Java system did not consider the audio playback factor too much, you know the earliest version of Java 1.1, there is no later javax.sound package, audio can only be transferred through the Applet package......

  Unfortunately, in the graphics program development, our program is unavoidable to use background music, effect sound and so on to cooperate with the image operation, ah, this is really the Sun god gave us a not small joke. Fortunately, Sun came to our rescue with the javax.sound package

  But the problem that followed was that the use of the javax.sound package, as is the case with Java multimedia tools, didn't provide a very good release mechanism. Windows development, if we do call MediaPlayer repeated N times may not be what is ok also, but in Java, if audio program can run over and over again, very prone to the cumulative loss of memory, so that the last thrown a Java. Lang. OutOfMemoryError, then... The program hangs, the user is stupid, we are crazy...

This has been the "is intolerable" problem, in view of this, so in my Loonframework development, the second integration of sound under the relevant methods, and strive to the simplest code, make the most perfect audio control class. In the Loonframework-game is not great now, the first part of the method, for you to see - brick!

Corresponding to the network resource call, in the Loonframework to establish their own uri class, the basic content is as follows:
(StreamHelper is Loonframework's own streaming media control class,getHttpStream method please replace.)


package org.loon.framework.game.net;

import org.loon.framework.game.helper.StreamHelper;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:Loonframework special uri( Uniform resource identifiers )
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email : ceponline@yahoo.com.cn
 * @version 0.1
 */
public class URI ...{

  //Transport protocol type
  public static final int _L_URI_HTTP = 1;

  public static final int _L_URI_UDP = 2;

  private String _uri;

  private int _type;

  
  public URI(String uri, int type) ...{
    _uri = new String(uri);
    _type = type;
  }

  
  public URI(String uri) ...{
    _uri = new String(uri);
    _type = URI._L_URI_HTTP;
  }

  
  public byte[] getData() ...{
    if (_uri == null) ...{
      return null;
    }
    return StreamHelper.getHttpStream(_uri);
  }

  public String getURI() ...{
    return _uri;
  }

  public int getType() ...{
    return _type;
  }

}

 in Loonframework The framework of , Custom made with a base SoundData class , For unified management of audio data sources. 

package org.loon.framework.game.sound;

import org.loon.framework.game.helper.StreamHelper;
import org.loon.framework.game.net.URI;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description: To obtain and cache sound file data (see further operations) Loonframework-game Framework) 
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email : ceponline@yahoo.com.cn
 * @version 0.1
 */
public class SoundData ...{

  private byte[] _data;

  private boolean _loop;

  private int _type;

  public static final int _L_SOUNDTYPE_MIDI = 1;

  public static final int _L_SOUNDTYPE_WAV = 2;

  
  public SoundData(URI uri, int type, boolean loop) ...{
    if (uri != null) ...{
      _data = uri.getData();
    }
    _type = type;
    _loop = loop;
  }
  
  
  public SoundData(byte[] data, int type, boolean loop) ...{

    if (data != null && data.length > 0) ...{
      _data = new byte[data.length];
      //Copy byte array directly
      System.arraycopy(data, 0, _data, 0, _data.length);
    }
    _type = type;
    _loop = loop;
  }
  
  
  public SoundData(String resName, int type, boolean loop) ...{
    this(StreamHelper.GetDataSource(resName),type,loop);
  }

  public byte[] getData() ...{
    return _data;
  }

  public boolean getLoop() ...{
    return _loop;
  }

  public void setLoop(boolean loop) ...{
    _loop = loop;
  }

  public int getType() ...{
    return _type;
  }

}

Loonframework will audio playback related methods, packaging and SoundPlay, programmers can ignore the internal details of javax.sound, but directly call SoundPlay to complete the relevant operations.


package org.loon.framework.game.sound;

import java.io.ByteArrayInputStream;

import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;

import org.loon.framework.game.net.URI;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description: For sound file manipulation ( Only for Loonframework Part of the method, see for more details Loonframework-game The framework )
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email : ceponline@yahoo.com.cn
 * @version 0.1
 */
public class SoundPlay implements MetaEventListener, Runnable ...{

  private int _sleepTime;

  private Clip _audio;

  private Sequencer _midi;

  private boolean _loop;

  private int _soundType;

  private boolean _playing;

  private Thread _thread = null;

  private boolean _isRun = false;

  
  public SoundPlay() ...{

    _loop = false;
    _soundType = 0;
    _sleepTime = 1000;
    _playing = false;

  }

  //Load sound file
  public boolean load(SoundData data) ...{
    reset();
    if (data == null || data.getData() == null) ...{
      return false;
    }
    return init(data.getData(), data.getType(), data.getLoop());
  }

  
  public boolean load(URI uri, int ftype, boolean loop) ...{

    //The refresh data
    reset();
    if (uri == null) ...{
      return false;
    }
    //Get SoundData
    SoundData data = new SoundData(uri, ftype, loop);
    if (data == null || data.getData() == null) ...{
      return false;
    }
    return init(data.getData(), data.getType(), data.getLoop());

  }

  
  private boolean init(byte[] data, int ftype, boolean loop) ...{
    boolean result = false;

    ByteArrayInputStream bis = null;

    try ...{
      bis = new ByteArrayInputStream(data);
    } catch (Exception e) ...{
      bis = null;
    }

    if (bis == null) ...{
      return false;
    }

    //Determine type
    switch (ftype) ...{

    // MIDI
    case SoundData._L_SOUNDTYPE_MIDI:

      //When MIDI does not exist
      if (_midi == null) ...{

        try ...{
          //Get the Sequencer
          _midi = MidiSystem.getSequencer();
          _midi.open();

        } catch (Exception ex) ...{
          _midi = null;
        }

        if (_midi != null) ...{
          _midi.addMetaEventListener(this);
        }

      }

      //When MIDI is still not available
      if (_midi != null) ...{
        //Recreate the Sequence
        Sequence sc = null;

        try ...{
          sc = MidiSystem.getSequence(bis);
        } catch (Exception e) ...{
          sc = null;
        }

        if (sc != null) ...{

          try ...{

            _midi.setSequence(sc);

            //Gets whether to loop
            _loop = loop;

            //Get whether or not to load
            result = true;

          } catch (Exception ee) ...{
          }

          //Get the sound type
          _soundType = SoundData._L_SOUNDTYPE_MIDI;

        }

      }

      try ...{
        bis.close();
      } catch (Exception ee) ...{
      }

      break;

    // Wav
    case SoundData._L_SOUNDTYPE_WAV:

      AudioFileFormat type = null;

      //Get the Audio
      try ...{
        type = AudioSystem.getAudioFileFormat(bis);
      } catch (Exception e) ...{
        type = null;
      }

      //Close the stream
      try ...{
        bis.close();
      } catch (Exception ex) ...{
      }

      if (type == null) ...{
        return false;
      }

      //Constructs an information object for a data row based on the specified information
      DataLine.Info di = new DataLine.Info(Clip.class, type.getFormat());

      //To Clip
      try ...{
        _audio = (Clip) AudioSystem.getLine(di);
      } catch (Exception e) ...{
      }

      //Play the file
      try ...{

        _audio.open(type.getFormat(), data, 0, data.length);

        _loop = loop;

        result = true;

      } catch (Exception e) ...{
      }

      //Get file type
      _soundType = SoundData._L_SOUNDTYPE_WAV;

      break;

    }

    return result;
  }

  public boolean play(SoundData data) ...{

    if (!load(data)) ...{
      return false;
    }

    return play();

  }

  public boolean play() ...{

    switch (_soundType) ...{

    case SoundData._L_SOUNDTYPE_MIDI:

      try ...{

        _midi.start();

        _playing = true;

        _soundType = SoundData._L_SOUNDTYPE_MIDI;

      } catch (Exception ee) ...{
      }

      break;

    case SoundData._L_SOUNDTYPE_WAV:

      if (_audio != null) ...{

        if (_loop) ...{

          //Set the cycle
          _audio.setLoopPoints(0, -1);
          _audio.setFramePosition(0);

          _audio.loop(Clip.LOOP_CONTINUOUSLY);

        } else ...{

          //Force the play position to 0
          _audio.setFramePosition(0);

          _audio.start();

        }

        _playing = true;

      }

      break;

    }

    return _playing;

  }

  
  public boolean AutoPlay(SoundData data) ...{
    if (!load(data)) ...{
      return false;
    }
    return AutoPlay();
  }

  
  public boolean AutoPlay() ...{
    _isRun = true;
    _thread = new Thread(this);
    _thread.start();
    return _playing;
  }

  
  public void stop() ...{

    if (_audio != null && _audio.isActive()) ...{
      try ...{
        _audio.stop();
      } catch (Exception e) ...{
      }
    }

    if (_midi != null) ...{
      _midi.stop();
    }
    _playing = false;
    _isRun = false;
  }

  
  public void reset() ...{

    stop();

    _loop = false;
    _soundType = 0;

    if (_midi != null) ...{

      _midi.close();

      _midi = null;

    }

    if (_audio != null && _audio.isOpen()) ...{

      _audio.close();

      _audio = null;

    }
    _isRun = false;
    _thread = null;
  }

  
  public void meta(MetaMessage meta) ...{
    //Determines if MIDI is looped
    if (_loop && _soundType == SoundData._L_SOUNDTYPE_MIDI
        && meta.getType() == 47) ...{

      if (_midi != null && _midi.isOpen()) ...{
        _midi.setMicrosecondPosition(0);
        _midi.start();

      }
    }

  }

  public void run() ...{
    while (_isRun) ...{
      play();
      //Because the play type is unique, only an _playing result is returned to determine this.
      if (_midi != null) ...{
        _playing = _midi.isRunning();
      }
      if (_audio != null) ...{
        _playing = _audio.isRunning();
      }
      //When play stops
      if (!_playing) ...{
        //The release of
        reset();
      }
      try ...{
        Thread.sleep(_sleepTime);
      } catch (InterruptedException e) ...{
        e.printStackTrace();
      }
    }
  }

  public int getSleepTime() ...{
    return _sleepTime;
  }

  
  public void setSleepTime(int time) ...{
    _sleepTime = time;
  }
}

Instead of having to deal with the heavy and heavy javax.sound, we had to deal with SoundData data and SoundPlay operations encapsulated as entities.

The method is as follows:


package org.test;

import org.loon.framework.game.helper.StreamHelper;
import org.loon.framework.game.net.URI;
import org.loon.framework.game.sound.SoundData;
import org.loon.framework.game.sound.SoundPlay;

/**
 * <p>Title: LoonFramework</p>
 * <p>Description:SoundPlay Play the test </p>
 * <p>Copyright: Copyright (c) 2007</p>
 * <p>Company: LoonFramework</p>
 * @author chenpeng 
 * @email : ceponline@yahoo.com.cn 
 * @version 0.1
 */
public class SoundPlayTest ...{

  static void selectPlay(int ftype)...{
    SoundData data=null;
    
    switch(ftype)...{
    //Play music from the network through the uri under the loonframework
    case 0:
      data=new SoundData(new URI("http://looframework.sourceforge.net/midi/ Who is the big hero .mid"),SoundData._L_SOUNDTYPE_MIDI,false);
      break;
    //Play music through the byte[] object of the music file under the local resource
    case 1:
      byte[] bytes=StreamHelper.GetResourceData("/midi/ Who is the big hero .mid");
      data=new SoundData(bytes,SoundData._L_SOUNDTYPE_MIDI,false);
      break;
      //Play music through the music file path
    case 2:
      data=new SoundData("C:/ Who is the big hero .mid",SoundData._L_SOUNDTYPE_MIDI,false);
      break;
    }
    SoundPlay play=new SoundPlay();
    //The difference between AutoPlay and Play method is that AutoPlay will automatically stop and release resources after playing, and Play needs to be stopped manually.
    //play.play(data);
    play.AutoPlay(data);
  }
  
  public static void main(String[]args)...{
    selectPlay(2);
  }
  
}

More detailed methods will be explained after the complete release of Loonframework-game.

In addition, since StreamHelper is associated with other methods in the Loonframework, inputStream to byte[] can be written as follows:


//Is for the inputStream obtained

  ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//To take byte[]
    byte[] arrayByte = null;
    try ...{
      //Each transfer size is 4096
      byte[] bytes = new byte[4096];
      bytes = new byte[is.available()];
      int read;
      while ((read = is.read(bytes)) >= 0) ...{
        byteArrayOutputStream.write(bytes, 0, read);
      }
      arrayByte = byteArrayOutputStream.toByteArray();
    } catch (IOException e) ...{
      return null;
    } finally ...{
      try ...{
        if (byteArrayOutputStream != null) ...{
          byteArrayOutputStream.close();
          byteArrayOutputStream = null;
        }
        if (is != null) ...{
          is.close();
          is = null;
        }

      } catch (IOException e) ...{
      }
    }


Related articles: