initial commit

This commit is contained in:
2013-03-22 19:19:12 +01:00
commit 817fcc796d
44 changed files with 1931 additions and 0 deletions

15
.classpath Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="/Mimis/main.jar"/>
<classpathentry kind="lib" path="/Mimis/lib/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="/Mimis/lib/jxinput.jar"/>
<classpathentry kind="lib" path="/Mimis/lib/log4j-1.2.16.jar"/>
<classpathentry kind="lib" path="lib/jl1.0.1.jar"/>
<classpathentry kind="lib" path="lib/ostermillerutils-1.08.01.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.4.jar"/>
<classpathentry kind="lib" path="lib/commons-cli-1.2.jar"/>
<classpathentry kind="lib" path="lib/jid3lib-0.5.4.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/bin
/.settings
/sound

17
.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Sound</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

43
build.xml Normal file
View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="jar" name="Build file for Project Shoutcast">
<!-- All -->
<target name="all" depends="javadoc, jar, launch4j"></target>
<!-- Javadoc -->
<target name="javadoc">
<javadoc access="private" author="true" classpath="" destdir="doc" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" packagenames="mimis.exception.macro,mimis.device.network,wiiusej,mimis.application.itunes,mimis.exception.util,mimis.device.javainput,wiiusej.wiiusejevents,wiiusej.wiiusejevents.utils,mimis.util.swing,mimis.exception.worker,mimis.application.lirc,mimis.application.cmd.windows.winamp,wiiusej.values,mimis.exception.event,mimis.device.lirc.remote,mimis.device.panel,mimis.exception.device,mimis.exception.button,mimis.application.robot,mimis.application.lirc.ipod,mimis.exception.task.action,mimis.exception.application,wiiusej.wiiusejevents.wiiuseapievents,mimis.application.cmd.windows.gomplayer,mimis.application.mpc,org.wiigee.logic,mimis.device.lirc,mimis.sequence,mimis.manager,org.wiigee.util,mimis.event,mimis.application.cmd.windows.wmp,mimis.value,mimis.device.javainput.extreme3d,mimis.event.router,mimis.application.cmd,mimis.worker,org.wiigee.event,mimis.device.wiimote,mimis.device.wiimote.gesture.event,wiiusej.wiiusejevents.physicalevents,mimis.util.multiplexer,mimis,org.wiigee.control,mimis.exception.device.javainput,mimis.util,mimis.application.cmd.windows,com.dt.iTunesController,org.wiigee.device,mimis.application.vlc,mimis.device.wiimote.gesture,mimis.device.jintellitype,mimis.event.feedback,mimis.device,org.wiigee.filter,mimis.exception.application.windows,mimis.application,mimis.sequence.state,mimis.device.javainput.rumblepad,com.melloware.jintellitype,mimis.exception.event.router,mimis.exception.task,mimis.exception" source="1.6" sourcepath="src" splitindex="true" use="true" version="true" />
</target>
<!-- Jar -->
<target name="jar">
<property name="jar.dir" value="." />
<jar destfile="${jar.dir}/stream.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="udp.StreamClient" />
<attribute name="Class-Path" value="." />
</manifest>
<fileset dir="bin" />
<!--zipfileset excludes="META-INF/*.SF" src="lib/commons-logging-1.1.1.jar" /-->
</jar>
<!--copy todir="${jar.dir}">
<fileset dir=".">
<include name="*.dll" />
<include name="*.exe" />
</fileset>
</copy-->
</target>
<!-- Launch4j -->
<target name="launch4j" depends="jar">
<property name="launch4j.dir" location="C:\Program Files (x86)\Launch4j" />
<path id="launch4j">
<pathelement location="${launch4j.dir}/launch4j.jar" />
<pathelement location="${launch4j.dir}/lib/xstream.jar" />
</path>
<taskdef name="launch4j" classname="net.sf.launch4j.ant.Launch4jTask">
<classpath refid="launch4j" />
</taskdef>
<launch4j configFile="launch4j.xml" />
<delete file="launch4j.log" />
</target>
</project>

BIN
lame.exe Normal file

Binary file not shown.

22
launch4j.xml Normal file
View File

@@ -0,0 +1,22 @@
<launch4jConfig>
<dontWrapJar>false</dontWrapJar>
<headerType>gui</headerType>
<jar>stream.jar</jar>
<outfile>stream.exe</outfile>
<errTitle></errTitle>
<cmdLine></cmdLine>
<chdir></chdir>
<priority>normal</priority>
<downloadUrl>http://java.com/download</downloadUrl>
<supportUrl></supportUrl>
<customProcName>false</customProcName>
<stayAlive>false</stayAlive>
<manifest></manifest>
<icon></icon>
<jre>
<path></path>
<minVersion>1.6.0</minVersion>
<maxVersion></maxVersion>
<jdkPreference>preferJre</jdkPreference>
</jre>
</launch4jConfig>

BIN
lib/commons-cli-1.2.jar Normal file

Binary file not shown.

BIN
lib/commons-io-2.4.jar Normal file

Binary file not shown.

BIN
lib/jid3lib-0.5.4.jar Normal file

Binary file not shown.

BIN
lib/jl1.0.1.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
libgomp-1.dll Normal file

Binary file not shown.

BIN
libmad.dll Normal file

Binary file not shown.

BIN
libmp3lame.dll Normal file

Binary file not shown.

BIN
pipes.dll Normal file

Binary file not shown.

BIN
play.exe Normal file

Binary file not shown.

BIN
pthreadgc2.dll Normal file

Binary file not shown.

BIN
sox.exe Normal file

Binary file not shown.

BIN
soxi.exe Normal file

Binary file not shown.

186
src/old/Converter.java Normal file
View File

@@ -0,0 +1,186 @@
package old;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javazoom.jl.decoder.Bitstream;
import javazoom.jl.decoder.BitstreamException;
import mimis.exception.worker.ActivateException;
import mimis.exception.worker.DeactivateException;
import mimis.worker.Worker;
import com.Ostermiller.util.CircularByteBuffer;
public class Converter extends Worker {
public static final String COMMAND = "lame --mp3input --cbr %s - - --quiet";
public static final int BYTES = 4096; // bytes
public static final int BUFFER = 30000; // milliseconds
public static final int BUFFERING = 1000; // milliseconds
protected int targetRate;
protected int rate;
protected int buffer;
protected boolean convert;
protected Process process;
protected InputStream sourceInputStream, processInputStream, inputStream;
protected OutputStream processOutputStream;
protected CircularByteBuffer circularByteBuffer;
protected BufferWorker bufferWorker;
public Converter(InputStream inputStream) {
this(inputStream, -1);
}
public Converter(InputStream inputStream, int targetRate) {
this.sourceInputStream = inputStream;
this.targetRate = targetRate;
bufferWorker = new BufferWorker();
convert = false;
}
public void exit() {
super.exit();
bufferWorker.exit();
}
public synchronized void activate() throws ActivateException {
/* Read bitrate */
BufferedInputStream bufferedInputStream = new BufferedInputStream(sourceInputStream);
Bitstream bitStream = new Bitstream(bufferedInputStream);
try {
rate = bitStream.readFrame().bitrate() / 1000;
buffer = BUFFER * rate / 8;
} catch (BitstreamException e) {
log.error(e);
throw new ActivateException();
}
/* Check for need to convert */
if (targetRate < 0 || rate == targetRate) {
log.debug("No conversion required");
inputStream = sourceInputStream;
} else {
log.debug("Converting from " + rate + "kbps to " + targetRate + "kbps");
try {
String command = String.format(COMMAND, rate > targetRate ? "-B " + targetRate : "-F -b " + targetRate);
log.debug("Starting process: " + command);
process = Runtime.getRuntime().exec(command);
processInputStream = process.getInputStream();
processOutputStream = process.getOutputStream();
/* Buffer output */
circularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
inputStream = circularByteBuffer.getInputStream();
bufferWorker.start();
convert = true;
} catch (IOException e) {
log.error(e);
throw new ActivateException();
}
}
super.activate();
notifyAll();
}
protected void deactivate() throws DeactivateException {
super.deactivate();
try {
sourceInputStream.close();
bufferWorker.stop();
if (convert) {
circularByteBuffer.clear();
convert = false;
}
inputStream.close();
} catch (IOException e) {
log.error(e);
throw new DeactivateException();
}
}
protected void work() {
if (!convert) {
try {
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
log.error(e);
}
return;
}
byte[] bytes = new byte[BYTES];
int read = 0;
try {
log.debug("Writing input to process");
while ((read = sourceInputStream.read(bytes)) > 0 && !deactivate) {
/* Limit buffer size */
while (inputStream.available() > buffer) {
int progress = (int) ((1 - (inputStream.available() - buffer) / (float) buffer) * 100);
log.trace("Waiting for buffer to empty: " + progress + "%");
sleep(BUFFERING);
}
processOutputStream.write(bytes, 0, read);
}
processOutputStream.close();
log.debug("Stopped writing input to process");
process.waitFor();
log.debug("Process finished");
} catch (IOException e) {
} catch (InterruptedException e) {
log.error(e);
}
stop();
}
public synchronized InputStream getInputStream() {
if (!active()) {
if (!activate) {
start();
}
try {
wait();
} catch (InterruptedException e) {
log.error(e);
}
}
return inputStream;
}
public synchronized void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
class BufferWorker extends Worker {
protected void work() {
byte[] bytes = new byte[BYTES];
int read = 0;
try {
OutputStream bufferOutputStream = circularByteBuffer.getOutputStream();
log.debug("Start buffering process output");
while ((read = processInputStream.read(bytes, 0, BYTES)) > 0) {
bufferOutputStream.write(bytes, 0, read);
}
log.debug("Finished buffering process output");
bufferOutputStream.close();
} catch (IOException e) {}
stop();
}
}
public static void main(String[] args) {
Mp3 mp3 = new Mp3(new File("stream.mp3"), 128);
InputStream inputStream = mp3.getInputStream();
/* Play */
//Utils.play(inputStream);
/* Write to file */
Utils.write(inputStream, new File("output.mp3"));
mp3.exit();
}
}

198
src/old/List.java Normal file
View File

@@ -0,0 +1,198 @@
package old;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Scanner;
import mimis.exception.worker.ActivateException;
import mimis.worker.Worker;
import com.Ostermiller.util.BufferOverflowException;
import com.Ostermiller.util.CircularByteBuffer;
import com.Ostermiller.util.CircularObjectBuffer;
public class List extends Worker {
public static final int STEP = 80; // milliseconds
public static final int RATE = 192; // kbps
public static final int OVERLAP = 20000; // milliseconds
protected File file;
protected String[] fileArray;
protected int rate;
protected int chunk;
protected int overlap;
protected byte[] bytes;
protected boolean next;
protected Mp3 mp3, nextMp3;
protected InputStream mp3InputStream;
protected OutputStream audioOutputStream;
protected CircularByteBuffer circularByteBuffer;
protected CircularObjectBuffer<String> circularStringBuffer;
public List(File file) {
this(file, RATE);
}
public List(File file, int rate) {
this.file = file;
this.rate = rate;
chunk = STEP * rate / 8;
overlap = OVERLAP * RATE / 8;
bytes = new byte[chunk];
next = true;
}
public void exit() {
super.exit();
if (mp3 != null) {
mp3.exit();
}
if (nextMp3 != null) {
nextMp3.exit();
}
}
protected synchronized void activate() throws ActivateException {
try {
Scanner scanner = new Scanner(file);
ArrayList<String> fileList = new ArrayList<String>();
while (scanner.hasNextLine()) {
fileList.add(scanner.nextLine());
}
if (fileList.size() > 0) {
fileArray = fileList.toArray(new String[0]);
circularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
audioOutputStream = circularByteBuffer.getOutputStream();
circularStringBuffer = new CircularObjectBuffer<String>(CircularByteBuffer.INFINITE_SIZE);
setNext();
super.activate();
notifyAll();
return;
}
} catch (FileNotFoundException e) {
log.error(e);
}
throw new ActivateException();
}
protected synchronized void work() {
try {
int left = chunk;
while (left > 0) {
/* Check for need to load next mp3 */
int available = mp3InputStream == null ? -1 : mp3InputStream.available();
boolean expect = mp3 == null ? false : mp3.active();
/* Act when no more data is expected */
if (!expect) {
if (available < overlap) {
setNext();
next = false;
nextMp3.start();
}
if (available < 1) {
swap();
}
}
/* Transfer data */
int read = mp3InputStream.read(bytes, 0, left);
left -= read;
audioOutputStream.write(bytes, 0, read);
}
} catch (IOException e) {
/* Swap to next if stream has stopped */
setNext();
swap();
} catch (IllegalStateException e) {
log.error(e);
}
sleep(STEP);
}
protected File getRandomFile() {
return new File(fileArray[(int) (Math.random() * fileArray.length)]);
}
public synchronized void setNext() {
if (nextMp3 == null) {
log.debug("Initialize next mp3");
nextMp3 = new Mp3(getRandomFile(), rate);
} else if (next) {
log.debug("Load next mp3");
nextMp3.setFile(getRandomFile());
}
}
public synchronized void next() {
log.debug("Stop current mp3");
mp3.stop();
}
public void swap() {
log.debug("Swap to next mp3");
Mp3 swapMp3 = mp3;
mp3 = nextMp3;
nextMp3 = swapMp3;
next = true;
/* Swap stream and announce title */
mp3InputStream = mp3.getInputStream();
try {
circularStringBuffer.write(mp3.getTitle());
} catch (BufferOverflowException e) {
log.error(e);
} catch (IllegalStateException e) {
log.error(e);
} catch (InterruptedException e) {
log.error(e);
}
}
public synchronized InputStream getInputStream() {
if (circularByteBuffer == null) {
start();
try {
wait();
} catch (InterruptedException e) {
log.error(e);
}
}
return circularByteBuffer.getInputStream();
}
public synchronized CircularObjectBuffer<String> getMetaBuffer() {
if (circularStringBuffer == null) {
start();
try {
wait();
} catch (InterruptedException e) {
log.error(e);
}
}
return circularStringBuffer;
}
public static void main(String[] args) {
int rate = 192;
List list = new List(new File("mp3"), rate);
/*Shoutcast shoutcast = new Shoutcast(null, rate, 9876);
shoutcast.start();
shoutcast.setInputStream(list.getInputStream());
shoutcast.setMetaBuffer(list.getMetaBuffer());*/
while (true) {
try {
Thread.sleep(15000);
list.next();
} catch (InterruptedException e) {}
}
}
}

79
src/old/Mp3.java Normal file
View File

@@ -0,0 +1,79 @@
package old;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import mimis.exception.worker.ActivateException;
import org.farng.mp3.MP3File;
import org.farng.mp3.TagException;
public class Mp3 extends Converter {
protected File file;
protected String title;
public Mp3(File file) {
this(file, -1);
}
public Mp3(File file, int targetRate) {
super(null, targetRate);
setFile(file);
title = "";
}
public synchronized void activate() throws ActivateException {
/* Open file */
try {
sourceInputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
log.error(e);
throw new ActivateException();
}
/* Read ID3V2 tags */
try {
MP3File mp3File = new MP3File(file);
String album = clean(mp3File.getID3v2Tag().getAlbumTitle());
String artist = clean(mp3File.getID3v2Tag().getLeadArtist());
String track = clean(mp3File.getID3v2Tag().getSongTitle());
if (album.isEmpty()) {
title = String.format("%s - %s", artist, track, album);
} else {
title = String.format("%s - %s {%s}", artist, track, album);
}
log.debug("Title: " + title);
} catch (IOException e) {
log.error(e);
} catch (TagException e) {
log.error(e);
}
try {
sourceInputStream.skip(100000);
} catch (IOException e) {}
super.activate();
}
protected String clean(String input) {
String output = input.replace("\0", "");
return output.replace("<EFBFBD><EFBFBD>", "");
}
public String getTitle() {
return title;
}
public void setFile(File file) {
this.file = file;
}
public static void main(String[] args) {
final Mp3 mp3 = new Mp3(new File("input.mp3"), 128);
Utils.write(mp3.getInputStream(), new File("one.mp3"));
mp3.setFile(new File("stream.mp3"));
Utils.write(mp3.getInputStream(), new File("two.mp3"));
mp3.exit();
}
}

42
src/old/Utils.java Normal file
View File

@@ -0,0 +1,42 @@
package old;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class Utils {
public static final int BUFFER = 2048; // bytes
public static void play(InputStream inputStream) {
try {
Thread.sleep(5000);
new Player(new BufferedInputStream(inputStream)).play();
} catch (JavaLayerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void write(InputStream inputStream, File file) {
byte[] bytes = new byte[BUFFER];
int read = 0;
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
while ((read = inputStream.read(bytes)) > 0) {
fileOutputStream.write(bytes, 0, read);
}
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

8
src/sound/Consumer.java Normal file
View File

@@ -0,0 +1,8 @@
package sound;
public interface Consumer {
public void start(Producer producer);
public void start();
public void stop();
public void exit();
}

13
src/sound/Format.java Normal file
View File

@@ -0,0 +1,13 @@
package sound;
import javax.sound.sampled.AudioFormat;
public interface Format extends Cloneable {
public interface Standard extends Format {
public AudioFormat getAudioFormat();
}
public interface Mp3 extends Format {
public int getRate();
}
}

View File

@@ -0,0 +1,76 @@
package sound;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class GreedyInputStream extends BufferedInputStream {
protected Log log = LogFactory.getLog(getClass());
protected static final int SLEEP = 500;
protected static final int BUFFER_SIZE = 30000; // in bytes
protected static final int MINIMUM_SIZE = 1000; // in bytes
protected int bufferSize;
protected int minimumSize;
protected boolean hoard;
public GreedyInputStream(InputStream inputStream) {
this(inputStream, BUFFER_SIZE, MINIMUM_SIZE);
}
public GreedyInputStream(InputStream inputStream, int bufferSize) {
super(inputStream, bufferSize);
this.bufferSize = bufferSize;
hoard = true;
}
public GreedyInputStream(InputStream inputStream, int bufferSize, int minimumSize) {
this(inputStream, bufferSize);
this.minimumSize = minimumSize;
}
public int read() throws IOException {
hoard();
byte[] buffer = new byte[1];
in.read(buffer, 0, 1);
return (int) buffer[0];
}
public int read(byte[] buffer, int offset, int length) throws IOException {
hoard();
in.read(buffer, offset, length);
return length;
}
public void hoard() throws IOException {
int available = available();
if (hoard && available < MINIMUM_SIZE) {
long time = System.currentTimeMillis();
do {
try {
Thread.sleep(SLEEP);
} catch (InterruptedException e) {
log.warn(e);
}
} while (available() < BUFFER_SIZE);
log.debug(String.format("Buffered %d bytes in %s milliseconds", BUFFER_SIZE - available, System.currentTimeMillis() - time));
}
}
public void clear() throws IOException {
this.buf = new byte[buf.length];
reset();
}
public void drain() {
drain(true);
}
public void drain(boolean drain) {
hoard = !drain;
}
}

119
src/sound/Port.java Normal file
View File

@@ -0,0 +1,119 @@
package sound;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.sound.sampled.AudioFormat;
import mimis.exception.worker.ActivateException;
import mimis.exception.worker.DeactivateException;
import mimis.worker.Worker;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sound.Format.Standard;
import sound.SoxBuilder.File;
import sound.SoxBuilder.Option;
import sound.SoxBuilder.File.Type;
public class Port extends Worker implements Consumer {
protected Log log = LogFactory.getLog(getClass());
protected static final int BUFFER_SIZE = 1024 * 4; // in bytes
protected String device;
protected Producer producer;
protected Process process;
protected InputStream producerInputStream;
protected OutputStream processOutputStream;
protected ProcessBuilder processBuilder;
public Port() {
this("0");
}
public Port(String device) {
this.device = device;
}
@SuppressWarnings("static-access")
public void start(Producer producer) {
this.producer = producer;
producerInputStream = producer.getInputStream();
String command = "";
if (producer instanceof Standard) {
AudioFormat audioFormat = ((Standard) producer).getAudioFormat();
SoxBuilder.addFile(File.setType(Type.STANDARD).setOptions(audioFormat));
} else if (producer instanceof Format.Mp3) {
SoxBuilder.addFile(File.setType(Type.STANDARD).setOption(File.Format.MP3));
}
command = SoxBuilder
.setOption(Option.QUIET)
.addFile(File.setType(Type.DEVICE))
.build();
log.debug(String.format("Build process (\"%s\")", command));
processBuilder = new ProcessBuilder(command.split(" "));
processBuilder.environment().put("AUDIODEV", device);
start(true);
}
protected void activate() throws ActivateException {
producer.start();
if (process == null) {
try {
process = processBuilder.start();
} catch (IOException e) {
log.error(e);
throw new ActivateException();
}
processOutputStream = process.getOutputStream();
}
super.activate();
}
protected void deactivate() throws DeactivateException {
super.deactivate();
try {
processOutputStream.flush();
} catch (IOException e) {
log.error(e);
throw new DeactivateException();
}
}
public void exit() {
try {
log.debug("close process output stream");
processOutputStream.close();
log.debug("wait for process to terminate");
process.waitFor();
} catch (IOException e) {
log.error(e);
} catch (InterruptedException e) {
log.error(e);
} finally {
process = null;
}
}
protected void work() {
try {
byte[] buffer = new byte[BUFFER_SIZE];
int read = producerInputStream.read(buffer, 0, buffer.length);
if (read > 0) {
processOutputStream.write(buffer, 0, read);
} else {
exit();
}
} catch (IOException e) {
log.error(e);
exit();
}
}
}

10
src/sound/Producer.java Normal file
View File

@@ -0,0 +1,10 @@
package sound;
import java.io.InputStream;
public interface Producer extends Format {
public InputStream getInputStream();
public void start();
public void stop();
public void exit();
}

159
src/sound/Source.java Normal file
View File

@@ -0,0 +1,159 @@
package sound;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
import mimis.exception.worker.ActivateException;
import mimis.exception.worker.DeactivateException;
import mimis.worker.Worker;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Source implements Consumer {
protected Log log = LogFactory.getLog(getClass());
protected static final int BUFFER_SIZE = 1024 * 4; // in bytes
protected static final int PLAY_FRAMES = 10; // count
protected String name;
protected Producer producer;
protected InputStream producerInputStream;
protected Worker worker;
public Source(String name) throws LineUnavailableException {
this.name = name;
}
public void start() {
if (worker != null) {
worker.start(true);
}
}
public void start(Producer producer) {
this.producer = producer;
producerInputStream = producer.getInputStream();
if (worker != null) {
worker.exit();
}
if (producer instanceof Format.Standard) {
log.debug("Format.Standard");
worker = new DefaultWorker((Format.Standard) producer);
} else if (producer instanceof Format.Mp3) {
log.debug("Format.Mp3");
worker = new Mp3Worker((Format.Mp3) producer);
}
start();
}
public void stop() {
if (worker != null) {
worker.stop();
}
}
public void exit() {
if (worker != null) {
worker.exit();
}
}
protected class DefaultWorker extends Worker {
protected Format.Standard format;
protected SourceDataLine line;
public DefaultWorker(Format.Standard format) {
this.format = format;
}
public void activate() throws ActivateException {
AudioFormat audioFormat = format.getAudioFormat();
try {
if (line == null) {
line = Tool.getSourceDataLine(name, audioFormat);
}
if (!line.isOpen()) {
line.open();
}
} catch (LineUnavailableException e) {
log.error(e);
throw new ActivateException();
}
if (!line.isRunning()) {
line.start();
}
super.activate();
}
public void deactivate() throws DeactivateException {
super.deactivate();
line.flush();
}
public void exit() {
super.exit();
line.close();
}
protected void work() {
try {
byte[] buffer = new byte[BUFFER_SIZE];
int read = producerInputStream.read(buffer, 0, buffer.length);
if (read > 0) {
line.write(buffer, 0, read);
} else {
exit();
}
} catch (IOException e) {
log.error(e);
exit();
}
}
}
protected class Mp3Worker extends Worker {
protected Format.Mp3 format;
protected Player player;
public Mp3Worker(Format.Mp3 format) {
this.format = format;
}
public void activate() throws ActivateException {
producer.start();
super.activate();
}
public void deactivate() throws DeactivateException {
super.deactivate();
producer.stop();
}
public void exit() {
super.exit();
player.close();
}
protected void work() {
try {
if (player == null) {
player = new Player(producerInputStream);
sleep(500);
}
player.play(PLAY_FRAMES);
} catch (JavaLayerException e) {
log.error(e);
}
if (player.isComplete()) {
stop();
}
}
}
}

322
src/sound/SoxBuilder.java Normal file
View File

@@ -0,0 +1,322 @@
package sound;
import java.util.HashMap;
import java.util.Map.Entry;
import javax.sound.sampled.AudioFormat;
import sound.SoxBuilder.Option.Combine;
import sound.SoxBuilder.Option.Replay;
public final class SoxBuilder {
protected static SoxBuilder instance;
protected static HashMap<String, String> optionMap;
protected static String files;
protected static String effects;
static {
instance = new SoxBuilder();
reset();
}
public static void reset() {
optionMap = new HashMap<String, String>();
files = "";
effects = "";
}
public static SoxBuilder setOption(Option option, String value) {
optionMap.put(option.getCode(), value);
return instance;
}
public static SoxBuilder setOption(Option option) {
return SoxBuilder.setOption(option, "");
}
public static SoxBuilder setOption(Option option, int value) {
return SoxBuilder.setOption(option, String.valueOf(value));
}
public static SoxBuilder setOption(Option option, Combine combine) {
return SoxBuilder.setOption(option, combine.getCode());
}
public static SoxBuilder setOption(Combine combine) {
return SoxBuilder.setOption(Option.COMBINE, combine);
}
public static SoxBuilder setOption(Option option, Replay replay) {
return SoxBuilder.setOption(option, replay.toString().toLowerCase());
}
public static SoxBuilder setOption(Replay replay) {
return SoxBuilder.setOption(Option.REPLAY, replay);
}
public static SoxBuilder addFile(File file) {
files = String.format("%s %s", files, file.build());
return instance;
}
public static SoxBuilder addEffect(Effect effect) {
effects = String.format("%s %s", effects, effect.build());
return instance;
}
public String build() {
String build = "sox";
for (Entry<String, String> entry : optionMap.entrySet()) {
String value = entry.getValue();
if (value.equals("")) {
build = String.format("%s %s", build, entry.getKey());
} else {
String option = String.format("%s %s", entry.getKey(), value);
build = String.format("%s %s", build, option);
}
}
build = String.format("%s%s%s", build, files, effects);
reset();
return build;
}
public enum Environment {
AUDIODRIVER, AUDIODEV
}
public enum Option {
BUFFER ("--buffer"), // default=8192
INPUT_BUFFER ("--input-buffer"),
CLOBBER ("--clobber"),
COMBINE ("--combine"), // |Combine|
NO_DITHER ("--no-dither"), // (-D)
EFFECTS_FILE ("--efects-file"),
GUARD ("--guard"), // (-G)
MIX ("-m"), // (--combine mix)
MERGE ("-M"), // (--combine merge)
MAGIC ("--magic"),
MULTI_THREADED ("--multi-threaded"),
SINGLE_THREADED ("--single-threaded"),
NORM ("--norm"), // [=dB-level]
PLAY_RATE_ARG ("--play-rate-arg"),
QUIET ("--no-show-progress"), // (-q)
REPEATABLE ("-R"),
REPLAY ("--replay-gain"), // |Replay|
MULTIPLY ("-T"), // (--combine multiply)
TEMP ("--temp");
protected String code;
private Option(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public enum Combine {
CONCATENATE ("concatenate"),
MERGE ("merge"), // (-M)
MIX ("mix"), // (-m)
MIX_POWER ("mix-power"),
MULTIPLY ("multiply"), // (-T)
SEQUENCE ("sequence");
protected String code;
private Combine(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
public enum Replay {
TRACK, ALBUM, OFF
}
}
public static class File {
protected static File instance;
protected static HashMap<String, String> optionMap;
protected static Type type;
static {
instance = new File();
reset();
}
public static void reset() {
optionMap = new HashMap<String, String>();
type = Type.PIPE;
}
public static File setOption(Option option, String value) {
optionMap.put(option.getCode(), value);
return instance;
}
public static File setOption(Option option) {
return File.setOption(option, "");
}
public static File setOption(Option option, int value) {
return File.setOption(option, String.valueOf(value));
}
public static File setOption(Option option, Encoding encoding) {
return File.setOption(option, encoding.getCode());
}
public static File setOption(Encoding encoding) {
return File.setOption(Option.ENCODING, encoding);
}
public static File setOption(Option option, Format format) {
return File.setOption(option, format.toString().toLowerCase());
}
public static File setOption( Format format) {
return File.setOption(Option.FORMAT, format);
}
public static File setOption(Option option, Endian endian) {
return File.setOption(option, endian.toString().toLowerCase());
}
public static File setOption(Endian endian) {
return File.setOption(Option.ENDIAN, endian);
}
public File setOptions(AudioFormat audioFormat) {
setOption(Option.CHANNELS, audioFormat.getChannels());
setOption(Option.RATE, String.format("%sk", String.valueOf(audioFormat.getSampleRate() / 1000f)));
AudioFormat.Encoding encoding = audioFormat.getEncoding();
int bits = audioFormat.getSampleSizeInBits();
if (encoding.equals(AudioFormat.Encoding.ALAW)) {
setOption(Format.AL);
setOption(Encoding.A_LAW);
} else if (encoding.equals(AudioFormat.Encoding.ULAW)) {
setOption(Format.UL);
setOption(Encoding.U_LAW);
} else if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED)) {
setOption(Format.valueOf(String.format("S%d", bits)));
setOption(Encoding.SIGNED_INTEGER);
} else if (encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED)) {
setOption(Format.valueOf(String.format("U%d", bits)));
setOption(Encoding.UNSIGNED_INTEGER);
}
setOption(audioFormat.isBigEndian() ? Endian.BIG : Endian.LITTLE);
return instance;
}
public static File setType(Type type) {
File.type = type;
return instance;
}
public String build() {
String build = type.getCode();
for (Entry<String, String> entry : optionMap.entrySet()) {
String value = entry.getValue();
if (value.equals("")) {
build = String.format("%s %s", entry.getKey(), build);
} else {
String option = String.format("%s %s", entry.getKey(), value);
build = String.format("%s %s", option, build);
}
}
reset();
return build;
}
public enum Option {
BITS ("--bits"), // (-b)
CHANNELS ("--channels"), // (-c)
ENCODING ("--encoding"), // (-e), |Encoding|
NO_GLOB ("--no-glob"),
RATE ("--rate"), // (-r)
FORMAT ("--type"), // (-t), |Format|
ENDIAN ("--endian"), // (-L, -B, -x), |Endian|
REVERSE_NIBBLES ("--reverse-nibbles"), // (-N)
REVERSE_BITS ("--reverse-bits"), // (-X)
/* Input only */
IGNORE_LENGTH ("--ignore-length"),
VOLUME ("--volume"), // (-v)
/* Output only */
ADD_COMMENT ("--add-comment"),
COMMENT ("--comment"),
COMMENT_FILE ("--comment-file"),
COMPRESSION ("--compression"); // -C
protected String code;
private Option(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
public enum Encoding {
SIGNED_INTEGER ("signed-integer"), // PCM data stored as signed integers
UNSIGNED_INTEGER ("unsigned-integer"), // PCM data stored as unsigned integers
FLOATING_POINT ("floating-point"), // PCM data stored as single precision (32-bit) or double precision (64-bit) floating-point numbers
A_LAW ("a-lawW"), // International telephony standard for logarithmic encoding to 8 bits per sample (~13-bit PCM)
U_LAW ("u-law"), // North American telephony standard for logarithmic encoding to 8 bits per sample (~14-bit PCM)
MU_LAW ("mu-law"), // alias for u-law (~14-bit PCM)
OKI_ADPCM ("oki-adpcm"), // OKI (VOX, Dialogic or Intel) 4-bit ADPCM (~12-bit PCM)
IMA_ADPCM ("ima-adpcm"), // IMA (DVI) 4-bit ADPCM (~13-bit PCM)
MS_ADPCM ("ms-adpcm"), // Microsoft 4-bit ADPCM (~14-bit PCM)
GSM_FULL_RATE ("gsm-full-rate"); // Several audio formats used for digital wireless telephone calls
protected String code;
private Encoding(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
public enum Format {
AIF, AIFC, AIFF, AIFFC, AL, AMB, AMR, ANY, ARL, AU, AVR, BIN, CAF, CDDA, CDR, CVS, CVSD, CVU, DAT, DVMS, EDU, F32, F64, FAP, FLAC, FSSD, GSM, GSRT, HCOM, HTK, IMA, IRCAM, LA, LPC, LPC10, LU, M3U, M4A, MAT, MAT4, MAT5, MAUD, MP2, MP3, MP4, NIST, OGG, PAF, PLS, PRC, PVF, RAW, S16, S24, S32, S8, SD2, SDS, SF, SLN, SMP, SND, SNDR, SNDT, SOU, SOX, SPH, TXW, U16, U24, U32, U8, UL, VMS, VOC, VORBIS, VOX, W64, WAV, WAVPCM, WV, WVE, XA, XI;
}
public enum Endian {
LITTLE, BIG, SWAP;
}
public enum Type {
STANDARD ("-"), // -t must be given
PIPE ("-p"), // (--sox-pipe)
DEVICE ("-d"), // (--default-device)
NULL ("-n"); // (--null)
protected String code;
private Type(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
}
public class Effect {
public String build() {
return null;
}
}
}

195
src/sound/Stream.java Normal file
View File

@@ -0,0 +1,195 @@
package sound;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.URL;
import mimis.exception.worker.ActivateException;
import mimis.exception.worker.DeactivateException;
import mimis.worker.Worker;
import com.Ostermiller.util.CircularByteBuffer;
import com.Ostermiller.util.CircularObjectBuffer;
public class Stream extends Worker implements Producer, Format.Mp3 {
public static final String HTTP = "http://shoutcast.omroep.nl:8104/";
public static final int STEP = 80; // in milliseconds
protected String http;
protected Socket socket;
protected InputStream socketInputStream;
protected OutputStreamWriter socketOutputStreamWriter;
protected GreedyInputStream greedyInputStream;
protected int meta;
protected int rate;
protected int chunk;
protected int untilMeta;
protected CircularByteBuffer audioCircularByteBuffer;
protected CircularObjectBuffer<String> metaCircularObjectBuffer;
protected String metaData;
public Stream() {
this(HTTP);
}
public Stream(String http) {
super(true);
this.http = http;
meta = -1;
rate = -1;
audioCircularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
metaCircularObjectBuffer = new CircularObjectBuffer<String>();
}
protected void connect(URL url) {
try {
/* Open socket communication */
socket = new Socket(url.getHost(), url.getPort());
socketInputStream = socket.getInputStream();
socketOutputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
/* Write stream request */
socketOutputStreamWriter.write("GET " + url.getFile() + " HTTP/1.1\r\n");
socketOutputStreamWriter.write("Host: " + url.getHost() + "\r\n");
socketOutputStreamWriter.write("Icy-MetaData: 1\r\n");
socketOutputStreamWriter.write("Connection: close\r\n");
socketOutputStreamWriter.write("\r\n");
socketOutputStreamWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
protected void activate() throws ActivateException {
try {
/* Initialize connection */
URL url = new URL(http);
/* Parse headers */
connect(url);
InputStreamReader inputStreamReader = new InputStreamReader(socketInputStream);
StringBuffer stringBuffer = new StringBuffer();
char character;
int skip = 0;
while ((character = (char) inputStreamReader.read()) > 0) {
++skip;
if (character == '\n') {
/* Fetch relevant headers */
String line = stringBuffer.toString().trim();
if (line.startsWith("icy-metaint")) {
meta = Integer.valueOf(line.substring(line.indexOf(":") + 1).trim());
} else if (line.startsWith("icy-br")) {
rate = Integer.valueOf(line.substring(line.indexOf(":") + 1).trim());
} else if (line.equals("")) {
break;
}
stringBuffer = new StringBuffer();
} else {
stringBuffer.append(character);
}
}
inputStreamReader.close();
/* Reconnect to bypass pre-buffering problems */
connect(url);
socketInputStream = socket.getInputStream();
socketInputStream.skip(skip);
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
}
/* Calculate streaming parameters */
untilMeta = meta;
chunk = STEP * rate / 8;
super.activate();
}
public void deactivate() throws DeactivateException {
super.deactivate();
audioCircularByteBuffer.clear();
metaCircularObjectBuffer.clear();
try {
greedyInputStream.clear();
} catch (IOException e) {
log.error(e);
throw new DeactivateException();
}
}
protected void work() {
int left = chunk;
/* Handle media at appropriate times */
while (meta > 0 && left >= untilMeta) {
stream(untilMeta);
meta();
left -= untilMeta;
untilMeta = meta;
}
/* Stream at fixed rate */
stream(left);
untilMeta -= left;
sleep(STEP);
}
protected void stream(int length) {
try {
byte[] bytes = new byte[length];
int read = 0;
while (length > 0 && (read = socketInputStream.read(bytes)) > 0) {
length -= read;
audioCircularByteBuffer.getOutputStream().write(bytes);
}
} catch (IOException e) {
log.error(e);
stop();
}
}
protected void meta() {
try {
/* Retrieve data length */
byte[] data = new byte[1];
socketInputStream.read(data);
int length = 16 * data[0];
data = new byte[length];
socketInputStream.read(data);
/* Check for new data */
String newMetaData = new String(data);
if (!newMetaData.isEmpty() && !newMetaData.equals(metaData)) {
metaData = newMetaData;
metaCircularObjectBuffer.write(new String(data));
log.debug("data: " + metaData);
}
return;
} catch (IOException e) {
log.error(e);
} catch (IllegalStateException e) {
log.error(e);
} catch (InterruptedException e) {
log.error(e);
}
stop();
}
public InputStream getInputStream() {
greedyInputStream = new GreedyInputStream(audioCircularByteBuffer.getInputStream());
return greedyInputStream;
}
public CircularObjectBuffer<String> getMetaBufferStream() {
return metaCircularObjectBuffer;
}
public int getRate() {
return rate;
}
}

91
src/sound/Target.java Normal file
View File

@@ -0,0 +1,91 @@
package sound;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Target implements Producer, Format.Standard {
protected Log log = LogFactory.getLog(getClass());
protected Standard format;
protected TargetDataLine line;
protected InputStream targetInputStream;
protected AudioFormat audioFormat;
public Target(String name) throws LineUnavailableException {
log.debug(String.format("Target \"%s\" without format", name));
line = Tool.getTargetDataLine(name);
audioFormat = line.getFormat();
targetInputStream = new TargetInputStream();
}
public Target(String name, AudioFormat audioFormat) throws LineUnavailableException {
log.debug(String.format("Target \"%s\" with format: %s", name, audioFormat));
this.audioFormat = audioFormat;
line = Tool.getTargetDataLine(name, audioFormat);
targetInputStream = new TargetInputStream();
}
public AudioFormat getAudioFormat() {
return audioFormat;
}
public InputStream getInputStream() {
return targetInputStream;
}
public class TargetInputStream extends InputStream {
protected boolean open;
public TargetInputStream() {
open = false;
}
public int read() throws IOException {
start();
byte[] buffer = new byte[1];
line.read(buffer, 0, 1);
return (int) buffer[0];
}
public int read(byte[] buffer, int offset, int length) {
start();
line.read(buffer, offset, length);
return length;
}
public int available() {
start();
return line.available();
}
}
public void start() {
if (!line.isOpen()) {
try {
line.open();
} catch (LineUnavailableException e) {
log.error(e);
}
}
if (!line.isRunning()) {
line.start();
}
}
public void stop() {
line.flush();
}
public void exit() {
line.close();
}
}

27
src/sound/Test.java Normal file
View File

@@ -0,0 +1,27 @@
package sound;
import javax.sound.sampled.AudioFormat;
public class Test {
public static void main(String[] args) {
AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 48000f, 16, 2, 4, 48000f, true);
try {
Producer p1 = new Target("Line-In (Creative SB X-Fi)");
Producer p2 = new Target("Line 1 (Virtual Audio Cable)", audioFormat);
Producer p3 = new Stream("http://ics2gss.omroep.nl:80/3fm-bb-mp3");
Consumer c1 = new Source("Java Sound Audio Engine");
Consumer c2 = new Port("Speakers (Creative SB X-Fi)");
c2.start(p3);
/*while (true) {
Thread.sleep(3000);
c2.stop();
Thread.sleep(1000);
c2.start();
}*/
} catch (Exception e) {
e.printStackTrace();
}
}
}

140
src/sound/Tool.java Normal file
View File

@@ -0,0 +1,140 @@
package sound;
import java.util.ArrayList;
import java.util.HashMap;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Port;
import javax.sound.sampled.Port.Info;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Tool {
protected static Log log = LogFactory.getLog(Tool.class);
protected static HashMap<String, Device<TargetDataLine>> targetMap;
protected static HashMap<String, Device<SourceDataLine>> sourceMap;
protected static ArrayList<String> portList;
protected static ArrayList<String> targetList;
protected static ArrayList<String> sourceList;
static {
Tool tool = new Tool();
targetMap = new HashMap<String, Device<TargetDataLine>>();
sourceMap = new HashMap<String, Device<SourceDataLine>>();
targetList = new ArrayList<String>();
sourceList = new ArrayList<String>();
portList = new ArrayList<String>();
for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
String name = mixerInfo.getName();
Mixer mixer = AudioSystem.getMixer(mixerInfo);
for (Line.Info lineInfo : mixer.getSourceLineInfo()) {
String lineClassName = lineInfo.getLineClass().getName();
if (lineClassName.equals("javax.sound.sampled.SourceDataLine")) {
if (mixer.isLineSupported(lineInfo)) {
log.debug("<Source> " + name);
sourceMap.put(name, tool.new Device<SourceDataLine>(mixer, lineInfo));
}
}
}
for (Line.Info lineInfo : mixer.getTargetLineInfo()) {
String lineClassName = lineInfo.getLineClass().getName();
if (lineClassName.equals("javax.sound.sampled.TargetDataLine")) {
if (mixer.isLineSupported(lineInfo)) {
log.debug("<Target> " + name);
targetMap.put(name, tool.new Device<TargetDataLine>(mixer, lineInfo));
}
} else if (lineClassName.equals("javax.sound.sampled.Port")) {
name = name.substring(5);
try {
Port port = (Port) mixer.getLine(lineInfo);
Port.Info portInfo = (Info) port.getLineInfo();
if (!targetMap.containsKey(name) || portInfo.equals(Port.Info.LINE_OUT) || portInfo.equals(Port.Info.SPEAKER)) {
log.debug("<Port> " + name);
portList.add(name);
}
} catch (LineUnavailableException e) {
log.error(e);
}
}
}
}
}
public static String[] getTargets() {
return targetMap.keySet().toArray(new String[0]);
}
public static String[] getSources() {
return sourceMap.keySet().toArray(new String[0]);
}
public static String[] getPorts() {
return portList.toArray(new String[0]);
}
public static TargetDataLine getTargetDataLine(String name) throws LineUnavailableException {
if (targetMap.containsKey(name)) {
return targetMap.get(name).getLine();
} else {
throw new LineUnavailableException();
}
}
public static TargetDataLine getTargetDataLine(String name, AudioFormat audioFormat) throws LineUnavailableException {
if (targetMap.containsKey(name)) {
return targetMap.get(name).getLine(audioFormat);
} else {
throw new LineUnavailableException();
}
}
public static SourceDataLine getSourceDataLine(String name) throws LineUnavailableException {
if (sourceMap.containsKey(name)) {
return sourceMap.get(name).getLine();
} else {
throw new LineUnavailableException();
}
}
public static SourceDataLine getSourceDataLine(String name, AudioFormat audioFormat) throws LineUnavailableException {
if (sourceMap.containsKey(name)) {
return sourceMap.get(name).getLine(audioFormat);
} else {
throw new LineUnavailableException();
}
}
public class Device<T> {
protected Mixer mixer;
protected Line.Info lineInfo;
public Device(Mixer mixer, Line.Info lineInfo) {
this.mixer = mixer;
this.lineInfo = lineInfo;
}
@SuppressWarnings("unchecked")
public T getLine() throws LineUnavailableException {
return (T) mixer.getLine(lineInfo);
}
@SuppressWarnings("unchecked")
public T getLine(AudioFormat audioFormat) throws LineUnavailableException {
DataLine.Info dataLineInfo = new DataLine.Info(lineInfo.getLineClass(), audioFormat);
return (T) mixer.getLine(dataLineInfo);
}
}
}

43
src/sound/Transducer.java Normal file
View File

@@ -0,0 +1,43 @@
package sound;
import java.io.InputStream;
public class Transducer implements Consumer, Producer {
public int rate;
public Transducer(Producer producer) {
//setProducer(producer);
}
public int getRate() {
return rate;
}
public InputStream getInputStream() {
// TODO Auto-generated method stub
return null;
}
public void start(Producer producer) {
// TODO Auto-generated method stub
}
@Override
public void start() {
// TODO Auto-generated method stub
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void exit() {
// TODO Auto-generated method stub
}
}

55
src/test/SoundAudit.java Normal file
View File

@@ -0,0 +1,55 @@
package test;
import javax.sound.sampled.*;
public class SoundAudit {
public static void main(String[] args) { try {
System.out.println("OS: "+System.getProperty("os.name")+" "+
System.getProperty("os.version")+"/"+
System.getProperty("os.arch")+"\nJava: "+
System.getProperty("java.version")+" ("+
System.getProperty("java.vendor")+")\n");
for (Mixer.Info thisMixerInfo : AudioSystem.getMixerInfo()) {
System.out.println("Mixer: "+thisMixerInfo.getDescription()+
" ["+thisMixerInfo.getName()+"]");
Mixer thisMixer = AudioSystem.getMixer(thisMixerInfo);
for (Line.Info thisLineInfo:thisMixer.getSourceLineInfo()) {
if (thisLineInfo.getLineClass().getName().equals(
"javax.sound.sampled.Port")) {
Line thisLine = thisMixer.getLine(thisLineInfo);
thisLine.open();
System.out.println(" Source Port: "
+thisLineInfo.toString());
for (Control thisControl : thisLine.getControls()) {
System.out.println(AnalyzeControl(thisControl));}
thisLine.close();}}
for (Line.Info thisLineInfo:thisMixer.getTargetLineInfo()) {
if (thisLineInfo.getLineClass().getName().equals(
"javax.sound.sampled.Port")) {
Line thisLine = thisMixer.getLine(thisLineInfo);
thisLine.open();
System.out.println(" Target Port: "
+thisLineInfo.toString());
for (Control thisControl : thisLine.getControls()) {
System.out.println(AnalyzeControl(thisControl));}
thisLine.close();}}}
} catch (Exception e) {e.printStackTrace();}}
public static String AnalyzeControl(Control thisControl) {
String type = thisControl.getType().toString();
if (thisControl instanceof BooleanControl) {
return " Control: "+type+" (boolean)"; }
if (thisControl instanceof CompoundControl) {
System.out.println(" Control: "+type+
" (compound - values below)");
String toReturn = "";
for (Control children:
((CompoundControl)thisControl).getMemberControls()) {
toReturn+=" "+AnalyzeControl(children)+"\n";}
return toReturn.substring(0, toReturn.length()-1);}
if (thisControl instanceof EnumControl) {
return " Control:"+type+" (enum: "+thisControl.toString()+")";}
if (thisControl instanceof FloatControl) {
return " Control: "+type+" (float: from "+
((FloatControl) thisControl).getMinimum()+" to "+
((FloatControl) thisControl).getMaximum()+")";}
return " Control: unknown type";}
}

29
src/test/lines/Main.java Normal file
View File

@@ -0,0 +1,29 @@
package test.lines;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
public class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("javax.sound.sampled.SourceDataLine"));
new AudioFormat(44100, 16, 2, true, false);
for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
Mixer mixer = AudioSystem.getMixer(mixerInfo);
for (Line.Info lineInfo : mixer.getTargetLineInfo()) {
try {
Line line = mixer.getLine(lineInfo);
if (mixer.isLineSupported(lineInfo) && line instanceof TargetDataLine) {
new TargetLine(mixer, (TargetDataLine) line);
}
} catch (LineUnavailableException e) {}
}
}
}
}

View File

@@ -0,0 +1,19 @@
package test.lines;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
public class SourceLine {
//private Mixer mixer;
private SourceDataLine line;
public SourceLine(Mixer mixer, SourceDataLine line) {
//this.mixer = mixer;
this.line = line;
System.out.println("SOURCE " + mixer.getMixerInfo().getName() + " || " + line.getLineInfo());
}
public int write(byte[] bytes, int offset, int length) {
return line.write(bytes, offset, length);
}
}

View File

@@ -0,0 +1,19 @@
package test.lines;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
public class TargetLine {
//private Mixer mixer;
private TargetDataLine line;
public TargetLine(Mixer mixer, TargetDataLine line) {
//this.mixer = mixer;
this.line = line;
System.out.println("TARGET " + mixer.getMixerInfo().getName() + " || " + line.getLineInfo());
}
public int read(byte[] bytes, int offset, int length) {
return line.read(bytes, offset, length);
}
}

1
stream.bat Normal file
View File

@@ -0,0 +1 @@
java -classpath bin udp.StreamClient 234.5.6.7 4567

BIN
stream.exe Normal file

Binary file not shown.

BIN
stream.jar Normal file

Binary file not shown.

BIN
wget.exe Normal file

Binary file not shown.

BIN
zlib1.dll Normal file

Binary file not shown.