Reputation: 2782
I am using AudioRecord
to record audio in android. After the recording is finished i am converting raw file to wav file. But the app crashed due to Out of memory if the size of the file is more than 70 MB.
Below is the code which i have used to convert raw file to 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));
}
}
Can anyone let me know is there any other way to convert large raw file to wav file. Or can we directly record audio to wav file using AudioRecord?
Thanks
Upvotes: 0
Views: 508
Reputation: 4654
What you expected? You are trying to fit all the data from raw file into a one-piece single array. Of course, when the file is large, you will be given "out-of-memory".
You need to implement block-by-block reading and writing.
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());
}
}
...
}
Also, I suggest you to perform a much simpler byte-order change:
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
}
Upvotes: 1
Reputation: 28609
Try setting
android:largeHeap="true"
in your application manifest to request a larger heap..
Upvotes: 1