|
|
|
|
@ -6,6 +6,7 @@ import javax.sound.sampled.*;
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
|
|
|
|
// MP3解码相关导入
|
|
|
|
|
import javazoom.jl.decoder.Bitstream;
|
|
|
|
|
@ -500,44 +501,143 @@ public class AudioProcessingService {
|
|
|
|
|
* @return merged file path
|
|
|
|
|
*/
|
|
|
|
|
public String mergeAudio(String filePath1, String filePath2) throws Exception {
|
|
|
|
|
AudioInputStream stream1 = AudioSystem.getAudioInputStream(new File(filePath1));
|
|
|
|
|
AudioInputStream stream2 = AudioSystem.getAudioInputStream(new File(filePath2));
|
|
|
|
|
|
|
|
|
|
AudioFormat format1 = stream1.getFormat();
|
|
|
|
|
AudioFormat format2 = stream2.getFormat();
|
|
|
|
|
// 检测文件格式
|
|
|
|
|
String fileExtension1 = filePath1.toLowerCase();
|
|
|
|
|
String fileExtension2 = filePath2.toLowerCase();
|
|
|
|
|
|
|
|
|
|
// Check if audio formats are compatible
|
|
|
|
|
if (!format1.matches(format2)) {
|
|
|
|
|
throw new IllegalArgumentException("Audio formats are not compatible, cannot merge");
|
|
|
|
|
// 如果两个文件都是MP3格式,使用MP3合并方法
|
|
|
|
|
if (fileExtension1.endsWith(".mp3") && fileExtension2.endsWith(".mp3")) {
|
|
|
|
|
return mergeMP3Audio(filePath1, filePath2);
|
|
|
|
|
} else {
|
|
|
|
|
// 其他格式使用原来的WAV合并方法
|
|
|
|
|
AudioInputStream stream1 = AudioSystem.getAudioInputStream(new File(filePath1));
|
|
|
|
|
AudioInputStream stream2 = AudioSystem.getAudioInputStream(new File(filePath2));
|
|
|
|
|
|
|
|
|
|
AudioFormat format1 = stream1.getFormat();
|
|
|
|
|
AudioFormat format2 = stream2.getFormat();
|
|
|
|
|
|
|
|
|
|
// Check if audio formats are compatible
|
|
|
|
|
if (!format1.matches(format2)) {
|
|
|
|
|
throw new IllegalArgumentException("Audio formats are not compatible, cannot merge");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read both audio files' data
|
|
|
|
|
byte[] audioData1 = stream1.readAllBytes();
|
|
|
|
|
byte[] audioData2 = stream2.readAllBytes();
|
|
|
|
|
|
|
|
|
|
stream1.close();
|
|
|
|
|
stream2.close();
|
|
|
|
|
|
|
|
|
|
// Merge audio data
|
|
|
|
|
byte[] mergedData = new byte[audioData1.length + audioData2.length];
|
|
|
|
|
System.arraycopy(audioData1, 0, mergedData, 0, audioData1.length);
|
|
|
|
|
System.arraycopy(audioData2, 0, mergedData, audioData1.length, audioData2.length);
|
|
|
|
|
|
|
|
|
|
// Create new audio stream
|
|
|
|
|
ByteArrayInputStream bais = new ByteArrayInputStream(mergedData);
|
|
|
|
|
AudioInputStream mergedStream = new AudioInputStream(bais, format1,
|
|
|
|
|
mergedData.length / format1.getFrameSize());
|
|
|
|
|
|
|
|
|
|
// Save merged file - use absolute path
|
|
|
|
|
File tempDir = new File(TEMP_DIR);
|
|
|
|
|
if (!tempDir.isAbsolute()) {
|
|
|
|
|
tempDir = new File(System.getProperty("user.dir"), TEMP_DIR);
|
|
|
|
|
}
|
|
|
|
|
String outputPath = new File(tempDir, "merge_" + System.currentTimeMillis() + ".wav").getAbsolutePath();
|
|
|
|
|
AudioSystem.write(mergedStream, AudioFileFormat.Type.WAVE, new File(outputPath));
|
|
|
|
|
|
|
|
|
|
mergedStream.close();
|
|
|
|
|
return outputPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 合并多个音频文件
|
|
|
|
|
* @param filePaths 音频文件路径列表
|
|
|
|
|
* @return 合并后的文件路径
|
|
|
|
|
*/
|
|
|
|
|
public String mergeMultipleAudio(List<String> filePaths) throws Exception {
|
|
|
|
|
if (filePaths == null || filePaths.size() < 2) {
|
|
|
|
|
throw new IllegalArgumentException("At least two audio files are required for merging");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read both audio files' data
|
|
|
|
|
byte[] audioData1 = stream1.readAllBytes();
|
|
|
|
|
byte[] audioData2 = stream2.readAllBytes();
|
|
|
|
|
|
|
|
|
|
stream1.close();
|
|
|
|
|
stream2.close();
|
|
|
|
|
|
|
|
|
|
// Merge audio data
|
|
|
|
|
byte[] mergedData = new byte[audioData1.length + audioData2.length];
|
|
|
|
|
System.arraycopy(audioData1, 0, mergedData, 0, audioData1.length);
|
|
|
|
|
System.arraycopy(audioData2, 0, mergedData, audioData1.length, audioData2.length);
|
|
|
|
|
|
|
|
|
|
// Create new audio stream
|
|
|
|
|
ByteArrayInputStream bais = new ByteArrayInputStream(mergedData);
|
|
|
|
|
AudioInputStream mergedStream = new AudioInputStream(bais, format1,
|
|
|
|
|
mergedData.length / format1.getFrameSize());
|
|
|
|
|
|
|
|
|
|
// Save merged file - use absolute path
|
|
|
|
|
File tempDir = new File(TEMP_DIR);
|
|
|
|
|
if (!tempDir.isAbsolute()) {
|
|
|
|
|
tempDir = new File(System.getProperty("user.dir"), TEMP_DIR);
|
|
|
|
|
// 检查所有文件是否都是MP3格式
|
|
|
|
|
boolean allMP3 = true;
|
|
|
|
|
for (String filePath : filePaths) {
|
|
|
|
|
if (!filePath.toLowerCase().endsWith(".mp3")) {
|
|
|
|
|
allMP3 = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String outputPath = new File(tempDir, "merge_" + System.currentTimeMillis() + ".wav").getAbsolutePath();
|
|
|
|
|
AudioSystem.write(mergedStream, AudioFileFormat.Type.WAVE, new File(outputPath));
|
|
|
|
|
|
|
|
|
|
mergedStream.close();
|
|
|
|
|
return outputPath;
|
|
|
|
|
if (allMP3) {
|
|
|
|
|
return mergeMultipleMP3Audio(filePaths);
|
|
|
|
|
} else {
|
|
|
|
|
// 对于混合格式,使用WAV合并方法
|
|
|
|
|
List<AudioInputStream> streams = new ArrayList<>();
|
|
|
|
|
List<byte[]> audioDataList = new ArrayList<>();
|
|
|
|
|
AudioFormat baseFormat = null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 读取所有音频文件
|
|
|
|
|
for (String filePath : filePaths) {
|
|
|
|
|
AudioInputStream stream = AudioSystem.getAudioInputStream(new File(filePath));
|
|
|
|
|
AudioFormat format = stream.getFormat();
|
|
|
|
|
|
|
|
|
|
if (baseFormat == null) {
|
|
|
|
|
baseFormat = format;
|
|
|
|
|
} else if (!baseFormat.matches(format)) {
|
|
|
|
|
throw new IllegalArgumentException("Audio formats are not compatible, cannot merge");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
streams.add(stream);
|
|
|
|
|
audioDataList.add(stream.readAllBytes());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算总数据长度
|
|
|
|
|
int totalLength = 0;
|
|
|
|
|
for (byte[] data : audioDataList) {
|
|
|
|
|
totalLength += data.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 合并音频数据
|
|
|
|
|
byte[] mergedData = new byte[totalLength];
|
|
|
|
|
int currentPosition = 0;
|
|
|
|
|
for (byte[] data : audioDataList) {
|
|
|
|
|
System.arraycopy(data, 0, mergedData, currentPosition, data.length);
|
|
|
|
|
currentPosition += data.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建新的音频流
|
|
|
|
|
if (baseFormat == null) {
|
|
|
|
|
throw new IOException("Unable to determine audio format, merge failed");
|
|
|
|
|
}
|
|
|
|
|
ByteArrayInputStream bais = new ByteArrayInputStream(mergedData);
|
|
|
|
|
AudioInputStream mergedStream = new AudioInputStream(bais, baseFormat,
|
|
|
|
|
mergedData.length / baseFormat.getFrameSize());
|
|
|
|
|
|
|
|
|
|
// 保存合并后的文件
|
|
|
|
|
File tempDir = new File(TEMP_DIR);
|
|
|
|
|
if (!tempDir.isAbsolute()) {
|
|
|
|
|
tempDir = new File(System.getProperty("user.dir"), TEMP_DIR);
|
|
|
|
|
}
|
|
|
|
|
String outputPath = new File(tempDir, "merge_multiple_" + System.currentTimeMillis() + ".wav").getAbsolutePath();
|
|
|
|
|
AudioSystem.write(mergedStream, AudioFileFormat.Type.WAVE, new File(outputPath));
|
|
|
|
|
|
|
|
|
|
mergedStream.close();
|
|
|
|
|
return outputPath;
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
// 关闭所有流
|
|
|
|
|
for (AudioInputStream stream : streams) {
|
|
|
|
|
try {
|
|
|
|
|
stream.close();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
// 忽略关闭异常
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -805,7 +905,7 @@ public class AudioProcessingService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get MP3 frame data
|
|
|
|
|
* Get MP3 frame data
|
|
|
|
|
*/
|
|
|
|
|
private byte[] getFrameData(Bitstream bitstream, Header header) throws IOException {
|
|
|
|
|
// Get frame data
|
|
|
|
|
@ -819,4 +919,83 @@ public class AudioProcessingService {
|
|
|
|
|
|
|
|
|
|
return frameData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 合并两个MP3文件
|
|
|
|
|
* @param filePath1 第一个MP3文件路径
|
|
|
|
|
* @param filePath2 第二个MP3文件路径
|
|
|
|
|
* @return 合并后的MP3文件路径
|
|
|
|
|
*/
|
|
|
|
|
private String mergeMP3Audio(String filePath1, String filePath2) throws IOException {
|
|
|
|
|
FileInputStream fis1 = new FileInputStream(filePath1);
|
|
|
|
|
FileInputStream fis2 = new FileInputStream(filePath2);
|
|
|
|
|
|
|
|
|
|
byte[] data1 = fis1.readAllBytes();
|
|
|
|
|
byte[] data2 = fis2.readAllBytes();
|
|
|
|
|
|
|
|
|
|
fis1.close();
|
|
|
|
|
fis2.close();
|
|
|
|
|
|
|
|
|
|
// 合并MP3数据
|
|
|
|
|
byte[] mergedData = new byte[data1.length + data2.length];
|
|
|
|
|
System.arraycopy(data1, 0, mergedData, 0, data1.length);
|
|
|
|
|
System.arraycopy(data2, 0, mergedData, data1.length, data2.length);
|
|
|
|
|
|
|
|
|
|
// 保存合并后的MP3文件
|
|
|
|
|
File tempDir = new File(TEMP_DIR);
|
|
|
|
|
if (!tempDir.isAbsolute()) {
|
|
|
|
|
tempDir = new File(System.getProperty("user.dir"), TEMP_DIR);
|
|
|
|
|
}
|
|
|
|
|
String outputPath = new File(tempDir, "merge_mp3_" + System.currentTimeMillis() + ".mp3").getAbsolutePath();
|
|
|
|
|
|
|
|
|
|
FileOutputStream fos = new FileOutputStream(outputPath);
|
|
|
|
|
fos.write(mergedData);
|
|
|
|
|
fos.close();
|
|
|
|
|
|
|
|
|
|
return outputPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 合并多个MP3文件
|
|
|
|
|
* @param filePaths MP3文件路径列表
|
|
|
|
|
* @return 合并后的MP3文件路径
|
|
|
|
|
*/
|
|
|
|
|
private String mergeMultipleMP3Audio(List<String> filePaths) throws IOException {
|
|
|
|
|
List<byte[]> audioDataList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// 读取所有MP3文件数据
|
|
|
|
|
for (String filePath : filePaths) {
|
|
|
|
|
FileInputStream fis = new FileInputStream(filePath);
|
|
|
|
|
byte[] data = fis.readAllBytes();
|
|
|
|
|
fis.close();
|
|
|
|
|
audioDataList.add(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算总数据长度
|
|
|
|
|
int totalLength = 0;
|
|
|
|
|
for (byte[] data : audioDataList) {
|
|
|
|
|
totalLength += data.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 合并MP3数据
|
|
|
|
|
byte[] mergedData = new byte[totalLength];
|
|
|
|
|
int currentPosition = 0;
|
|
|
|
|
for (byte[] data : audioDataList) {
|
|
|
|
|
System.arraycopy(data, 0, mergedData, currentPosition, data.length);
|
|
|
|
|
currentPosition += data.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存合并后的MP3文件
|
|
|
|
|
File tempDir = new File(TEMP_DIR);
|
|
|
|
|
if (!tempDir.isAbsolute()) {
|
|
|
|
|
tempDir = new File(System.getProperty("user.dir"), TEMP_DIR);
|
|
|
|
|
}
|
|
|
|
|
String outputPath = new File(tempDir, "merge_multiple_mp3_" + System.currentTimeMillis() + ".mp3").getAbsolutePath();
|
|
|
|
|
|
|
|
|
|
FileOutputStream fos = new FileOutputStream(outputPath);
|
|
|
|
|
fos.write(mergedData);
|
|
|
|
|
fos.close();
|
|
|
|
|
|
|
|
|
|
return outputPath;
|
|
|
|
|
}
|
|
|
|
|
}
|