Android: 如何混合两个音频文件并使用soundPool播放它们

3
我正在尝试开发一个使用音频混合创作音乐的安卓应用程序。一开始,我只是尝试同时播放这些声音,但当我这样做时,它们会失去同步。经过几个小时阅读论坛后,我意识到,在循环模式下同时播放多个声音的最佳方法就是将音频文件合并为一个文件,然后将它们作为单个文件播放。以下是我正在使用的代码:
        //Oppening file 1
        InputStream is = getAssets().open("sounds/sound_1.ogg");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        //End Oppening file 1

        //Oppening file 2
        InputStream is_2 = getAssets().open("sounds/sound_2.ogg");
        int size_2 = is_2.available();
        byte[] buffer_2 = new byte[size_2];
        is_2.read(buffer_2);
        is_2.close();
        //End Oppening file 2

        //Get Bigger size and Merge Files
        int total_size =0;

        byte[] buffer_final;
        if(buffer.length>buffer_2.length){
            total_size = buffer_2.length;   
        }else{
            total_size = buffer.length-1;
        }

        buffer_final= new byte[total_size];

        for(int i=30; i<total_size-30;i++){


            float a =buffer[i];
            float b =buffer_2[i];
            float c = (a+b)/2;
            buffer_final[i]=(byte) c;      

        }

        FileOutputStream fos = new FileOutputStream(f);        
        fos.write(buffer_final);
        fos.close();

然后,使用soundPool读取生成的文件并尝试重现它。如果我在不合并文件的情况下使用这个公式(因此只使用一个声音、创建一个新文件,然后读取它),它能够完美地工作,因此我认为问题在于文件合并,可能不像只是将字节相加然后除以2那么简单。做完这一步后,日志告诉我:“无法加载样本(null)”。当我尝试重现时,日志说样本还没有准备好。请问有关这方面的任何帮助吗?我已经搜索了几周,但没有解决......这是我第一次编写Android程序,也是第一次接触音频,所以有点迷失。问题是,我如何混音?我是否采用了正确的方法?问题出在哪里?感谢您的阅读和帮助 :)

非常好格式化的第一篇帖子!一个清晰简洁的问题。干得好。 - davehale23
2个回答

1

如果您使用的是原始PCM数据,则对样本进行平均处理就可以了。您需要做的是先将OGG文件转换为PCM缓冲区。如果您想保持输出为OGG,则需要在完成后将其转换回来。

我的经验主要是与MP3库而不是OGG有关,但我听说JOrbis很不错。


一旦你在缓冲区中有了原始音频,你可以像你尝试的那样添加/分割它们。不过,如果你想要它在大多数播放器上播放,你还需要对结果进行一些重新转换。 - Geobits
谢谢大家,很抱歉回复晚了。最终我使用音频池成功地实现了同时播放多个声音而没有延迟,所以我根本不需要将它们合并 :) 所以对我来说问题已经解决了!! - TurboTi
@TurboTi 你好,请解释一下你是如何合并两个音频文件的? - sandeep
@TurboTi 谢谢你的回答。但是我需要实现一个音频混合器,就像上面的代码一样,而不是像声音池那样。使用上面的代码,我得到了输出,但是它只有模糊的声音,没有任何音乐或声音。 - sandeep
@sandeep,你解决了你的问题吗?我需要与你相同的功能,请帮帮我。 - Arun Badole
显示剩余4条评论

0

这样做

soundPool = new SoundPool(NUM_SOUNDS, AudioManager.STREAM_MUSIC, 0);

NUM_SOUNDS 是 soundPool 可以同时播放的声音数量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接