Android手機的聲波通信源代碼

最近一年在Android手機中出現了大量的比較優秀的用聲波握手通信的應用程序,比如茄子快傳,支付寶聲波支付,還有小米的聲波握手傳輸等。其基本思路都是首先建立wifi熱點,然後用聲波通信的方法將wifi熱點name和password傳輸給對方,最後對方收到name和密碼後自動鏈接wifi熱點並傳輸各種大文件。該技術的主要難點在於聲波通信,下面是我最近寫的聲波通信程序,源代碼下載地址:http://download.csdn.net/detail/hcb1230/6442449

該代碼可以實現在兩個手機間用聲波傳輸信息。iphone上的chirp,android中的茄子快傳,支付寶聲波支付等衆多軟件都使用了聲波通信作爲握手服務。

[文件] SinVoicePlayer.java 

 

/*
 * Copyright (C) 2013 gujicheng
 * 
 * Licensed under the GPL License Version 2.0;
 * you may not use this file except in compliance with the License.
 * 
 * If you have any question, please contact me.
 * 
 *************************************************************************
 **                   Author information                                **
 *************************************************************************
 ** Email: [email protected]                                         **
 ** QQ   : 29600731                                                     **
 ** Weibo: http://weibo.com/gujicheng197                                **
 *************************************************************************
 */
package com.libra.sinvoice;

import java.util.ArrayList;
import java.util.List;

import android.media.AudioFormat;
import android.text.TextUtils;

import com.libra.sinvoice.Buffer.BufferData;

public class SinVoicePlayer implements Encoder.Listener, Encoder.Callback, PcmPlayer.Listener, PcmPlayer.Callback {
    private final static String TAG = "SinVoicePlayer";

    private final static int STATE_START = 1;
    private final static int STATE_STOP = 2;
    private final static int STATE_PENDING = 3;

    private final static int DEFAULT_GEN_DURATION = 100;

    private String mCodeBook;
    private List<Integer> mCodes = new ArrayList<Integer>();

    private Encoder mEncoder;
    private PcmPlayer mPlayer;
    private Buffer mBuffer;

    private int mState;
    private Listener mListener;
    private Thread mPlayThread;
    private Thread mEncodeThread;

    public static interface Listener {
        void onPlayStart();

        void onPlayEnd();
    }

    public SinVoicePlayer() {
        this(Common.DEFAULT_CODE_BOOK);
    }

    public SinVoicePlayer(String codeBook) {
        this(codeBook, Common.DEFAULT_SAMPLE_RATE, Common.DEFAULT_BUFFER_SIZE, Common.DEFAULT_BUFFER_COUNT);
    }

    public SinVoicePlayer(String codeBook, int sampleRate, int bufferSize, int buffCount) {
        mState = STATE_STOP;
        mBuffer = new Buffer(buffCount, bufferSize);

        mEncoder = new Encoder(this, sampleRate, SinGenerator.BITS_16, bufferSize);
        mEncoder.setListener(this);
        mPlayer = new PcmPlayer(this, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
        mPlayer.setListener(this);

        setCodeBook(codeBook);
    }

    public void setListener(Listener listener) {
        mListener = listener;
    }

    public void setCodeBook(String codeBook) {
        if (!TextUtils.isEmpty(codeBook) && codeBook.length() < Encoder.getMaxCodeCount() - 1) {
            mCodeBook = codeBook;
        }
    }

    private boolean convertTextToCodes(String text) {
        boolean ret = true;

        if (!TextUtils.isEmpty(text)) {
            mCodes.clear();
            mCodes.add(Common.START_TOKEN);
            int len = text.length();
            for (int i = 0; i < len; ++i) {
                char ch = text.charAt(i);
                int index = mCodeBook.indexOf(ch);
                if (index > -1) {
                    mCodes.add(index + 1);
                } else {
                    ret = false;
                    LogHelper.d(TAG, "invalidate char:" + ch);
                    break;
                }
            }
            if (ret) {
                mCodes.add(Common.STOP_TOKEN);
            }
        } else {
            ret = false;
        }

        return ret;
    }

    public void play(final String text) {
        if (STATE_STOP == mState && null != mCodeBook && convertTextToCodes(text)) {
            mState = STATE_PENDING;

            mPlayThread = new Thread() {
                @Override
                public void run() {
                    mPlayer.start();
                }
            };
            if (null != mPlayThread) {
                mPlayThread.start();
            }

            mEncodeThread = new Thread() {
                @Override
                public void run() {
                    LogHelper.d(TAG, "encode start");
                    mEncoder.encode(mCodes, DEFAULT_GEN_DURATION);
                    LogHelper.d(TAG, "encode end");

                    LogHelper.d(TAG, "stop player start");
                    stopPlayer();
                    LogHelper.d(TAG, "stop player end");

                    mEncoder.stop();
                    mPlayer.stop();
                }
            };
            if (null != mEncodeThread) {
                mEncodeThread.start();
            }

            LogHelper.d(TAG, "play");
            mState = STATE_START;
        }
    }

    public void stop() {
        if (STATE_START == mState) {
            mState = STATE_PENDING;

            LogHelper.d(TAG, "force stop start");
            mEncoder.stop();
            if (null != mEncodeThread) {
                try {
                    mEncodeThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    mEncodeThread = null;
                }
            }

            LogHelper.d(TAG, "force stop end");
        }
    }

    private void stopPlayer() {
        if (mEncoder.isStoped()) {
            mPlayer.stop();
        }

        // put end buffer
        mBuffer.putFull(BufferData.getEmptyBuffer());

        if (null != mPlayThread) {
            try {
                mPlayThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                mPlayThread = null;
            }
        }

        mBuffer.reset();
        mState = STATE_STOP;
    }

    @Override
    public void onStartEncode() {
        LogHelper.d(TAG, "onStartGen");
    }

    @Override
    public void freeEncodeBuffer(BufferData buffer) {
        if (null != buffer) {
            mBuffer.putFull(buffer);
        }
    }

    @Override
    public BufferData getEncodeBuffer() {
        return mBuffer.getEmpty();
    }

    @Override
    public void onEndEncode() {
    }

    @Override
    public BufferData getPlayBuffer() {
        return mBuffer.getFull();
    }

    @Override
    public void freePlayData(BufferData data) {
        mBuffer.putEmpty(data);
    }

    @Override
    public void onPlayStart() {
        if (null != mListener) {
            mListener.onPlayStart();
        }
    }

    @Override
    public void onPlayStop() {
        if (null != mListener) {
            mListener.onPlayEnd();
        }
    }

}

. [文件] SinVoiceRecognition.java

/*
 * Copyright (C) 2013 gujicheng
 * 
 * Licensed under the GPL License Version 2.0;
 * you may not use this file except in compliance with the License.
 * 
 * If you have any question, please contact me.
 * 
 *************************************************************************
 **                   Author information                                **
 *************************************************************************
 ** Email: [email protected]                                         **
 ** QQ   : 29600731                                                     **
 ** Weibo: http://weibo.com/gujicheng197                                **
 *************************************************************************
 */
package com.libra.sinvoice;

import android.text.TextUtils;

import com.libra.sinvoice.Buffer.BufferData;

public class SinVoiceRecognition implements Record.Listener, Record.Callback, VoiceRecognition.Listener, VoiceRecognition.Callback {
    private final static String TAG = "SinVoiceRecognition";

    private final static int STATE_START = 1;
    private final static int STATE_STOP = 2;
    private final static int STATE_PENDING = 3;

    private Buffer mBuffer;
    private Record mRecord;
    private VoiceRecognition mRecognition;

    private Thread mRecordThread;
    private Thread mRecognitionThread;
    private int mState;
    private Listener mListener;

    private String mCodeBook;
    private int mMaxCodeIndex;

    public static interface Listener {
        void onRecognitionStart();

        void onRecognition(char ch);

        void onRecognitionEnd();
    }

    public SinVoiceRecognition() {
        this(Common.DEFAULT_CODE_BOOK);
    }

    public SinVoiceRecognition(String codeBook) {
        this(codeBook, Common.DEFAULT_SAMPLE_RATE, Common.DEFAULT_BUFFER_SIZE, Common.DEFAULT_BUFFER_COUNT);
    }

    public SinVoiceRecognition(String codeBook, int sampleRate, int bufferSize, int bufferCount) {
        mState = STATE_STOP;
        mBuffer = new Buffer(bufferCount, bufferSize);

        mRecord = new Record(this, sampleRate, Record.CHANNEL_1, Record.BITS_16, bufferSize);
        mRecord.setListener(this);
        mRecognition = new VoiceRecognition(this, sampleRate, Record.CHANNEL_1, Record.BITS_16);
        mRecognition.setListener(this);

        mMaxCodeIndex = Encoder.getMaxCodeCount() - 2;

        setCodeBook(codeBook);
    }

    public void setListener(Listener listener) {
        mListener = listener;
    }

    public void setCodeBook(String codeBook) {
        if (!TextUtils.isEmpty(codeBook) && codeBook.length() <= mMaxCodeIndex) {
            mCodeBook = codeBook;
        }
    }

    public void start() {
        if (STATE_STOP == mState) {
            mState = STATE_PENDING;

            mRecognitionThread = new Thread() {
                @Override
                public void run() {
                    mRecognition.start();
                }
            };
            if (null != mRecognitionThread) {
                mRecognitionThread.start();
            }

            mRecordThread = new Thread() {
                @Override
                public void run() {
                    mRecord.start();

                    LogHelper.d(TAG, "record thread end");

                    LogHelper.d(TAG, "stop recognition start");
                    stopRecognition();
                    LogHelper.d(TAG, "stop recognition end");
                }
            };
            if (null != mRecordThread) {
                mRecordThread.start();
            }

            mState = STATE_START;
        }
    }

    private void stopRecognition() {
        mRecognition.stop();

        // put end buffer
        BufferData data = new BufferData(0);
        mBuffer.putFull(data);

        if (null != mRecognitionThread) {
            try {
                mRecognitionThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                mRecognitionThread = null;
            }
        }

        mBuffer.reset();
    }

    public void stop() {
        if (STATE_START == mState) {
            mState = STATE_PENDING;

            LogHelper.d(TAG, "force stop start");
            mRecord.stop();
            if (null != mRecordThread) {
                try {
                    mRecordThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    mRecordThread = null;
                }
            }

            mState = STATE_STOP;
            LogHelper.d(TAG, "force stop end");
        }
    }

    @Override
    public void onStartRecord() {
        LogHelper.d(TAG, "start record");
    }

    @Override
    public void onStopRecord() {
        LogHelper.d(TAG, "stop record");
    }

    @Override
    public BufferData getRecordBuffer() {
        BufferData buffer = mBuffer.getEmpty();
        if (null == buffer) {
            LogHelper.d(TAG, "get null empty buffer");
        }
        return buffer;
    }

    @Override
    public void freeRecordBuffer(BufferData buffer) {
        if (null != buffer) {
            if (!mBuffer.putFull(buffer)) {
                LogHelper.d(TAG, "put full buffer failed");
            }
        }
    }

    @Override
    public BufferData getRecognitionBuffer() {
        BufferData buffer = mBuffer.getFull();
        if (null == buffer) {
            LogHelper.d(TAG, "get null full buffer");
        }
        return buffer;
    }

    @Override
    public void freeRecognitionBuffer(BufferData buffer) {
        if (null != buffer) {
            if (!mBuffer.putEmpty(buffer)) {
                LogHelper.d(TAG, "put empty buffer failed");
            }
        }
    }

    @Override
    public void onStartRecognition() {
        LogHelper.d(TAG, "start recognition");
    }

    @Override
    public void onRecognition(int index) {
        LogHelper.d(TAG, "zzzzzzzzzzzzzrecognition:" + index);
        if (null != mListener) {
            if (Common.START_TOKEN == index) {
                mListener.onRecognitionStart();
            } else if (Common.STOP_TOKEN == index) {
                mListener.onRecognitionEnd();
            } else if (index > 0 && index <= mMaxCodeIndex) {
                mListener.onRecognition(mCodeBook.charAt(index - 1));
            }
        }
    }

    @Override
    public void onStopRecognition() {
        LogHelper.d(TAG, "stop recognition");
    }

}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章