Android:混合音频

时间:2012-01-10 13:19:11

标签: android android-ndk

我正在开发一款Android应用,可以使用mediarecorder录制语音并使用媒体播放器播放音乐。

我的目标是将两个音频混合成一个文件,因为Android不提供任何API,我正在寻找一个合理的解决方案。

此刻,在播放时我正在使用带有MIC源的新媒体录制器来捕获音频并保存,但这非常差!!!

无论如何混合音频?包括任何原生溶液lix SOX或FFMPEG?

或者,无论如何使用媒体播放器输出作为源来记录到文件而不是使用MIC?

任何建议都表示赞赏。

谢谢。

1 个答案:

答案 0 :(得分:1)

当我遇到同样的问题时,我能够找到混合文件的解决方案。 由于无法混合两个mp3文件,您必须先将其转换为波形格式,然后设置标题值。之后添加数据字段。我是按照以下方式做到的。希望我的代码能帮到你。

class 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文件的路径