分類:
因?yàn)樯弦黄┛痛a有點(diǎn)太多,就單開(kāi)了,這兩天主要在看Android語(yǔ)音錄制和壓縮轉(zhuǎn)碼相關(guān)知識(shí),前端時(shí)間看見(jiàn)騰訊官方微博宣布,已經(jīng)開(kāi)放出即使聊天軟件正在等待審批,但這個(gè)直接影響電話運(yùn)營(yíng)商,能通過(guò)的可能性應(yīng)該不大,但我對(duì)這方面的技術(shù)很有興趣,所以就試試看。其中涉及到很多聲音方面的處理問(wèn)題,在android中有兩個(gè)類可以錄制語(yǔ)音:AudioRecord和MediaRecorder,MediaRecorder主要是錄制音頻并寫(xiě)入文件,而AudioRecord主要是錄制音頻流,錄制的音頻流為pcm格式,關(guān)于pcm格式可以自行搜索一下,在傳輸過(guò)程中可以轉(zhuǎn)換為amr格式,但沒(méi)有相關(guān)可以類庫(kù)有點(diǎn)麻煩,另外iphone不支持播放amr格式音頻,如果需要跨兩個(gè)平臺(tái)可以使用AAC,壓縮比也不錯(cuò),音質(zhì)也很好,我還沒(méi)有測(cè)試過(guò),網(wǎng)上評(píng)議而已。編碼方面大家都推薦speex,我看了一下,需要是用System.loadLibrary加載進(jìn)speex提供的類庫(kù)。下面記錄一下寫(xiě)的一個(gè)邊錄制邊播放的一段代碼吧
- package voice.hcent.com;
-
- import java.io.IOException;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Looper;
- import android.os.Process;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
- import android.widget.Button;
- import android.widget.Toast;
-
- import android.media.AudioFormat;
- import android.media.AudioManager;
- import android.media.AudioRecord;
- import android.media.AudioTrack;
- import android.media.MediaRecorder;
-
- public class VoiceHcentActivity extends Activity {
-
- static {
- System.loadLibrary("media_jni");
- }
-
- public int frequency = 8000;
- private int rBufferSize, pBufferSize;
- private Button startSpeech;
- private AudioRecord recorder;
- private VoiceSpeech vspeech;
- private AudioTrack player;
- private boolean stopSpeech = false;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- init();
-
- test();
- }
-
- public void init(){
- try{
- startSpeech = (Button)findViewById(R.id.StartSpeech);
-
- //設(shè)置播放器緩沖區(qū)大小
- pBufferSize = AudioTrack.getMinBufferSize(frequency, AudioFormat.CHANNEL_CONFIGURATION_MONO,
- AudioFormat.ENCODING_PCM_16BIT);
-
- //獲取播放器對(duì)象
- player = new AudioTrack(AudioManager.STREAM_MUSIC, frequency,
- AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
- pBufferSize, AudioTrack.MODE_STREAM);
-
- //設(shè)置錄音緩沖區(qū)大小
- rBufferSize = AudioRecord.getMinBufferSize(frequency,
- AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
-
- //獲取錄音機(jī)對(duì)象
- recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
- frequency, AudioFormat.CHANNEL_CONFIGURATION_MONO,
- AudioFormat.ENCODING_PCM_16BIT, rBufferSize);
-
- }catch (Exception e) {
- String msg = "ERROR init: "+e.getStackTrace();
- VoiceHcentActivity.this.toastMsg(msg);
- }
- }
-
- /**
- * 開(kāi)始錄音
- */
- public void startRecord(){
- stopSpeech = false;
- vspeech = new VoiceSpeech();
- vspeech.start();
- }
-
- /**
- * 結(jié)束錄音
- */
- public void stopRecord() {
- stopSpeech = true;
- }
-
- /**
- * 開(kāi)始播放錄音
- */
- public void startPlay(){
-
- //設(shè)置播放器音量
- player.setStereoVolume(0.7f, 0.7f);
-
- player.play();
- }
-
- /**
- * 結(jié)束播放錄音
- */
- public void stopPlay(){
- player.stop();
- }
-
- public void test(){
-
- startSpeech.setOnTouchListener(new View.OnTouchListener() {
-
- public boolean onTouch(View arg0, MotionEvent arg1) {
-
- switch (arg1.getAction()) {
-
- case MotionEvent.ACTION_DOWN: //開(kāi)始說(shuō)話
- startPlay();
- startRecord();
-
- toastMsg("starting record!");
- break;
-
- case MotionEvent.ACTION_UP: //停止說(shuō)話
- Log.i("hcent", "111");
- stopPlay();
- Log.i("hcent", "222");
- stopRecord();
- toastMsg("stoped record!");
- break;
-
- default:
- break;
- }
-
- return false;
- }
- });
-
- }
-
- public class VoiceSpeech extends Thread{
-
- @Override
- public void run() {
- super.run();
- try {
- byte[] tempBuffer, readBuffer = new byte[rBufferSize];
- int bufResult = 0;
- recorder.startRecording();
- while(!stopSpeech){
- bufResult = recorder.read(readBuffer, 0, rBufferSize);
- if(bufResult>0 && bufResult%2==0){
- tempBuffer = new byte[bufResult];
- System.arraycopy(readBuffer, 0, tempBuffer, 0, rBufferSize);
- player.write(tempBuffer, 0, tempBuffer.length);
- }
- Log.d("hcent", "get read:"+bufResult+"___"+readBuffer.length);
- }
- recorder.stop();
- Looper.prepare();
- VoiceHcentActivity.this.toastMsg("AudioSpeech have ended!");
- Looper.loop();
- } catch (Exception e) {
- String msg = "ERROR AudioRecord: "+e.getStackTrace();
- Looper.prepare();
- VoiceHcentActivity.this.toastMsg(msg);
- Looper.loop();
- }
- }
- }
- @Override
- protected void onDestroy(){
- player.release();
- recorder.release();
- super.onDestroy();
- Process.killProcess(Process.myPid());
- }
- public void toastMsg(String msg){
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- Log.e("hcent", msg);
- }
- }
- 猜你在找
- 13樓 我想我還有夢(mèng) 2015-04-22 10:45發(fā)表 [回復(fù)]
 - 現(xiàn)在這個(gè)還有人關(guān)注嗎 ,少類庫(kù),跑步起來(lái)。
- 12樓 z0810 2014-07-14 09:53發(fā)表 [回復(fù)]
 - 最近也在研究這個(gè),求demo,QQ:1467581753 . 感謝。
- 11樓 shengfakun1234 2014-06-10 21:51發(fā)表 [回復(fù)]
 - media_jni這個(gè)類庫(kù)可以發(fā)一個(gè)嗎?1002168636@qq.com
- 10樓 util_c 2014-06-10 21:44發(fā)表 [回復(fù)]
 - 發(fā)個(gè)DEMO給我行嗎?605858069@qq.com
- 9樓 u011355656 2014-03-11 16:20發(fā)表 [回復(fù)]
 - 求“media_jni”內(nèi)庫(kù)感激不盡??!
- 8樓 cool_wuli 2014-02-27 21:45發(fā)表 [回復(fù)]
 - 同求demo576660144@qq.com
- 7樓 zyayy 2014-01-06 15:43發(fā)表 [回復(fù)]
 - 兄弟,android初學(xué)者 最近遇到音頻壓縮的問(wèn)題 能否發(fā)個(gè)demo學(xué)習(xí)下啊 450459217@qq.com
- 6樓 yuanxiaodon 2013-12-10 16:46發(fā)表 [回復(fù)]
 - 求Demo1269396188@qq.com
- 5樓 tangshengji 2013-11-18 15:17發(fā)表 [回復(fù)]
 - 朋友,把這個(gè)Demo發(fā)給我唄,謝謝了:
393019384@qq.com
- 4樓 parrzhang 2013-07-11 22:09發(fā)表 [回復(fù)]
 - System.loadLibrary("media_jni");
這個(gè)類庫(kù)是在哪里的
- 3樓 gene 2013-04-18 17:32發(fā)表 [回復(fù)]
 - 朋友你好,你給我一個(gè)demo嘛
genehang@163.com
- 2樓 devin_sz 2013-02-02 17:47發(fā)表 [回復(fù)]
 - 兄弟,遇到了聲音壓縮的問(wèn)題,能否發(fā)個(gè)demo給我
devin_sz@yeah.net
- 1樓 buaakuan 2012-03-19 20:55發(fā)表 [回復(fù)]
 - 你好,我是android初學(xué)者,24行的"media_jni"是什么呢,這個(gè)在本地有默認(rèn)的嗎?需要編寫(xiě)它的代碼嗎?
|