同时播放两个声音 - Android

时间:2014-08-27 10:55:03

标签: android audio merge android-mediaplayer mixing

是否可以同时播放两个声音(mp3)文件?我尝试过使用两个不同的MediaPlayer对象 -

MediaPlayer mediaPlayer;
MediaPlayer mediaPlayer2;

播放声音,但这不起作用。我不能使用SoundPool,因为使用的声音文件大约每个10MB(因为SoundPool不能很好地处理声音文件> 3MB)。

以下是一些熟悉我情况的代码 -

@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();
}

有什么建议吗?有没有办法使这2个MediaPlayer对象的方法工作?如果没有那么还有其他选择吗?代码会有所帮助!

3 个答案:

答案 0 :(得分:2)

所以同时播放两个音频文件肯定是一个问题,所以我想,另一种看待问题的方法是以编程方式将两个音频文件合并为一个,然后播放。事实证明,使用WAV文件很容易实现(MP3和其他压缩格式需要首先解压缩?)。无论如何,这是我的表现方式:

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();

以下是支持功能:

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;
    } 

本质上,代码的作用是:它获取两个音频文件的字节(一个在R.raw中的应用程序内,另一个在外部存储目录中),总结它们并写入新的字节到另一个文件。

此代码的问题在于它会产生一定量的背景噪音。它不是很多,但我相信在某些点(可能是极值?)的字节总和会导致噪音。如果有人知道如何解决这个问题,你可以编辑答案并告诉我。

P.S。这是一个开源的语音转换器应用程序,具有戏剧性的背景噪音效果,称为Kylo Ren语音转换器(https://github.com/advaitsaravade/Kylo-Ren-Voice-Changer

答案 1 :(得分:0)

我在MediaPlayer中使用了Service的两个实例。我的代码与你的代码类似。我遇到了一些问题,但终于解决了。请在Unable to play two MediaPlayer at same time in Nexus 5

查看我的答案

如果您仍然遇到问题,请填写完整的代码和logcat错误。

答案 2 :(得分:-3)

您还可以尝试创建两个片段,每个片段都播放声音。 我有另一个问题,如果我播放一个mp3文件,然后单击后退按钮,然后再次启动活动,ican再次播放相同的文件。您可以同时阅读Android Mediaplayer multiple instances when activity resumes播放声音