在java

时间:2018-01-10 15:29:42

标签: java audio wav

我正在处理一个音频项目并正在使用this audio library。它有一个方法可以读取wav文件并返回一个值为-1到1的双精度数组(每秒44100个音频值)。该库中的所有方法似乎都使用相同的双数组格式来保存音频。

然而,该方法不起作用。以下是我提供的wav file示例,此处是程序读取该文件的recording(在收听前调低音量)。
 它与原始文件的长度不同,并且会失真。这是该方法背后的代码(TL; DR在阅读之前阅读我的评论):

public static double[] read(String filename) {
        byte[] data = readByte(filename);
        int n = data.length;
        double[] d = new double[n/2];
        for (int i = 0; i < n/2; i++) {
            d[i] = ((short) (((data[2*i+1] & 0xFF) << 8) + (data[2*i] & 0xFF))) / ((double) Short.MAX_VALUE);
        }
        return d;
    }

    // return data as a byte array
    private static byte[] readByte(String filename) {
        byte[] data = null;
        AudioInputStream ais = null;
        try {

            // try to read from file
            File file = new File(filename);
            if (file.exists()) {
                ais = AudioSystem.getAudioInputStream(file);
                int bytesToRead = ais.available();
                data = new byte[bytesToRead];
                int bytesRead = ais.read(data);
                if (bytesToRead != bytesRead)
                    throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
            }

            // try to read from URL
            else {
                URL url = StdAudio.class.getResource(filename);
                ais = AudioSystem.getAudioInputStream(url);
                int bytesToRead = ais.available();
                data = new byte[bytesToRead];
                int bytesRead = ais.read(data);
                if (bytesToRead != bytesRead)
                    throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
            }
        }
        catch (IOException e) {
            throw new IllegalArgumentException("could not read '" + filename + "'", e);
        }

        catch (UnsupportedAudioFileException e) {
            throw new IllegalArgumentException("unsupported audio format: '" + filename + "'", e);
        }

        return data;
    }

我测试了readByte()方法返回的字节数组的长度(read()方法使用的),它是49016个位置。原始剪辑为4秒,采样率为44100,阵列应为44100 * 4左右。失真的音频有点超过第二个持续时间,与失真的wav文件的长度相匹配,因此我认为问题出在readByte()方法中。我可能是错的(有人让我知道,如果是这样),但由于这一点,我认为问题出在这个代码中。这里消除异常处理程序是代码(返回一个字节数组):

    byte[] data = null;
    AudioInputStream ais = null;
    try {

        // try to read from file
        File file = new File(filename);
        if (file.exists()) {
            ais = AudioSystem.getAudioInputStream(file);
            int bytesToRead = ais.available();
            data = new byte[bytesToRead];
            int bytesRead = ais.read(data);
            if (bytesToRead != bytesRead)
                throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
        }

        // try to read from URL
        else {
            URL url = StdAudio.class.getResource(filename);
            ais = AudioSystem.getAudioInputStream(url);
            int bytesToRead = ais.available();
            data = new byte[bytesToRead];
            int bytesRead = ais.read(data);
            if (bytesToRead != bytesRead)
                throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
        }
    } 

...

    return data;

为什么这个字节数组的数据失真?

编辑:我尝试将我尝试播放的wav文件转换为大约一半的采样率,它似乎正常播放(仍有点偏离)。 Here是由此产生的录音。有任何想法如何更改代码,让它读取44100采样率文件? “getAudioInputStream”方法是否采用比44100更低的采样率?这个库说它“假设音频是单声道的,采样率为44,100”,所以这看起来像个错误。

1 个答案:

答案 0 :(得分:0)

您可以为.info-blocks .info-blocks-in分配固定高度 请参见下面的代码段(在不同的屏幕宽度下进行测试):

.info-blocks {
  margin-bottom: 15px;
  /* background: #efefef; */
}

.info-blocks i.icon-info-blocks {
  float: left;
  color: #FFEB3B;
  font-size: 30px;
  min-width: 50px;
  margin-top: 7px;
  text-align: center;
  background: #002e5b;
  width: 72px;
  height: 72px;
  padding-top: 7px;
  border: 1px solid #002e5b;
  border-radius: 50%;
}

.info-blocks .info-blocks-in {
  padding: 0 10px;
  height:80px;
  overflow: hidden;
}

.info-blocks .info-blocks-in h3 {
  color: #002e5b;
  font-size: 18px;
  line-height: 28px;
  margin: 0px;
  margin-bottom: 8px;
  font-family: 'Montserrat', sans-serif;
  font-weight: 600;
}

.info-blocks .info-blocks-in p {
  font-size: 14px;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://code.iconify.design/1/1.0.3/iconify.min.js"></script>

<br>
<body>
<div class="container">
<div class="row">
  <div class="col-sm-4 info-blocks">
    <i class="icon-info-blocks"><span class="iconify" data-icon="mdi:map-legend" data-inline="false"></span></i>
    <div class="info-blocks-in">
      <h3>Explore</h3>
      <p>Lorem ipsum dolor sit amet</p>
    </div>
  </div>
</div>
<div class="row">
  <div class="col-sm-4 info-blocks">
    <i class="icon-info-blocks"><span class="iconify" data-icon="mdi:map-legend" data-inline="false"></span></i>
    <div class="info-blocks-in">
      <h3>Explore</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut magna eleifend, fermentum arcu et, euismod neque. Sed ante elit.</p>
    </div>
  </div>
</div>
<div class="row">
  <div class="col-sm-4 info-blocks">
    <i class="icon-info-blocks"><span class="iconify" data-icon="mdi:map-legend" data-inline="false"></span></i>
    <div class="info-blocks-in">
      <h3>Explore</h3>
      <p>Lorem Ipsum</p>
    </div>
  </div>
</div>
</div>
</body>