view audio/java/StreamSource.java @ 61:eff6bddf82e3 tip

Finally implemented perceptual brightness thing.
author samer
date Sun, 11 Oct 2015 10:20:42 +0100
parents 63cefb01cbab
children
line wrap: on
line source
/*
 *	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 ishara.audio;
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; }
}