使用Java提高/降低AudioInputStream的音频播放速度

使用Java提高/降低AudioInputStream的音频播放速度,java,audio,audioinputstream,Java,Audio,Audioinputstream,使用我正在使用的Java进入复杂的音频世界,基本上我在Github上改进并发布了Java 该库的主要类是,代码有注释,易于理解 问题是它支持许多功能,除了提高/降低音频速度。比如说,当你改变视频速度时,YouTube也会这样做 我不知道如何实现这样的功能。我的意思是,当我将音频写入targetFormat的采样率时,我该怎么做?每次我都要重新启动音频 AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGN

使用我正在使用的Java进入复杂的音频世界,基本上我在Github上改进并发布了Java

该库的主要类是,代码有注释,易于理解


问题是它支持许多功能,除了提高/降低音频速度。比如说,当你改变视频速度时,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)