Reputation: 133
I am trying to take a .wav that I have recorded and then take create a new output stream of part of that wav. The ultimate goal is to allow me to take a wav, split it at a certain point and insert new audio in the middle of it.
I was using FFMPEG to do this but with FFMPEG performance has gotten pretty bad with the latest versions of Android.
I think my biggest issue is a lack of fully understanding the .read() and .write() methods.
Here is what I have attempted
final int SAMPLE_RATE = 44100; // Hz
final int ENCODING = AudioFormat.ENCODING_PCM_16BIT;
final int CHANNEL_MASK = AudioFormat.CHANNEL_IN_MONO;
in1 = new FileInputStream(Environment.getExternalStorageDirectory() + "/recording.wav");
out = new FileOutputStream(Environment.getExternalStorageDirectory() + "/recording_part_1.wav");
// Write out the wav file header
wavHeader.writeWavHeader(out, CHANNEL_MASK, SAMPLE_RATE, ENCODING);
while (in1.read(buffer, 0, buffer.length) != -1) {
out.write(buffer);
}
out.close();
in1.close();
File fileToSave = new File(Environment.getExternalStorageDirectory() + "/GMT/recording_part_1.wav");
try {
// This is not put in the try/catch/finally above since it needs to run
// after we close the FileOutputStream
wavHeader.updateWavHeader(fileToSave);
} catch (IOException ex) {
}
The above works, but it just copies the whole thing. The recording code, writeWaveHeader and updateWavHeader are all from this gist, https://gist.github.com/kmark/d8b1b01fb0d2febf5770.
I have tried things like
for (int i = 0; i < in1.getChannel().size() / 2; i++) {
out.write(in1.read(buffer, i, 1));
}
but that does not work at all. I also thought maybe
byte[] byteInput = new byte[(int)in1.getChannel().size() - 44];
while (in1.read(byteInput, 44, byteInput.length - 45) != -1) {
out.write(byteInput, 44, byteInput.length /2);
}
hoping that would only create a new file with half of the file. I keep looking at the documentation but I am doing something wrong.
Upvotes: 0
Views: 113
Reputation: 365
Take a look at the docs of FileInputStream
Your approaches are not that bad. This one could work with some work:
for (int i = 0; i < in1.getChannel().size() / 2; i++) {
out.write(in1.read(buffer, i, 1));
}
The Docs say:
read(byte[] b, int off, int len) Reads up to len bytes of data from this input stream into an array of bytes.
You pass the buffer as byte[] which is correct.
Then you pass i as offset. Your offset should be 0 (So from start of the audio file).
And for the len you pass 1. This should be the lenght you want to copy. So pass in1.getChannel().size() / 2 there (Until mid of the audio file).
You don't even need a loop in that case because the read method does everything for you. To edit the start and end of your part you need to change the 2.&3. parameter.
So this should work for you:
byte[] buffer = new byte[(int)(in1.gerChannel().size() / 2)];
in1.read(buffer, 0, (int)(in1.gerChannel().size() / 2));
out.write(buffer);
Upvotes: 1