JavaSoundAudioDevice.java 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * 11/26/04 Buffer size modified to support JRE 1.5 optimizations.
  3. * (CPU usage < 1% under P4/2Ghz, RAM < 12MB).
  4. * jlayer@javazoom.net
  5. * 11/19/04 1.0 moved to LGPL.
  6. * 06/04/01 Too fast playback fixed. mdm@techie.com
  7. * 29/01/00 Initial version. mdm@techie.com
  8. *-----------------------------------------------------------------------
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Library General Public License as published
  11. * by the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Library General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Library General Public
  20. * License along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. *----------------------------------------------------------------------
  23. */
  24. package javazoom.jl.player;
  25. import javax.sound.sampled.AudioFormat;
  26. import javax.sound.sampled.AudioSystem;
  27. import javax.sound.sampled.DataLine;
  28. import javax.sound.sampled.Line;
  29. import javax.sound.sampled.LineUnavailableException;
  30. import javax.sound.sampled.SourceDataLine;
  31. import javazoom.jl.decoder.Decoder;
  32. import javazoom.jl.decoder.JavaLayerException;
  33. /**
  34. * The <code>JavaSoundAudioDevice</code> implements an audio
  35. * device by using the JavaSound API.
  36. *
  37. * @since 0.0.8
  38. * @author Mat McGowan
  39. */
  40. public class JavaSoundAudioDevice extends AudioDeviceBase
  41. {
  42. private SourceDataLine source = null;
  43. private AudioFormat fmt = null;
  44. private byte[] byteBuf = new byte[4096];
  45. protected void setAudioFormat(AudioFormat fmt0)
  46. {
  47. fmt = fmt0;
  48. }
  49. protected AudioFormat getAudioFormat()
  50. {
  51. if (fmt==null)
  52. {
  53. Decoder decoder = getDecoder();
  54. fmt = new AudioFormat(decoder.getOutputFrequency(),
  55. 16,
  56. decoder.getOutputChannels(),
  57. true,
  58. false);
  59. }
  60. return fmt;
  61. }
  62. protected DataLine.Info getSourceLineInfo()
  63. {
  64. AudioFormat fmt = getAudioFormat();
  65. //DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, 4000);
  66. DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);
  67. return info;
  68. }
  69. public void open(AudioFormat fmt) throws JavaLayerException
  70. {
  71. if (!isOpen())
  72. {
  73. setAudioFormat(fmt);
  74. openImpl();
  75. setOpen(true);
  76. }
  77. }
  78. protected void openImpl()
  79. throws JavaLayerException
  80. {
  81. }
  82. // createSource fix.
  83. protected void createSource() throws JavaLayerException
  84. {
  85. Throwable t = null;
  86. try
  87. {
  88. Line line = AudioSystem.getLine(getSourceLineInfo());
  89. if (line instanceof SourceDataLine)
  90. {
  91. source = (SourceDataLine)line;
  92. //source.open(fmt, millisecondsToBytes(fmt, 2000));
  93. source.open(fmt);
  94. /*
  95. if (source.isControlSupported(FloatControl.Type.MASTER_GAIN))
  96. {
  97. FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN);
  98. c.setValue(c.getMaximum());
  99. }*/
  100. source.start();
  101. }
  102. } catch (RuntimeException ex)
  103. {
  104. t = ex;
  105. }
  106. catch (LinkageError ex)
  107. {
  108. t = ex;
  109. }
  110. catch (LineUnavailableException ex)
  111. {
  112. t = ex;
  113. }
  114. if (source==null) throw new JavaLayerException("cannot obtain source audio line", t);
  115. }
  116. public int millisecondsToBytes(AudioFormat fmt, int time)
  117. {
  118. return (int)(time*(fmt.getSampleRate()*fmt.getChannels()*fmt.getSampleSizeInBits())/8000.0);
  119. }
  120. protected void closeImpl()
  121. {
  122. if (source!=null)
  123. {
  124. source.close();
  125. }
  126. }
  127. protected void writeImpl(short[] samples, int offs, int len)
  128. throws JavaLayerException
  129. {
  130. if (source==null)
  131. createSource();
  132. byte[] b = toByteArray(samples, offs, len);
  133. source.write(b, 0, len*2);
  134. }
  135. protected byte[] getByteArray(int length)
  136. {
  137. if (byteBuf.length < length)
  138. {
  139. byteBuf = new byte[length+1024];
  140. }
  141. return byteBuf;
  142. }
  143. protected byte[] toByteArray(short[] samples, int offs, int len)
  144. {
  145. byte[] b = getByteArray(len*2);
  146. int idx = 0;
  147. short s;
  148. while (len-- > 0)
  149. {
  150. s = samples[offs++];
  151. b[idx++] = (byte)s;
  152. b[idx++] = (byte)(s>>>8);
  153. }
  154. return b;
  155. }
  156. protected void flushImpl()
  157. {
  158. if (source!=null)
  159. {
  160. source.drain();
  161. }
  162. }
  163. public int getPosition()
  164. {
  165. int pos = 0;
  166. if (source!=null)
  167. {
  168. pos = (int)(source.getMicrosecondPosition()/1000);
  169. }
  170. return pos;
  171. }
  172. /**
  173. * Runs a short test by playing a short silent sound.
  174. */
  175. public void test()
  176. throws JavaLayerException
  177. {
  178. try
  179. {
  180. open(new AudioFormat(22050, 16, 1, true, false));
  181. short[] data = new short[22050/10];
  182. write(data, 0, data.length);
  183. flush();
  184. close();
  185. }
  186. catch (RuntimeException ex)
  187. {
  188. throw new JavaLayerException("Device test failed: "+ex);
  189. }
  190. }
  191. }