diff audio/java/StreamSource.java @ 0:672052bd81f8

Initial partial import.
author samer
date Wed, 19 Dec 2012 22:38:28 +0000
parents
children 63cefb01cbab
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audio/java/StreamSource.java	Wed Dec 19 22:38:28 2012 +0000
@@ -0,0 +1,103 @@
+/*
+ *	StreamSource.java
+ *
+ *	Copyright (c) 2012, Samer Abdallah, King's College London.
+ *	All rights reserved.
+ *
+ *	This software is provided AS iS and WITHOUT ANY WARRANTY;
+ *	without even the implied warranty of MERCHANTABILITY or
+ *	FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+package samer.audio.alt;
+import  javax.sound.sampled.*;
+import  java.io.*;
+
+public class StreamSource extends AudioSource
+{
+	InputStream		in;
+
+	public StreamSource(AudioInputStream ain) throws Exception { super(ain.getFormat()); in=ain; }
+	public StreamSource(AudioInputStream ain, AudioFormat target) throws Exception {
+		this(prepareStream(ain,target));
+	}
+
+	// AudioSource interface methods
+	public void dispose() {
+		print("Closing audio stream...");
+		try { in.close(); } catch (IOException ex) {}
+	}
+
+	public void start() {}
+	public void stop() {}
+	public int  read(byte [] buf, int off, int len) throws Exception {
+		return in.read(buf,off,len);
+	}
+
+	public static AudioInputStream prepareStream(AudioInputStream ain, AudioFormat target) throws Exception {
+		// convert to target format if required
+		print("Preparing audio stream...");
+		print("  / audio format: "+ain.getFormat().toString());
+		if (target==null) {
+			AudioFormat fin=ain.getFormat();
+			ain=convertFormat(new AudioFormat( fin.getSampleRate(), 16, fin.getChannels(), true, false), ain);
+		} else {
+			ain=convertFormat(target, ain);
+		}
+		print("  \\ final format: "+ain.getFormat().toString());
+		return ain;
+	}
+
+	private static AudioInputStream convertVia(AudioFormat fout, AudioInputStream sin, AudioFormat fint) throws Exception
+	{
+		print("  | Trying recursive via "+fint.toString());
+		AudioInputStream sint=AudioSystem.getAudioInputStream(fint,sin);
+		AudioFormat fres=sint.getFormat();
+		if (!fres.equals(fint)) {
+			print("  |            obtained  "+fres.toString());
+		}
+		return convertFormat(fout, sint);
+	}
+
+	public static AudioInputStream convertFormat(AudioFormat fout, AudioInputStream sin) throws Exception
+	{
+		AudioFormat fin=sin.getFormat();
+
+		if (fin.equals(fout)) return sin;
+		if (fin.getEncoding()!=AudioFormat.Encoding.PCM_SIGNED) {
+			if (fin.getEncoding().getClass().getName().startsWith("javazoom.spi.")) {
+				// these are broken, must go via 16 bit decode with no channels change
+				print("  ! Detected noncompliant Javazoom decoder, going via 16 bit.");
+				return convertVia( fout, sin, new AudioFormat( 
+					fin.getSampleRate(), 16, fin.getChannels(), true, fout.isBigEndian()));
+			}
+
+			// first get into PCM encoding, then try recursive
+			try {
+				return convertVia( fout, sin, new AudioFormat( 
+					fin.getSampleRate(), fout.getSampleSizeInBits(),
+					fin.getChannels(), true, fout.isBigEndian()));
+			} catch (IllegalArgumentException ex) { 
+				print("  * Direct conversion failed"); 
+			}
+			return convertVia( fout, sin, new AudioFormat( 
+				fin.getSampleRate(), fin.getSampleSizeInBits(),
+				fin.getChannels(), true, fout.isBigEndian()));
+		} 
+
+		if (	!unify(fin.getChannels(),fout.getChannels()) 
+			|| !unify(fin.getSampleSizeInBits(),fout.getSampleSizeInBits())) {
+			// convert these before doing any sample rate conversion
+			return convertVia(fout, sin, new AudioFormat( 
+				fin.getSampleRate(), fout.getSampleSizeInBits(),
+				fout.getChannels(), true, fout.isBigEndian()));
+		}
+
+		// the only thing left is sample rate
+		return AudioSystem.getAudioInputStream(fout,sin);
+	}
+
+	private static boolean unify(int x, int y) { return x==-1 || y==-1 || x==y; }
+	private static boolean unify(float x, float y) { return x==-1 || y==-1 || x==y; }
+}
+