版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
直接給上個簡略的使用手機錄音解說代碼:packagecn。com.chenzheng_java.media;importjava.io.IOException;importandroid。app。Activity;importandroid.media.MediaRecorder;importandroid。os。Bundle;publicclassMediaRecordActivityextendsActivity{MediaRecordermediaRecorder;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreat(yī)e(savedInstanceState);setContentView(R.layout。main);mediaRecorder=newMediaRecorder();record();}/***開頭錄制*/privat(yī)evoidrecord(){/***mediaRecorder.setAudioSource設(shè)置聲音來源。*MediaRecorder.AudioSource這個內(nèi)部類簡略的介紹了聲音來源.*該類中有很多音頻來源,不過最主要使用的還是手機上的麥克風(fēng),MediaRecorder.AudioSource。MIC*/mediaRecorder.setAudioSource(MediaRecorder。AudioSource.MIC);/***mediaRecorder.setOutputFormat(yī)代表輸出文件的格式。該語句必須在setAudioSource之后,在prepare之前。*OutputFormat(yī)內(nèi)部類,定義了音頻輸出的格式,主要包含MPEG_4、THREE_GPP、RAW_AMR……等.*/mediaRecorder。setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);/***mediaRecorder.setAddioEncoder()方法可以設(shè)置音頻的編碼*AudioEncoder內(nèi)部類簡略定義了兩種編碼:AudioEncoder.DEFAULT、AudioEncoder.AMR_NB*/mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);/***設(shè)置錄音之后,保存音頻文件的位置*/mediaRecorder.setOutputFile("file:///sdcard/myvido/a.3pg");/***調(diào)用start開頭錄音之前,肯定要調(diào)用prepare方法。*/try{mediaRecorder.prepare();mediaRecorder.start();}catch(IllegalStat(yī)eExceptione){e。printStackTrace();}catch(IOExceptione){e.printStackTrace();}}/****此外,還有和MediaRecorder有關(guān)的幾個參數(shù)與方法,我們一起來看一下:*sampleRateInHz:音頻的采樣頻率,每秒鐘能夠采樣的次數(shù),采樣率越高,音質(zhì)越高。*給出的實例是44100、22050、11025但不限于這幾個參數(shù).例如要采集低質(zhì)量的音頻就可以使用4000、8000等低采樣率**channelConfig:聲道設(shè)置:android支持雙聲道立體聲和單聲道。MONO單聲道,STEREO立體聲**recorder.stop();停止錄音*recorder.reset();重置錄音,會重置到setAudioSource這一步*recorder.release();解除對錄音資源的占用*/}???android中AudioRecord采集音頻的參數(shù)說明在android中采集音頻的api是android.media.AudioRecord類其中構(gòu)造器的幾個參數(shù)就是標(biāo)準(zhǔn)的聲音采集參數(shù)以下是參數(shù)的含義解釋publicAudioRecord(intaudioSource,intsampleRateInHz,intchannelConfig,intaudioFormat(yī),intbufferSizeInBytes)Since:APILevel3Classconstructor.ParametersaudioSourcetherecordingsource.SeeMediaRecorder.AudioSourceforrecordingsourcedefinitions。音頻源:指的是從哪里采集音頻。這里我們當(dāng)然是從麥克風(fēng)采集音頻,所以此參數(shù)的值為MICsampleRateInHzthesamplerateexpressedinHertz。Examplesofratesare(butnotlimitedto)44100,22050and11025。采樣率:音頻的采樣頻率,每秒鐘能夠采樣的次數(shù),采樣率越高,音質(zhì)越高。給出的實例是44100、22050、11025但不限于這幾個參數(shù)。例如要采集低質(zhì)量的音頻就可以使用4000、8000等低采樣率。channelConfigdescribestheconfigurationoftheaudiochannels。SeeCHANNEL_IN_M(jìn)ONOandCHANNEL_IN_STEREO聲道設(shè)置:android支持雙聲道立體聲和單聲道.MONO單聲道,STEREO立體聲audioFormattheformat(yī)inwhichtheaudiodataisrepresented。SeeENCODING_PCM_16BITandENCODING_PCM_8BIT編碼制式和采樣大小:采集來的數(shù)據(jù)當(dāng)然使用PCM編碼(脈沖代碼調(diào)制編碼,即PCM編碼。PCM通過抽樣、量化、編碼三個步驟將連續(xù)變化的模擬信號轉(zhuǎn)換為數(shù)字編碼。)android支持的采樣大小16bit或者8bit。當(dāng)然采樣大小越大,那么信息量越多,音質(zhì)也越高,現(xiàn)在主流的采樣大小都是16bit,在低質(zhì)量的語音傳輸?shù)臅r候8bit足夠了.bufferSizeInBytesthetotalsize(inbytes)ofthebufferwhereaudiodataiswrittentoduringtherecording。Newaudiodatacanbereadfromthisbufferinsmallerchunksthanthissize.SeegetMinBufferSize(int,int,int)todeterminetheminimumrequiredbuffersizeforthesuccessfulcreationofanAudioRecordinstance.UsingvaluessmallerthangetMinBufferSize()willresultinaninitializationfailure.采集數(shù)據(jù)需要的緩沖區(qū)的大小,如果不知道最小需要的大小可以在getMinBufferSize()查看.采集到的數(shù)據(jù)保存在一個byteBuffer中,可以使用流將其讀出.亦可保存成為文件的形式HYPERLINK”http://blog.csdn.net/peijiangping1989/article/details/7042610"Android使用AudioRecord錄音相關(guān)和音頻文件的封裝分類:HYPERLINK"http://blog.csdn.net/peijiangping1989/article/category/939391"Android流媒體學(xué)習(xí)在Android中錄音可以用MediaRecord錄音,操作比較簡潔.但是不夠?qū)I(yè),就是不能對音頻進(jìn)行處理。如果要進(jìn)行音頻的實時的處理或者音頻的一些封裝就可以用AudioRecord來進(jìn)行錄音了.這里給出一段代碼.實現(xiàn)了AudioRecord的錄音和WAV格式音頻的封裝。用AudioTrack和AudioTrack類可以進(jìn)行邊錄邊播,可以參考:HYPERLINK"http://blog.sina./s/blog_6309e1ed0100j1rw。html"http://blog.sina.com.cn/s/blog_6309e1ed0100j1rw.html我們這里的代碼沒有播放。但是有封裝和詳解,如下:[java]HYPERLINK”http://blog。csdn.net/peijiangping1989/article/details/7042610#"viewplainHYPERLINK"http://blog.csdn.net/peijiangping1989/article/details/7042610#"copypackagecom。ppmeet;importjava.io.File;importjava。io.FileInputStream;importjava.io。FileNotFoundException;importjava.io.FileOutputStream;importjava。io.IOException;importandroid.a(chǎn)pp。Activity;importandroid。graphics.PixelFormat(yī);importandroid.media。AudioFormat;importandroid.media。AudioRecord;importandroid.media。MediaRecorder;importandroid。os.Bundle;importandroid.view.View;importandroid。view.View.OnClickListener;importandroid.view.Window;importandroid.view。WindowManager;importandroid.widget.Button;/***classname:TestAudioRecord<BR〉*classdescription:用AudioRecord來進(jìn)行錄音<BR>*PS:<BR〉**@version1.002011/09/21*@authorCODYY)peijiangping*/publicclassTestAudioRecordextendsActivity{//音頻獵取源privateintaudioSource=MediaRecorder.AudioSource.MIC;//設(shè)置音頻采樣率,44100是目前的標(biāo)準(zhǔn),但是某些設(shè)備仍然支持22050,16000,11025privat(yī)estaticintsampleRateInHz=44100;//設(shè)置音頻的錄制的聲道CHANNEL_IN_STEREO為雙聲道,CHANNEL_CONFIGURATION_MONO為單聲道privatestat(yī)icintchannelConfig=AudioFormat.CHANNEL_IN_STEREO;//音頻數(shù)據(jù)格式:PCM16位每個樣本。保證設(shè)備支持。PCM8位每個樣本。不愿定能得到設(shè)備支持。privat(yī)estaticintaudioFormat=AudioFormat.ENCODING_PCM_16BIT;//緩沖區(qū)字節(jié)大小privateintbufferSizeInBytes=0;privat(yī)eButtonStart;privat(yī)eButtonStop;privateAudioRecordaudioRecord;privatebooleanisRecord=false;//設(shè)置正在錄制的狀態(tài)//AudioName裸音頻數(shù)據(jù)文件privatestaticfinalStringAudioName="/sdcard/love.raw";//NewAudioName可播放的音頻文件privatestaticfinalStringNewAudioName="/sdcard/new。wav";publicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);getWindow().setFormat(PixelFormat.TRANSLUCENT);//讓界面橫屏requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉界面標(biāo)題getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams。FLAG_FULLSCREEN);//重新設(shè)置界面大小setContentView(R.layout。main);init();}privatevoidinit(){Start=(Button)this.findViewById(R.id.start);Stop=(Button)this.findViewById(R。id。stop);Start。setOnClickListener(newTestAudioListener());Stop.setOnClickListener(newTestAudioListener());creat(yī)AudioRecord();}privat(yī)evoidcreat(yī)AudioRecord(){//獲得緩沖區(qū)字節(jié)大小bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRat(yī)eInHz,channelConfig,audioFormat);//創(chuàng)建AudioRecord對象audioRecord=newAudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormat,bufferSizeInBytes);}classTestAudioListenerimplementsOnClickListener{@OverridepublicvoidonClick(Viewv){if(v==Start){startRecord();}if(v==Stop){stopRecord();}}}privatevoidstartRecord(){audioRecord.startRecording();//讓錄制狀態(tài)為trueisRecord=true;//開啟音頻文件寫入線程newThread(newAudioRecordThread())。start();}privatevoidstopRecord(){close();}privatevoidclose(){if(audioRecord!=null){System。out.println("stopRecord");isRecord=false;//停止文件寫入audioRecord.stop();audioRecord。release();//釋放資源audioRecord=null;}}classAudioRecordThreadimplementsRunnable{@Overridepublicvoidrun(){writeDateTOFile();//往文件中寫入裸數(shù)據(jù)copyWaveFile(AudioName,NewAudioName);//給裸數(shù)據(jù)加上頭文件}}/***這里將數(shù)據(jù)寫入文件,但是并不能播放,由于AudioRecord獲得的音頻是原始的裸音頻,*如果需要播放就必須加入一些格式或者編碼的頭信息。但是這樣的好處就是你可以對音頻的裸數(shù)據(jù)進(jìn)行處理,比如你要做一個愛說話的TOM*貓在這里就進(jìn)行音頻的處理,然后重新封裝所以說這樣得到的音頻比較容易做一些音頻的處理.*/privatevoidwriteDat(yī)eTOFile(){//new一個byte數(shù)組用來存一些字節(jié)數(shù)據(jù),大小為緩沖區(qū)大?。鈟te[]audiodata=newbyte[bufferSizeInBytes];FileOutputStreamfos=null;intreadsize=0;try{Filefile=newFile(AudioName);if(file。exists()){file.delete();}fos=newFileOutputStream(file);//建立一個可存取字節(jié)的文件}catch(Exceptione){e.printStackTrace();}while(isRecord==true){readsize=audioRecord.read(audiodata,0,bufferSizeInBytes);if(AudioRecord.ERROR_INVALID_OPERATION!=readsize){try{fos。write(audiodata);}catch(IOExceptione){e。printStackTrace();}}}try{fos。close();//關(guān)閉寫入流}catch(IOExceptione){e.printStackTrace();}}//這里得到可播放的音頻文件privatevoidcopyWaveFile(StringinFilename,StringoutFilename){FileInputStreamin=null;FileOutputStreamout=null;longtotalAudioLen=0;longtotalDataLen=totalAudioLen+36;longlongSampleRate=sampleRateInHz;intchannels=2;longbyteRate=16*sampleRateInHz*channels/8;byte[]data=newbyte[bufferSizeInBytes];try{in=newFileInputStream(inFilename);out=newFileOutputStream(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();}cat(yī)ch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}/***這里供應(yīng)一個頭信息。插入這些信息就可以得到可以播放的文件。*為我為啥插入這44個字節(jié),這個還真沒深化商量,不過你隨便打開一個wav*音頻的文件,可以發(fā)現(xiàn)前面的頭文件可以說基本一樣哦。每種格式的文件都有*自己特有的頭文件。*/privatevoidWriteWaveFileHeader(FileOutputStreamout,longtotalAudioLen,longtotalDataLen,longlongSampleRate,intchannels,longbyteRate)throwsIOException{byte[]header=newbyte[44];header[0]='R’;//RIFF/WAVEheaderheader[1]=’I';header[2]=’F’;header[3]='F';header[4]=(byte)(totalDat(yī)aLen&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'chunkheader[13]='m’;header[14]='t’;header[15]='’;header[16]=16;//4bytes:sizeof'fmt’chunkheader[17]=0;header[18]=0;header[19]=0;header[20]=1;//format=1header[21]=0;header[22]=(byte)channels;header[23]=0;header[24]=(byte)(longSampleRate&0xff);header[25]=(byte)((longSampleRat(yī)e>>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);//blockalignheader[33]=0;header[34]=16;//bitspersampleheader[35]=0;header[36]=’d’;header[37]='a';header[38]=’t’;header[39]='a';header[40]=(byte)(totalAudioLen&0xff);header[41]=(byte)((totalAudioL(fēng)en>>8)&0xff);header[42]=(byte)((totalAudioLen>〉16)&0xff);header[43]=(byte)((totalAudioLen>>24)&0xff);out.write(header,0,44);}@OverrideprotectedvoidonDestroy(){close();super.onDestroy();}}+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Android入門(9)AudioRecord和AudioTrack類的使用(2010—05-0709:07:05AudioRecord和AudioTrack類是Android獵取和播放音頻流的重要類,放置在android.media包中。與該包中的MediaRecorder和MediaPlayer類不同,AudioRecord和AudioTrack類在獵取和播放音頻數(shù)據(jù)流時無需通過文件保存和文件讀取,可以動態(tài)地直接獵取和播放音頻流,在實時處理音頻數(shù)據(jù)流時格外有用。當(dāng)然,如果用戶只想錄音后寫入文件或從文件中取得音頻流進(jìn)行播放,那么直接使用MediaRecorder和MediaPlayer類是首選方案,由于這兩個類使用格外便利,而且成功率很高。而AudioRecord和AudioTrack類的使用卻比較簡潔,我們發(fā)現(xiàn)很多人都不能成功地使用這兩個類,甚至認(rèn)為Android的這兩個類是不能工作的。其實,AudioRecord和AudioTrack類的使用雖然比較簡潔,但是可以工作,我們不僅可以很好地使用了這兩個類,而且還通過套接字(Socket)實現(xiàn)了音頻數(shù)據(jù)的網(wǎng)絡(luò)傳輸,做到了一端使用AudioRecord獵取音頻流然后通過套接字傳輸出去,而另一端通過套接字接收后使用AudioTrack類播放。下面是我們對AudioRecord和AudioTrack類在使用方面的閱歷總結(jié):(1)創(chuàng)建AudioRecord和AudioTrack類對象:創(chuàng)建這兩個類的對象比較簡潔,通過對文檔的反復(fù)和仔細(xì)理解,并通過多次失敗的嘗試,并在北理工的某個Android大牛的網(wǎng)上的文章啟發(fā)下,我們也最終成功地創(chuàng)建了這兩個類的對象.創(chuàng)建AudioRecord和AudioTrack類對象的代碼如下:AudioRecord類:m_in_buf_size=AudioRecord.getMinBufferSize(8000,
AudioFormat。CHANNEL_CONFIGURATION_M(jìn)ONO,?AudioFormat.ENCODING_PCM_16BIT);
m_in_rec=newAudioRecord(MediaRecorder。AudioSource。MIC,?8000,?AudioFormat.CHANNEL_CONFIGURATION_MONO,?AudioFormat.ENCODING_PCM_16BIT,
m_in_buf_size);AudioTrack類:m_out_buf_size=android。media。AudioTrack.getMinBufferSize(8000,?AudioFormat(yī)。CHANNEL_CONFIGURATION_MONO,?AudioFormat。ENCODING_PCM_16BIT);m_out_trk=newAudioTrack(AudioManager.STREAM_MUSIC,8000,?AudioFormat(yī).CHANNEL_CONFIGURATION_MONO,?AudioFormat.ENCODING_PCM_16BIT,?m_out_buf_size,?AudioTrack.MODE_STREAM);(2)關(guān)于AudioRecord和AudioTrack類的監(jiān)聽函數(shù),不用也行。(3)調(diào)試方面,包括初始化后看logcat信息,以確定類的工作狀態(tài),初始化是否成功等。編寫好代碼,沒有語法錯誤,調(diào)用模擬器運行、調(diào)試代碼時,logcat發(fā)揮了很好的功用.剛調(diào)試時,常常會消滅模擬器顯示消滅格外,這時我們可以在代碼的一些關(guān)鍵語句后添加如Log。d("test1","OK");這樣的語句進(jìn)行標(biāo)識,消滅格外時我們就可以在logcat窗口觀察代碼執(zhí)行到哪里消滅格外,然后進(jìn)行相應(yīng)的修改、調(diào)試.模擬器不會消滅格外時,又遇到了錄放音的問題。錄音方面,剛開頭選擇將語音編碼數(shù)據(jù)存放在多個固定大小的文件中進(jìn)行傳送,但是這種情況下會消滅聲音斷續(xù)的現(xiàn)象,而且要反復(fù)的建立文件,比較麻煩,后來想到要進(jìn)行網(wǎng)上傳輸,直接將語音編碼數(shù)據(jù)以數(shù)據(jù)流的形式傳送,經(jīng)過驗證,這種方法可行并且使代碼更加簡潔.放音方面,將接收到的數(shù)據(jù)流存放在一個數(shù)組中,然后將數(shù)組中數(shù)據(jù)寫到AudioTrack中。剛開頭只是“嘟”幾聲,經(jīng)過檢查發(fā)現(xiàn)只是把數(shù)據(jù)寫一次,加入循環(huán),讓數(shù)據(jù)反復(fù)寫到AudioTrack中,就可以聽到正常的語音了。接下來的工作主要是改善話音質(zhì)量與話音延遲,在進(jìn)行通話的過程中,觀察logcat(yī)窗口,發(fā)現(xiàn)向數(shù)組中寫數(shù)據(jù)時會消滅Bufferflow的情況,于是把重心轉(zhuǎn)移到數(shù)組大小的影響上,經(jīng)過試驗,發(fā)現(xiàn)AudioRecord一次會讀640個數(shù)據(jù),然后就對錄音和放音中有數(shù)組的地方進(jìn)行實驗修改。AudioRecord和AudioTrack進(jìn)行實例化時,參數(shù)中各有一個數(shù)組大小,經(jīng)過試驗這個數(shù)組大小和AudioRecord和AudioTrack能正常實例化所需的最小Buffer大小(即上面實例化時的m_in_buf_size和m_out_buf_size參數(shù))相等且服務(wù)器方進(jìn)行緩存數(shù)據(jù)的數(shù)組尺寸是上述數(shù)值的2倍時,語音質(zhì)量最好.由于錄音和放音的速度不全都,受到北理工大牛的啟發(fā),在錄音方面,將存放錄音數(shù)據(jù)的數(shù)組放到LinkedList中,當(dāng)LinkedList中數(shù)組個數(shù)達(dá)到2(這個也是經(jīng)過試驗驗證話音質(zhì)量最好時的數(shù)據(jù))時,將先錄好的數(shù)組中數(shù)據(jù)傳送出去。經(jīng)過上述反復(fù)試驗和修改,最終使雙方通話質(zhì)量較好,且延時較短(也許有2秒鐘)。(4)通過套接字傳輸和接收數(shù)據(jù)數(shù)據(jù)傳送部分,使用的是套接字.通信雙方,通過不同的端口向服務(wù)器發(fā)送懇求,與服務(wù)器連接上后,開頭通話向服務(wù)器發(fā)送數(shù)據(jù),服務(wù)器通過一個套接字接收到一方的數(shù)據(jù)后,先存在一個數(shù)組中,然后將該數(shù)組中數(shù)據(jù)以數(shù)據(jù)流的形式再通過另一個套接字傳送到另一方。這樣就實現(xiàn)了雙方數(shù)據(jù)的傳送。(5)代碼架構(gòu)為避開反復(fù)錄入和讀取數(shù)據(jù)占用較多資源,使程序在進(jìn)行錄放音時不能執(zhí)行其他命令,故將錄音和放音各寫成一個線程類,然后在主程序中,通過MENU掌握通話的開頭、停止、結(jié)束。最后說明,AudioRecord和AudioTrack類可以用,只是略微簡潔些。以下貼出雙方通信的源碼,盼望對大家有所幫助:主程序Daudioclient:packagecn.Daudioclient;importandroid.app.Activity;?importandroid.os.Bundle;
importandroid.view.Menu;?importandroid.view.MenuItem;publicclassDaudioclientextendsActivity{
?publicstaticfinalintMENU_START_ID=Menu.FIRST;?publicstaticfinalintMENU_STOP_ID=Menu。FIRST+1;?publicstat(yī)icfinalintMENU_EXIT_ID=Menu.FIRST+2;??protectedSaudioserverm_player;
protectedSaudioclientm_recorder;???@Override
publicvoidonCreate(BundlesavedInstanceState){?super.onCreate(savedInstanceState);?setContentView(R。layout.main);?}?
publicbooleanonCreateOptionsMenu(MenuaMenu)?{
booleanres=super.onCreat(yī)eOptionsMenu(aMenu);aMenu.a(chǎn)dd(0,MENU_START_ID,0,"START");?aMenu。add(0,MENU_STOP_ID,0,"STO(shè)P");
aMenu。add(0,MENU_EXIT_ID,0,”EXIT");returnres;?}?publicbooleanonOptionsItemSelected(MenuItemaMenuItem)?{?switch(aMenuItem.getItemId()){
caseMENU_START_ID:
{?m_player=newSaudioserver();?m_recorder=newSaudioclient();m_player。init();?m_recorder.init();m_recorder.start();?m_player.start();
?}?break;?caseMENU_STOP_ID:?{
m_recorder.free();?m_player.free();m_player=null;?m_recorder=null;?}?break;?caseMENU_EXIT_ID:?{
intpid=android.os。Process.myPid();?android.os.Process。killProcess(pid);?}?break;
default:?break;?}returnsuper.onOptionsItemSelected(aMenuItem);?}?}錄音程序Saudioclient:packa。Daudioclient;importjava.io.DataOutputStream;?importjava.io.IOException;?importjava.net。Socket;?importjava。net.UnknownHostException;?importjava。util.LinkedList;importandroid.media。AudioFormat;?importandroid.media.AudioRecord;?importandroid.media。MediaRecorder;?importandroid。util.Log;publicclassSaudioclientextendsThread?{?
protectedAudioRecordm_in_rec;?protectedintm_in_buf_size;?protectedbyte[]m_in_bytes;?protectedbooleanm_keep_running;?protectedSockets;?protectedDataOutputStreamdout;
protectedLinkedList<byte[]〉m_in_q;
?publicvoidrun()?{?try?{?byte[]bytes_pkg;?m_in_rec.startRecording();?while(m_keep_running)?{?m_in_rec.read(m_in_bytes,0,m_in_buf_size);?bytes_pkg=m_in_bytes。clone();?if(m_in_q.size()〉=2)?{?dout.write(m_in_q.removeFirst(),0,m_in_q.removeFirst().length);
}
m_in_q.add(bytes_pkg);?}?
m_in_rec。stop();?m_in_rec=null;?m_in_bytes=null;
dout.close();??}?cat(yī)ch(Exceptione)?{
e.printStackTrace();?}?}??publicvoidinit()
{?m_in_buf_size=AudioRecord.getMinBufferSize(8000,?AudioFormat(yī).CHANNEL_CONFIGURATION_MONO,
AudioFormat(yī).ENCODING_PCM_16BIT);
?m_in_rec=newAudioRecord(MediaRecorder.AudioSource.MIC,?8000,?AudioFormat(yī)。CHANNEL_CONFIGURATION_MONO,?AudioFormat。ENCODING_PCM_16BIT,
m_in_buf_size);??m_in_bytes=newbyte[m_in_buf_size];??m_keep_running=true;
m_in_q=newLinkedList〈byte[]〉();??try
{?s=newSocket("192。168.1.100",4332);?dout=newDataOutputStream(s.getOutputStream());?//newThread(R1)。start();?}?catch(UnknownHostExceptione)?{
//TODOAuto-generatedcatchblock
e.printStackTrace();?}?cat(yī)ch(IOExceptione)?{
//TODOAuto—generatedcatchblock?e.printStackTrace();
}}??publicvoidfree()?{?m_keep_running=false;?try{?Thread.sleep(1000);?}catch(Exceptione){?Log.d("sleepexceptions。。.\n",””);?}?}?}
放音程序Saudioserver:packagecn。Daudioclient;importjava.io.DataInputStream;?importjava.io.IOException;?importjava.net.Socket;importandroid.media。AudioFormat;?importandroid。media.AudioManager;?importandroid。media.AudioTrack;?importandroid.util.Log;publicclassSaudioserverextendsThread?{?protectedAudioTrackm_out_trk;?protectedintm_out_buf_size;
protectedbyte[]m_out_bytes;
protectedbooleanm_keep_running;?privateSockets;?privat(yī)eDataInputStreamdin;?publicvoidinit()?{?try?{
s=newSocket("192。168.1。100”,4331);
din=newDat(yī)aInputStream(s。getInputStream());?
m_keep_running=true;?
m_out_buf_size=AudioTrack.getMinBufferSize(8000,
AudioFormat(yī).CHANNEL_CONFIGURATION_MONO,?AudioFormat。ENCODING_PCM_16BIT);m_out_trk=newAudioTrack(AudioManager.STREAM_MUSIC,8000,?AudioFormat(yī).CHANNEL_CONFIGURATION_M(jìn)ONO,?AudioFormat.ENCODING_PCM_16BIT,
m_out_buf_size,?AudioTrack.MODE_STREAM);?
m_out_bytes=newbyte[m_out_buf_size];??//newThread(R1).start();
?}?catch(Exceptione)
{?e.printStackTrace();?}?}??publicvoidfree()?{
m_keep_running=false;?try{
Thread.sleep(1000);?}catch(Exceptione){?Log.d("sleepexceptions...\n”,”");
}
}?
publicvoidrun()?{?byte[]bytes_pkg=null;?m_out_trk。play();?while(m_keep_running){?try
{?din。read(m_out_bytes);
bytes_pkg=m_out_bytes.clone();?m_out_trk.write(bytes_pkg,0,bytes_pkg。length);?}
catch(Exceptione)
{?e。printStackTrace();?}??}?
m_out_trk.stop();
m_out_trk=null;?try{?din。close();?}cat(yī)ch(IOExceptione){?//TODOAuto—generatedcatchblock?e。printStackTrace();?}?}?}??+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++HYPERLINK”http://hi.baid/??С??1984519/blog/item/7cba4c39b1a753dfd46225ce.html"AndroidAudioRecord實現(xiàn)音頻錄制??//由于程序可能用到對手機SD卡的讀取,所以在manifest。xml里需要配置對sd卡存取的權(quán)限:?//〈uses-permissionandroid:name="android。permission.WRITE_EXTERNAL_STORAGE"/>?//<uses-permissionandroid:name="android.permission。MOUNT_UNMOUNT_FILESYSTEMS"/>?importjava.io.BufferedInputStream;?importjava.io。BufferedOutputStream;?importjava.io。DataInputStream;?importjava。io。DataOutputStream;?importjava。io.File;?importjava。io.FileInputStream;?importjava。io。FileOutputStream;?importjava.io.IOException;??importandroid.app。Activity;?importandroid.content.Context;?importandroid。media。AudioFormat;
importandroid.media.AudioManager;?importandroid.media.AudioRecord;
importandroid。media.AudioTrack;?importandroid.media.MediaRecorder;?importandroid.os。AsyncTask;?importandroid。os。Bundle;?importandroid.os。Environment;?importandroid。util.Log;
importandroid。view.View;?importandroid.view。View.OnClickListener;?importandroid.widget.Button;?importandroid.widget.TextView;??importcom.telenav.funnl。android。R;?/**
*該實例中,我們使用AudioRecord類來完成我們的音頻錄制程序?*AudioRecord類,我們可以使用三種不同的read方法來完成錄制工作,?*每種方法都有其有用的場合?*一、實例化一個AudioRecord類我們需要傳入幾種參數(shù)?*1、AudioSource:這里可以是MediaRecorder.AudioSource。MIC?*2、SampleRateInHz:錄制頻率,可以為8000hz或者11025hz等,不同的硬件設(shè)備這個值不同?*3、ChannelConfig:錄制通道,可以為udioFormat.CHANNEL_CONFIGURATION_M(jìn)ONO和udioFormat.CHANNEL_CONFIGURATION_STEREO
*4、AudioFormat:錄制編碼格式,可以為AudioFormat(yī).ENCODING_16BIT和BIT,其中16BIT的仿真性比8BIT好,但是需要消耗更多的電量和存儲空間?*5、BufferSize:錄制緩沖大?。嚎梢酝ㄟ^getMinBufferSize來獵取?*這樣我們就可以實例化一個AudioRecord對象了?*二、創(chuàng)建一個文件,用于保存錄制的內(nèi)容
*同上篇?*三、打開一個輸出流,指向創(chuàng)建的文件
*DataOutputStreamdos=newDataOutputStream(newBufferedOutputSream(newFileOutputStream(file)))?*四、現(xiàn)在就可以開頭錄制了,我們需要創(chuàng)建一個字節(jié)數(shù)組來存儲從udioRecorder中返回的音頻數(shù)據(jù),但是?*注意,我們定義的數(shù)組要小于定義AudioRecord時指定的那個ufferSize
*short[]buffer=newshort[BufferSize/4];?*startRecording();
*然后一個循環(huán),調(diào)用AudioRecord的read方法實現(xiàn)讀取?*另外使用MediaPlayer是無法播放使用AudioRecord錄制的音頻的,為了實現(xiàn)播放,我們需要
*使用AudioTrack類來實現(xiàn)?*AudioTrack類允許我們播放原始的音頻數(shù)據(jù)?*?*?*一、實例化一個AudioTrack同樣要傳入幾個參數(shù)
*1、StreamType:在AudioManager中有幾個常量,其中一個是TREAM_MUSIC;?*2、SampleRat(yī)eInHz:最好和AudioRecord使用的是同一個值?*3、ChannelConfig:同上?*4、AudioFormat:同上
*5、BufferSize:通過AudioTrack的靜態(tài)方法getMinBufferSize來獵取?*6、Mode:可以是AudioTrack.MODE_STREAM和MODE_STATIC,關(guān)于這兩種不同之處,可以查閱文檔?*二、打開一個輸入流,指向剛剛錄制內(nèi)容保存的文件,然后開頭播放,邊讀取邊播放?*?*實現(xiàn)時,音頻的錄制和播放分別使用兩個AsyncTask來完成?*/?publicclassPCMRecordActivityextendsActivityimplementsOnClickListener{??privat(yī)eTextViewstateView;??privateButtonbtnStart,btnStop,btnPlay,btnFinish;??privateRecordTaskrecorder;?privatePl(wèi)ayTaskplayer;?privat(yī)eFilefpath;?privateFileaudioFile;
privateContextcontext;??privatebooleanisRecording=true,isPlaying=false;//標(biāo)記??frequence=16000;//8000;//錄制頻率,單位hz.這里的值注意了,寫的不好,可能實例化AudioRecord對象的時候,會出錯。我開頭寫成11025就不行.這取決于硬件設(shè)備?privat(yī)eintchannelConfig=AudioFormat.CHANNEL_CONFIGURATION_MONO;
privateintaudioEncoding=AudioFormat。ENCODING_PCM_16BIT;
publicvoidonCreate(BundlesavedInstanceStat(yī)e){?super.onCreate(savedInstanceStat(yī)e);?setContentView(R。layout.my_audio_record);??stat(yī)eView=(TextView)this。findViewById(R.id。view_state);?stateView。setText("startrecording。.”);?btnStart=(Button)this。findViewById(R.id。btn_start);?btnStart。setText("start”);?btnStart。setOnClickListener(this);?btnStop=(Button)this.findViewById(R。id.btn_stop);
btnStop.setText(”stop");?btnStop.setOnClickListener(this);?btnPl(wèi)ay=(Button)this。findViewById(R。id.btn_play);?btnPlay。setText("play”);?btnPlay。setOnClickListener(this);?btnFinish=(Button)this.findViewById(R.id。btn_finish);?btnFinish。setText("finish");?btnFinish.setOnClickListener(this);?btnStop。setEnabled(false);?btnPlay.setEnabled(false);?btnFinish.setEnabled(false);
?if(Environment.getExternalStorageState().equals(Environment。MEDIA_MOUNTED))//手機有SD卡的情況?{?//在這里我們創(chuàng)建一個文件,用于保存錄制內(nèi)容?fpath=newFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/data/files/”);?fpath.mkdirs();//創(chuàng)建文件夾
}else//手機無SD卡的情況?{?fpat(yī)h=this。getCacheDir();?}??try{?//創(chuàng)建臨時文件,注意這里的格式為.pcm?audioFile=File.creat(yī)eTempFile("recording","。pcm",fpath);?}catch(IOExceptione){?//TODOAuto-generatedcatchblock?e。printStackTrace();?}?}?
publicvoidonClick(Viewv){?intid=v。getId();
switch(id){?caseR.id.btn_start:?//開頭錄制?
//這里啟動錄制任務(wù)?recorder=newRecordTask();?recorder。execute();??break;?caseR.id.btn_stop:
//停止錄制
this.isRecording=false;?//更新狀態(tài)
//在錄制完成時設(shè)置,在RecordTask的onPostExecute中完成?break;?caseR。id。btn_pla
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版學(xué)校球場施工合同模板(含場地通風(fēng)與散熱)2篇
- 二零二五年度婚禮現(xiàn)場舞臺搭建與燈光音響租賃合同6篇
- 個性化家庭收養(yǎng)協(xié)議2024版版
- 二零二五年度履約保證金協(xié)議書范本:文化旅游項目2篇
- 醫(yī)療器械2025年度原材料供應(yīng)與加工合作協(xié)議3篇
- 2025年度智慧農(nóng)業(yè)灌溉增壓泵供應(yīng)與安裝服務(wù)合同3篇
- 二零二五年度城市更新項目存量房買賣合作框架協(xié)議2篇
- 二零二五版煤礦股權(quán)轉(zhuǎn)讓及礦山安全生產(chǎn)責(zé)任書4篇
- 2025版園藝用樹苗買賣合同規(guī)范范本3篇
- 二零二五年度市場分析預(yù)測專家顧問聘請書3篇
- 2024年供應(yīng)鏈安全培訓(xùn):深入剖析與應(yīng)用
- 飛鼠養(yǎng)殖技術(shù)指導(dǎo)
- 壞死性筋膜炎
- 整式的加減單元測試題6套
- 股權(quán)架構(gòu)完整
- 山東省泰安市2022年初中學(xué)業(yè)水平考試生物試題
- 注塑部質(zhì)量控制標(biāo)準(zhǔn)全套
- 人教A版高中數(shù)學(xué)選擇性必修第一冊第二章直線和圓的方程-經(jīng)典例題及配套練習(xí)題含答案解析
- 銀行網(wǎng)點服務(wù)禮儀標(biāo)準(zhǔn)培訓(xùn)課件
- 二年級下冊數(shù)學(xué)教案 -《數(shù)一數(shù)(二)》 北師大版
- 晶體三極管資料
評論
0/150
提交評論