2016-03-06 135 views
0

我想从给定的mp3文件中提取字节数组,以便对后者应用快速傅里叶变换。执行的FFT将为我的宠物项目音乐推荐系统提供一些功能。将mp3文件输入流转换为字节输出流的性能问题

我写了下面的代码以提取从给定的MP3文件的字节:

public class TrackSample { 

private static byte[] readBytesInPredefinedFormat(TargetDataLine format, InputStream inStream) throws IOException { 
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
    byte[] buffer = new byte[8192]; 
    int bytesRead; 
    while ((bytesRead = inStream.read(buffer)) > 0) { 
     int count = format.read(buffer, 0, buffer.length); 
     if (count > 0) { 
      byteArrayOutputStream.write(buffer, 0, count); 
     } 
     byteArrayOutputStream.write(buffer, 0, bytesRead); 
    } 
    byte[] bytes = byteArrayOutputStream.toByteArray(); 
    byteArrayOutputStream.close(); 
    inStream.close(); 
    return bytes; 
} 

public static byte[] getTrackBytes(String pathToTrackSample) throws IOException, LineUnavailableException { 
    FileInputStream fileInputStream = new FileInputStream(pathToTrackSample); 
    final AudioFormat format = CurrentAudioFormat.getAudioFormat(); //Fill AudioFormat with the wanted settings 
    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 

    TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info); 
    line.open(format); 
    line.start(); 

    return readBytesInPredefinedFormat(line, fileInputStream); 
    } 
} 

和指定的音频格式是

public class CurrentAudioFormat { 

    public static AudioFormat getAudioFormat(){ 
     float sampleRate = 44100; 
     int sampleSizeInBits = 8; 
     int channels = 1; //mono 
     boolean signed = true; 
     boolean bigEndian = true; 
     return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian); 
    } 
} 

我试图在以下MP3测试该代码文件:

File type ID: MPG3 
Num Tracks:  1 
---- 
Data format:  2 ch, 44100 Hz, '.mp3' (0x00000000) 0 bits/channel, 0 bytes/packet, 1152 frames/packet, 0 bytes/frame 
       no channel layout. 
estimated duration: 104.176325 sec 
audio bytes: 4167053 
audio packets: 3988 
bit rate: 320000 bits per second 
packet size upper bound: 1052 
maximum packet size: 1045 
audio data file offset: 3169 
optimized 
audio 4591692 valid frames + 576 priming + 1908 remainder = 4594176 

该系统的特点是:

  • 处理器:Intel core i5,1.4 GHz;
  • 内存:DDR3,4GB
  • 操作系统:Mac OS X船长巨岩

花了大约5分钟,提取该MP3文件的字节数组。

什么是可能的瓶颈,我该如何改进它们?

+0

你为什么不用'AudioSystem.getAudioInputStream(File)'来读取文件? –

+0

我不知道'AudioSystem.getAudioInputStream(File)'。你能给我一个使用这种格式的例子吗?我在DataLine.Info info = new DataLine.Info(TargetDataLine.class,format);行上收到编译类型错误;和line.open(格式); –

+0

有时缓冲区不会写入其最后一位并使用format.read(buffer,0,buffer.length);要读取一些以前不应读取的块,应使用format.read(buffer,0,bytesRead);我不是说这是问题,但它会给你带来一些噪音的坏音频样本 – achabahe

回答

2

要读取的字节数,你只需要

while ((bytesRead = inStream.read(buffer)) > -1) { 
    byteArrayOutputStream.write(buffer, 0, bytesRead); 
} 

我不知道为什么你正在阅读的两倍。

为了确保你得到的是正确的尝试将它重新保存到一个新的音频文件。

-

标准的方式来读取音频文件是

AudioInputStream audioInputStream=null; 
    try { 
    audioInputStream=AudioSystem.getAudioInputStream(new File(file)); 
    } 
    catch(UnsupportedAudioFileException auf) { auf.printStackTrace(); } 

那么你通过这个的AudioInputStream到你的阅读方法。

+0

Thx有关将数据保存回mp3文件的建议。我做到了,无法播放它。我认为AudioFormat类存在问题,即我没有正确指定它。 –

+0

你如何读/写mp3? java不能这样做,所以你必须有一些外部库。 – gpasch

+0

int count = format.read(buffer,0,buffer.length);其中format是AudioFormat类的实例 - 这是我读取的mp3文件。我只是将字节[]保存到mp3文件。你可以建议任何第三方库在java中使用mp3格式吗? –