Java AudioInputStream如何支持带负数字节的跳过

问题描述 投票:1回答:2

我试图用AudioInputStream skip(long bytes)方法跳过负数字节。

问题是尝试(假设少量字节...):

int skipped = audioInputStream.skip(-bytes);

总是返回0,如本答案Java AudioInputStream skip with negative number of bytes always returns 0所述

我需要创建一个支持负数字节或类似向后的实现。


github上图书馆的Here is the full code

我所做的就是每次用户跳过音频时都会重新创建这条线,当我可以做得更好时,只需要向后或向前移动就会非常慢。现在它只支持前进......

/**                                                                                                                   
 * Skip bytes in the File input stream. It will skip N frames matching to bytes, so it will never skip given bytes len
 *                                                                                                                    
 * @param bytes                                                                                                       
 *            the bytes                                                                                               
 * @return value bigger than 0 for File and value = 0 for URL and InputStream                                         
 * @throws StreamPlayerException                                                                                      
 *             the stream player exception                                                                            
 */                                                                                                                   
public long seek(long bytes) throws StreamPlayerException {                                                           
    long totalSkipped = 0;                                                                                            

    //If it is File                                                                                                   
    if (dataSource instanceof File) {                                                                                 

        //Check if the requested bytes are more than totalBytes of Audio                                              
        long bytesLength = getTotalBytes();                                                                           
        System.out.println("Bytes: " + bytes + " BytesLength: " + bytesLength);                                       
        if ( ( bytesLength <= 0 ) || ( bytes >= bytesLength )) {                                                      
            generateEvent(Status.EOM, getEncodedStreamPosition(), null);                                              
            return totalSkipped;                                                                                      
        }                                                                                                             

        logger.info(() -> "Bytes to skip : " + bytes);                                                                
        Status previousStatus = status;                                                                               
        status = Status.SEEKING;                                                                                      

        try {                                                                                                         
            synchronized (audioLock) {                                                                                
                generateEvent(Status.SEEKING, AudioSystem.NOT_SPECIFIED, null);                                       
                initAudioInputStream();                                                                               
                if (audioInputStream != null) {                                                                       

                    long skipped;                                                                                     
                    // Loop until bytes are really skipped.                                                           
                    while (totalSkipped < ( bytes )) { //totalSkipped < (bytes-SKIP_INACCURACY_SIZE)))                
                        //System.out.println("Running");                                                              
                        skipped = audioInputStream.skip(bytes - totalSkipped);                                        
                        if (skipped == 0)                                                                             
                            break;                                                                                    
                        totalSkipped += skipped;                                                                      
                        logger.info("Skipped : " + totalSkipped + "/" + bytes);                                       
                        if (totalSkipped == -1)                                                                       
                            throw new StreamPlayerException(StreamPlayerException.PlayerException.SKIP_NOT_SUPPORTED);

                        logger.info("Skeeping:" + totalSkipped);                                                      
                    }                                                                                                 
                }                                                                                                     
            }                                                                                                         
            generateEvent(Status.SEEKED, getEncodedStreamPosition(), null);                                           
            status = Status.OPENED;                                                                                   
            if (previousStatus == Status.PLAYING)                                                                     
                play();                                                                                               
            else if (previousStatus == Status.PAUSED) {                                                               
                play();                                                                                               
                pause();                                                                                              
            }                                                                                                         

        } catch (IOException ex) {                                                                                    
            logger.log(Level.WARNING, ex.getMessage(), ex);                                                           
        }                                                                                                             
    }                                                                                                                 
    return totalSkipped;                                                                                              
}                                                                                                                     
java audio skip audioinputstream
2个回答
2
投票

你可以创建自己的缓冲区,它可能是ByteArrayOutputStream,但这是一个臃肿的东西 - 几分钟后总是让我内存不足 - 或者有你自己的Vector或其他ArrayList。

我尝试使用10分钟.wav文件并且运行正常 - 只要播放并将字节添加到缓冲区。

EG

Vector v=new Vector();
byte[] data=new byte[basicU];
while(true) {
  k=audioInputStream.read(data, 0, data.length);
  v.add(data);
  if(k<0) break;
  tot+=k;
}

--

这是我用seek搜索文件的方法。我有一个生成搜索信号的线程。当我们有多次寻求时,问题就很复杂了。我使用变量K来检查是否需要将数据添加到缓冲区。我不使用跳过但正常阅读;只是不要在线上播放。

public void play() {
  boolean seekingBack=false;
  int i, j, k=0, seekPos=0, basicU=1024;
  AudioFormat targetFormat=null;
  int tot=0;
        new Thread() {
          public void run() {
            while(true) {
              numBytes=(Math.random()>0.5?1:-1)*500000;
              try { Thread.sleep(5000); } catch (Exception e) {} 
              seekSignal=true;
            }
          }}.start();
      try {
      File fileIn=new File("........");
        AudioInputStream audioInputStream=AudioSystem.getAudioInputStream(fileIn);
        targetFormat=audioInputStream.getFormat();
        DataLine.Info dinfo=new DataLine.Info(SourceDataLine.class, targetFormat);
        SourceDataLine line=null;
        line=(SourceDataLine)AudioSystem.getLine(dinfo);
        if(line==null) return;
        line.open(targetFormat);
        line.start();
        Vector v=new Vector();
        byte[] data=new byte[basicU];
        int K=0;
        while(true) {
          if(seekingBack) { // seeking backwards
            K=seekPos;
            k=data.length;
            for(j=0; j<data.length; j++)
              if(seekPos+j<v.size()) data[j]=((Byte)v.get(seekPos+j)).byteValue();
              else { k=j; break; }
            line.write(data, 0, k);
            seekPos+=k;
            K+=k;
            if(seekPos>v.size()-1) seekingBack=false;
          }
          else { // normal playing
            k=audioInputStream.read(data, 0, data.length);
            if(k<0) break;
            line.write(data, 0, k);
            if(K>=v.size()) for(j=0; j<k; j++) v.add(data[j]);
            K+=k;
          }
          if(seekSignal) { // received a seek signal
            if(seekingBack) { // we are on a previous back seek - reading from the buffer
            if(numBytes<0) {
              seekPos+=numBytes;
              if(seekPos<0) seekPos=0;
            }
            else { // depending on where the seek will go (in the buffer or actual audio stream)
              if(numBytes+seekPos<v.size())
                seekPos+=numBytes;
              else { // actual stream
                int rem=numBytes-(v.size()-seekPos);
                K=v.size();
                while(rem>0) {
                  k=audioInputStream.read(data, 0, data.length);
                  if(k<0) break;
                  if(K>=v.size()) for(j=0; j<k; j++) v.add(data[j]);
                  rem-=k;
                  K+=k;
                }
              }
            }
            }
            else { // we are not processing a previous back seek
            if(numBytes>=0) { // forward
                while(numBytes>0) {
                  k=audioInputStream.read(data, 0, data.length);
                  if(k<0) break;
                  if(K>=v.size()) for(j=0; j<k; j++) v.add(data[j]);
                  numBytes-=k;
                  K+=k;
                }
            }
            else { // backward
              seekingBack=true; seekPos=v.size()+numBytes; if(seekPos<0) seekPos=0; }
            }
            seekSignal=false;
          }
        }
        line.stop();
        line.close();
      }
      catch(Exception ex) { ex.printStackTrace(); System.out.println("audio problem "+ex); }
}

0
投票

使用您自己的缓冲区,其中包含历史滚动窗口。我将构建一个辅助类,通过分配List<byte[]>来管理历史记录,例如8192字节。然后你需要一些简单的溢出机制,抛出最旧的块,结合一些指针操作来跟踪你实际在流中的位置。祝好运!

© www.soinside.com 2019 - 2024. All rights reserved.