package com.jssrc.resample; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.spi.FormatConversionProvider; /** * @author Maksim Khadkevich */ public class JSSRCSampleRateConversionProvider extends FormatConversionProvider { private static final AudioFormat.Encoding[] inputEncodings = { AudioFormat.Encoding.PCM_SIGNED, }; private static final AudioFormat.Encoding[] outputEncodings = { AudioFormat.Encoding.PCM_SIGNED, }; public AudioFormat.Encoding[] getSourceEncodings() { AudioFormat.Encoding[] encodings = new AudioFormat.Encoding[inputEncodings.length]; System.arraycopy(inputEncodings, 0, encodings, 0, inputEncodings.length); return encodings; } public AudioFormat.Encoding[] getTargetEncodings() { AudioFormat.Encoding[] encodings = new AudioFormat.Encoding[outputEncodings.length]; System.arraycopy(outputEncodings, 0, encodings, 0, outputEncodings.length); return encodings; } public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat) { if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) { AudioFormat.Encoding encs[] = new AudioFormat.Encoding[1]; encs[0] = AudioFormat.Encoding.PCM_SIGNED; return encs; } else { return new AudioFormat.Encoding[0]; } } public AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat) { return new AudioFormat[0]; } /** */ public AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream) { if (isConversionSupported(targetEncoding, sourceStream.getFormat())) { AudioFormat sourceFormat = sourceStream.getFormat(); AudioFormat targetFormat = new AudioFormat(targetEncoding, sourceFormat.getSampleRate(), sourceFormat.getSampleSizeInBits(), sourceFormat.getChannels(), sourceFormat.getFrameSize(), sourceFormat.getFrameRate(), sourceFormat.isBigEndian()); return getAudioInputStream(targetFormat, sourceStream); } else { throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); } } public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream) { AudioFormat inputFormat = sourceStream.getFormat(); AudioFormat outputFormat = targetFormat; if (isConversionSupported(inputFormat, outputFormat)) { JSSRCResampler resampler = new JSSRCResampler(inputFormat, outputFormat, sourceStream); // set sample size from source stream if possible long length = AudioSystem.NOT_SPECIFIED; if (AudioSystem.NOT_SPECIFIED != sourceStream.getFrameLength()) { length = (long) (sourceStream.getFrameLength() * targetFormat.getSampleRate() / inputFormat.getSampleRate()); } return new AudioInputStream(resampler, outputFormat, length); } throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetFormat.toString()); } /** * Determines whether the codec supports conversion from one * particular format to another. * * @param inputFormat format of the incoming data * @return true if the conversion is supported, otherwise false */ public boolean isConversionSupported(AudioFormat inputFormat, AudioFormat outputFormat) { AudioFormat.Encoding inputEncoding = inputFormat.getEncoding(); AudioFormat.Encoding outputEncoding = outputFormat.getEncoding(); int inputSampleSize = inputFormat.getSampleSizeInBits(); int outputSampleSize = outputFormat.getSampleSizeInBits(); boolean inputIsBigEndian = inputFormat.isBigEndian(); boolean outputIsBigEndian = outputFormat.isBigEndian(); if (inputFormat.getSampleRate() == outputFormat.getSampleRate()) { return false; } if (inputIsBigEndian || outputIsBigEndian) { return false; } if (((inputSampleSize == 8) && (outputSampleSize == 8)) || ((inputSampleSize == 16) && (outputSampleSize == 16))) { if ((inputEncoding == AudioFormat.Encoding.PCM_SIGNED)) { if ((outputEncoding == AudioFormat.Encoding.PCM_SIGNED)) { return true; } else { return false; } } else { return false; } } else { return false; } } }