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

📄 samplerateconversionprovider.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		}				private int roundDown(double a) {			//return a<0?((int) (a-0.5f)):((int) (a+0.5f));			//return a<0?(-((int) -a)):((int) a);			//return (int) a;			return (int) Math.floor(a);		}				private int roundUp(double a) {			//return a<0?((int) (a-0.5f)):((int) (a+0.5f));			//return a<0?(-((int) -a)):((int) a);			return (int) Math.ceil(a);		}		private void convertSampleAndHold(				float[] inSamples, double inSampleOffset, int inSampleCount, double increment, 				float[] outSamples, int outSampleOffset, int outSampleCount, float[] history, int historyLength) {			if (DEBUG_STREAM) {				TDebug.out("convertSampleAndHold(inSamples["+inSamples.length+"], "					+roundDown(inSampleOffset)+" to "+roundDown(inSampleOffset+increment*(outSampleCount-1))+", "					+"outSamples["+outSamples.length+"], "+outSampleOffset+" to "+(outSampleOffset+outSampleCount-1)+")");				System.out.flush();			}			for (int i=0; i<outSampleCount; i++) {				int iInIndex=roundDown(inSampleOffset+increment*i);				if (iInIndex<0) {					outSamples[i+outSampleOffset]=history[iInIndex+historyLength];					if (DEBUG_STREAM) {						TDebug.out("convertSampleAndHold: using history["+(iInIndex+historyLength)+" because inIndex="+iInIndex);					}				} 				else if (iInIndex>=inSampleCount) {					if (DEBUG_STREAM_PROBLEMS) {						TDebug.out("convertSampleAndHold: INDEX OUT OF BOUNDS outSamples["+i+"]=inSamples[roundDown("+inSampleOffset+")="+iInIndex+"];");					}				} else {					outSamples[i+outSampleOffset]=inSamples[iInIndex];					//outSamples[i]=inSamples[roundDown(inSampleOffset)];				}				//inSampleOffset+=increment; <- this produces too much rounding errors...			}		}		private void convertLinearInterpolation(				float[] inSamples, double inSampleOffset, int inSampleCount, double increment, 				float[] outSamples, int outSampleOffset, int outSampleCount, float[] history, int historyLength) {			if (DEBUG_STREAM) {				TDebug.out("convertLinearInterpolate(inSamples["+inSamples.length+"], "					+roundDown(inSampleOffset)+" to "+roundDown(inSampleOffset+increment*(outSampleCount-1))+", "					+"outSamples["+outSamples.length+"], "+outSampleOffset+" to "+(outSampleOffset+outSampleCount-1)+")");				System.out.flush();			}			for (int i=0; i<outSampleCount; i++) {				try {					double dInIndex=inSampleOffset+increment*i-1;					int iInIndex=(int) Math.floor(dInIndex);					double factor=1.0d-(dInIndex-iInIndex);					float value=0;					for (int x=0; x<2; x++) {						if (iInIndex>=inSampleCount) {							// we clearly need more samples !							if (DEBUG_STREAM_PROBLEMS) {								TDebug.out("linear interpolation: INDEX OUT OF BOUNDS iInIndex="+iInIndex+" inSampleCount="+inSampleCount);							}						} 						else if (iInIndex<0) {							int histIndex=iInIndex+historyLength;							if (histIndex>=0) {								value+=history[histIndex]*factor;								if (DEBUG_STREAM) {									TDebug.out("linear interpolation: using history["+iInIndex+"]");								}							} 							else if (DEBUG_STREAM_PROBLEMS) {								TDebug.out("linear interpolation: history INDEX OUT OF BOUNDS iInIndex="+iInIndex+" histIndex="+histIndex+" history length="+historyLength);							}						} else {							value+=inSamples[iInIndex]*factor;						}						factor=1-factor;						iInIndex++;					}					outSamples[i+outSampleOffset]=value;					//outSamples[i]=inSamples[roundDown(inSampleOffset)];				} catch (ArrayIndexOutOfBoundsException aioobe) {  					if (DEBUG_STREAM_PROBLEMS) {						TDebug.out("**** REAL INDEX OUT OF BOUNDS ****** outSamples["+i+"]=inSamples[roundDown("+inSampleOffset+")="+roundDown(inSampleOffset)+"];");					}					//throw aioobe;				}				//inSampleOffset+=increment; <- this produces too much rounding errors...			}		}		private double inSamples2outSamples(double inSamples) {			return inSamples*targetSampleRate/sourceSampleRate;		}		private double outSamples2inSamples(double outSamples) {			return outSamples*sourceSampleRate/targetSampleRate;		}		/**		 * Main read method. It blocks until all samples are converted or		 * the source stream is at its end or closed.<br>		 * The sourceStream's sample rate is converted following		 * the current setting of <code>conversionAlgorithm</code>.		 * At most outBuffer.getSampleCount() are converted. In general,		 * if the return value (and outBuffer.getSampleCount()) is less		 * after processing this function, then it is an indicator		 * that it was the last block to be processed.		 * 		 * @see #setConversionAlgorithm(int)		 * @param outBuffer the buffer that the converted samples will be written to.		 * @throws IllegalArgumentException when outBuffer's channel count does not match		 * @return number of samples in outBuffer ( == outBuffer.getSampleCount())		 *         or -1. A return value of 0 is only possible when outBuffer has 0 samples.		 */		public synchronized int read(FloatSampleBuffer outBuffer) throws IOException {			if (isClosed()) {				return -1;			}			if (outBuffer.getChannelCount()!=thisBuffer.getChannelCount()) {				throw new IllegalArgumentException("passed buffer has different channel count");			}			if (outBuffer.getSampleCount()==0) {				return 0;			}			if (TDebug.TraceAudioConverter) {				TDebug.out(">SamplerateConverterStream.read("+outBuffer.getSampleCount()+"frames)");			}			float[] outSamples;			float[] inSamples;			float[] history;			double increment=outSamples2inSamples(1.0);			int writtenSamples=0;			do {				// check thisBuffer with samples of source stream				int inSampleCount=thisBuffer.getSampleCount();				if (roundDown(dPos)>=inSampleCount || !thisBufferValid) {					// need to load new data of sourceStream					readFromSourceStream();					if (isClosed()) {						break;					}					inSampleCount=thisBuffer.getSampleCount();				}				// calculate number of samples to write				int writeCount=outBuffer.getSampleCount()-writtenSamples;				// check whether this exceeds the current in-buffer				if (roundDown(outSamples2inSamples((double) writeCount)+dPos)>=inSampleCount) {					int lastOutIndex=roundUp(inSamples2outSamples(((double) inSampleCount)-dPos));					// normally, the above formula gives the exact writeCount.					// but due to rounding issues, sometimes it has to be decremented once.					// so we need to iterate to get the last index and then increment it once to make 					// it the writeCount (=the number of samples to write)					while (roundDown(outSamples2inSamples((double) lastOutIndex)+dPos)>=inSampleCount) {						lastOutIndex--;						if (DEBUG_STREAM) {							TDebug.out("--------- Decremented lastOutIndex="+lastOutIndex);						}					}					if (DEBUG_STREAM_PROBLEMS) {						int testLastOutIndex=writeCount-1;						if (DEBUG_STREAM_PROBLEMS) {							while (roundDown(outSamples2inSamples((double) testLastOutIndex)+dPos)>=inSampleCount) {								testLastOutIndex--;							}						}						if (testLastOutIndex!=lastOutIndex) {							TDebug.out("lastOutIndex wrong: lastOutIndex="+lastOutIndex+" testLastOutIndex="+testLastOutIndex+" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");						}					}					writeCount=lastOutIndex+1;				}				// finally do the actual conversion - separated per channel				for (int channel=0; channel<outBuffer.getChannelCount(); channel++) {					inSamples=thisBuffer.getChannel(channel);					outSamples=outBuffer.getChannel(channel);					history=historyBuffer.getChannel(channel);					switch (conversionAlgorithm) {						case SAMPLE_AND_HOLD: convertSampleAndHold(inSamples, dPos, inSampleCount, increment, 												outSamples, writtenSamples, writeCount, history, historyBuffer.getSampleCount()); break;						case LINEAR_INTERPOLATION: convertLinearInterpolation(inSamples, dPos, inSampleCount, increment, 												outSamples, writtenSamples, writeCount, history, historyBuffer.getSampleCount()); break;					}				}				writtenSamples+=writeCount;				// adjust new position				dPos+=outSamples2inSamples((double) writeCount);			} while (!isClosed() && writtenSamples<outBuffer.getSampleCount());			if (writtenSamples<outBuffer.getSampleCount()) {				outBuffer.changeSampleCount(writtenSamples, true);			}			if (TDebug.TraceAudioConverter) {				testOutFramesReturned+=outBuffer.getSampleCount();				TDebug.out("< return "+outBuffer.getSampleCount()+"frames. Total="+testOutFramesReturned+" frames. Read total "+testInFramesRead+" frames from source stream");			}			return outBuffer.getSampleCount();		}				//////////////////// utility methods ////////////////////////				protected double sourceFrames2targetFrames(double sourceFrames) {			return targetSampleRate/sourceSampleRate*sourceFrames;		}		protected double targetFrames2sourceFrames(double targetFrames) {			return sourceSampleRate/targetSampleRate*targetFrames;		}		protected long sourceBytes2targetBytes(long sourceBytes) {			long sourceFrames=sourceBytes/getSourceFrameSize();			long targetFrames=(long) sourceFrames2targetFrames(sourceFrames);			return targetFrames*getFrameSize();		}		protected long targetBytes2sourceBytes(long targetBytes) {			long targetFrames=targetBytes/getFrameSize();			long sourceFrames=(long) targetFrames2sourceFrames(targetFrames);			return sourceFrames*getSourceFrameSize();		}				public int getFrameSize() {			return getFormat().getFrameSize();		}		public int getSourceFrameSize() {			return sourceStream.getFormat().getFrameSize();		}		//////////////////// methods overwritten of AudioInputStream ////////////////////////				public int read() throws IOException {			if (getFormat().getFrameSize() != 1) {				throw new IOException("frame size must be 1 to read a single byte");			}			// very ugly, but efficient. Who uses this method anyway ?			byte[] temp = new byte[1];			int result = read(temp);			if (result <= 0) {				return -1;			}			return temp[0] & 0xFF;		}				/**		 * @see #read(byte[], int, int)		 */		public int read(byte[] abData) throws IOException {			return read(abData, 0, abData.length);		}		/**		 * Read nLength bytes that will be the converted samples		 * of the original inputStream.		 * When nLength is not an integral number of frames,		 * this method may read less than nLength bytes.		 */		public int read(byte[] abData, int nOffset, int nLength)		throws	IOException {			if (isClosed()) {				return -1;			}			int frameCount=nLength/getFrameSize();			if (writeBuffer==null) {				writeBuffer=new FloatSampleBuffer(getFormat().getChannels(), frameCount, getFormat().getSampleRate());			} else {				writeBuffer.changeSampleCount(frameCount, false);			}			int writtenSamples=read(writeBuffer);			if (writtenSamples==-1) {				return -1;			}			int written=writeBuffer.convertToByteArray(abData, nOffset, getFormat());			return written;		}			public synchronized long skip(long nSkip) throws IOException {			// only returns integral frames			long sourceSkip = targetBytes2sourceBytes(nSkip);			long sourceSkipped = sourceStream.skip(sourceSkip);			flush();			return sourceBytes2targetBytes(sourceSkipped);		}				public int available() throws IOException {			return (int) sourceBytes2targetBytes(sourceStream.available());		}				public void mark(int readlimit) {			sourceStream.mark((int) targetBytes2sourceBytes(readlimit));		}		public synchronized void reset() throws IOException {			sourceStream.reset();			flush();		}			public boolean markSupported() {			return sourceStream.markSupported();		}			public void close() throws IOException {			if (isClosed()) {				return;			}			sourceStream.close();			// clean memory, this will also be an indicator that			// the stream is closed			thisBuffer=null;			historyBuffer=null;			byteBuffer=null;		}				///////////////////////////// additional methods /////////////////////////////		public boolean isClosed() {			return thisBuffer==null;		}				/**		 * Flushes the internal buffers		 */		public synchronized void flush() {			if (!isClosed()) {				thisBufferValid=false;				historyBuffer.makeSilence();			}		}				/////////////////////////// Properties ///////////////////////////////////////				public synchronized void setTargetSampleRate(float sr) {			if (sr>0) {				targetSampleRate=sr;				//((SRCAudioFormat) getFormat()).setSampleRate(sr);				resizeBuffers();			}		}				public synchronized void setConversionAlgorithm(int algo) {			if ((algo==SAMPLE_AND_HOLD || algo==LINEAR_INTERPOLATION) 				&& (algo!=conversionAlgorithm)) {					conversionAlgorithm=algo;					resizeBuffers();			}		}		public synchronized float getTargetSampleRate() {			return targetSampleRate;		}				public synchronized int getConversionAlgorithm() {			return conversionAlgorithm; 		}	}	/**	   Obviously, this class is used to be able to set the	   frame rate/sample rate after the AudioFormat object	   has been created. It assumes the PCM case where the	   frame rate is always in sync with the sample rate.	   (MP)	*/	public static class SRCAudioFormat extends AudioFormat {		private float sampleRate;				public SRCAudioFormat(AudioFormat targetFormat) {			super(targetFormat.getEncoding(),				targetFormat.getSampleRate(),				targetFormat.getSampleSizeInBits(),				targetFormat.getChannels(),				targetFormat.getChannels()*targetFormat.getSampleSizeInBits()/8,				targetFormat.getSampleRate(),				targetFormat.isBigEndian());			this.sampleRate=targetFormat.getSampleRate();		}			public void setSampleRate(float sr) {			if (sr>0) {				this.sampleRate=sr;			}		}				public float getSampleRate() {			return this.sampleRate;		}				public float getFrameRate() {			return this.sampleRate;		}	}}/*** SampleRateConversionProvider.java ***/

⌨️ 快捷键说明

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