使用TrackAudio播放AES加密的mp3

問題背景

最近項(xiàng)目可能需要對(duì)聲音進(jìn)行加密,解密祷蝌,進(jìn)行識(shí)別認(rèn)證茅撞,在網(wǎng)上有一篇文章介紹了如何使用AES算法在java中對(duì)音頻進(jìn)行加密: Android 加密/解密音頻文件(AES)
其具體的做法就是將加密文件和解密文件全部保存到存儲(chǔ)器上巨朦,在未來項(xiàng)目中需要頻繁的讀寫硬盤可不是一個(gè)好的建議米丘,所以尋找能夠保存的是加密的音頻,然后直接對(duì)加密音頻進(jìn)行解密罪郊,之后直接在內(nèi)存中進(jìn)行播放蠕蚜。
于是又找到了一篇關(guān)于實(shí)時(shí)播放wav,但是我們需要的mp3悔橄,最好還是解決實(shí)時(shí)播放wav文章的最初原作者同樣給出了實(shí)時(shí)解碼mp3的解決方法:Android Audio: Play an MP3 file on an AudioTrack靶累;
下面的代碼就是混合了他們所有人的產(chǎn)物腺毫,部分內(nèi)容也是直接翻譯過來。

項(xiàng)目已上傳

Github-使用TrackAudio播放AES加密的mp3

這里的邏輯

為什么加密和TrackAudio能夠混在一起用挣柬,講下這里的邏輯:因?yàn)椴シ舖p3使用TrackAudio潮酒,它使用的是音頻流,即輸入的是byte[],而AES解密后輸出也是byte[],所以AES解密后直接輸出byte的邪蛔,再傳遞給TrackAudio進(jìn)行音頻播放也就順理成章了急黎。
而具體的流程就是:使用AES機(jī)密mp3文件,并將解密后的文件newByte_track(byte[]類型)侧到,直接交給ByteArrayInputStream變成InputStream in勃教;

InputStream in = new ByteArrayInputStream(newByte_track); 
Bitstream bitstream = new Bitstream(in);

變?yōu)锽itstream bitstream ,而Jlayer正好可以將bitstream 作為輸入匠抗,然后輸出SampleBuffer

SampleBuffer sampleBuffer = (SampleBuffer) mDecoder.decodeFrame(header, bitstream);

最后把SampleBuffer 轉(zhuǎn)換為byte[],我們的TrackAudio是可以直接播放byte[]故源。

首先不談加密,直接播放mp3

以下來自翻譯
在Android中能夠播放mp3的接口只有MediaPlayer汞贸,沉重绳军,慢,并且僅提供高級(jí)接口矢腻,如果你需要修改或者混合音頻流的話门驾,你就得自己動(dòng)手,AudioTrack就能幫到你多柑,我建議先閱讀(<a >the article about playing a WAV</a>) 這篇文章奶是,它包含了一些關(guān)于PCM基本常識(shí)。
因?yàn)閃AV文件基本可以算無損顷蟆,而MP3就不同了诫隅,它已經(jīng)經(jīng)過復(fù)雜的算法解碼過腐魂,所以我們需要借助第三方代碼帐偎,允許我們將MP3數(shù)據(jù)轉(zhuǎn)換為raw PCM數(shù)據(jù),之后就可以按部就班的讓AudioTrack播放了蛔屹。
經(jīng)過漫長的搜索削樊,終于找到了一款mp3解碼器<a >Jlayer</a>。它可以輕松的解碼MP3(當(dāng)然從Jlayer的界面也能看出兔毒,它是為Java SE 平臺(tái)專設(shè)的漫贞,時(shí)間也是許久之前,不過Android也基于java育叁,所以索性就試試)迅脐,Jlayer的授權(quán)協(xié)議類LGPL 協(xié)議,對(duì)商用app也非常友好豪嗽。
在使用Jlayer之前谴蔑,首先把它導(dǎo)入進(jìn)來到你的項(xiàng)目中來豌骏。
下邊是調(diào)用Jlayer代碼

InputStream in = new ByteArrayInputStream(newByte_track); 
        Bitstream bitstream = new Bitstream(in);
                    final int READ_THRESHOLD = 2147483647;
                    int framesReaded = READ_THRESHOLD;
                    Header header;
                    for(; framesReaded-- > 0 && (header = bitstream.readFrame()) != null;) {
                        SampleBuffer sampleBuffer = (SampleBuffer) mDecoder.decodeFrame(header, bitstream);
                        Log.e("header",String.valueOf(header.framesize ));
                        short[] buffer = sampleBuffer.getBuffer();
                        for (short s : buffer) {
                          outStream.write(s & 0xff);
                          outStream.write((s >> 8 ) & 0xff);
                          }                                                                       
                        bitstream.closeFrame();
                    }
                    byte[] Byte_JLayer=outStream.toByteArray();

這里需要說明下:

 short[] buffer = sampleBuffer.getBuffer();
                        for (short s : buffer) {
                          outStream.write(s & 0xff);
                          outStream.write((s >> 8 ) & 0xff);
                          }     

上邊的代碼表示的是將short類型的值寫入到“數(shù)據(jù)輸出流”中,見[DataOutputStream(數(shù)據(jù)輸出流)的認(rèn)知隐锭、源碼和示例;計(jì)算機(jī)內(nèi)的存儲(chǔ)都是利用二進(jìn)制的補(bǔ)碼進(jìn)行存儲(chǔ)的窃躲,byte類型的數(shù)字要&0xff再賦值給int類型,其本質(zhì)原因就是想保持二進(jìn)制補(bǔ)碼的一致性钦睡,見byte為什么要與上0xff蒂窒?
這里參數(shù)修改如下時(shí)荞怒,播放的音樂的完整性和播放開始的速度都是不一樣的洒琢。

                    //大約需要14s,但是歌曲可以完整保存下來
//                   final int READ_THRESHOLD = 2147483647;//我試著改動(dòng)了褐桌,沒有變化;
                    //需要3s纬凤,但是音樂沒有播放完就結(jié)束了
                    final int READ_THRESHOLD = 1024;//我試著改動(dòng)了,沒有變化;
                    int framesReaded = READ_THRESHOLD;

其中

mDecoder = new Decoder();

這里Decoder類的完整類名javazoom.jl.decoder.Decoder.Decoder()撩嚼,當(dāng)然代碼時(shí)死的停士,不需要記憶,但是你要知道它的原理完丽,然后實(shí)現(xiàn)它恋技。
當(dāng)然也可以走原生路線,找一個(gè)用C寫的MP3解碼器(這里也有一個(gè)連接逻族,但是我沒有實(shí)現(xiàn)蜻底,需要JNI和NDK的知識(shí)),在此不提聘鳞,
如果你需要在你的app中解碼mp3薄辅,這篇文章可以幫助到你。
在使用Jlayer成功獲得到數(shù)據(jù) byte[] Byte_JLayer抠璃,剩下的工作就交給AudioTrack了站楚,當(dāng)然在將byte[] Byte_JLayer存入AudioTrack,首先是配置AudioTrack:

        final int sampleRate = 44100;
        
        final int minBufferSize = AudioTrack.getMinBufferSize(sampleRate,
                //MI3:CHANNEL_OUT_STEREO //[]AudioFormat.CHANNEL_OUT_STEREO
                //CHANNEL_OUT_MONO影響不大搏嗡,只要是new AudioTrack構(gòu)建時(shí)選擇AudioFormat.CHANNEL_OUT_STEREO即可           
                AudioFormat.CHANNEL_OUT_STEREO,   
                AudioFormat.ENCODING_PCM_16BIT);
        //這里的關(guān)鍵詞就是復(fù)制窿春,粘貼,調(diào)參數(shù)剛剛拿了一個(gè)舊的mp2采盒,試過旧乞,當(dāng)然是錯(cuò)誤的  
        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate,
                AudioFormat.CHANNEL_OUT_STEREO, // CHANNEL_OUT_STEREO 聲音嘈雜 ,CHANNEL_OUT_DEFAULT磅氨,CHANNEL_IN_DEFAULT尺栖,也是有噪音              
                AudioFormat.ENCODING_PCM_16BIT,//AudioFormat.CHANNEL_CONFIGURATION_DEFAULT也是有聲音
                2*minBufferSize,
                AudioTrack.MODE_STREAM);

AES加密解密具體流程

高級(jí)加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard,縮寫:AES)烦租,在密碼學(xué)中又稱Rijndael加密法延赌,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)货徙。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用皮胡。(來自百度百科)

加密的過程

我直接使用Android 加密/解密音頻文件(AES)中的加密方法痴颊。加密的過程簡單來說就是讀取文件轉(zhuǎn)換為byte[],解密,他的思路就是保存為音樂文件屡贺,然后播放蠢棱,而我的思路是直接交給AudioTrack和Jlayer去運(yùn)行byte,這樣每次就不用保存到存儲(chǔ)空間上甩栈,而對(duì)外泻仙,mp3一直處于加密狀態(tài),在PC端也同樣無法播放量没。

備注

我在加密過程中注意玉转,使用mp3(通常下載的歌曲沒有問題),但是注意如果使用Adobe Audition時(shí)就要注意如果輸出的格式進(jìn)行了設(shè)置殴蹄,有時(shí)Jlayer和AudioTrack也是無法滿足的究抓,有時(shí)會(huì)有噪音的輸出,有時(shí)就是沒有聲音袭灯,例如我在使用Adobe Audition導(dǎo)出mp2后刺下,修改后綴為mp3,依然還是無法播放稽荧,因?yàn)楸窘坛痰慕獯a就是面向mp3而存在橘茉。

下邊的這些參數(shù)實(shí)際也是跟隨android設(shè)備進(jìn)行設(shè)置的,可以通過調(diào)整細(xì)微的參數(shù)姨丈,看AudioTrack播放音樂時(shí)會(huì)有不同的表現(xiàn)畅卓。

效果圖

將代碼保重的54wall拷貝到手機(jī)的內(nèi)部存儲(chǔ)器或者SD卡上,54wall文件夾中有一個(gè)q.mp3,是導(dǎo)盲犬小Q的一個(gè)音樂蟋恬,然后運(yùn)行項(xiàng)目后就是下邊的效果翁潘,此時(shí)的q.mp3是沒有加密過的,直接點(diǎn)擊play筋现,就可以播放唐础,點(diǎn)擊encryp是進(jìn)行加密保存到存儲(chǔ)器上,再進(jìn)行play是不能播放的矾飞,這時(shí)點(diǎn)擊toJLayer則Activity進(jìn)行跳轉(zhuǎn),使用Jlayer進(jìn)行播放呀邢,注意洒沦,這時(shí)需要消耗一定的時(shí)間,進(jìn)行解碼价淌,開始是沒有聲音的申眼。


encryption.jpg

廣告

鯉魚日語一個(gè)簡單背日語的APP,歡迎下載,期待Star舒憾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末香拉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子濒翻,更是在濱河造成了極大的恐慌屁柏,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件有送,死亡現(xiàn)場離奇詭異淌喻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)雀摘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門裸删,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阵赠,你說我怎么就攤上這事涯塔。” “怎么了清蚀?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵伤塌,是天一觀的道長。 經(jīng)常有香客問我轧铁,道長每聪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任齿风,我火速辦了婚禮药薯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘救斑。我一直安慰自己童本,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布脸候。 她就那樣靜靜地躺著穷娱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪运沦。 梳的紋絲不亂的頭發(fā)上泵额,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音携添,去河邊找鬼嫁盲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛烈掠,可吹牛的內(nèi)容都是我干的羞秤。 我是一名探鬼主播缸托,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瘾蛋!你這毒婦竟也來了俐镐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤哺哼,失蹤者是張志新(化名)和其女友劉穎佩抹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幸斥,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匹摇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了甲葬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廊勃。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖经窖,靈堂內(nèi)的尸體忽然破棺而出坡垫,到底是詐尸還是另有隱情,我是刑警寧澤画侣,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布冰悠,位于F島的核電站,受9級(jí)特大地震影響配乱,放射性物質(zhì)發(fā)生泄漏溉卓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一搬泥、第九天 我趴在偏房一處隱蔽的房頂上張望桑寨。 院中可真熱鬧,春花似錦忿檩、人聲如沸尉尾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沙咏。三九已至,卻和暖如春班套,著一層夾襖步出監(jiān)牢的瞬間肢藐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工孽尽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窖壕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓杉女,卻偏偏與公主長得像瞻讽,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熏挎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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