Uses 59K of libraries. Click here for Pure Java version (661L/6K/15K).
1 | !7 |
2 | |
3 | // AudioLoop from jsresources.org |
4 | |
5 | import javax.sound.sampled.DataLine; |
6 | import javax.sound.sampled.SourceDataLine; |
7 | import javax.sound.sampled.TargetDataLine; |
8 | import javax.sound.sampled.AudioFormat; |
9 | import javax.sound.sampled.AudioSystem; |
10 | import javax.sound.sampled.LineUnavailableException; |
11 | import javax.sound.sampled.Mixer; |
12 | import javax.sound.sampled.AudioFileFormat; |
13 | |
14 | import gnu.getopt.Getopt; lib 1009286 // getopt |
15 | |
16 | static boolean DEBUG; |
17 | static final int DEFAULT_INTERNAL_BUFSIZ = 40960; |
18 | static final int DEFAULT_EXTERNAL_BUFSIZ = 40960; |
19 | |
20 | |
21 | p { |
22 | String strMixerName = null; |
23 | float fFrameRate = 44100.0F; |
24 | int nInternalBufferSize = DEFAULT_INTERNAL_BUFSIZ; |
25 | int nExternalBufferSize = DEFAULT_EXTERNAL_BUFSIZ; |
26 | |
27 | Getopt g = new Getopt("AudioLoop", args, "hlr:i:e:M:D"); |
28 | int c; |
29 | while ((c = g.getopt()) != -1) |
30 | { |
31 | switch (c) |
32 | { |
33 | case 'h': |
34 | printUsage(); |
35 | ret; |
36 | |
37 | case 'l': |
38 | javaSound_listMixers(); |
39 | ret; |
40 | |
41 | case 'r': |
42 | fFrameRate = Float.parseFloat(g.getOptarg()); |
43 | if (DEBUG) { out("AudioLoop.main(): frame rate: " + fFrameRate); } |
44 | break; |
45 | |
46 | case 'i': |
47 | nInternalBufferSize = Integer.parseInt(g.getOptarg()); |
48 | if (DEBUG) { out("AudioLoop.main(): internal buffer size: " + nInternalBufferSize); } |
49 | break; |
50 | |
51 | case 'e': |
52 | nExternalBufferSize = Integer.parseInt(g.getOptarg()); |
53 | if (DEBUG) { out("AudioLoop.main(): external buffer size: " + nExternalBufferSize); } |
54 | break; |
55 | |
56 | case 'M': |
57 | strMixerName = g.getOptarg(); |
58 | if (DEBUG) { out("AudioLoop.main(): mixer name: " + strMixerName); } |
59 | break; |
60 | |
61 | case 'D': |
62 | DEBUG = true; |
63 | break; |
64 | |
65 | case '?': |
66 | printUsage(); |
67 | ret; |
68 | |
69 | default: |
70 | out("AudioLoop.main(): getopt() returned: " + c); |
71 | break; |
72 | } |
73 | } |
74 | AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, fFrameRate, 16, 2, 4, fFrameRate, false); |
75 | if (DEBUG) { out("AudioLoop.main(): audio format: " + audioFormat); } |
76 | AudioLoop audioLoop = null; |
77 | try |
78 | { |
79 | audioLoop = new AudioLoop(audioFormat, |
80 | nInternalBufferSize, |
81 | nExternalBufferSize, |
82 | strMixerName); |
83 | } |
84 | catch (LineUnavailableException e) |
85 | { |
86 | e.printStackTrace(); |
87 | System.exit(1); |
88 | } |
89 | audioLoop.start(); |
90 | } |
91 | |
92 | |
93 | // TODO: params for audio quality, optionally use compression and decompression in the loop (see ~/AudioLoop.java) |
94 | |
95 | /** <titleabbrev>AudioLoop</titleabbrev> |
96 | <title>Recording and playing back the recorded data immediately</title> |
97 | |
98 | <formalpara><title>Purpose</title> |
99 | <para> |
100 | This program opens two lines: one for recording and one |
101 | for playback. In an infinite loop, it reads data from |
102 | the recording line and writes them to the playback line. |
103 | You can use this to measure the delays inside Java Sound: |
104 | Speak into the microphone and wait untill you hear |
105 | yourself in the speakers. This can be used to |
106 | experience the effect of changing the buffer sizes: use |
107 | the <option>-e</option> and <option>-i</option> options. |
108 | You will notice that the |
109 | delays change, too. |
110 | </para></formalpara> |
111 | |
112 | <formalpara><title>Usage</title> |
113 | <para> |
114 | <cmdsynopsis> |
115 | <command>java AudioLoop</command> |
116 | <arg choice="plain"><option>-l</option></arg> |
117 | </cmdsynopsis> |
118 | <cmdsynopsis> |
119 | <command>java AudioLoop</command> |
120 | <arg><option>-M <replaceable>mixername</replaceable></option></arg> |
121 | <arg><option>-e <replaceable>buffersize</replaceable></option></arg> |
122 | <arg><option>-i <replaceable>buffersize</replaceable></option></arg> |
123 | </cmdsynopsis> |
124 | </para></formalpara> |
125 | |
126 | <formalpara><title>Parameters</title> |
127 | <variablelist> |
128 | <varlistentry> |
129 | <term><option>-l</option></term> |
130 | <listitem><para>lists the available mixers</para></listitem> |
131 | </varlistentry> |
132 | <varlistentry> |
133 | <term><option>-M <replaceable>mixername</replaceable></option></term> |
134 | <listitem><para>selects a mixer to play on</para></listitem> |
135 | </varlistentry> |
136 | <varlistentry> |
137 | <term><option>-e <replaceable>buffersize</replaceable></option></term> |
138 | <listitem><para>the buffer size to use in the application ("extern")</para></listitem> |
139 | </varlistentry> |
140 | <varlistentry> |
141 | <term><option>-i <replaceable>buffersize</replaceable></option></term> |
142 | <listitem><para>the buffer size to use in Java Sound ("intern")</para></listitem> |
143 | </varlistentry> |
144 | </variablelist> |
145 | </formalpara> |
146 | |
147 | <formalpara><title>Bugs, limitations</title> |
148 | <para> |
149 | There is no way to stop the program besides brute force |
150 | (ctrl-C). There is no way to set the audio quality. |
151 | </para> |
152 | |
153 | <para>The example requires that the soundcard and its driver |
154 | as well as the Java Sound implementation support full-duplex |
155 | operation. In Linux either use <ulink |
156 | url="http://www.tritonus.org/">Tritonus</ulink> or enable |
157 | full-duplex in Sun's Java Sound implementation (search the |
158 | archive of java-linux).</para> |
159 | </formalpara> |
160 | |
161 | <formalpara><title>Source code</title> |
162 | <para> |
163 | <ulink url="AudioLoop.java.html">AudioLoop.java</ulink>, |
164 | <ulink url="AudioCommon.java.html">AudioCommon.java</ulink>, |
165 | <ulink url="http://www.urbanophile.com/arenn/hacking/download.html">gnu.getopt.Getopt</ulink> |
166 | </para> |
167 | </formalpara> |
168 | */ |
169 | sclass AudioLoop extends Thread { |
170 | private TargetDataLine m_targetLine; |
171 | private SourceDataLine m_sourceLine; |
172 | private boolean m_bRecording; |
173 | private int m_nExternalBufferSize; |
174 | |
175 | |
176 | /* |
177 | * We have to pass an AudioFormat to describe in which |
178 | * format the audio data should be recorded and played. |
179 | */ |
180 | public AudioLoop(AudioFormat format, |
181 | int nInternalBufferSize, |
182 | int nExternalBufferSize, |
183 | String strMixerName) |
184 | throws LineUnavailableException |
185 | { |
186 | Mixer mixer = null; |
187 | if (strMixerName != null) |
188 | { |
189 | Mixer.Info mixerInfo = javaSound_getMixerInfo(strMixerName); |
190 | if (DEBUG) { out("AudioLoop.<init>(): mixer info: " + mixerInfo); } |
191 | mixer = AudioSystem.getMixer(mixerInfo); |
192 | if (DEBUG) { out("AudioLoop.<init>(): mixer: " + mixer); } |
193 | } |
194 | /* |
195 | * We retrieve and open the recording and the playback line. |
196 | */ |
197 | DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format, nInternalBufferSize); |
198 | DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, format, nInternalBufferSize); |
199 | if (mixer != null) |
200 | { |
201 | m_targetLine = (TargetDataLine) mixer.getLine(targetInfo); |
202 | m_sourceLine = (SourceDataLine) mixer.getLine(sourceInfo); |
203 | } |
204 | else |
205 | { |
206 | m_targetLine = (TargetDataLine) AudioSystem.getLine(targetInfo); |
207 | m_sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo); |
208 | } |
209 | if (DEBUG) { out("AudioLoop.<init>(): SourceDataLine: " + m_sourceLine); } |
210 | if (DEBUG) { out("AudioLoop.<init>(): TargetDataLine: " + m_targetLine); } |
211 | m_targetLine.open(format, nInternalBufferSize); |
212 | m_sourceLine.open(format, nInternalBufferSize); |
213 | m_nExternalBufferSize = nExternalBufferSize; |
214 | } |
215 | |
216 | public void start() { |
217 | m_targetLine.start(); |
218 | m_sourceLine.start(); |
219 | super.start(); |
220 | } |
221 | |
222 | public void run() { |
223 | byte[] abBuffer = new byte[m_nExternalBufferSize]; |
224 | int nBufferSize = abBuffer.length; |
225 | m_bRecording = true; |
226 | while (m_bRecording) { |
227 | if (DEBUG) { out("Trying to read: " + nBufferSize); } |
228 | /* |
229 | * read a block of data from the recording line. |
230 | */ |
231 | int nBytesRead = m_targetLine.read(abBuffer, 0, nBufferSize); |
232 | if (DEBUG) { out("Read: " + nBytesRead); } |
233 | /* |
234 | * And now, we write the block to the playback |
235 | * line. |
236 | */ |
237 | m_sourceLine.write(abBuffer, 0, nBytesRead); |
238 | } |
239 | } |
240 | } |
241 | |
242 | svoid out(S s) { print(s); } |
243 | |
244 | static void printUsage() { |
245 | out("AudioLoop: usage:"); |
246 | out("\tjava AudioLoop -h"); |
247 | out("\tjava AudioLoop -l"); |
248 | out("\tjava AudioLoop [-D] [-M <mixername>] [-e <buffersize>] [-i <buffersize>]"); |
249 | } |
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, wtqryiryparv
No comments. add comment
Snippet ID: | #1009283 |
Snippet name: | Echo! [WORKS] |
Eternal ID of this version: | #1009283/10 |
Text MD5: | 6ad6865d8594e4cc800646974e5e6a5e |
Transpilation MD5: | c134b729202e6fe00cd4a22744a0ec31 |
Author: | stefan |
Category: | javax / sound |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2017-07-21 01:37:51 |
Source code size: | 7684 bytes / 249 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 433 / 559 |
Version history: | 9 change(s) |
Referenced in: | [show references] |