Java (Sound) - 将二维整数数组转换为字节数组
Java (Sound) - Converting a 2D int array into a byte array
我正在尝试混合 2 个音频剪辑(相同格式,相同长度)。对于我的每个剪辑,我将它们转换为字节数组,将这些字节数组转换为 2D int 数组,添加它们,并将我的新 2D int 数组转换为字节数组,然后将其写入磁盘。
这很好用……只在一个频道上。我创建的文件,在本例中为 test.wav,只有左耳有声音。
在我的程序中,我有一个方法允许我将 2D int 选项卡存储到 txt 文件中。我尝试分析 test.wav,将其转换为字节数组,然后转换为 2D int 数组,这与我转换原始剪辑的方式相同。我得到两个向量,一个用于每个音频通道。在我的第一个向量中,我得到了我应该拥有的东西,我的两个剪辑的左通道相加,但在我的第二个向量(右通道)中,我得到了连续的 -1 和 0。我猜我的 TabToByte 方法有问题,但我不能指手画脚。
如有任何帮助,我们将不胜感激!
提前致谢。
代码:
public class Main {
public static void main (String[] args) {
//My audio clips
String wavFile1 = "C:\Users\Alban.Alban-PC\Documents\Java\Generateur-de-musiques-commerciales\Samples\Fa.wav";
String wavFile2 = "C:\Users\Alban.Alban-PC\Documents\Java\Generateur-de-musiques-commerciales\Samples\Drum beat.wav";
try {
AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(wavFile1));
AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(wavFile2));
//frameLength of each clip
int frameLength1 = (int) clip1.getFrameLength();
int frameLength2 = (int) clip2.getFrameLength();
//Frame size = 4 because I'm using 2-channels with 16-bits encoded sound
int frameSize1 = (int) clip1.getFormat().getFrameSize();
int frameSize2 = (int) clip2.getFormat().getFrameSize();
//Number of channels = 2
int numChannels = clip1.getFormat().getChannels();
//byte array to store my entier clips
byte[] eightBitByteArray1 = new byte[frameLength1 * frameSize1];
byte[] eightBitByteArray2 = new byte[frameLength2 * frameSize2];
//Converts my clips into chosen byte arrays
clip1.read(eightBitByteArray1);
clip2.read(eightBitByteArray2);
//I want to store my clip samples in 2D int arrays
int[][] toReturn1 = new int[numChannels][frameLength1];
int[][] toReturn2 = new int[numChannels][frameLength2];
int[][] toReturn = new int[numChannels][frameLength2];
//I convert each byte array into 2D int arrays
toReturn1 = ByteToTab(eightBitByteArray1);
toReturn2 = ByteToTab(eightBitByteArray2);
//I add my 2 int arrays
//This is equivalent to mixing my clips
toReturn = addTab(toReturn1, toReturn2);
//I convert my new int array into a new byte array
byte[] mix = TabToByte(toReturn);
//I store my 2D int arrays in txt files to see if I get proper results
fichierTxt(toReturn1, "do.txt");
fichierTxt(toReturn2, "drum.txt");
fichierTxt(toReturn, "mix.txt");
//I create an inputStream with my new byte array
InputStream byteArray = new ByteArrayInputStream(mix);
//I create a new clip
AudioInputStream ais = new AudioInputStream(byteArray,
clip1.getFormat(), clip1.getFrameLength());
//I write it on the disk
AudioSystem.write(ais,
AudioFileFormat.Type.WAVE,
new File("C:\Users\Alban.Alban-PC\Documents\Java\test.wav"));
} catch (UnsupportedAudioFileException e) {
} catch (IOException e) {e.printStackTrace(); }
}
//Transforms 2 bytes into a single int
public static int getSixteenBitSample(int high, int low) {
return (high << 8) + (low & 0x00ff);
}
//Creates a byte array from a 2D int array
public static byte[] TabToByte (int[][] tab) {
byte[] b = new byte[tab[0].length*4];
int count = 0;
for (int i = 0; i < tab[0].length; i ++){
for (int j = 0; j <tab.length; j++){
for (int k = 0; k < 2; k++){
b[count] = (byte)(tab[j][i] >>> (count * 8));
count++;
}
}
}
return b;
}
//Creates a 2D int array from a byte array
public static int[][] ByteToTab (byte[] array) {
int sampleIndex = 0;
int[][] toReturn = new int [2][array.length/4];
for (int t = 0; t < array.length;) {
for (int channel = 0; channel < 2; channel++) {
int low = (int) array[t];
t++;
int high = (int) array[t];
t++;
int sample = getSixteenBitSample(high, low);
toReturn[channel][sampleIndex] = sample;
}
sampleIndex++;
}
return toReturn;
}
//Ajouter 2 tableaux de même dimension entre eux
public static int[][] addTab(int[][] tab1, int[][] tab2) {
int[][] tab = new int[tab1.length][tab1[0].length];
for (int i = 0; i < tab1.length; i ++) {
for (int j = 0; j < tab1[0].length; j++) {
tab [i][j] = tab1[i][j]+tab2[i][j];
}
}
return tab;
}
//To write a 2D tab into a txt file
public static void fichierTxt(int[][] tab, String s) {
try {
String s1 = "C:\Users\Alban.Alban-PC\Documents\Java\";
String st = s1 +s;
File fichier = new File(st);
fichier.createNewFile();
FileWriter fichierWrite = new FileWriter(fichier);
for (int i = 0; i < tab.length; i++){
fichierWrite.write("[ ");
for (int j = 0; j < tab[i].length; j ++){
fichierWrite.write(tab[i][j]+" ");
}
fichierWrite.write("]");
fichierWrite.write(System.lineSeparator());
}
fichierWrite.close();
} catch (Exception e) {}
}
}
你有
b[count] = (byte)(tab[j][i] >>> (count * 8));
count++;
你应该
b[count] = (byte)(tab[j][i] >>> (k * 8));
count++;
您可能打算向下移动 0
或 8
。
移动 count * 8
会得到奇怪的结果:(jls)
[…] only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND
operator &
with the mask value 0x1f
(0b11111
). The shift distance actually used is therefore always in the range 0
to 31
, inclusive.
我正在尝试混合 2 个音频剪辑(相同格式,相同长度)。对于我的每个剪辑,我将它们转换为字节数组,将这些字节数组转换为 2D int 数组,添加它们,并将我的新 2D int 数组转换为字节数组,然后将其写入磁盘。 这很好用……只在一个频道上。我创建的文件,在本例中为 test.wav,只有左耳有声音。 在我的程序中,我有一个方法允许我将 2D int 选项卡存储到 txt 文件中。我尝试分析 test.wav,将其转换为字节数组,然后转换为 2D int 数组,这与我转换原始剪辑的方式相同。我得到两个向量,一个用于每个音频通道。在我的第一个向量中,我得到了我应该拥有的东西,我的两个剪辑的左通道相加,但在我的第二个向量(右通道)中,我得到了连续的 -1 和 0。我猜我的 TabToByte 方法有问题,但我不能指手画脚。
如有任何帮助,我们将不胜感激! 提前致谢。
代码:
public class Main {
public static void main (String[] args) {
//My audio clips
String wavFile1 = "C:\Users\Alban.Alban-PC\Documents\Java\Generateur-de-musiques-commerciales\Samples\Fa.wav";
String wavFile2 = "C:\Users\Alban.Alban-PC\Documents\Java\Generateur-de-musiques-commerciales\Samples\Drum beat.wav";
try {
AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(wavFile1));
AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(wavFile2));
//frameLength of each clip
int frameLength1 = (int) clip1.getFrameLength();
int frameLength2 = (int) clip2.getFrameLength();
//Frame size = 4 because I'm using 2-channels with 16-bits encoded sound
int frameSize1 = (int) clip1.getFormat().getFrameSize();
int frameSize2 = (int) clip2.getFormat().getFrameSize();
//Number of channels = 2
int numChannels = clip1.getFormat().getChannels();
//byte array to store my entier clips
byte[] eightBitByteArray1 = new byte[frameLength1 * frameSize1];
byte[] eightBitByteArray2 = new byte[frameLength2 * frameSize2];
//Converts my clips into chosen byte arrays
clip1.read(eightBitByteArray1);
clip2.read(eightBitByteArray2);
//I want to store my clip samples in 2D int arrays
int[][] toReturn1 = new int[numChannels][frameLength1];
int[][] toReturn2 = new int[numChannels][frameLength2];
int[][] toReturn = new int[numChannels][frameLength2];
//I convert each byte array into 2D int arrays
toReturn1 = ByteToTab(eightBitByteArray1);
toReturn2 = ByteToTab(eightBitByteArray2);
//I add my 2 int arrays
//This is equivalent to mixing my clips
toReturn = addTab(toReturn1, toReturn2);
//I convert my new int array into a new byte array
byte[] mix = TabToByte(toReturn);
//I store my 2D int arrays in txt files to see if I get proper results
fichierTxt(toReturn1, "do.txt");
fichierTxt(toReturn2, "drum.txt");
fichierTxt(toReturn, "mix.txt");
//I create an inputStream with my new byte array
InputStream byteArray = new ByteArrayInputStream(mix);
//I create a new clip
AudioInputStream ais = new AudioInputStream(byteArray,
clip1.getFormat(), clip1.getFrameLength());
//I write it on the disk
AudioSystem.write(ais,
AudioFileFormat.Type.WAVE,
new File("C:\Users\Alban.Alban-PC\Documents\Java\test.wav"));
} catch (UnsupportedAudioFileException e) {
} catch (IOException e) {e.printStackTrace(); }
}
//Transforms 2 bytes into a single int
public static int getSixteenBitSample(int high, int low) {
return (high << 8) + (low & 0x00ff);
}
//Creates a byte array from a 2D int array
public static byte[] TabToByte (int[][] tab) {
byte[] b = new byte[tab[0].length*4];
int count = 0;
for (int i = 0; i < tab[0].length; i ++){
for (int j = 0; j <tab.length; j++){
for (int k = 0; k < 2; k++){
b[count] = (byte)(tab[j][i] >>> (count * 8));
count++;
}
}
}
return b;
}
//Creates a 2D int array from a byte array
public static int[][] ByteToTab (byte[] array) {
int sampleIndex = 0;
int[][] toReturn = new int [2][array.length/4];
for (int t = 0; t < array.length;) {
for (int channel = 0; channel < 2; channel++) {
int low = (int) array[t];
t++;
int high = (int) array[t];
t++;
int sample = getSixteenBitSample(high, low);
toReturn[channel][sampleIndex] = sample;
}
sampleIndex++;
}
return toReturn;
}
//Ajouter 2 tableaux de même dimension entre eux
public static int[][] addTab(int[][] tab1, int[][] tab2) {
int[][] tab = new int[tab1.length][tab1[0].length];
for (int i = 0; i < tab1.length; i ++) {
for (int j = 0; j < tab1[0].length; j++) {
tab [i][j] = tab1[i][j]+tab2[i][j];
}
}
return tab;
}
//To write a 2D tab into a txt file
public static void fichierTxt(int[][] tab, String s) {
try {
String s1 = "C:\Users\Alban.Alban-PC\Documents\Java\";
String st = s1 +s;
File fichier = new File(st);
fichier.createNewFile();
FileWriter fichierWrite = new FileWriter(fichier);
for (int i = 0; i < tab.length; i++){
fichierWrite.write("[ ");
for (int j = 0; j < tab[i].length; j ++){
fichierWrite.write(tab[i][j]+" ");
}
fichierWrite.write("]");
fichierWrite.write(System.lineSeparator());
}
fichierWrite.close();
} catch (Exception e) {}
}
}
你有
b[count] = (byte)(tab[j][i] >>> (count * 8));
count++;
你应该
b[count] = (byte)(tab[j][i] >>> (k * 8));
count++;
您可能打算向下移动 0
或 8
。
移动 count * 8
会得到奇怪的结果:(jls)
[…] only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical
AND
operator&
with the mask value0x1f
(0b11111
). The shift distance actually used is therefore always in the range0
to31
, inclusive.