我想将两个MP3文件合并成一个MP3文件。例如,如果第一个文件是1分钟,第二个文件是30秒,那么输出应该是一分钟。在这一分钟中,应该播放两个文件。
我在Android上还没有做过,但是我用Adobe Flex做过。 我想逻辑是相同的。 我按照以下步骤进行:
song1ByteArray
,song2ByteArray
)song1ByteArray
是较大的数组)。创建一个函数,返回混合后的字节数组。
private ByteArray mix2Songs(ByteArray song1ByteArray, ByteArray song2ByteArray){
int arrLength=song1ByteArray.length;
for(int i=0;i<arrLength;i+=8){ // 这里如果你看到我们每次增加8的长度,因为立体声音频有左右两个通道,每个通道占4个字节。
// 读取第一首歌曲的左右声道值
float source1_L=song1ByteArray.readFloat();// 我不确定readFloat()函数是否存在于Android中,但会有相应的函数。
float source1_R=song1ByteArray.readFloat();
float source2_L=0;
float source2_R=0;
if(song2ByteArray.bytesAvailable>0){
source2_L=song1ByteArray.readFloat();//歌曲2的左声道
source2_R=song1ByteArray.readFloat(); //歌曲2的右声道
}
returnResultArr.writeFloat((source_1_L+source_2_L)/2); // 源1和源2左声道的平均值
returnResultArr.writeFloat((source_1_R+source_2_R)/2); // 源1和源2右声道的平均值
}
return returnResultArr;
}
示例:
// First convert audiofile to audioinputstream
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
audioInputStream2 = AudioSystem.getAudioInputStream(soundFile2);
// Create one collection list object using arraylist then add all AudioInputStreams
Collection list=new ArrayList();
list.add(audioInputStream2);
list.add(audioInputStream);
// Then pass the audioformat and collection list to MixingAudioInputStream constructor
MixingAudioInputStream mixer=new MixingAudioInputStream(audioFormat, list);
// Finally read data from mixed AudionInputStream and give it to SourceDataLine
nBytesRead =mixer.read(abData, 0,abData.length);
int nBytesWritten = line.write(abData, 0, nBytesRead);
-m
选项
java AudioConcat [ -D ] [ -c ] | [ -m ] | [ -f ] -o outputfile inputfile ...
Parameters.
-c
selects concatenation mode
-m
selects mixing mode
-f
selects float mixing mode
-o outputfile
The filename of the output file
inputfile
the name(s) of input file(s)
这个人在一个与你的项目非常相似的项目中使用了JLayer库。他还为你提供了一个指南,告诉你如何直接重新编译jar文件将该库集成到你的Android应用程序中。
简单地说,通过改写他的代码,你可以很容易地完成你的任务:
public static byte[] decode(String path, int startMs, int maxMs)
throws IOException, com.mindtherobot.libs.mpg.DecoderException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
float totalMs = 0;
boolean seeking = true;
File file = new File(path);
InputStream inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (! done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (! seeking) {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
if (output.getSampleFrequency() != 44100
|| output.getChannelCount() != 2) {
throw new com.mindtherobot.libs.mpg.DecoderException("mono or non-44100 MP3 not supported");
}
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8 ) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
return outStream.toByteArray();
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
Log.w(TAG, "Decoder error", e);
throw new com.mindtherobot.libs.mpg.DecoderException(e);
} finally {
IOUtils.safeClose(inputStream);
}
}
public static byte[] mix(String path1, String path2) {
byte[] pcm1 = decode(path1, 0, 60000);
byte[] pcm2 = decode(path2, 0, 60000);
int len1=pcm1.length;
int len2=pcm2.length;
byte[] pcmL;
byte[] pcmS;
int lenL; // length of the longest
int lenS; // length of the shortest
if (len2>len1) {
lenL = len1;
pcmL = pcm1;
lenS = len2;
pcmS = pcm2;
} else {
lenL = len2;
pcmL = pcm2;
lenS = len1;
pcmS = pcm1;
}
for (int idx = 0; idx < lenL; idx++) {
int sample;
if (idx >= lenS) {
sample = pcmL[idx];
} else {
sample = pcmL[idx] + pcmS[idx];
}
sample=(int)(sample*.71);
if (sample>127) sample=127;
if (sample<-128) sample=-128;
pcmL[idx] = (byte) sample;
}
return pcmL;
}
要合并(重叠)两个音频文件,您可以使用此FFMPEG库。
这里是文档
在他们的示例中,您只需输入所需的命令。因此,让我们谈谈我们需要的命令。
-i [FISRST_FILE_PATH] -i [SECOND_FILE_PATH] -filter_complex amerge -ac 2 -c:a libmp3lame -q:a 4 [OUTPUT_FILE_PATH]
对于第一个和第二个文件路径,您将获得声音文件的绝对路径。
1- 如果它在存储中,则是Environment.getExternalStorageDirectory().getAbsolutePath()
的子文件夹。
2- 如果它是assets文件,则应该是file:///android_asset/
的子文件夹。
对于输出路径,请确保添加扩展名 例如。
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/File Name.mp3"
我没找到什么比较好的解决方案,但我们可以在这里做一些小技巧.. :) 你可以将两个mp3文件分别赋值给两个不同的MediaPlayer对象。然后用一个按钮同时播放两个文件,比较这两个mp3文件以找到最长的持续时间。之后使用AudioReorder来录制该时长,这样就可以解决你的问题了。我知道这不是正确的方式,但希望能对你有所帮助.. :)
mediaPlayer.start()
命令。 - Apurva