【问题标题】:Out of memory exception converting raw file to wav in AudioRecorder在AudioRecorder中将原始文件转换为wav的内存不足异常
【发布时间】:2015-06-04 05:06:20
【问题描述】:

我正在使用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 文件吗?

谢谢

【问题讨论】:

    标签: android audiorecord


    【解决方案1】:

    尝试设置

    android:largeHeap="true"
    

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

    android docs

    【讨论】:

    • 感谢马特的回复。但是,这能保证超过 1GB 的文件吗?
    • :O 我真的不知道...你为什么要在 Android 上处理一个 1gb 的音频文件...如果这是项目的要求,你可能需要找到一个更好的实现允许从磁盘主动读取数据,以避免将整个剪辑加载到内存中。
    【解决方案2】:

    你期待什么?您正在尝试将原始文件中的所有数据放入一个整体的单个数组中。 当然,当文件很大的时候,就会报“out-of-memory”。

    需要实现逐块读写。

    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
            }
    

    【讨论】:

      猜你喜欢
      • 2012-01-27
      • 2017-04-01
      • 2018-11-09
      • 2014-08-01
      • 1970-01-01
      • 2021-05-11
      • 1970-01-01
      • 2016-04-11
      • 1970-01-01
      相关资源
      最近更新 更多