📄 javasoundrenderer.java
字号:
{ //logger.fine("Available: " + sourceLine.available()); //logger.fine("length: " + length); //logger.fine("sourceLine.getBufferSize(): " + sourceLine.getBufferSize()); final int n = sourceLine.write(data, offset, length); // TODO: this can block for a very long time if it doesn't if (n >= length) break; else if (n == 0) { // TODO: we could choose to handle a write failure this way, // assuming that it is considered legal to call stop while process is being called. // however, that seems like a bad idea in general.// if (!sourceLine.isRunning())// { // buffer.setLength(offset);// buffer.setOffset(length);// return INPUT_BUFFER_NOT_CONSUMED; // our write was interrupted.// } logger.warning("sourceLine.write returned 0, offset=" + offset + "; length=" + length + "; available=" + sourceLine.available() + "; frame size in bytes" + sourceLine.getFormat().getFrameSize() + "; sourceLine.isActive() = " + sourceLine.isActive() + "; " + sourceLine.isOpen() + "; sourceLine.isRunning()=" + sourceLine.isRunning() ); return BUFFER_PROCESSED_FAILED; // sourceLine.write docs indicate that this will only happen if there is an error. } else { offset += n; length -= n; } } if (bufferNotConsumed) { // return INPUT_BUFFER_NOT_CONSUMED if not all bytes were written buffer.setLength(newBufferLength); buffer.setOffset(newBufferOffset); return INPUT_BUFFER_NOT_CONSUMED; } if (buffer.isEOM()) { // TODO: the proper way to do this is to implement Drainable, and let the processor call our drain method. sourceLine.drain(); // we need to ensure that the media finishes playing, otherwise the EOM event will // be posted before the media finishes playing. } return BUFFER_PROCESSED_OK; } /* ----------------------------- */ public int hashCode() { return super.hashCode() ^ 0xAD; // TODO: this hash code change is useless. // TODO: for putting entries into the plugin manager, PlugInManager.addPlugIn appears to // create a hash only based on the full class name, and only the last 22 chars of it. // that is, ClassNameInfo.makeHashValue("com.sun.media.renderer.audio.JavaSoundRenderer") // and ClassNameInfo.makeHashValue("net.sf.fmj.media.renderer.audio.JavaSoundRenderer") // both return the same value, as does // ClassNameInfo.makeHashValue("udio.JavaSoundRenderer") // therefore, this trick of creating a different hash code for this class, does nothing to avoid the // warnings, when JMF is ahead in the classpath: // Problem adding net.sf.fmj.media.renderer.audio.JavaSoundRenderer to plugin table.// Already hash value of 1262232571547748861 in plugin table for class name of com.sun.media.renderer.audio.JavaSoundRenderer } /* -------------------- private methods ----------------------- */ /** * Convert javax.sound.sampled.AudioFormat to javax.media.format.AudioFormat. */ public static AudioFormat convertFormat(javax.sound.sampled.AudioFormat format) { Encoding encoding = format.getEncoding(); int channels = format.getChannels(); float frameRate = format.getFrameRate(); int frameSize = format.getFrameSize() < 0 ? format.getFrameSize() : (format.getFrameSize() * 8); float sampleRate = format.getSampleRate(); int sampleSize = format.getSampleSizeInBits(); int endian = format.isBigEndian() ? AudioFormat.BIG_ENDIAN : AudioFormat.LITTLE_ENDIAN; int signed = AudioFormat.NOT_SPECIFIED; String encodingString = AudioFormat.LINEAR; if (encoding == Encoding.PCM_SIGNED) { signed = AudioFormat.SIGNED; encodingString = AudioFormat.LINEAR; } else if (encoding == Encoding.PCM_UNSIGNED) { signed = AudioFormat.UNSIGNED; encodingString = AudioFormat.LINEAR; } else if (encoding == Encoding.ALAW) { encodingString = AudioFormat.ALAW; } else if (encoding == Encoding.ULAW) { encodingString = AudioFormat.ULAW; } else { encodingString = encoding.toString(); } AudioFormat jmfFormat = new AudioFormat( encodingString, (double) sampleRate, sampleSize, channels, endian, signed, frameSize, frameRate, AudioFormat.byteArray ); return jmfFormat; } /** * * @return null if doesn't match any mpeg encoding */ private static Encoding toMpegEncoding(String encodingStr) { // TODO: perhaps we should use reflection to avoid class not found problems if javazoom is not in the classpath. final Encoding[] mpegEncodings = new Encoding[] { MpegEncoding.MPEG1L1, MpegEncoding.MPEG1L2, MpegEncoding.MPEG1L3, MpegEncoding.MPEG2DOT5L1, MpegEncoding.MPEG2DOT5L2, MpegEncoding.MPEG2DOT5L3, MpegEncoding.MPEG2L1, MpegEncoding.MPEG2L2, MpegEncoding.MPEG2L3, }; for (int i = 0; i < mpegEncodings.length; ++i) { if (encodingStr.equals(mpegEncodings[i].toString())) return mpegEncodings[i]; } return null; } /** * * @return null if doesn't match any vorbis encoding */ private static Encoding toVorbisEncoding(String encodingStr) { // TODO: perhaps we should use reflection to avoid class not found problems if javazoom is not in the classpath. final Encoding[] vorbisEncodings = new Encoding[] { VorbisEncoding.VORBISENC }; for (int i = 0; i < vorbisEncodings.length; ++i) { if (encodingStr.equals(vorbisEncodings[i].toString())) return vorbisEncodings[i]; } return null; } public static javax.sound.sampled.AudioFormat convertFormat(AudioFormat format) { String encodingString = format.getEncoding(); int channels = format.getChannels(); double frameRate = format.getFrameRate(); int frameSize = format.getFrameSizeInBits() / 8; double sampleRate = format.getSampleRate(); int sampleSize = format.getSampleSizeInBits(); boolean endian = (format.getEndian() == AudioFormat.BIG_ENDIAN); int signed = format.getSigned(); Encoding encoding; if (AudioFormat.LINEAR.equals(encodingString)) { switch(signed) { case AudioFormat.SIGNED: encoding = Encoding.PCM_SIGNED; break; case AudioFormat.UNSIGNED: encoding = Encoding.PCM_UNSIGNED; break; default: encoding = Encoding.PCM_SIGNED; // TODO: return null } } else if (AudioFormat.ALAW.equals(encodingString)) { encoding = Encoding.ALAW; } else if (AudioFormat.ULAW.equals(encodingString)) { encoding = Encoding.ULAW; } else if (toMpegEncoding(encodingString) != null) { encoding = toMpegEncoding(encodingString); } else if (toVorbisEncoding(encodingString) != null) { encoding = toVorbisEncoding(encodingString); } else { encoding = new CustomEncoding(encodingString); } final javax.sound.sampled.AudioFormat sampledFormat; if (encoding == Encoding.PCM_SIGNED) { sampledFormat = new javax.sound.sampled.AudioFormat( (float)sampleRate, sampleSize, channels, true, endian ); } else if (encoding == Encoding.PCM_UNSIGNED) { sampledFormat = new javax.sound.sampled.AudioFormat( (float)sampleRate, sampleSize, channels, false, endian ); } else if (encoding instanceof MpegEncoding) { // TODO: perhaps we should use reflection to avoid class not found problems if javazoom is not in the classpath. return new MpegAudioFormat( encoding, (float) sampleRate, sampleSize, channels, //signed, frameSize, (float) frameRate, endian, new HashMap() ); } else if (encoding instanceof VorbisEncoding) { // TODO: perhaps we should use reflection to avoid class not found problems if javazoom is not in the classpath. return new VorbisAudioFormat( encoding, (float) sampleRate, sampleSize, channels, //signed, frameSize, (float) frameRate, endian, new HashMap() ); } else { sampledFormat = new javax.sound.sampled.AudioFormat( encoding, (float)sampleRate, sampleSize, channels, frameSize, (float)frameRate, endian ); } return sampledFormat; } private static List getMixers() { Vector mixers = new Vector(); Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo(); for (int i=0; i<mixerInfos.length; i++) { Mixer mixer = AudioSystem.getMixer(mixerInfos[i]); mixers.add(mixer); } return mixers; } private static void getMixer(String name) { Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo(); for (int i=0; i<mixerInfos.length; i++) { //mixerInfos[i]; } } /* private void logControls(SourceDataLine line) { sourceLine.getControl(BooleanControl.Type.MUTE); sourceLine.getControl(FloatControl.Type.VOLUME); sourceLine.getControl(FloatControl.Type.BALANCE); sourceLine.getControl(FloatControl.Type.PAN); Control[] audioControls = line.getControls(); } */ private void logControls(Control[] controls) { for (int i=0; i<controls.length; i++) { Control control = controls[i]; logger.info("control: " + control); Type controlType = control.getType(); if (controlType instanceof CompoundControl.Type) { logControls(((CompoundControl)control).getMemberControls()); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -