iApp錄音實(shí)現(xiàn)聲音反饋

demo簡(jiǎn)介

iApp要想實(shí)現(xiàn)邊錄邊聽(tīng)功能就不能使用iApp帶有的bly來(lái)進(jìn)行錄音甘凭。
既然iApp的代碼不能滿足我們裕偿,我們就使用Android SDK來(lái)滿足自己宪赶!
利用AndroidSDK提供的AudioRecord來(lái)進(jìn)行錄音采樣就能獲取音頻的裸流栈幸。
實(shí)現(xiàn)了錄音,我們還有一個(gè)播放音頻這時(shí)候難道要用iApp提供的bfm嗎嵌牺?
我們可以使用AndroidSDK提供的AudioTrack來(lái)播放錄下來(lái)的聲音打洼。
話就不多說(shuō)了下面就開(kāi)始敲代碼吧!喵~

mian載入事件code

//錄音緩存文件
ss audiotmpfile = "/sdcard/RecordAudioFile/audio_tmp.pcm"
//錄音保存文件
ss audiosavefile = "/sdcard/RecordAudioFile/audio.wav"
//音源 0.默認(rèn) 1.是麥克風(fēng) 5.相機(jī)前置麥克風(fēng) 8.揚(yáng)聲器
ss audiosource = 1
//采樣率 48000-4000Hz
ss sampleRateInHz = 44100
//通道 12.雙通道 2.單通道 4.左通道 8.右通道; (通道指耳機(jī)的左和右)立體音
ss channel = 12
//音頻數(shù)據(jù)格式 2.16bit 3.8bit
ss audioformat = 2
//計(jì)算采樣的緩沖區(qū)大小
java(ss.samplebuffersize,null,"android.media.AudioRecord.getMinBufferSize","int",ss.sampleRateInHz,"int",2,"int",ss.audioformat)
//------視圖單機(jī)監(jiān)聽(tīng)
cls("android.view.View$OnClickListener",c)
ss type = 0
javacb(hd,c)
{
  sgsz(st_aS,0,view)
  java(index,ss.ids,"java.util.ArrayList.indexOf","Object",view)
  f(index==0)
  {
    //效果按鈕
    ug(view,"text",text)
    f(text=="效果(普通)")
    {
      us(view,"text","效果(反聽(tīng))")
      ss type = 1
    }
    else
    {
      us(view,"text","效果(普通)")
      ss type = 0
    }
  }
  else f(index==1)
  {
    //錄音按鈕
    fn lly.createAudioRecord(ss.sampleRateInHz)
    f(ss.type==0)
    {
      fn lly.startRecord(ss.audioRecord,ss.samplebuffersize,ss.audiotmpfile)
    }
    else f(ss.type==1)
    {
      fn lly.createAudioTrack(ss.sampleRateInHz)
      fn lly.startRecord(ss.audioRecord,ss.track,ss.samplebuffersize,ss.audiotmpfile)
    }
  }
  else f(index==2)
  {
    //暫停按鈕
    ug(view,"text",text)
    f(text=="暫停錄音")
    {
      fn lly.pauseRecord();
      us(view,"text","繼續(xù)錄音")
    }
    else
    {
      us(view,"text","暫停錄音")
      gslist(ss.ids,1,view)
      java(null,view,"android.view.View.performClick")
    }
  }
  else f(index==3)
  {
    //停止按鈕
    fn lly.stopRecord(ss.audioRecord,ss.track,ss.audiotmpfile,ss.audiosavefile)
    tw("已保存錄音文件")
  }
  else f(index==4)
  {
    //播放按鈕
    fn lly.AudioPlay(ss.audiosavefile)
  }
  f(ss.error!=null)
  {
    syso(ss.error)
    tw(ss.error)
    ss error = null
  }
}
//------視圖單機(jī)監(jiān)聽(tīng)------
//------放置按鈕--------
sl("效果(普通)|開(kāi)始錄音|暫停錄音|停止錄音|播放錄音","|",bntexts)
for(str;bntexts)
{
  nvw(3,1,"按鈕","width=-2\nheight=-2\ntext="+str,bn)
  java(null,bn,"android.view.View.setOnClickListener","android.view.View$OnClickListener",hd)
  aslist(ss.ids,bn)
}
//------放置按鈕--------

fn函數(shù)庫(kù)

先新建一個(gè)lly.myu逆粹,把下面的copy進(jìn)去募疮。

剩下的操作直接調(diào)用就行了!
反聽(tīng)效果有一個(gè)問(wèn)題 AudioRecord讀取數(shù)據(jù)需要150ms左右然后用AudioTrack寫入也需要150ms左右造成了300ms左右才有聲音的延遲僻弹。

//創(chuàng)建AudioRecord對(duì)象
fn createAudioRecord(samplebuffersize)
javanew(ss.audioRecord,"android.media.AudioRecord","int",1,"int",ss.sampleRateInHz,"int",12,"int",2,"int",samplebuffersize)
end fn

//創(chuàng)建AudioTrack對(duì)象
fn createAudioTrack(samplebuffersize)
javanew(ss.track,"android.media.AudioTrack","int",3,"int",ss.sampleRateInHz,"int",12,"int",2,"int",samplebuffersize,"int",1)
//java(null,ss.track,"android.media.AudioTrack.play")
end fn

//開(kāi)始普通錄音
fn startRecord(audiorecord,samplebuffersize,filepath)
f(ss.isRecord)
{
  ss error = "method:startRecord message:Recording"
  endcode
}
t()
{
  fn lly.AudioRecordWriteStream(audiorecord,samplebuffersize,filepath)
}
ss isRecord = true
end fn

//開(kāi)始帶反音效果錄制
fn startRecord(audiorecord,audiotrack,samplebuffersize,filepath)
f(ss.isRecord)
{
  ss error = "method:startRecord message:Recording"
  endcode
}
t()
{
  fn lly.ReturnBackAudioWriteStream(audiorecord,audiotrack,samplebuffersize,filepath)
}
ss isRecord = true
end fn

//暫停錄音(可以不調(diào)用本函數(shù) 直接使用(ss isRecord = false)即可;
fn pauseRecord()
ss isRecord = false
end fn

//停止錄音
fn stopRecord(audiorecord,audiotrack,filepath,newfilepath)
ss isRecord = false
java(null,audiorecord,"android.media.AudioRecord.release")
f(ss.audiotrack!=null)
{
  java(null,audiotrack,"android.media.AudioTrack.release")
}
fn lly.pcmDataAddHeader(filepath,newfilepath)
end fn

//輸出普通音頻到文件里
fn AudioRecordWriteStream(audiorecord,samplebuffersize,filepath)
cls("byte",c)
//------創(chuàng)建目錄和文件------
javanew(file,"java.io.File","String",filepath)
java(filep,file,"java.io.File.getParentFile")
java(iserror,filep,"java.io.File.mkdirs")
java(iserror,file,"java.io.File.createNewFile")
//------創(chuàng)建目錄和文件------
//創(chuàng)建追加輸出流
javanew(os,"java.io.FileOutputStream","java.io.File",file,"boolean",true)
java(bytes,null,"java.lang.reflect.Array.newInstance","java.lang.Class",c,"int",samplebuffersize)
//開(kāi)始錄音
java(null,audiorecord,"android.media.AudioRecord.startRecording")
//讀取采樣數(shù)據(jù)
java(state,audiorecord,"android.media.AudioRecord.read","byte[]",bytes,"int",0,"int",samplebuffersize)
w(state!=-3&&ss.isRecord)
{
java(state,audiorecord,"android.media.AudioRecord.read","byte[]",bytes,"int",0,"int",samplebuffersize)
java(null,os,"java.io.OutputStream.write","byte[]",bytes,"int",0,"int",samplebuffersize)
}
java(null,os,"java.io.OutputStream.close")
java(null,audiorecord,"android.media.AudioRecord.stop")
end fn

//輸出帶反音音頻到文件里
fn ReturnBackAudioWriteStream(audiorecord,audiotrack,samplebuffersize,filepath)
cls("byte",c)
//------創(chuàng)建目錄和文件------
javanew(file,"java.io.File","String",filepath)
java(filep,file,"java.io.File.getParentFile")
java(iserror,filep,"java.io.File.mkdirs")
java(iserror,file,"java.io.File.createNewFile")
//------創(chuàng)建目錄和文件------
//創(chuàng)建追加輸出流
javanew(os,"java.io.FileOutputStream","java.io.File",file,"boolean",true)
//播放回音
java(null,audiotrack,"android.media.AudioTrack.play")
java(bytes,null,"java.lang.reflect.Array.newInstance","java.lang.Class",c,"int",samplebuffersize)
//開(kāi)始錄音
java(null,audiorecord,"android.media.AudioRecord.startRecording")
//讀取采樣數(shù)據(jù)
java(state,audiorecord,"android.media.AudioRecord.read","byte[]",bytes,"int",0,"int",samplebuffersize)
w(state!=-3&&ss.isRecord)
{
java(state,audiorecord,"android.media.AudioRecord.read","byte[]",bytes,"int",0,"int",samplebuffersize)
java(null,audiotrack,"android.media.AudioTrack.write","byte[]",bytes,"int",0,"int",samplebuffersize)
java(null,os,"java.io.OutputStream.write","byte[]",bytes,"int",0,"int",samplebuffersize)
}
//關(guān)閉輸出流
java(null,os,"java.io.OutputStream.close")
//在這里暫停是為了防止用戶按下停止時(shí)AudioRevord還在采樣但已經(jīng)停止工作會(huì)結(jié)束當(dāng)前函數(shù)酝锅,所以要吧關(guān)閉輸出流寫在他們上面!
java(null,audiorecord,"android.media.AudioRecord.stop")
java(null,audiotrack,"android.media.AudioTrack.pause")
end fn

//給裸流添加頭數(shù)據(jù)(因?yàn)閕App沒(méi)辦法使用一些運(yùn)算符所以這里的數(shù)據(jù)是固定的所以可能會(huì)照成無(wú)法播放)
fn pcmDataAddHeader(filepath,newfilepath)
//------創(chuàng)建目錄和文件------
javanew(file,"java.io.File","String",filepath)
javanew(newfile,"java.io.File","String",newfilepath)
java(filep,newfile,"java.io.File.getParentFile")
java(iserror,filep,"java.io.File.mkdirs")
java(iserror,newfile,"java.io.File.createNewFile")
//------創(chuàng)建目錄和文件------
javanew(is,"java.io.FileInputStream","java.io.File",file)
javanew(os,"java.io.FileOutputStream","java.io.File",newfile)
//頭數(shù)據(jù)
s a = "82 73 70 70 36 115 248 0 87 65 86 69 102 109 116 32 16 0 0 0 1 0 2 0 68 172 0 0 16 177 2 0 4 0 16 0 100 97 116 97 0 115 248 0"
sl(a," ",b)
//輸出44位頭數(shù)據(jù)
for(c;b)
{
s(c+0,c)
java(null,os,"java.io.OutputStream.write","int",c)
}
java(len,is,"java.io.InputStream.available")
cls("byte",c)
java(bytes,null,"java.lang.reflect.Array.newInstance","java.lang.Class",c,"int",len)
//拷貝裸數(shù)據(jù)進(jìn)來(lái)
java(len,is,"java.io.InputStream.read","byte[]",bytes,"int",0,"int",len)
java(null,os,"java.io.OutputStream.write","byte[]",bytes,"int",0,"int",len)
java(null,os,"java.io.OutputStream.close")
end fn

//播放音頻
fn AudioPlay(filepath)
bfm(filepath,ss.mp)
bfms(ss.mp,"st")
bfms(ss.mp,"sl",true)
bfms(ss.mp, "ip", c)
f(!c)
{
  ss error = "method:AudioPlay message:PlayError"
  endcode
}
utw(null,"AudioPlayer","alertwindow.iyu","exit",true,v)
{
  bfms(ss.mp, "sp")
  bfms(ss.mp, "re")
  ss mp = null
}
gvs(v,2,ss.vp)
gvs(v,3,ss.vt)
gvs(v,4,ss.vtt)
bfms(ss.mp, "dn", dn)
us(ss.vp,"max",dn)
fn lly.timetoformat(dn)
us(ss.vtt,"text",ss.timeformat)
ssj(ss.vp,"touchmonitor")
{
  ug(st_vW,"progress",ps)
  bfms(ss.mp, "seekto", ps)
}
t()
{
  w(ss.mp!=null)
  {
    ufnsui()
    {
      bfms(ss.mp, "cn", cdn)
      us(ss.vp,"progress",cdn)
      fn lly.timetoformat(cdn)
      us(ss.vt,"text",ss.timeformat)
    }
  stop(1000)
  }
}
end fn

//給時(shí)間加格式
fn timetoformat(num)
s(num/1000/60,m)
s(num/1000%60,s)
f(m<10)
{
  ss("0"+m,m)
}
f(s<10)
{
  ss("0"+s,s)
}
ss(m+":"+s,ss.timeformat)
end fn

效果圖

源碼下載(本接口不經(jīng)常開(kāi)啟)

入群下載(如果無(wú)法跳轉(zhuǎn)請(qǐng)復(fù)制群號(hào))
Q群:947756726

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奢方,一起剝皮案震驚了整個(gè)濱河市搔扁,隨后出現(xiàn)的幾起案子爸舒,更是在濱河造成了極大的恐慌,老刑警劉巖稿蹲,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扭勉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苛聘,警方通過(guò)查閱死者的電腦和手機(jī)涂炎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)设哗,“玉大人唱捣,你說(shuō)我怎么就攤上這事⊥遥” “怎么了震缭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)战虏。 經(jīng)常有香客問(wèn)我拣宰,道長(zhǎng),這世上最難降的妖魔是什么烦感? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任巡社,我火速辦了婚禮,結(jié)果婚禮上手趣,老公的妹妹穿的比我還像新娘晌该。我一直安慰自己,他們只是感情好绿渣,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布朝群。 她就那樣靜靜地躺著,像睡著了一般怯晕。 火紅的嫁衣襯著肌膚如雪潜圃。 梳的紋絲不亂的頭發(fā)上缸棵,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天舟茶,我揣著相機(jī)與錄音,去河邊找鬼堵第。 笑死吧凉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踏志。 我是一名探鬼主播阀捅,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼针余!你這毒婦竟也來(lái)了饲鄙?” 一聲冷哼從身側(cè)響起凄诞,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忍级,沒(méi)想到半個(gè)月后帆谍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡轴咱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年汛蝙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朴肺。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窖剑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戈稿,到底是詐尸還是另有隱情西土,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布器瘪,位于F島的核電站翠储,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏橡疼。R本人自食惡果不足惜援所,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望欣除。 院中可真熱鬧住拭,春花似錦、人聲如沸历帚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挽牢。三九已至谱煤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間禽拔,已是汗流浹背刘离。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睹栖,地道東北人硫惕。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像野来,于是被迫代替她去往敵國(guó)和親恼除。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容