在AudioRecorder中将原始文件转换为wav的内存不足异常

时间:2015-06-04 05:06:20

标签: android audiorecord

我正在使用AudioRecord在Android中录制音频。录制完成后,我将原始文件转换为wav文件。但是,如果文件大小超过70 MB,应用程序会由于内存不足而崩溃。

以下是我用来将原始文件转换为wav的代码。

private void rawToWave(final File rawFile, final File waveFile) throws IOException {

    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;
    try {
        output = new DataOutputStream(new FileOutputStream(waveFile));
        // WAVE header
        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, SAMPLE_RATE); // sample rate
        writeInt(output, SAMPLE_RATE * 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
        // Audio data (conversion big endian -> little endian)
        short[] shorts = new short[rawData.length / 2];
        ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
        ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
        for (short s : shorts) {
            bytes.putShort(s);
        }
        output.write(bytes.array());
    } finally {
        if (output != null) {
            output.close();
        }
    }
}

private void writeInt(final DataOutputStream output, final int value) throws IOException {
    output.write(value >> 0);
    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 >> 0);
    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));
    }
}

任何人都可以告诉我有没有其他方法可以将大型原始文件转换为wav文件。或者我们可以使用AudioRecord直接将音频录制到wav文件吗?

由于

2 个答案:

答案 0 :(得分:0)

尝试设置

android:largeHeap="true"

在您的应用程序清单中请求更大的堆..

android docs

答案 1 :(得分:0)

你的期望是什么?您正在尝试将原始文件中的所有数据放入一个单一的数组中。 当然,当文件很大时,你会被给予&#34;内存不足&#34;。

你需要实现逐块读写。

try (DataOutputStream output = new DataOutputStream(new FileOutputStream(waveFile))) {
    ...
    // blah-blah-blah, RIFF-headers
    ...

    try(DataInputStream input = new DataInputStream(new FileInputStream(rawFile))) {

        byte[] rawData = new byte[16384]; // 16k is enough
        int len;
        while ((len = input.read(buffer)) > 0) { // while data left in file
            short[] shorts = new short[len / 2];
            ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
            ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
            for (short s : shorts) {
                bytes.putShort(s);
            }
            output.write(bytes.array());
        }
    }
    ...
}

另外,我建议你执行更简单的字节顺序更改:

        byte[] rawData = new byte[16384]; // 16k is enough
        int len;
        while ((len = input.read(buffer)) > 0) { // while data left in file
            for (int i = 0; i < len; i += 2) {
               byte t = rawData[i + 1];    // just swap even and odd bytes;
               rawData[i + 1] = rawData[i];
               rawData[i] = rawData[i + 1];
            }
            output.write(rawData, 0, len); // then write the buffer to the output
        }