将mic录音和伴奏混合成wav。

public class MixRunnable implements Runnable {
        private MixRecorder context;
        /**
         * AudioRecord创建参数类
         *
         * @author christ
         */
        private static class RecorderParameter {
                // 音频获取源
                private static int audioSource = MediaRecorder.AudioSource.MIC;
                // 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
                private static final int sampleRateInHz = 44100 ;
                // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
                private static final int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
                // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
                private static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
                // 缓冲区字节大小
                private static int bufferSizeInBytes;
        }
        // 设置运行状态
        private boolean isRunning = true ;
        // AudioRecord对象
        private static AudioRecord recorder;
        // 设置MediaPlayer对象
        private static MediaPlayer mediaPlayer;
        // 伴奏文件
        private FileInputStream accompany;
        // 原唱文件
        private FileInputStream original;
        // 得分
        private int score;
        private boolean isFirst = true ;
        /**
         * 混音评分线程的构造方法
         *
         * @param accompany
         *                :伴奏文件路径
         * @param original
         *                :原唱文件路径
         * @throws FileNotFoundException
         */
        public MixRunnable(MixRecorder context, String accompany, String original) throws FileNotFoundException {
                this .context = context;
                this .accompany = new FileInputStream(accompany);
                this .original = new FileInputStream(original);
                creatAudioRecord();
                mediaPlayer = new MediaPlayer();
        }
        @Override
        public void run() {
                try {
                        // MediaPlayer准备
                        mediaPlayer.reset();
                        mediaPlayer.setDataSource( "/sdcard/111.wav" );
                        // mediaPlayer.setDataSource(accompany.getFD());
                        mediaPlayer.setOnCompletionListener( new OnCompletionListener() {
                                @Override
                                public void onCompletion(MediaPlayer mp) {
                                        isRunning = false ;
                                }
                        });
                        mediaPlayer.prepare();
                        // 跳过头
                        accompany.read( new byte [ 44 ]);
                        original.read( new byte [ 44 ]);
                        FileOutputStream fos = new FileOutputStream( new File( "/sdcard/love.raw" ));
                        // 开始读
                        byte [] sourceReader = new byte [RecorderParameter.bufferSizeInBytes * 2 ];
                        short [] sourceShortArray;
                        short [] audioReader = new short [sourceReader.length / 4 ];
                        mediaPlayer.start();
                        recorder.startRecording();
                        while (isRunning) {
                                int sourceReadSize = accompany.read(sourceReader, 0 , sourceReader.length);
                                if (sourceReadSize < 0 ) {
                                        isRunning = false ;
                                        continue ;
                                }
                                sourceShortArray = byteToShortArray(sourceReader, sourceReadSize / 2 );
                                recorder.read(audioReader, 0 , audioReader.length);
                                short [] oneSecond = mixVoice(sourceShortArray, audioReader, sourceReadSize / 2 );
                                byte [] outStream = new byte [oneSecond.length * 2 ];
                                for ( int i = 0 ; i < oneSecond.length; i++) {
                                        byte [] b = shortToByteArray(oneSecond<i>);
                                        outStream[ 2 * i] = b[ 0 ];
                                        outStream[ 2 * i + 1 ] = b[ 1 ];
                                }
                                Log.d( "mtime4" , "" + System.currentTimeMillis());
                                fos.write(outStream);
                                // 评分
                                byte [] srcBuffer = new byte [outStream.length];
                                original.read(srcBuffer);
                                int x = score(byteToShortArray(srcBuffer, srcBuffer.length / 2 ), oneSecond);
                                System.out.println(x);
                        }
                        if (mediaPlayer.isPlaying()) {
                                mediaPlayer.stop();
                        }
                        recorder.release();
                        mediaPlayer.release();
                        fos.close();
                        copyWaveFile( "/sdcard/love.raw" , "/sdcard/haah.wav" );
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }
        /**
         * 创建AudioRecord对象方法
         */
        private void creatAudioRecord() {
                // 获得缓冲区字节大小
                RecorderParameter.bufferSizeInBytes = AudioRecord.getMinBufferSize(RecorderParameter.sampleRateInHz,
                                RecorderParameter.channelConfig, RecorderParameter.audioFormat) * 20 ;
                // 创建AudioRecord对象
                recorder = new AudioRecord(RecorderParameter.audioSource, RecorderParameter.sampleRateInHz,
                                RecorderParameter.channelConfig, RecorderParameter.audioFormat,
                                RecorderParameter.bufferSizeInBytes);
        }
        private short [] mixVoice( short [] source, short [] audio, int items) {
                short [] array = new short [items];
                for ( int i = 0 ; i < items; i++) {
                        array<i> = ( short ) ((source<i> + audio[i / 2 ]) / 2 );
                }
                return array;
        }
        /**
         * byte数组转换成short数组
         *
         * @param data
         * @param items
         * @return
         */
        private short [] byteToShortArray( byte [] data, int items) {
                short [] retVal = new short [items];
                for ( int i = 0 ; i < retVal.length; i++)
                        retVal<i> = ( short ) ((data[i * 2 ] & 0xff ) | (data[i * 2 + 1 ] & 0xff ) << 8 );
                return retVal;
        }
        /**
         * short转byte数组
         *
         * @param s
         * @return
         */
        private byte [] shortToByteArray( short s) {
                byte [] shortBuf = new byte [ 2 ];
                for ( int i = 0 ; i < 2 ; i++) {
                        int offset = (shortBuf.length - 2 + i) * 8 ;
                        shortBuf<i> = ( byte ) ((s >>> offset) & 0xff );
                }
                return shortBuf;
        }
        /**
         * <a href="\"http://www.eoeandroid.com/home.php?mod=space&uid=7300\"" target="\"_blank\"">@return</a> the recorder
         */
        public static AudioRecord getRecorder() {
                return recorder;
        }
        public static MediaPlayer getMediaPlayer() {
                return mediaPlayer;
        }
        /**
         * 设置线程运行状态
         *
         * @param isRunning
         */
        public void setIsRunning( boolean isRunning) {
                this .isRunning = isRunning;
        }
        /**
         * 获取线程运行状态
         *
         * @return
         */
        public boolean IsRunning() {
                return isRunning;
        }
        public int getScore() {
                return score;
        }
        private void copyWaveFile(String inFilename, String outFilename) {
                FileInputStream in = null ;
                FileOutputStream out = null ;
                long totalAudioLen = 0 ;
                long totalDataLen = totalAudioLen + 36 ;
                long longSampleRate = RecorderParameter.sampleRateInHz;
                int channels = 2 ;
                long byteRate = 16 * RecorderParameter.sampleRateInHz * channels / 8 ;
                byte [] data = new byte [RecorderParameter.bufferSizeInBytes];
                try {
                        in = new FileInputStream(inFilename);
                        out = new FileOutputStream(outFilename);
                        totalAudioLen = in.getChannel().size();
                        totalDataLen = totalAudioLen + 36 ;
                        WriteWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
                        while (in.read(data) != - 1 ) {
                                out.write(data);
                        }
                        in.close();
                        out.close();
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
        /**
         * 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。 为我为啥插入这44个字节,这个还真没深入研究,不过你随便打开一个wav
         * 音频的文件,可以发现前面的头文件可以说基本一样哦。每种格式的文件都有 自己特有的头文件。
         */
        private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen,
                        long longSampleRate, int channels, long byteRate) throws IOException {
                byte [] header = new byte [ 44 ];
                header[ 0 ] = 'R' ; // RIFF/WAVE header
                header[ 1 ] = 'I' ;
                header[ 2 ] = 'F' ;
                header[ 3 ] = 'F' ;
                header[ 4 ] = ( byte ) (totalDataLen & 0xff );
                header[ 5 ] = ( byte ) ((totalDataLen >> 8 ) & 0xff );
                header[ 6 ] = ( byte ) ((totalDataLen >> 16 ) & 0xff );
                header[ 7 ] = ( byte ) ((totalDataLen >> 24 ) & 0xff );
                header[ 8 ] = 'W' ;
                header[ 9 ] = 'A' ;
                header[ 10 ] = 'V' ;
                header[ 11 ] = 'E' ;
                header[ 12 ] = 'f' ; // 'fmt ' chunk
                header[ 13 ] = 'm' ;
                header[ 14 ] = 't' ;
                header[ 15 ] = ' ' ;
                header[ 16 ] = 16 ; // 4 bytes: size of 'fmt ' chunk
                header[ 17 ] = 0 ;
                header[ 18 ] = 0 ;
                header[ 19 ] = 0 ;
                header[ 20 ] = 1 ; // format = 1
                header[ 21 ] = 0 ;
                header[ 22 ] = ( byte ) channels;
                header[ 23 ] = 0 ;
                header[ 24 ] = ( byte ) (longSampleRate & 0xff );
                header[ 25 ] = ( byte ) ((longSampleRate >> 8 ) & 0xff );
                header[ 26 ] = ( byte ) ((longSampleRate >> 16 ) & 0xff );
                header[ 27 ] = ( byte ) ((longSampleRate >> 24 ) & 0xff );
                header[ 28 ] = ( byte ) (byteRate & 0xff );
                header[ 29 ] = ( byte ) ((byteRate >> 8 ) & 0xff );
                header[ 30 ] = ( byte ) ((byteRate >> 16 ) & 0xff );
                header[ 31 ] = ( byte ) ((byteRate >> 24 ) & 0xff );
                header[ 32 ] = ( byte ) ( 2 * 16 / 8 ); // block align
                header[ 33 ] = 0 ;
                header[ 34 ] = 16 ; // bits per sample
                header[ 35 ] = 0 ;
                header[ 36 ] = 'd' ;
                header[ 37 ] = 'a' ;
                header[ 38 ] = 't' ;
                header[ 39 ] = 'a' ;
                header[ 40 ] = ( byte ) (totalAudioLen & 0xff );
                header[ 41 ] = ( byte ) ((totalAudioLen >> 8 ) & 0xff );
                header[ 42 ] = ( byte ) ((totalAudioLen >> 16 ) & 0xff );
                header[ 43 ] = ( byte ) ((totalAudioLen >> 24 ) & 0xff );
                out.write(header, 0 , 44 );
        }
        private int score( short [] src, short [] user) {
                int srcZ = 0 , userZ = 0 ;
                boolean isAsc = false ;
                boolean uisAsc = false ;
                for ( int i = 1 ; i < src.length; i++) {
                        if (isAsc) {
                                if (src[i - 1 ] > src<i>) {
                                        isAsc = false ;
                                }
                        } else {
                                if (src[i - 1 ] < src<i>) {
                                        isAsc = true ;
                                        srcZ += 1 ;
                                }
                        }
                        if (uisAsc) {
                                if (user[i - 1 ] > user<i>) {
                                        uisAsc = false ;
                                }
                        } else {
                                if (user[i - 1 ] < user<i>) {
                                        uisAsc = true ;
                                        userZ += 1 ;
                                }
                        }
                }
                return Math.abs(srcZ - userZ);
        }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值