使用Java提高/降低AudioInputStream的音频播放速度
使用我正在使用的Java进入复杂的音频世界,基本上我在Github上改进并发布了Java 该库的主要类是,代码有注释,易于理解使用Java提高/降低AudioInputStream的音频播放速度,java,audio,audioinputstream,Java,Audio,Audioinputstream,使用我正在使用的Java进入复杂的音频世界,基本上我在Github上改进并发布了Java 该库的主要类是,代码有注释,易于理解 问题是它支持许多功能,除了提高/降低音频速度。比如说,当你改变视频速度时,YouTube也会这样做 我不知道如何实现这样的功能。我的意思是,当我将音频写入targetFormat的采样率时,我该怎么做?每次我都要重新启动音频 AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGN
问题是它支持许多功能,除了提高/降低音频速度。比如说,当你改变视频速度时,YouTube也会这样做 我不知道如何实现这样的功能。我的意思是,当我将音频写入
targetFormat
的采样率时,我该怎么做?每次我都要重新启动音频
AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate()*2, nSampleSizeInBits, sourceFormat.getChannels(),
nSampleSizeInBits / 8 * sourceFormat.getChannels(), sourceFormat.getSampleRate(), false);
播放音频的代码为:
/**
* Main loop.
*
* Player Status == STOPPED || SEEKING = End of Thread + Freeing Audio Resources.<br>
* Player Status == PLAYING = Audio stream data sent to Audio line.<br>
* Player Status == PAUSED = Waiting for another status.
*/
@Override
public Void call() {
// int readBytes = 1
// byte[] abData = new byte[EXTERNAL_BUFFER_SIZE]
int nBytesRead = 0;
int audioDataLength = EXTERNAL_BUFFER_SIZE;
ByteBuffer audioDataBuffer = ByteBuffer.allocate(audioDataLength);
audioDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
// Lock stream while playing.
synchronized (audioLock) {
// Main play/pause loop.
while ( ( nBytesRead != -1 ) && status != Status.STOPPED && status != Status.SEEKING && status != Status.NOT_SPECIFIED) {
try {
//Playing?
if (status == Status.PLAYING) {
// System.out.println("Inside Stream Player Run method")
int toRead = audioDataLength;
int totalRead = 0;
// Reads up a specified maximum number of bytes from audio stream
//wtf i have written here xaxaxoaxoao omg //to fix! cause it is complicated
for (; toRead > 0
&& ( nBytesRead = audioInputStream.read(audioDataBuffer.array(), totalRead, toRead) ) != -1; toRead -= nBytesRead, totalRead += nBytesRead)
// Check for under run
if (sourceDataLine.available() >= sourceDataLine.getBufferSize())
logger.info(() -> "Underrun> Available=" + sourceDataLine.available() + " , SourceDataLineBuffer=" + sourceDataLine.getBufferSize());
//Check if anything has been read
if (totalRead > 0) {
trimBuffer = audioDataBuffer.array();
if (totalRead < trimBuffer.length) {
trimBuffer = new byte[totalRead];
//Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array
// The number of components copied is equal to the length argument.
System.arraycopy(audioDataBuffer.array(), 0, trimBuffer, 0, totalRead);
}
//Writes audio data to the mixer via this source data line
sourceDataLine.write(trimBuffer, 0, totalRead);
// Compute position in bytes in encoded stream.
int nEncodedBytes = getEncodedStreamPosition();
// Notify all registered Listeners
listeners.forEach(listener -> {
if (audioInputStream instanceof PropertiesContainer) {
// Pass audio parameters such as instant
// bit rate, ...
listener.progress(nEncodedBytes, sourceDataLine.getMicrosecondPosition(), trimBuffer, ( (PropertiesContainer) audioInputStream ).properties());
} else
// Pass audio parameters
listener.progress(nEncodedBytes, sourceDataLine.getMicrosecondPosition(), trimBuffer, emptyMap);
});
}
} else if (status == Status.PAUSED) {
//Flush and stop the source data line
if (sourceDataLine != null && sourceDataLine.isRunning()) {
sourceDataLine.flush();
sourceDataLine.stop();
}
try {
while (status == Status.PAUSED) {
Thread.sleep(50);
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
logger.warning("Thread cannot sleep.\n" + ex);
}
}
} catch (IOException ex) {
logger.log(Level.WARNING, "\"Decoder Exception: \" ", ex);
status = Status.STOPPED;
generateEvent(Status.STOPPED, getEncodedStreamPosition(), null);
}
}
// Free audio resources.
if (sourceDataLine != null) {
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();
sourceDataLine = null;
}
// Close stream.
closeStream();
// Notification of "End Of Media"
if (nBytesRead == -1)
generateEvent(Status.EOM, AudioSystem.NOT_SPECIFIED, null);
}
//Generate Event
status = Status.STOPPED;
generateEvent(Status.STOPPED, AudioSystem.NOT_SPECIFIED, null);
//Log
logger.info("Decoding thread completed");
return null;
}
/**
*主回路。
*
*播放器状态==停止| |查找=线程结束+释放音频资源。
*播放器状态==播放=发送到音频线路的音频流数据。
*玩家状态==暂停=等待其他状态。
*/
@凌驾
公开作废通知(){
//int readBytes=1
//字节[]abData=新字节[外部缓冲区大小]
int nBytesRead=0;
int audioDataLength=外部缓冲区大小;
ByteBuffer audioDataBuffer=ByteBuffer.allocate(audioDataLength);
audioDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
//播放时锁定流。
同步(音频锁){
//主播放/暂停循环。
而((nBytesRead!=-1)&&status!=status.STOPPED&&status!=status.SEEKING&&status!=status.未指定){
试一试{
//玩?
如果(状态==状态.播放){
//System.out.println(“内部流播放器运行方法”)
int toRead=音频数据长度;
int totalRead=0;
//从音频流中读取指定的最大字节数
//我在这里写了XAXOAXAO omg//来修复!因为它很复杂
对于(;探路者>0)
&&(nBytesRead=audioInputStream.read(audioDataBuffer.array(),totalRead,toRead))!=-1;toRead-=nBytesRead,totalRead+=nBytesRead)
//检查运行不足
if(sourceDataLine.available()>=sourceDataLine.getBufferSize())
logger.info(()->“Underrun>Available=“+sourceDataLine.Available()+”,SourceDataLineBuffer=“+sourceDataLine.getBufferSize());
//检查是否已阅读任何内容
如果(totalRead>0){
trimBuffer=audioDataBuffer.array();
if(totalRead{
if(属性容器的音频输入流实例){
//传递音频参数,如instant
//比特率。。。
progress(nEncodedBytes,sourceDataLine.getMicrosecondPosition(),trimBuffer,((PropertiesContainer)audioInputStream.properties());
}否则
//传递音频参数
progress(nEncodedBytes,sourceDataLine.getMicrosecondPosition(),trimBuffer,emptyMap);
});
}
}else if(status==status.PAUSED){
//刷新并停止源数据行
if(sourceDataLine!=null&&sourceDataLine.isRunning()){
sourceDataLine.flush();
sourceDataLine.stop();
}
试一试{
while(status==status.PAUSED){
睡眠(50);
}
}捕获(中断异常例外){
Thread.currentThread().interrupt();
警告(“线程无法睡眠。\n”+ex);
}
}
}捕获(IOEX异常){
logger.log(Level.WARNING,“\”解码器异常:\”,ex);
status=status.STOPPED;
generateEvent(Status.STOPPED,getEncodedStreamPosition(),null);
}
}
//免费音频资源。
if(sourceDataLine!=null){
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();
sourceDataLine=null;
}
//关闭小溪。
closeStream();
//关于“终止媒体”的通知
如果(nBytesRead==-1)
generateEvent(Status.EOM,AudioSystem.NOT_指定,null);
}
//生成事件
status=status.STOPPED;
generateEvent(Status.STOPPED,AudioSystem.NOT_指定,null);
//日志
logger.info(“解码线程完成”);
返回null;
}
如果您愿意,可以免费下载并单独查看该库。:)我需要一些帮助 看看你链接的库,这似乎不是一个专门针对这个pla的好地方
public class AudioActivity extends Activity {
AudioTrack audio = new AudioTrack(AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
intSize, //size of pcm file to read in bytes
AudioTrack.MODE_STATIC);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//read track from file
File file = new File(getFilesDir(), fileName);
int size = (int) file.length();
byte[] data = new byte[size];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(data, 0, size);
fileInputStream.close();
audio.write(data, 0, data.length);
} catch (IOException e) {}
}
//change playback speed by factor
void changeSpeed(double factor) {
audio.setPlaybackRate((int) (audio.getPlaybackRate() * factor));
}
}
original_samples = [0, 0.1, 0.2, 0.3, 0.4, 0.5]
def faster(samples):
new_samples = []
for i = 0 to samples.length:
if i is even:
new_samples.add(0.5 * (samples[i] + samples[i+1]))
return new_samples
faster_samples = faster(original_samples)