⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 javasoundcodec.java

📁 FMJ(freedom media for java)是java视频开发的新选择
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package net.sf.fmj.media.codec;import java.io.BufferedInputStream;import java.io.IOException;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;import javax.media.Buffer;import javax.media.Format;import javax.media.ResourceUnavailableException;import javax.media.format.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;import javax.sound.sampled.UnsupportedAudioFileException;import javax.sound.sampled.AudioFormat.Encoding;import javax.sound.sampled.spi.FormatConversionProvider;import com.sun.media.sound.JDK13Services;import javazoom.spi.mpeg.sampled.file.MpegEncoding;import javazoom.spi.vorbis.sampled.file.VorbisAudioFormat;import javazoom.spi.vorbis.sampled.file.VorbisEncoding;import net.sf.fmj.codegen.MediaCGUtils;import net.sf.fmj.media.AbstractCodec;import net.sf.fmj.media.BufferQueueInputStream;import net.sf.fmj.media.renderer.audio.JavaSoundRenderer;import net.sf.fmj.utility.FormatUtils;import net.sf.fmj.utility.LoggerSingleton;/** * Converts formats that JavaSound can convert. *  * This has to do some tricks because of the delay in getting data from the converted audio output stream. * The streams are designed as streams, not buffer-based, so all our threading and buffer queue tricks * mean that we don't get an output buffer right away for an input one.  The missing output buffers build up. * And then we get EOM, and if the graph processing isn't done right, most of the output buffers never make it to the renderer. *  * TODO: if this is put ahead of com.ibm.media.codec.audio.PCMToPCM in the registry, there are problems playing the safexmas movie. * @author Ken Larson * */public class JavaSoundCodec extends AbstractCodec{	private static final Logger logger = LoggerSingleton.logger;	public JavaSoundCodec()	{		inputFormats = new Format[] {				new AudioFormat(AudioFormat.ULAW),				new AudioFormat(AudioFormat.ALAW),				new AudioFormat(AudioFormat.LINEAR),//				MP3 formats: Only work if MP3 SPI in classpath.  TODO: detect dynamically?				new AudioFormat(MpegEncoding.MPEG1L1.toString()),				new AudioFormat(MpegEncoding.MPEG1L2.toString()),				new AudioFormat(MpegEncoding.MPEG1L3.toString()),				new AudioFormat(MpegEncoding.MPEG2DOT5L1.toString()),				new AudioFormat(MpegEncoding.MPEG2DOT5L2.toString()),				new AudioFormat(MpegEncoding.MPEG2DOT5L3.toString()),				new AudioFormat(MpegEncoding.MPEG2L1.toString()),				new AudioFormat(MpegEncoding.MPEG2L2.toString()),				new AudioFormat(MpegEncoding.MPEG2L3.toString()),//				OGG formats: Only work if OGG SPI in classpath.  TODO: detect dynamically?				new AudioFormat(VorbisEncoding.VORBISENC.toString()),				};	// TODO: get dynamically from java sound.  Not sure if this is possible	}		//@Override	public Format[] getSupportedOutputFormats(Format input)	{		if (input == null)		{			return new Format[] {new AudioFormat(AudioFormat.LINEAR)};	// TODO		}		final javax.sound.sampled.AudioFormat javaSoundFormat = JavaSoundRenderer.convertFormat((AudioFormat) input);				// TODO: we could call AudioSystem.getTargetEncodings(javaSoundFormat); rather than hard code the PCM ones:		final javax.sound.sampled.AudioFormat[] targets1 = AudioSystem.getTargetFormats(Encoding.PCM_UNSIGNED, javaSoundFormat);		final javax.sound.sampled.AudioFormat[] targets2 = AudioSystem.getTargetFormats(Encoding.PCM_SIGNED, javaSoundFormat);				final javax.sound.sampled.AudioFormat[] targetsSpecial;				// for some reason, AudioSystem.getTargetFormats doesn't return anything for MpegAudioFormat		// TODO: check using class name, to avoid class not found exception if javazoom is not in the classpath.		if (javaSoundFormat instanceof javazoom.spi.mpeg.sampled.file.MpegAudioFormat)		{			javax.sound.sampled.AudioFormat decodedFormat =			    new javax.sound.sampled.AudioFormat(javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED,			    		javaSoundFormat.getSampleRate(),			                    16,			                    javaSoundFormat.getChannels(),			                    javaSoundFormat.getChannels() * 2,			                    javaSoundFormat.getSampleRate(),			                    false);			targetsSpecial = new javax.sound.sampled.AudioFormat[] {decodedFormat};		}		else if (javaSoundFormat instanceof VorbisAudioFormat)		{			// TODO: what is the correct mapping?			javax.sound.sampled.AudioFormat decodedFormat =			    new javax.sound.sampled.AudioFormat(javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED,			    		javaSoundFormat.getSampleRate(),			                    16,			                    javaSoundFormat.getChannels(),			                    javaSoundFormat.getChannels() * 2,			                    javaSoundFormat.getSampleRate(),			                    false);			targetsSpecial = new javax.sound.sampled.AudioFormat[] {decodedFormat};		}				else		{			targetsSpecial = new javax.sound.sampled.AudioFormat[0];		}				final Format[] result = new Format[targets1.length + targets2.length + targetsSpecial.length];		for (int i = 0; i < targets1.length; ++i)		{			result[i] = JavaSoundRenderer.convertFormat(targets1[i]);			logger.finer("getSupportedOutputFormats: " + result[i]);		}		for (int i = 0; i < targets2.length; ++i)		{			result[targets1.length + i] = JavaSoundRenderer.convertFormat(targets2[i]);			logger.finer("getSupportedOutputFormats: " + result[targets1.length + i]);		}		for (int i = 0; i < targetsSpecial.length; ++i)		{			result[targets1.length + targets2.length + i] = JavaSoundRenderer.convertFormat(targetsSpecial[i]);			logger.finer("getSupportedOutputFormats: " + result[targets1.length + targets2.length + i]);		}				// this all really depends on where MP3 decoding is handled in JavaSound with an SPI.		for (int i = 0; i < result.length; ++i)		{			AudioFormat a = ((AudioFormat) result[i]);			AudioFormat inputAudioFormat = (AudioFormat) input;			// converting from a sound format with a specific sample rate to one without causes problems building filter graphs.			// if the input format specifies a sample rate, we are only really interested in output formats with concrete sample			// rates.			if (FormatUtils.specified(inputAudioFormat.getSampleRate()) && !FormatUtils.specified(a.getSampleRate()))				result[i] = null;	// TODO: remove from array.							}		return result;	}	private BufferQueueInputStream bufferQueueInputStream;	private volatile AudioInputStream audioInputStream;	// set in one thread and read in another	private volatile AudioInputStream audioInputStreamConverted;	private AudioInputStreamThread audioInputStreamThread;		private class AudioInputStreamThread extends Thread	{		private final BufferQueueInputStream bufferQueueInputStream;				public AudioInputStreamThread(final BufferQueueInputStream bufferQueueInputStream)		{			super();			this.bufferQueueInputStream = bufferQueueInputStream;		}		public void run()		{			// TODO: this could take a while, perhaps it somehow needs to be done in prefetch.			try			{				audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(bufferQueueInputStream));//				audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(bufferQueueInputStream) {////					public synchronized int available() throws IOException//					{//						// TODO Auto-generated method stub//						int value = super.available();//						if (trace)//							logger.fine(this + " available=" + value);//						return value;//					}////					public synchronized void mark(int readlimit)//					{//						// TODO Auto-generated method stub//						if (trace)//							logger.fine(this + " mark");//						super.mark(readlimit);//					}////					public synchronized int read() throws IOException//					{//						if (trace)//							logger.fine(this + " read");//						// TODO Auto-generated method stub//						return super.read();//					}////					public synchronized int read(byte[] b, int off, int len) throws IOException//					{//						int result = super.read(b, off, len);//						//						if (trace)//							logger.fine(this + " read " + len + " returning " + result);//						//						return result;//					}////					public synchronized void reset() throws IOException//					{	//						if (trace)//						logger.fine(this + " RESET");////						// TODO Auto-generated method stub//						super.reset();//					}//					//				});			} catch (UnsupportedAudioFileException e)			{				logger.log(Level.WARNING, "" + e, e);	// TODO				//throw new ResourceUnavailableException(e.getMessage());				return;			} catch (IOException e)			{				logger.log(Level.WARNING, "" + e, e);	// TODO				//throw new ResourceUnavailableException(e.getMessage());				return;			}						final javax.sound.sampled.AudioFormat javaSoundAudioFormat = JavaSoundRenderer.convertFormat((AudioFormat) outputFormat);			logger.fine("javaSoundAudioFormat converted (out)=" + javaSoundAudioFormat);			audioInputStreamConverted = getAudioInputStream(javaSoundAudioFormat, audioInputStream);					}	}		// copied and modified from AudioSystem, to handle exceptions.    private static AudioInputStream getAudioInputStream(javax.sound.sampled.AudioFormat targetFormat,		       AudioInputStream sourceStream) {		if (sourceStream.getFormat().matches(targetFormat)) {			return sourceStream;		}			List codecs = getFormatConversionProviders();				for(int i = 0; i < codecs.size(); i++) {			FormatConversionProvider codec = (FormatConversionProvider) codecs.get(i);			if (codec.getClass().getName().equals("org.tritonus.sampled.convert.AlawFormatConversionProvider"))				continue;	// skip this one.			try			{			if(codec.isConversionSupported(targetFormat,sourceStream.getFormat()) ) {				return codec.getAudioInputStream(targetFormat,sourceStream);			}			}			catch (Exception e)			{	// tritonus throws exceptions like://				Exception in thread "Thread-8" java.lang.IllegalArgumentException: format conversion not supported//				at org.tritonus.sampled.convert.AlawFormatConversionProvider.getAudioInputStream(AlawFormatConversionProvider.java:116)//				at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:950)				logger.log(Level.WARNING, "" + e, e);			}		}				// we ran out of options...		throw new IllegalArgumentException("Unsupported conversion: " + targetFormat + " from " + sourceStream.getFormat());	 	}		    private static List getFormatConversionProviders()	{		return getProviders(FormatConversionProvider.class);	}	private static List getProviders(Class providerClass)	{		return JDK13Services.getProviders(providerClass);	}		private boolean trace;	void setTrace(boolean value)	{	this.trace = value;	}	// @Override	public void open() throws ResourceUnavailableException	{		super.open();						bufferQueueInputStream = new BufferQueueInputStream();	// TODO: limit should be total bytes, not number of bufers.//		bufferQueueInputStream.setTrace(((AudioFormat) inputFormat).getEncoding().equals("LINEAR") && ((AudioFormat) inputFormat).getSampleRate() == 22050.0);//		this.setTrace(((AudioFormat) inputFormat).getEncoding().equals("LINEAR") && ((AudioFormat) inputFormat).getSampleRate() == 22050.0);				// create fake header (see below)		final javax.sound.sampled.AudioFormat javaSoundAudioFormat = JavaSoundRenderer.convertFormat((AudioFormat) inputFormat);		logger.fine("javaSoundAudioFormat converted (in)=" + javaSoundAudioFormat);				final byte[] header = fakeHeader(javaSoundAudioFormat);		if (header == null)			throw new ResourceUnavailableException("Unable to reconstruct header for format: " + inputFormat);		if (header.length > 0)		{			Buffer headerBuffer = new Buffer();			headerBuffer.setData(header);			headerBuffer.setLength(header.length);			bufferQueueInputStream.put(headerBuffer);		}				audioInputStreamThread = new AudioInputStreamThread(bufferQueueInputStream);		audioInputStreamThread.start();			}		private int totalIn;	private int totalOut;	//@Override	public int process(Buffer input, Buffer output)	{        if (!checkInputBuffer(input))        {            return BUFFER_PROCESSED_FAILED;        }        // we can't do this since we need to put the EOM into the bufferQueueInputStream, so it will return EOS to the audio input stream.//        if (isEOM(input))//        {//            propagateEOM(output);	// TODO: what about data? can there be any?//            return BUFFER_PROCESSED_OK;//        }          		try		{			if (trace) logger.fine("process: " + MediaCGUtils.bufferToStr(input));			totalIn += input.getLength();			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -