12

I am really facing problem from last couple of days but I am not able to find the exact solution please help me.

I want to merge two .mp3 or any audio file and play final single one mp3 file. But when I am combine two file the final file size is ok but when I am trying to play it just play first file, I have tried this with SequenceInputStream or byte array but I am not able to get exact result please help me.

My code is the following:

public class MerginFileHere extends Activity {
public ArrayList<String> audNames;
byte fileContent[];
byte fileContent1[];
FileInputStream ins,ins1;
FileOutputStream fos = null;
String combined_file_stored_path = Environment
        .getExternalStorageDirectory().getPath()
        + "/AudioRecorder/final.mp3";

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    audNames = new ArrayList<String>();
    String file1 = Environment.getExternalStorageDirectory().getPath()
            + "/AudioRecorder/one.mp3";

    String file2 = Environment.getExternalStorageDirectory().getPath()
            + "/AudioRecorder/two.mp3";

    File file = new File(Environment.getExternalStorageDirectory()
            .getPath() + "/AudioRecorder/" + "final.mp3");

    try {
        file.createNewFile();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    audNames.add(file1);
    audNames.add(file2);

    Button btn = (Button) findViewById(R.id.clickme);
    btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            createCombineRecFile();
        }
    });
}

public void createCombineRecFile() {
    // String combined_file_stored_path = // File path in String to store
    // recorded audio

    try {
        fos = new FileOutputStream(combined_file_stored_path, true);
    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

        try {
            File f = new File(audNames.get(0));
            File f1 = new File(audNames.get(1));
            Log.i("Record Message", "File Length=========>>>" + f.length()+"------------->"+f1.length());


            fileContent = new byte[(int) f.length()];
            ins = new FileInputStream(audNames.get(0));
            int r = ins.read(fileContent);// Reads the file content as byte

            fileContent1 = new byte[(int) f1.length()];
            ins1 = new FileInputStream(audNames.get(1));
            int r1 = ins1.read(fileContent1);// Reads the file content as byte
                                            // from the list.






            Log.i("Record Message", "Number Of Bytes Readed=====>>>" + r);

            //fos.write(fileContent1);// Write the byte into the combine file.


            byte[] combined = new byte[fileContent.length + fileContent1.length];

            for (int i = 0; i < combined.length; ++i)
            {
                combined[i] = i < fileContent.length ? fileContent[i] : fileContent1[i - fileContent.length];
            }
            fos.write(combined);
            //fos.write(fileContent1);*



        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    try {
        fos.close();
        Log.v("Record Message", "===== Combine File Closed =====");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}
Morten Kristensen
  • 7,412
  • 4
  • 32
  • 52
Alok Tiwari
  • 607
  • 2
  • 7
  • 21
  • 8
    You cannot just copy the bytes of two separate MP3 files one after another and expect it to work. MP3 files are **NOT** raw audio data... They have headers and time data... A simple concatenation would result in a invalid MP3 file. The first file normally plays fine because it is "valid" since the time data is still valid, this is not true for the second MP3 file that has been appended. – initramfs Sep 13 '13 at 13:28
  • 1
    Actually, you can concatenate mp3 files under some circumstances. But there are a number of things that you should be aware of (see e.g. [this post](http://john.freml.in/mp3-clean)). – Michael Sep 13 '13 at 13:31
  • @Michael Hmm... Interesting... but given that the OP is having issues with playback I'd assume simple concatenation won't work for him/her... Especially if he/she is producing code that will be used on all MP3 files... – initramfs Sep 13 '13 at 13:39
  • 2
    a solution mentioned here is quite good http://stackoverflow.com/a/11452687/3098394 – user3098394 Dec 13 '13 at 13:57

2 Answers2

3

I already published an app with this function... try my method using SequenceInputStream, in my app I just merge 17 MP3 files in one and play it using the JNI Library MPG123, but I tested the file using MediaPlayer without problems.

This code isn't the best, but it works...

private void mergeSongs(File mergedFile,File...mp3Files){
        FileInputStream fisToFinal = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(mergedFile);
            fisToFinal = new FileInputStream(mergedFile);
            for(File mp3File:mp3Files){
                if(!mp3File.exists())
                    continue;
                FileInputStream fisSong = new FileInputStream(mp3File);
                SequenceInputStream sis = new SequenceInputStream(fisToFinal, fisSong);
                byte[] buf = new byte[1024];
                try {
                    for (int readNum; (readNum = fisSong.read(buf)) != -1;)
                        fos.write(buf, 0, readNum);
                } finally {
                    if(fisSong!=null){
                        fisSong.close();
                    }
                    if(sis!=null){
                        sis.close();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fos!=null){
                    fos.flush();
                    fos.close();
                }
                if(fisToFinal!=null){
                    fisToFinal.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } 
GhostDerfel
  • 1,533
  • 1
  • 11
  • 18
  • It prints any error? Can you give-me more information? Did you tried to debug the code and understand why only one file was merged? – GhostDerfel Apr 07 '15 at 17:15
  • 1
    Yes, I have debugged the code. It executes normally but, when I play final file, it have only first clip. it does not have 2nd and 3rd clip. – Ali Apr 08 '15 at 11:25
  • The file has the expected size after merging all the files and only the first clip is played or the files are not merged? – GhostDerfel Apr 08 '15 at 16:05
  • only first file merged. – Ali Apr 10 '15 at 09:33
  • That is really strange, just tested the code again with 4 mp3 files and works as expected. Not sure what is the problem, also your answer for my previous question is conflicting with this one. If only the first file is merged then an error or something should happen to prevent the files to be merged and before you stated that the code run normally. – GhostDerfel Apr 10 '15 at 12:49
  • Great library :) much better then my solution – GhostDerfel Apr 13 '15 at 13:08
  • @GauravPrajapati this is a really old thread, I would recommend to search for a newer answer then using this piece of code above (still works but there are better solutions and libraries available now) – GhostDerfel Feb 12 '20 at 14:33
  • mergedFile size increases but the duration stays same as the first file. Please provide a solution! Tried [this](https://stackoverflow.com/questions/35340025/how-to-merge-two-or-more-mp3-audio-file-in-android) one, but it causes the same problem – Raihanul Alam Hridoy Mar 31 '20 at 17:16
0

Mp3 files are some frames.

You can concatenate these files by appending the streams to each other if and only if the bit rate and sample rate of your files are same.

If not, the first file plays because it has truly true encoding but the second file can not decode to an true mp3 file.

Suggestion: convert your files with some specific bit rate and sample rate, then use your function.

Mehdi Khademloo
  • 2,754
  • 2
  • 20
  • 40
  • I've set the sample rate and encoding bit rate using mRecorder.setAudioSamplingRate(44100); mRecorder.setAudioEncodingBitRate(96000); But it still only plays the first file. Any ideas? – filipebarretto May 24 '16 at 20:37