如何在java中将Wav文件分割成通道?

发布于 2024-11-02 21:56:56 字数 103 浏览 1 评论 0原文

我想编写一个Java程序来将wav文件分割成多个通道。输入将是一个 wav 文件,输出将是与通道数量一样多的 wav 文件。我可以用 Java 读取 wav 文件,但是如何将其拆分为多个通道?

I would like to write a Java program to split 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

朦胧时间 2024-11-09 21:56:57

这是一个完整的例子:

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

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);
    }
}
够钟 2024-11-09 21:56:57

找到了一种非常简单的方法,但不确定它的计算效率如何...

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];
    }
}

这适用于 16 位 wav PCM,其中 0 和 0立体声阵列中的 1 索引是左声道,2 & 是左声道。 3 是右声道(均为 8 位单声道)。

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

人海汹涌 2024-11-09 21:56:56

Wave 标头包含每个样本的样本大小(以位为单位)字段以及波形文件中编码的通道数。

有了这些信息,您就可以分割通道:波形文件中的样本数据包含每个通道交错的样本。

即,如果您有两个通道(A,B),则您有 sA1、sB1、sA2、SB2、sA3、sB3 - 第一个用于 A 的样本,然后是一个用于 B 的样本,然后又是一个用于 A 的样本,依此类推。这意味着如果您有样本大小,即 16 位,您将从文件中读取属于通道 A 的 2 个字节,然后读取属于通道 B 的 2 个字节,依此类推。

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.

泪是无色的血 2024-11-09 21:56:56

如果深度为 16 位,则意味着每个样本将占用 2 个字节。这意味着左声道数据将以字节 {0,1}、{4,5}... 为单位。

在我的项目中,我使用 AudioRecord 从两个内置麦克风录制立体声。

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];
}

然后我从立体声中得到了两个通道。

希望这会有所帮助!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文