2017-04-23 58 views
1

我從wav文件獲取數據並想要將字節寫回wav。android如何將字節寫入wav文件

我已經得到了來自wav.here字節是我的代碼

我知道0-43字節是頭和44-1是數據

byte[] soundBytes; 
     try { 
      InputStream inputStream = new FileInputStream(getRealPathFromURI(this,uri)); 
      soundBytes = toByteArray(inputStream); 
      for (int i = 0; i != -1 ; i++) { 

       if(soundBytes[i]<0) { 
        k =soundBytes[i] + 256; 
       } else {k = soundBytes[i];} 
       System.out.println("byte " + i + ": " + k); 
      } 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 


    } 
} 

public byte[] toByteArray(InputStream in) throws IOException { 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int read = 0; 
    byte[] buffer = new byte[1024]; 
    while (read != -1) { 
     read = in.read(buffer); 
     if (read != -1) 
      out.write(buffer,0,read); 
    } 
    out.close(); 
    return out.toByteArray(); 
} 
+0

我很困惑Android是否實現Java類TargetDataLine。如果是的話,這個類將處理所有的.wav頭文件/格式,你所要做的就是提供按照格式轉換成字節的PCM。但我不清楚Android使用多少Java音頻。 –

回答

1

下面的代碼轉換原始的PCM文件轉換成原始文件。正如你所說的,你得到了原始字節,你可以使用這些字節創建一個原始文件,並將該文件發送到下面的rawToWave()方法或操作rawToWave()方法,以便直接將需要轉換的字節[]轉換爲原始文件。

public void rawToWave(final File rawFile) throws IOException { 

    File waveFile = DirectoryOperations.createDirAndAudioFile("vocal.wav");// creating the empty wav file. 

    byte[] rawData = new byte[(int) rawFile.length()]; 
    DataInputStream input = null; 
    try { 
     input = new DataInputStream(new FileInputStream(rawFile)); 
     input.read(rawData); 
    } finally { 
     if (input != null) { 
      input.close(); 
     } 
    } 

    DataOutputStream output = null;//following block is converting raw to wav. 
    try { 
     output = new DataOutputStream(new FileOutputStream(waveFile)); 
     // WAVE header 
     // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 
     writeString(output, "RIFF"); // chunk id 
     writeInt(output, 36 + rawData.length); // chunk size 
     writeString(output, "WAVE"); // format 
     writeString(output, "fmt "); // subchunk 1 id 
     writeInt(output, 16); // subchunk 1 size 
     writeShort(output, (short) 1); // audio format (1 = PCM) 
     writeShort(output, (short) 1); // number of channels 
     writeInt(output, RECORDER_SAMPLERATE); // sample rate 
     writeInt(output, RECORDER_SAMPLERATE * 2); // byte rate 
     writeShort(output, (short) 2); // block align 
     writeShort(output, (short) 16); // bits per sample 
     writeString(output, "data"); // subchunk 2 id 
     writeInt(output, rawData.length); // subchunk 2 size 
     output.write(fullyReadFileToBytes(rawFile)); 

    } finally { 
     if (output != null) { 
      output.close(); 
     } 
    } 
} 

private byte[] fullyReadFileToBytes(File f) throws IOException { 
    int size = (int) f.length(); 
    byte bytes[] = new byte[size]; 
    byte tmpBuff[] = new byte[size]; 
    try (FileInputStream fis = new FileInputStream(f)) { 
     int read = fis.read(bytes, 0, size); 
     if (read < size) { 
      int remain = size - read; 
      while (remain > 0) { 
       read = fis.read(tmpBuff, 0, remain); 
       System.arraycopy(tmpBuff, 0, bytes, size - remain, read); 
       remain -= read; 
      } 
     } 
    } 

    return bytes; 
} 

private void writeInt(final DataOutputStream output, final int value) throws IOException { 
    output.write(value); 
    output.write(value >> 8); 
    output.write(value >> 16); 
    output.write(value >> 24); 
} 

private void writeShort(final DataOutputStream output, final short value) throws IOException { 
    output.write(value); 
    output.write(value >> 8); 
} 

private void writeString(final DataOutputStream output, final String value) throws IOException { 
    for (int i = 0; i < value.length(); i++) { 
     output.write(value.charAt(i)); 
    } 
} 
+0

whats recorder採樣率和RECORDER_SAMPLERATE * 2是什麼意思? –

+0

我有0-43字節,他們是頭,不是嗎?所以我真的不需要像RIFF WAVE那樣寫東西? –

+0

@陳韋綱RECORDER_SAMPLERATE是音頻文件的採樣率(如44100 Hz)。在Java中,字節是8位,短是16位,所以你需要乘以2來防止過載。您的文件是Wav文件,因此前44個字節是標題。上面的方法是爲原始文件,所以你需要擺脫第一個44字節使用這種方法,或者你說你不需要做即興波動的事情。 – ACAkgul