Andorid pcm轉(zhuǎn)碼wav

參考文章:https://blog.csdn.net/hesong1120/article/details/79043482

最近工作開發(fā)中茉稠,碰到一個BUG,由于WebApp開發(fā)钾麸,一套H5代碼適用于Android和IOS,但是發(fā)語音時,Android無法打開IOS的pcm格式文件穷蛹,而IOS同樣無法打開Android的wav格式文件。很尷尬沐绒,嘗試了直接改文件后綴名強轉(zhuǎn)俩莽,可惜會損壞文件。那么只有轉(zhuǎn)碼這一條路可以走了乔遮。

Android中扮超,想要播放,那么就需要單獨判斷pcm文件蹋肮,轉(zhuǎn)碼給wav出刷,再使用mediaplayer播放。

先上代碼:

  /**
     * PCM文件轉(zhuǎn)WAV文件
     * @param inPcmFilePath 輸入PCM文件路徑
     * @param outWavFilePath 輸出WAV文件路徑
     * @param sampleRate 采樣率坯辩,例如15000
     * @param channels 聲道數(shù) 單聲道:1或雙聲道:2
     * @param bitNum 采樣位數(shù)馁龟,8或16
     */
    public static void convertPcmToWav(String inPcmFilePath, String outWavFilePath, int sampleRate,
                                      int channels, int bitNum) {
        FileInputStream in = null;
        FileOutputStream out = null;
        byte[] data = new byte[1024];

        try {
            //采樣字節(jié)byte率
            long byteRate = sampleRate * channels * bitNum / 8;

            in = new FileInputStream(inPcmFilePath);
            out = new FileOutputStream(outWavFilePath);

            //PCM文件大小
            long totalAudioLen = in.getChannel().size();

            //總大小,由于不包括RIFF和WAV漆魔,所以是44 - 8 = 36坷檩,在加上PCM文件大小
            long totalDataLen = totalAudioLen + 36;

            writeWaveFileHeader(out, totalAudioLen, totalDataLen, sampleRate, channels, byteRate);

            int length = 0;
            while ((length = in.read(data)) > 0) {
                out.write(data, 0, length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 輸出WAV文件
     * @param out WAV輸出文件流
     * @param totalAudioLen 整個音頻PCM數(shù)據(jù)大小
     * @param totalDataLen 整個數(shù)據(jù)大小
     * @param sampleRate 采樣率
     * @param channels 聲道數(shù)
     * @param byteRate 采樣字節(jié)byte率
     * @throws IOException
     */
    private static void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                            long totalDataLen, int sampleRate, int channels, long byteRate) throws IOException {
        byte[] header = new byte[44];
        header[0] = 'R'; // RIFF
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        header[4] = (byte) (totalDataLen & 0xff);//數(shù)據(jù)大小
        header[5] = (byte) ((totalDataLen >> 8) & 0xff);
        header[6] = (byte) ((totalDataLen >> 16) & 0xff);
        header[7] = (byte) ((totalDataLen >> 24) & 0xff);
        header[8] = 'W';//WAVE
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        //FMT Chunk
        header[12] = 'f'; // 'fmt '
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';//過渡字節(jié)
        //數(shù)據(jù)大小
        header[16] = 16; // 4 bytes: size of 'fmt ' chunk
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        //編碼方式 10H為PCM編碼格式
        header[20] = 1; // format = 1
        header[21] = 0;
        //通道數(shù)
        header[22] = (byte) channels;
        header[23] = 0;
        //采樣率,每個通道的播放速度
        header[24] = (byte) (sampleRate & 0xff);
        header[25] = (byte) ((sampleRate >> 8) & 0xff);
        header[26] = (byte) ((sampleRate >> 16) & 0xff);
        header[27] = (byte) ((sampleRate >> 24) & 0xff);
        //音頻數(shù)據(jù)傳送速率,采樣率*通道數(shù)*采樣深度/8
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        // 確定系統(tǒng)一次要處理多少個這樣字節(jié)的數(shù)據(jù)改抡,確定緩沖區(qū)矢炼,通道數(shù)*采樣位數(shù)
        header[32] = (byte) (channels * 16 / 8);
        header[33] = 0;
        //每個樣本的數(shù)據(jù)位數(shù)
        header[34] = 16;
        header[35] = 0;
        //Data chunk
        header[36] = 'd';//data
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        header[40] = (byte) (totalAudioLen & 0xff);
        header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
        header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
        header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
        out.write(header, 0, 44);
    }

詳細的音頻知識筆者一知半解,想要了解的朋友可以查看上面的參考文章阿纤,有詳細介紹句灌。調(diào)用convertPcmToWav方法可以將pcm文件轉(zhuǎn)化成wav文件。下面是筆者在項目中的使用方法:

 if(end.equals("pcm")){
                String pcmPath=f.getPath();
                String wavPath=f.getPath().replace("pcm","wav");
                AudioRecoderUtils audioRecoderUtils=AudioRecoderUtils.getInstance();
                audioRecoderUtils.convertPcmToWav(pcmPath,wavPath,15000,1,8);
                audioRecoderUtils.playerStart(wavPath);
            } 

End

筆者的Github Blog欠拾,希望各位大大提意見胰锌,點個star,謝謝
傳送門:WusyBlog

求互粉互贊藐窄,互贊所有文章可以私聊我资昧。哈哈,希望我們的原創(chuàng)文章能讓更多朋友看到荆忍,一起變強榛搔。

筆者新開通了微信公眾號——飲水思源|wusy 計劃持續(xù)運營诺凡,每日為您分享Android干貨、原創(chuàng)文章践惑。微信掃描下方的二維碼關(guān)注我腹泌,開發(fā)學(xué)習(xí)路上不迷路。謝謝各位


飲水思源|wusy.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尔觉,一起剝皮案震驚了整個濱河市凉袱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侦铜,老刑警劉巖专甩,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钉稍,居然都是意外死亡涤躲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門贡未,熙熙樓的掌柜王于貴愁眉苦臉地迎上來种樱,“玉大人,你說我怎么就攤上這事俊卤∧奂罚” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵消恍,是天一觀的道長岂昭。 經(jīng)常有香客問我,道長狠怨,這世上最難降的妖魔是什么约啊? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮佣赖,結(jié)果婚禮上恰矩,老公的妹妹穿的比我還像新娘。我一直安慰自己茵汰,他們只是感情好枢里,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布孽鸡。 她就那樣靜靜地躺著蹂午,像睡著了一般。 火紅的嫁衣襯著肌膚如雪彬碱。 梳的紋絲不亂的頭發(fā)上豆胸,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音巷疼,去河邊找鬼晚胡。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的估盘。 我是一名探鬼主播瓷患,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遣妥!你這毒婦竟也來了擅编?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤箫踩,失蹤者是張志新(化名)和其女友劉穎爱态,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體境钟,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡锦担,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了慨削。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洞渔。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖理盆,靈堂內(nèi)的尸體忽然破棺而出痘煤,到底是詐尸還是另有隱情,我是刑警寧澤猿规,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布衷快,位于F島的核電站,受9級特大地震影響姨俩,放射性物質(zhì)發(fā)生泄漏蘸拔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一环葵、第九天 我趴在偏房一處隱蔽的房頂上張望调窍。 院中可真熱鬧,春花似錦张遭、人聲如沸邓萨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缔恳。三九已至,卻和暖如春洁闰,著一層夾襖步出監(jiān)牢的瞬間歉甚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工扑眉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纸泄,地道東北人赖钞。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像聘裁,于是被迫代替她去往敵國和親雪营。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

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