I’ve been trying to merge two WAVE files on Android for quite some time now, but can't seem to get it working fine.
Everything looks great, files are read and written to the output file, which is also read at a later stage and has the file size that I expect to see.
Problems occur immediately after the merge of the application is completed. This message will be displayed in the log: An error occurred in updateListener, the recording is interrupted , which is an extAudioRecorder
message extAudioRecorder
and appears when OnRecordPositionUpdateListener
reaches the catch clause (exception has the following detailMessage: write failed: EBADF (bad file number) ). It doesn't seem to break anything, so I'm not too worried about it.
The real problem occurs when I try to create a MediaPlayer
and call setDataSource(String path)
on the MediaPlayer instance. Whenever I do this with a merged file, the following error message will be displayed in the log: Unable to create a media player (pressing IOException
contains the following detailMessage: setDataSourceFD failed: status = 0x80000000 ). Please note that the first time the file will play perfectly (this first file was not created by the combineWaveFiles()
method). This error message appears indicating that the audio file format is incorrect and / or MediaPlayer cannot be read.
My question is: if anyone sees any real problems with the code below (I know that it is not optimal in many ways, but I prefer to work first and then worry about performance).
public static String MergeRecordings(String cumulativeFile, String recordFile, int sampleRate, int bpp, int bufferSize, int channels) { if (cumulativeFile == null) { return recordFile; } else if (recordFile == null) { return cumulativeFile; } String outputFile = FileUtils.getFilePath(null, MDSettings.shared().getMainActivity()); FileUtils.combineWaveFiles(cumulativeFile, recordFile, outputFile, sampleRate, bpp, bufferSize, channels); //FileUtils.removeFile(cumulativeFile); //FileUtils.removeFile(recordFile); return outputFile; } //creates a new file containing file1 + file2 stuck together as such. private static void combineWaveFiles(String file1, String file2, String outputFile, int sampleRate, int bpp, int bufferSize, int channels) { FileInputStream in1 = null, in2 = null; FileOutputStream out = null; long longSampleRate = sampleRate; long byteRate = sampleRate * channels * bpp / 8; byte[] data; try { try { in1 = new FileInputStream(file1); } catch (Exception e) { } try { in2 = new FileInputStream(file2); } catch (FileNotFoundException e) { } out = new FileOutputStream(outputFile); long file1Size = 0; long file2Size = 0; if (in1 != null) { file1Size = in1.getChannel().size() - 44; } if (in2 != null) { file2Size = in2.getChannel().size() - 44; } long totalAudioLen = file1Size + file2Size; long totalDataLen = totalAudioLen + 36; FileUtils.writeWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate, bpp); if (in1 != null) { in1.skip(44); data = new byte[bufferSize]; if (file1Size < bufferSize) { data = new byte[(int)file1Size]; } while (in1.read(data) != -1) { out.write(data); file1Size -= bufferSize; if (file1Size <= 0) { break; } else if (file1Size < bufferSize) { data = new byte[(int)file1Size]; } } } if (in2 != null) { in2.skip(44); data = new byte[bufferSize]; if (file2Size < bufferSize) { data = new byte[(int)file2Size]; } while (in2.read(data) != -1) { out.write(data); file2Size -= bufferSize; if (file2Size <= 0) { break; } else if (file2Size < bufferSize) { data = new byte[(int)file2Size]; } } } out.close(); if (in1 != null) { in1.close(); } if (in2 != null) { in2.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static void writeWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate, int bpp) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte)(totalDataLen & 0xff); header[5] = (byte)((totalDataLen >> 8) & 0xff); header[6] = (byte)((totalDataLen >> 16) & 0xff); header[7] = (byte)((totalDataLen >> 24) & 0xff); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte)(longSampleRate & 0xff); header[25] = (byte)((longSampleRate >> 8) & 0xff); header[26] = (byte)((longSampleRate >> 16) & 0xff); header[27] = (byte)((longSampleRate >> 24) & 0xff); header[28] = (byte)(byteRate & 0xff); header[29] = (byte)((byteRate >> 8) & 0xff); header[30] = (byte)((byteRate >> 16) & 0xff); header[31] = (byte)((byteRate >> 24) & 0xff); header[32] = (byte)(channels * bpp); //(2 * 16 / 8); header[33] = 0; header[34] = (byte)bpp; header[35] = 0; header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte)(totalAudioLen & 0xff); header[41] = (byte)((totalAudioLen >> 8) & 0xff); header[42] = (byte)((totalAudioLen >> 16) & 0xff); header[43] = (byte)((totalAudioLen >> 24) & 0xff); out.write(header, 0, 44); }
Most of this code is taken from this answer .