1 /*
   2  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.util.ArrayList;
  25 
  26 import javax.sound.sampled.AudioFormat;
  27 import javax.sound.sampled.AudioSystem;
  28 import javax.sound.sampled.Control;
  29 import javax.sound.sampled.DataLine;
  30 import javax.sound.sampled.LineListener;
  31 import javax.sound.sampled.LineUnavailableException;
  32 import javax.sound.sampled.SourceDataLine;
  33 import javax.sound.sampled.AudioFormat.Encoding;
  34 import javax.sound.sampled.Control.Type;
  35 
  36 import com.sun.media.sound.AudioFloatConverter;
  37 
  38 /**
  39  * This is a SourceDataLine simulator used for testing SoftSynthesizer
  40  * without using real SourceDataLine / Audio Device.
  41  *
  42  * @author Karl Helgason
  43  */
  44 
  45 public class DummySourceDataLine implements SourceDataLine {
  46 
  47     private int bufferSize = -1;
  48 
  49     private AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false);
  50 
  51     private DataLine.Info sourceLineInfo;
  52 
  53     private boolean active = false;
  54 
  55     private long framepos = 0;
  56 
  57     private boolean opened = false;
  58 
  59     private int framesize = 0;
  60 
  61     public DummySourceDataLine()
  62     {
  63         ArrayList<AudioFormat> formats = new ArrayList<AudioFormat>();
  64         for (int channels = 1; channels <= 2; channels++) {
  65             formats.add(new AudioFormat(Encoding.PCM_SIGNED,
  66                     AudioSystem.NOT_SPECIFIED, 8, channels, channels,
  67                     AudioSystem.NOT_SPECIFIED, false));
  68             formats.add(new AudioFormat(Encoding.PCM_UNSIGNED,
  69                     AudioSystem.NOT_SPECIFIED, 8, channels, channels,
  70                     AudioSystem.NOT_SPECIFIED, false));
  71             for (int bits = 16; bits < 32; bits += 8) {
  72                 formats.add(new AudioFormat(Encoding.PCM_SIGNED,
  73                         AudioSystem.NOT_SPECIFIED, bits, channels, channels
  74                                 * bits / 8, AudioSystem.NOT_SPECIFIED, false));
  75                 formats.add(new AudioFormat(Encoding.PCM_UNSIGNED,
  76                         AudioSystem.NOT_SPECIFIED, bits, channels, channels
  77                                 * bits / 8, AudioSystem.NOT_SPECIFIED, false));
  78                 formats.add(new AudioFormat(Encoding.PCM_SIGNED,
  79                         AudioSystem.NOT_SPECIFIED, bits, channels, channels
  80                                 * bits / 8, AudioSystem.NOT_SPECIFIED, true));
  81                 formats.add(new AudioFormat(Encoding.PCM_UNSIGNED,
  82                         AudioSystem.NOT_SPECIFIED, bits, channels, channels
  83                                 * bits / 8, AudioSystem.NOT_SPECIFIED, true));
  84             }
  85             formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  86                     AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
  87                     AudioSystem.NOT_SPECIFIED, false));
  88             formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  89                     AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
  90                     AudioSystem.NOT_SPECIFIED, true));
  91             formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  92                     AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
  93                     AudioSystem.NOT_SPECIFIED, false));
  94             formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  95                     AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
  96                     AudioSystem.NOT_SPECIFIED, true));
  97         }
  98         AudioFormat[] formats_array = formats.toArray(new AudioFormat[formats
  99                 .size()]);
 100         sourceLineInfo = new DataLine.Info(SourceDataLine.class,
 101                 formats_array, AudioSystem.NOT_SPECIFIED,
 102                 AudioSystem.NOT_SPECIFIED);
 103 
 104     }
 105 
 106     public void open() throws LineUnavailableException {
 107         open(format);
 108     }
 109 
 110     public void open(AudioFormat format) throws LineUnavailableException {
 111         if (bufferSize == -1)
 112             bufferSize = ((int) (format.getFrameRate() / 2))
 113                     * format.getFrameSize();
 114         open(format, bufferSize);
 115     }
 116 
 117     public void open(AudioFormat format, int bufferSize)
 118             throws LineUnavailableException {
 119         this.format = format;
 120         this.bufferSize = bufferSize;
 121         this.framesize = format.getFrameSize();
 122         opened = true;
 123     }
 124 
 125     public boolean isOpen() {
 126         return opened;
 127     }
 128 
 129     public int write(byte[] b, int off, int len) {
 130         if (!isOpen())
 131             return 0;
 132         if (len % framesize != 0)
 133             throw new IllegalArgumentException(
 134                     "Number of bytes does not represent an integral number of sample frames.");
 135 
 136 
 137         int flen = len / framesize;
 138         framepos += flen;
 139 
 140         long time =  (long) (flen * (1000.0 / (double) getFormat()
 141                 .getSampleRate()));
 142         try {
 143             Thread.sleep(time);
 144         } catch (InterruptedException e) {
 145             e.printStackTrace();
 146             return 0;
 147         }
 148 
 149         return len;
 150     }
 151 
 152     public int available() {
 153         return 0;
 154     }
 155 
 156     public void drain() {
 157     }
 158 
 159     public void flush() {
 160     }
 161 
 162     public int getBufferSize() {
 163         return bufferSize;
 164     }
 165 
 166     public AudioFormat getFormat() {
 167         return format;
 168     }
 169 
 170     public int getFramePosition() {
 171         return (int) getLongFramePosition();
 172     }
 173 
 174     public float getLevel() {
 175         return AudioSystem.NOT_SPECIFIED;
 176     }
 177 
 178     public long getLongFramePosition() {
 179         return framepos;
 180     }
 181 
 182     public long getMicrosecondPosition() {
 183         return (long) (getLongFramePosition() * (1000000.0 / (double) getFormat()
 184                 .getSampleRate()));
 185     }
 186 
 187     public boolean isActive() {
 188         return active;
 189     }
 190 
 191     public boolean isRunning() {
 192         return active;
 193     }
 194 
 195     public void start() {
 196         active = true;
 197     }
 198 
 199     public void stop() {
 200         active = false;
 201     }
 202 
 203     public void close() {
 204         stop();
 205     }
 206 
 207     public Control getControl(Type control) {
 208         throw new IllegalArgumentException("Unsupported control type : "
 209                 + control);
 210     }
 211 
 212     public Control[] getControls() {
 213         return new Control[0];
 214     }
 215 
 216     public javax.sound.sampled.Line.Info getLineInfo() {
 217         return sourceLineInfo;
 218     }
 219 
 220     public boolean isControlSupported(Type control) {
 221         return false;
 222     }
 223 
 224     public void addLineListener(LineListener listener) {
 225     }
 226 
 227     public void removeLineListener(LineListener listener) {
 228     }
 229 
 230 }