简体   繁体   中英

Write part of FileInputStream into FileOutPutstream

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.

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM