samer@0
|
1 /*
|
samer@0
|
2 * LineSink.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2000, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 */
|
samer@0
|
11
|
samer@0
|
12 package samer.audio;
|
samer@0
|
13 import samer.core.*;
|
samer@0
|
14 import samer.core.types.*;
|
samer@0
|
15 import samer.tools.*;
|
samer@0
|
16 import java.io.*;
|
samer@0
|
17 import javax.sound.sampled.*;
|
samer@0
|
18
|
samer@0
|
19 /**
|
samer@0
|
20 An AudioSink that sends samples to a Java Sound SourceDataLine.
|
samer@0
|
21 Audio format can be determined in several ways (see below).
|
samer@0
|
22 <p> Object is a Viewable, and is called "lineout".
|
samer@0
|
23 Reads property "scale" from current environment, but scale
|
samer@0
|
24 can be adjusted afterwards.
|
samer@0
|
25 @see samer.audio.AudioSink
|
samer@0
|
26 */
|
samer@0
|
27
|
samer@0
|
28 public class LineSink extends VLine implements AudioSink
|
samer@0
|
29 {
|
samer@0
|
30 private SourceDataLine line;
|
samer@0
|
31 private AudioFormat fmt;
|
samer@0
|
32 private int bufsize=0;
|
samer@0
|
33 private VDouble scale;
|
samer@0
|
34
|
samer@0
|
35 /** Create LineSink reading from given TargetDataLine */
|
samer@0
|
36 public LineSink(SourceDataLine l, AudioFormat f) throws Exception {
|
samer@0
|
37 super("lineout");
|
samer@0
|
38 line=l; fmt=f;
|
samer@0
|
39 Shell.push(getNode());
|
samer@0
|
40 scale=new VDouble("scale",1.0,0);
|
samer@0
|
41 Shell.pop();
|
samer@0
|
42 }
|
samer@0
|
43
|
samer@0
|
44 public DataLine getLine() { return line; }
|
samer@0
|
45 public boolean isOpen() { return line.isOpen(); }
|
samer@0
|
46 public void setBufferSize(int b) { bufsize=b; }
|
samer@0
|
47
|
samer@0
|
48 /**
|
samer@0
|
49 * Returns the object used to store the scale factor for conversion from
|
samer@0
|
50 * doubles/floats to shorts/bytes. This is multiplied by 128 for conversion
|
samer@0
|
51 * to 8 bit audio, or 32768 for conversion to 16 bit audio.
|
samer@0
|
52 */
|
samer@0
|
53 public VDouble getScale() { return scale; }
|
samer@0
|
54
|
samer@0
|
55 public void dispose() { scale.dispose(); super.dispose(); }
|
samer@0
|
56
|
samer@0
|
57 /** Open the line using either the current format or the line's default format if
|
samer@0
|
58 * none has been set.
|
samer@0
|
59 */
|
samer@0
|
60 public void openImpl() throws Exception {
|
samer@0
|
61 if (bufsize==0) line.open(fmt); else line.open(fmt,bufsize);
|
samer@0
|
62 }
|
samer@0
|
63
|
samer@0
|
64 public void closeImpl() throws Exception { line.close(); }
|
samer@0
|
65
|
samer@0
|
66 /** Commands are :"set scale". */
|
samer@0
|
67 public void getCommands(Registry r) {
|
samer@0
|
68 r.add("set scale").group();
|
samer@0
|
69 super.getCommands(r);
|
samer@0
|
70 }
|
samer@0
|
71
|
samer@0
|
72 public void execute(String cmd, Environment env) throws Exception {
|
samer@0
|
73 if (cmd.equals("set scale")) { env.datum().get(scale); }
|
samer@0
|
74 else super.execute(cmd,env);
|
samer@0
|
75 }
|
samer@0
|
76
|
samer@0
|
77 public Task writer(final double dbuf[], final int off, final int len) {
|
samer@0
|
78 return new Writer(2*len) {
|
samer@0
|
79 public void write(double dbuf[], int off, int len) throws Exception {
|
samer@0
|
80 Util.doubleToShort(dbuf,buf,off,len,scale.value);
|
samer@0
|
81 super.write(2*len);
|
samer@0
|
82 }
|
samer@0
|
83 public void run() throws Exception {
|
samer@0
|
84 super.run(); Util.doubleToShort(dbuf,buf,off,len,scale.value);
|
samer@0
|
85 }
|
samer@0
|
86 };
|
samer@0
|
87 }
|
samer@0
|
88
|
samer@0
|
89 public Task writer(final float dbuf[], final int off, final int len) {
|
samer@0
|
90 return new Writer(2*len) {
|
samer@0
|
91 public void write(float dbuf[], int off, int len) throws Exception {
|
samer@0
|
92 Util.floatToShort(dbuf,buf,off,len,(float)scale.value);
|
samer@0
|
93 super.write(2*len);
|
samer@0
|
94 }
|
samer@0
|
95 public void run() throws Exception {
|
samer@0
|
96 super.run(); Util.floatToShort(dbuf,buf,off,len,(float)scale.value);
|
samer@0
|
97 }
|
samer@0
|
98 };
|
samer@0
|
99 }
|
samer@0
|
100
|
samer@0
|
101 protected class Writer implements Task {
|
samer@0
|
102 byte buf[];
|
samer@0
|
103 int size;
|
samer@0
|
104
|
samer@0
|
105 public Writer(int bufsize) { size=bufsize; buf=new byte[size]; }
|
samer@0
|
106
|
samer@0
|
107 public void starting() { start(); }
|
samer@0
|
108 public void stopping() { stop(); }
|
samer@0
|
109 public void dispose() {}
|
samer@0
|
110 public void run() throws Exception {
|
samer@0
|
111 if (line.write(buf,0,size)<=0) throw new EOFException();
|
samer@0
|
112 changed();
|
samer@0
|
113 }
|
samer@0
|
114
|
samer@0
|
115 public void write(int size) throws Exception {
|
samer@0
|
116 if (line.write(buf,0,size)<=0) throw new EOFException();
|
samer@0
|
117 changed();
|
samer@0
|
118 }
|
samer@0
|
119 }
|
samer@0
|
120
|
samer@0
|
121 public static DataLine.Info lineInfo(AudioFormat fmt) {
|
samer@0
|
122 return new DataLine.Info( SourceDataLine.class, fmt);
|
samer@0
|
123 }
|
samer@0
|
124
|
samer@0
|
125 public static DataLine.Info lineInfo(AudioFormat fmt, int bufsize) {
|
samer@0
|
126 return new DataLine.Info( SourceDataLine.class, fmt, bufsize);
|
samer@0
|
127 }
|
samer@0
|
128 }
|
samer@0
|
129
|