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