I have one application that can record audios in WAV format. It has editing options like:
- insert at the start
- insert at the end
- insert in between
- override
- delete up to end
It is observed that distorted noise occurs if we perform any of above editing operations more than one time.
Below are the WAV file configuration details:
- ENCODING_PCM_16BIT
- CHANNEL_IN_MONO
- 8000(sample rate)
WAV file header:
fileWriter.setLength(0); // Set file length to 0, to prevent unexpected behavior in case the file already existed
fileWriter.writeBytes("RIFF");
fileWriter.writeInt(0); // Final file size not known yet, write 0
fileWriter.writeBytes("WAVE"); // format
fileWriter.writeBytes("fmt "); // subchunk 1 id
fileWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM
fileWriter.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM
fileWriter.writeShort(Short.reverseBytes(samplingSpec.numberOfChannels()));// Number of channels, 1 for mono, 2 for stereo
fileWriter.writeInt(Integer.reverseBytes(samplingSpec.sampleRate())); // Sample rate
fileWriter.writeInt(Integer.reverseBytes(samplingSpec.sampleRate() * samplingSpec.sampleSizeInBytes() * samplingSpec.numberOfChannels())); // Byte rate, SampleRate*NumberOfChannels*BitsPerSample/8
fileWriter.writeShort(Short.reverseBytes((short) (samplingSpec.numberOfChannels() * samplingSpec.sampleSizeInBytes()))); // Block align, NumberOfChannels*BitsPerSample/8
fileWriter.writeShort(Short.reverseBytes(samplingSpec.sampleSizeInBits())); // Bits per sample
fileWriter.writeBytes("data");
fileWriter.writeInt(0); // Data chunk size not known yet, write 0
Once recording completed, we are updating the WAV file header:
byte[] sizes = ByteBuffer
.allocate(8)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt((int) (fileWriter.length() - 8)) // ChunkSize
.putInt((int) (fileWriter.length() - 44)) // Subchunk2Size
.array();
try {
fileWriter.seek(4);
fileWriter.write(sizes, 0, 4);
// Subchunk2Size
fileWriter.seek(40);
fileWriter.write(sizes, 4, 4);
} catch (IOException ex) {
// Rethrow but we still close accessWave in our finally
throw ex;
} finally {
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException ex) {
//
}
}
}
Scenario:
I am recording Audio then I am performing first edit operation as insert at the end. The code is as below:
RandomAccessFile temp = null;
RandomAccessFile origin = null;
int length;
byte[] sizes = new byte[0];
isUrgent = getUrgentFl();
try {
try {
temp = new RandomAccessFile(tempFile, "rw");
origin = new RandomAccessFile(originalFile, "rw");
} catch (Exception e) {
Log.e("combineWaveFile1 : ", "combineWaveFile1_Exception" + e.getMessage());
}
byte[] buffer = new byte[1024]; // 8192
try {
try {
origin.seek(origin.length());
} catch (Exception e) {
Log.e("combineWaveFile1 : ", "combineWaveFile1_Exception" + e.getMessage());
}
try {
while ((length = temp.read(buffer)) > 0) {
origin.write(buffer, 0, length);
}
} catch (Exception e) {
Log.e("combineWaveFile2 : ", "combineWaveFile2_Exception" + e.getMessage());
}
//////////////////
try {
sizes = ByteBuffer
.allocate(8)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt((int) (origin.length() - 8)) // ChunkSize
.putInt((int) (origin.length() - 44)) // Subchunk2Size
.array();
} catch (Exception e) {
Log.e("combineWaveFile3 : ", "combineWaveFile3_Exception" + e.getMessage());
}
//noinspection CaughtExceptionImmediatelyRethrown
try {
//accessWave = new RandomAccessFile(fileWriter, "rw");
// ChunkSize
//originFile.write(0);
origin.seek(4);
origin.write(sizes, 0, 4);
// Subchunk2Size
origin.seek(40);
origin.write(sizes, 4, 4);
//originFile.write(0);
} catch (Exception e) {
Log.e("combineWaveFile4 : ", "combineWaveFile4_Exception" + e.getMessage());
} finally {
if (tempFile != null) {
try {
temp.close();
File f = new File(tempFile);
if (f.exists()) {
f.delete();
}
} catch (Exception e) {
Log.e("combineWaveFile5 : ", "combineWaveFile5_Exception" + e.getMessage());
}
}
if (origin != null) {
try {
origin.close();
} catch (Exception e) {
Log.e("combineWaveFile6 : ", "combineWaveFile6_Exception" + e.getMessage());
}
}
}
After completing first insert at the end operation then I am performing insert in between operation. Code for it as below:
RandomAccessFile temp = null;
RandomAccessFile origin = null;
RandomAccessFile newRecordFile = null;
int length;
long seekBytesLength = 0;
byte[] sizes = new byte[0];
try {
try {
temp = new RandomAccessFile(tempFile, "rw");
origin = new RandomAccessFile(originalFile, "rw");
} catch (Exception e) {
Log.e("insertInBetween1 : ", "insertInBetween1_Exception" + e.getMessage());
}
byte[] buffer = new byte[1024];
try {
try {
long totalLength = origin.length();
long oneByteOfLength = totalLength / 100;
seekBytesLength = oneByteOfLength * Constants.seekPosition;
//long skipBytesFromLength = totalLength - seekBytesLength;
} catch (Exception e) {
Log.e("insertInBetween2 : ", "insertInBetween2_Exception" + e.getMessage());
}
if (seekBytesLength != 0) {
try {
origin.seek(seekBytesLength);
} catch (Exception e) {
Log.e("insertInBetween3 : ", "insertInBetween3_Exception" + e.getMessage());
}
try {
temp.seek(temp.length());
while ((length = origin.read(buffer)) > 0) {
temp.write(buffer, 0, length);
}
} catch (Exception e) {
Log.e("insertInBetween4 : ", "insertInBetween4_Exception" + e.getMessage());
}
} else {
try {
origin.getChannel().position(0);
temp.seek(temp.length());
while ((length = origin.read(buffer)) > 0) {
temp.write(buffer, 0, length);
}
} catch (Exception e) {
Log.e("insertInBetween5 : ", "insertInBetween5_Exception" + e.getMessage());
}
try {
File originFile = new File(originalFile);
File tmpFile = new File(tempFile);
if (originFile.delete()) {
tmpFile.renameTo(originFile);
}
} catch (Exception e) {
Log.e("insertInBetween6 : ", "insertInBetween6_Exception" + e.getMessage());
}
}
/////////////////
try {
sizes = ByteBuffer
.allocate(8)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt((int) (temp.length() - 8)) // ChunkSize
.putInt((int) (temp.length() - 44)) // Subchunk2Size
.array();
} catch (Exception e) {
Log.e("insertInBetween7 : ", "insertInBetween7_Exception" + e.getMessage());
}
//no inspection CaughtException Immediately Rethrown
try {
temp.seek(4);
temp.write(sizes, 0, 4);
// Subchunk2Size
temp.seek(40);
temp.write(sizes, 4, 4);
} catch (Exception e) {
Log.e("insertInBetween8 : ", "insertInBetween8_Exception" + e.getMessage());
}
/////////////////////
try {
if (seekBytesLength != 0) {
appendFiles(origin, temp, tempFile, seekBytesLength);
}
} catch (Exception e) {
Log.e("insertInBetween9 : ", "insertInBetween9_Exception" + e.getMessage());
}
} catch (Exception e) {
Log.e("insertInBetween10 : ", "insertInBetween10_Exception" + e.getMessage());
}
finally {
if (seekBytesLength == 0) {
File tmpFile = new File(tempFile);
if (tmpFile.exists()) {
tmpFile.delete();
}
}
}
} catch (Exception e) {
Log.e("insertInBetween11 : ", "insertInBetween11_Exception" + e.getMessage());
}
**// appendFiles method :**
int length;
byte[] sizes = new byte[0];
isUrgent = getUrgentFl();
try {
byte[] buffer = new byte[1024];
// byte[] buffer = new byte[BUFFER_SIZE];
try {
try {
originFile.seek(seekBytesLength);
} catch (Exception e) {
Log.e("appendFiles1 : ", "appendFiles1_Exception" + e.getMessage());
}
try {
while ((length = tempFile.read(buffer)) > 0) {
originFile.write(buffer, 0, length);
}
} catch (Exception e) {
Log.e("appendFiles2 : ", "appendFiles2_Exception" + e.getMessage());
}
//////////////////
try {
sizes = ByteBuffer
.allocate(8)
.order(ByteOrder.LITTLE_ENDIAN)
// There are probably a bunch of different/better ways to calculate
// these two given your circumstances. Cast should be safe since if the WAV is
// > 4 GB we've already made a terrible mistake.
.putInt((int) (originFile.length() - 8)) // ChunkSize
.putInt((int) (originFile.length() - 44)) // Subchunk2Size
.array();
} catch (Exception e) {
Log.e("appendFiles3 : ", "appendFiles3_Exception" + e.getMessage());
}
//noinspection CaughtExceptionImmediatelyRethrown
try {
originFile.seek(4);
originFile.write(sizes, 0, 4);
// Subchunk2Size
originFile.seek(40);
originFile.write(sizes, 4, 4);
//originFile.write(0);
} catch (Exception e) {
Log.e("appendFiles4 : ", "appendFiles4_Exception" + e.getMessage());
} finally {
if (originFile != null) {
try {
originFile.close();
} catch (Exception e) {
Log.e("appendFiles6 : ", "appendFiles6_Exception" + e.getMessage());
}
}
if (tempFile != null) {
try {
tempFile.close();
File f = new File(tempFileName);
if (f.exists()) {
f.delete();
}
} catch (Exception e) {
Log.e("appendFiles5 : ", "appendFiles5_Exception" + e.getMessage());
}
}
}
The distortion issue occurs here randomly for any edit operation. So, please guide me, how to handle this issue?
Sorry for my bad English.