DummySourceDataLine.java revision 8729:0242fce0f717
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
24import java.util.ArrayList;
25
26import javax.sound.sampled.AudioFormat;
27import javax.sound.sampled.AudioSystem;
28import javax.sound.sampled.Control;
29import javax.sound.sampled.DataLine;
30import javax.sound.sampled.LineListener;
31import javax.sound.sampled.LineUnavailableException;
32import javax.sound.sampled.SourceDataLine;
33import javax.sound.sampled.AudioFormat.Encoding;
34import javax.sound.sampled.Control.Type;
35
36import 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
45public 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}
231