开发者

How to split a Wav file into channels in java?

开发者 https://www.devze.com 2023-02-28 02:32 出处:网络
I would like to write a Java program to s开发者_如何学Cplit a wav file into channels. The input would be a wav file, and the output would be as many wav files as there are channels. I can read a wav f

I would like to write a Java program to s开发者_如何学Cplit a wav file into channels. The input would be a wav file, and the output would be as many wav files as there are channels. I can read a wav file in Java but, how can I split it into channels?


The Wave header includes fields for the sample size (in bits) for each sample and the number of channels encoded within the wave file.

With this information in hand, you can split the channels: The sample data in a wave file contains the samples for each channel interleaved.

I.e. if you had two channels (A,B) you have sA1, sB1, sA2, SB2, sA3, sB3 - first a sample for A, then one for B, then one for A again and so on. That means if you have the sample size, i.e. 16 bit you read 2 bytes from the file which belong to channel A, then 2 bytes that belong to channel B and so on.


If you have a 16 bit depth, so that means each sample will take 2 bytes. That means the left channel data will be in bytes {0,1}, {4,5}... and so on.

In my project, I used AudioRecord recording stereo sound from two internal microphones.

private int audioSource = MediaRecorder.AudioSource.MIC;   
private static int sampleRateInHz = 44100;  
private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;  
private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;  

readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);   
for(int i = 0; i < readsize/2; i = i + 2)
{

      leftChannelAudioData[i] = audiodata[2*i];
      leftChannelAudioData[i+1] = audiodata[2*i+1]; 
      rightChannelAudioData[i] =  audiodata[2*i+2];
      rightChannelAudioData[i+1] = audiodata[2*i+3];
}

Then I got the two channels from the stereo sound.

Hope this would help!


Here is a complete example:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

public class ChannelSplitter {

    public static void main(String[] args) throws Exception {

        String filename = "test.wav";

        File sourceFile = new File(filename);
        File leftTargetFile = new File("left_"+filename);
        File rightTargetFile = new File("right_"+filename);

        AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(sourceFile);
        AudioFileFormat.Type targetFileType = fileFormat.getType();
        AudioFormat audioFormat = fileFormat.getFormat();

        AudioInputStream inputAIS = AudioSystem.getAudioInputStream(sourceFile);

        ByteArrayOutputStream leftbaos = new ByteArrayOutputStream();
        ByteArrayOutputStream rightbaos = new ByteArrayOutputStream();

        byte[] bytes = new byte[(audioFormat.getSampleSizeInBits()/8)*2];

        while (true) {

            int readsize = inputAIS.read(bytes);   

            if(readsize==-1){
                break;
            }

            rightbaos.write(bytes,0,bytes.length/2);
            leftbaos.write(bytes,bytes.length/2,bytes.length/2);
        }

        byte[] leftData = leftbaos.toByteArray();
        byte[] rightData = rightbaos.toByteArray();

        AudioFormat outFormat = new AudioFormat(audioFormat.getEncoding(),audioFormat.getSampleRate(),audioFormat.getSampleSizeInBits(),1,audioFormat.getFrameSize()/2, audioFormat.getFrameRate(),audioFormat.isBigEndian());

        ByteArrayInputStream leftbais = new ByteArrayInputStream(leftData);
        AudioInputStream leftoutputAIS = new AudioInputStream(leftbais, outFormat, leftData.length / outFormat.getFrameSize());
        AudioSystem.write(leftoutputAIS, targetFileType, leftTargetFile);

        ByteArrayInputStream rightbais = new ByteArrayInputStream(rightData);
        AudioInputStream rightoutputAIS = new AudioInputStream(rightbais, outFormat, rightData.length / outFormat.getFrameSize());
        AudioSystem.write(rightoutputAIS, targetFileType, rightTargetFile);
    }
}


Found a pretty easy way of doing it, not sure how computationally efficient it is though...

public void splitByteArray (byte [] fileContent, byte [] fileContentLeft, byte [] fileContentRight) {
    for (int i = 0; i < fileContent.length; i += 4) {
        fileContentLeft[i] = fileContent[i];
        fileContentLeft[i + 1] = fileContent[i + 1];
        fileContentRight[i + 2] = fileContent[i + 2];
        fileContentRight[i + 3] = fileContent[i + 3];
    }
}

This works for 16-bit wav PCM where 0 & 1 index in stereo array is the left channel and 2 & 3 are the right channel (both 8-bit mono).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号