Android: 混合音频

3
我正在开发一款Android应用程序,使用mediarecorder录制声音并使用mediaplayer播放音乐。
我的目标是将两个音频混合成一个文件,但由于Android没有提供任何API来实现这一目标,因此我正在寻找一个合理的解决方案。
目前,在播放时,我使用一个新的mediarecorder和MIC源来捕获音频并保存它,但效果非常差!
有没有任何混合音频的方法?包括使用SOX或FFMPEG等任何本地解决方案?
或者,有没有任何方法可以使用mediaplayer输出作为源来录制文件,而不是使用MIC?
欢迎任何建议。
谢谢。
1个回答

1
当我遇到相同的问题时,我能够找到混合文件的解决方案。由于两个mp3文件的混合是不可能的,您必须首先将其转换为波形格式,然后设置头值。之后添加数据字段。我是这样做的。希望我的代码能帮到你。
类MixFile扩展自AsyncTask {
    ProgressDialog dialog;
    protected void onPreExecute() {
        dialog= new ProgressDialog(MainActivity.this);
        dialog.setCancelable(false);
        dialog.setMessage("Mixing two wav files");
        dialog.show();
    }
    @Override
    protected Void doInBackground(Void... arg0) {
        short[] audioData1 = null;
        short[] audioData2 = null;

        int n = 0;

        try {
            DataInputStream in1;

//打开一个文件输入流 in1 = new DataInputStream(new FileInputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/one.wav")); //使用指定路径的文件输入流 in1 = new DataInputStream(new FileInputStream(path1)); //创建一个字节数组输出流 ByteArrayOutputStream bos = new ByteArrayOutputStream();

            try {

                while ((n = in1.read()) != -1) {
                    bos.write(n);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
            bb.order(ByteOrder.LITTLE_ENDIAN);
            ShortBuffer sb = bb.asShortBuffer();
            audioData1 = new short[sb.capacity()];

            for (int i = 0; i < sb.capacity(); i++) {
                audioData1[i] = sb.get(i);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            DataInputStream in1;
            in1 = new DataInputStream(new FileInputStream(path2));
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            try {

                while ((n = in1.read()) != -1) {
                    bos.write(n);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }


            ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
            bb.order(ByteOrder.LITTLE_ENDIAN);
            ShortBuffer sb = bb.asShortBuffer();
            audioData2=  new short[sb.capacity()];

            sb.get(audioData2);


            System.out.println();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // find the max:



        float max = 0;

        Log.d("File audio lenght 1 ", ""+audioData1.length);
        Log.d("File audio lenght 2 ", ""+audioData2.length);

        System.out.println("MainActivity.MixFile.doInBackground() 1"+audioData1.length);
        System.out.println("MainActivity.MixFile.doInBackground() 2"+audioData2.length);

        if(audioData1.length > audioData2.length){

        for (int i = 22; i < audioData2.length; i++) {
            if (Math.abs(audioData1[i] + audioData2[i]) > max)
                max = Math.abs(audioData1[i] + audioData2[i]);
        }

        System.out.println("" + (Short.MAX_VALUE - max));
        int a, b, c;
        // now find the result, with scaling:
        for (int i = 22; i < audioData2.length; i++) {
            a = audioData1[i];
            b = audioData2[i];

            c = Math.round(Short.MAX_VALUE * (audioData1[i] + audioData2[i])
                    / max);

            if (c > Short.MAX_VALUE)
                c = Short.MAX_VALUE;
            if (c < Short.MIN_VALUE)
                c = Short.MIN_VALUE;


            audioData1[i] = (short) c; 

        }

        // to turn shorts back to bytes.
        byte[] end = new byte[audioData1.length * 2];
        ByteBuffer.wrap(end).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(audioData1);

        try {
            OutputStream out  = new FileOutputStream(Environment.getExternalStorageDirectory() + "/assets/mixer12.wav");
            for (int i = 0; i < end.length; i++) {
                out.write(end[i]);
                out.flush();
            }
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        }else{

            System.out.println("MainActivity.MixFile.doInBackground() smaller one");
            for (int i = 22; i < audioData1.length; i++) {
                if (Math.abs(audioData2[i] + audioData1[i]) > max)
                    max = Math.abs(audioData2[i] + audioData1[i]);
            }

            System.out.println("" + (Short.MAX_VALUE - max));
            int a, b, c;
            // now find the result, with scaling:
            for (int i = 22; i < audioData1.length; i++) {
                a = audioData2[i];
                b = audioData1[i];

                c = Math.round(Short.MAX_VALUE * (audioData2[i] + audioData1[i])
                        / max);

                if (c > Short.MAX_VALUE)
                    c = Short.MAX_VALUE;
                if (c < Short.MIN_VALUE)
                    c = Short.MIN_VALUE;


                audioData2[i] = (short) c; 

            }

            // to turn shorts back to bytes.
            byte[] end = new byte[audioData2.length * 2];
            ByteBuffer.wrap(end).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(audioData2);

            try {
                OutputStream out  = new FileOutputStream(Environment.getExternalStorageDirectory() + "/Assets/mixer1.wav");
                for (int i = 0; i < end.length; i++) {
                    out.write(end[i]);
                    out.flush();
                }
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }



        }
        return null;
    }

在活动中,我将其称为以下内容:
 public class MainActivity extends Activity implements OnClickListener {

  new MixFile().execute();

  }

这里的path1和path2是您想要混合的wav文件的路径。

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