2

Is it possible to play two sound (mp3) files at the same time? I have tried using two different MediaPlayer objects-

MediaPlayer mediaPlayer;
MediaPlayer mediaPlayer2;

to play the sounds, but that does not work. I cannot use SoundPool either as the sound files in use are around 10MB each (since SoundPool doesn't work well with sound files > 3MB).

Here is some code to get familiar with my situation-

@Override
public void onResume() {
    super.onResume();
    if(mediaPlayer == null)
    {
    mediaPlayer = MediaPlayer.create(getActivity().getApplicationContext(), R.raw.song1);
    }
    if(mediaPlayer2 == null)
    {
    mediaPlayer2 = MediaPlayer.create(getActivity().getApplicationContext(), R.raw.song2);
    }
}
private void startPlaying() {
mediaPlayer.setLooping(true);
mediaPlayer.start();
mediaPlayer2.start();
}

Any suggestions? Is there some way to make this 2 MediaPlayer objects approach work? If not then what other options are there? Code would be helpful!

Advait Saravade
  • 3,029
  • 29
  • 34
  • do you want to join it together or to play the two files at the same time. – Akshay Mukadam Aug 27 '14 at 11:09
  • @james i need to play the two files at the same time. – Advait Saravade Aug 27 '14 at 12:09
  • Did you find an answer to this? I am trying to get this working. – Totem Jan 12 '17 at 16:24
  • @Totem I did. Sort of. It combines the two audio files into a single file, and plays that using a single media player instance. Only issue is I haven't had the time to perfect it. There is still some noise that is generated due to the combination of the two files. Do you still need me to post some code? – Advait Saravade Jan 12 '17 at 21:05
  • Well, I wouldn't say no, if you have some handy! I have been reading up on this, and I'm aware of the idea of 'summing' two files. However, I'm not sure how that would be done exactly. Perhaps it just a matter of using a '+' sign somewhere? – Totem Jan 12 '17 at 22:12
  • 1
    @Totem It's a + and ÷. Averages. I'll post the code as an answer. – Advait Saravade Jan 13 '17 at 23:28

3 Answers3

2

So playing two audio files simultaneously is definitely an issue so I thought, another way to look at the problem would be to combine two audio files programmatically into one, and play that. That turned out to be simple to implement with WAV files (MP3 and other compressed formats would need to be uncompressed first?). Anyway, here's how I did it:

InputStream is = getResources().openRawResource(R.raw.emokylotheme); // Name of file 1

byte [] bytesTemp2 = fullyReadFileToBytes(new File(
Environment.getExternalStorageDirectory().getAbsolutePath()+
"/Kylo Ren/"+filename+"_morphed.wav")); // Name of file 2

byte [] sample2 = convertInputStreamToByteArray(is);
byte[] temp2 = bytesTemp2.clone();

RandomAccessFile randomAccessFile2 = new RandomAccessFile(new File(
Environment.getExternalStorageDirectory().getAbsolutePath()+
"/Kylo Ren/"+filename+"_morphed.wav"), "rw");

//seek to skip 44 bytes for WAV formats
randomAccessFile2.seek(44);
for (int n = 0; n < bytesTemp2.length; n++)
{
    bytesTemp2[n] = (byte) ((temp2[n] + (sample2[n])));
} 

randomAccessFile2.write(bytesTemp2);
randomAccessFile2.close();

And here are the support functions:

public byte[] convertInputStreamToByteArray(InputStream inputStream)
     {
     byte[] bytes= null;

     try
     {
     ByteArrayOutputStream bos = new ByteArrayOutputStream();

     byte data[] = new byte[1024];
     int count;

     while ((count = inputStream.read(data)) != -1)
     {
     bos.write(data, 0, count);
     }

    bos.flush();
     bos.close();
     inputStream.close();

    bytes = bos.toByteArray();
     }
     catch (IOException e)
     {
     e.printStackTrace();
     }
     return bytes;
     }


byte[] fullyReadFileToBytes(File f) throws IOException {
        int size = (int) f.length();
        byte bytes[] = new byte[size];
        byte tmpBuff[] = new byte[size];
        FileInputStream fis= new FileInputStream(f);
        try { 

            int read = fis.read(bytes, 0, size);
            if (read < size) {
                int remain = size - read;
                while (remain > 0) {
                    read = fis.read(tmpBuff, 0, remain);
                    System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
                    remain -= read;
                } 
            } 
        }  catch (IOException e){
            throw e;
        } finally { 
            fis.close();
        } 

        return bytes;
    } 

In essence, what the code does is: It gets the bytes of the two audio files (one is within the app in R.raw and the other is in the external storage directory), sums them up, and writes the new bytes to another file.

The issue with this code is that it generates some amount of background noise. It isn't a lot but I believe the summing up of the bytes at certain points (maybe extremas?) leads to the noise. If someone knows how to fix this, could you edit the answer and let me know.

P.S. this was for an open source voice changer app with dramatic background noise effects called Kylo Ren Voice Changer (https://github.com/advaitsaravade/Kylo-Ren-Voice-Changer)

Advait Saravade
  • 3,029
  • 29
  • 34
0

I have used two instances of MediaPlayer in a Service. My code is similar to yours. I had some problems but finally solved it. Please check my answer here Unable to play two MediaPlayer at same time in Nexus 5

If you still have problems, please put your full code and the logcat error.

Community
  • 1
  • 1
allo86
  • 946
  • 1
  • 9
  • 23
-3

You can also try to create two fragments and each play a sound. I have another problem if i played an mp3 file, then click the back button and then start the activity again and ican play the same file again. You can will read Android Mediaplayer multiple instances when activity resumes play sound in the same time

Community
  • 1
  • 1