精品专区-精品自拍9-精品自拍三级乱伦-精品自拍视频-精品自拍视频曝光-精品自拍小视频

網(wǎng)站建設(shè)資訊

NEWS

網(wǎng)站建設(shè)資訊

Android音頻開發(fā)(4):如何存儲(chǔ)和解析wav文件

無(wú)論是文字、圖像還是聲音,都必須以一定的格式來(lái)組織和存儲(chǔ)起來(lái),這樣播放器才知道以怎樣的方式去解析這一段數(shù)據(jù),例如,對(duì)于原始的圖像數(shù)據(jù),我們常見的格式有 YUV、Bitmap,而對(duì)于音頻來(lái)說,最簡(jiǎn)單常見的格式就是 wav 格式了。

成都創(chuàng)新互聯(lián)公司2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元武江做網(wǎng)站,已為上家服務(wù),為武江各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220

wav 格式,與 bitmap 一樣,都是微軟開發(fā)的一種文件格式規(guī)范,它們都有一個(gè)相似之處,就是整個(gè)文件分為兩部分,第一部分是“文件頭”,記錄重要的參數(shù)信息,對(duì)于音頻而言,就包括:采樣率、通道數(shù)、位寬等等,對(duì)于圖像而言,就包括:圖像的寬高、色彩位數(shù)等等;第二部分是“數(shù)據(jù)塊”,即一幀一幀的二進(jìn)制數(shù)據(jù),對(duì)于音頻而言,就是原始的 PCM 數(shù)據(jù);對(duì)于圖像而言,就是 RGB 數(shù)據(jù)。

前面幾篇文章講了如何利用 Android 平臺(tái)的 API 完成原始音頻信號(hào)的采集和播放,而本文則重點(diǎn)關(guān)注如何在 Android 平臺(tái)上,將采集到的 PCM 音頻數(shù)據(jù)保存到 wav 文件,同時(shí),也介紹如何讀取和解析 wav 文件。

而文章最后,我還會(huì)給出一段 AudioDemo 程序,該程序?qū)⒆罱膸灼恼律婕暗降拇a綜合起來(lái)了,演示了一個(gè)完整的 Android 音頻從采集到播放的全過程。

下面言歸正傳,講講如何讀寫 wav 文件格式。

1. 文件頭

首先,我們了解一下 wav 格式的“文件頭”,可以參考這篇文章:《WAVE PCM soundfile format》

 Android音頻開發(fā)(4):如何存儲(chǔ)和解析wav文件

我們可以簡(jiǎn)單地分析一下這個(gè) wav 格式頭,它主要分為三個(gè)部分:

第一部分,屬于最“頂層”的信息塊,通過“ChunkID”來(lái)表示這是一個(gè) “RIFF”格式的文件,通過“Format”填入“WAVE”來(lái)標(biāo)識(shí)這是一個(gè) wav 文件。而“ChunkSize”則記錄了整個(gè) wav 文件的字節(jié)數(shù)。

第二部分,屬于“fmt”信息塊,主要記錄了本 wav 音頻文件的詳細(xì)音頻參數(shù)信息,例如:通道數(shù)、采樣率、位寬等等(含義請(qǐng)參考我的第一篇文章《Android音頻開發(fā)(1):基礎(chǔ)知識(shí)》)

第三部分,屬于“data”信息塊,由“Subchunk2Size”這個(gè)字段來(lái)記錄后面存儲(chǔ)的二進(jìn)制原始音頻數(shù)據(jù)的長(zhǎng)度。

分析到這里,我想大家應(yīng)該就明白了,其實(shí),做一種多媒體格式的解析,也不是一件特別復(fù)雜的事,說白了,格式就是一種規(guī)范,告訴你,我的二進(jìn)制數(shù)據(jù)是怎么存儲(chǔ)的,你應(yīng)該按照什么樣的方式來(lái)解析。

具體而言,我們可以定義一個(gè)如下的 Java 類來(lái)抽象和描述 wav 文件頭:

/*
 *  COPYRIGHT NOTICE  
 *  Copyright (C) 2016, Jhuster 
 *  https://github.com/Jhuster/AudioDemo
 *   
 *  @license under the Apache License, Version 2.0 
 *
 *  @file    WavFileHeader.java
 *  
 *  @version 1.0     
 *  @author  Jhuster
 *  @date    2016/03/19
 */
package com.jhuster.audiodemo.api;

public class WavFileHeader {    
   
    public String mChunkID = "RIFF";
    public int mChunkSize = 0;    
    public String mFormat = "WAVE";

    public String mSubChunk1ID = "fmt ";
    public int mSubChunk1Size = 16;
    public short mAudioFormat = 1;    
    public short mNumChannel = 1;
    public int mSampleRate = 8000;
    public int mByteRate = 0;
    public short mBlockAlign = 0;
    public short mBitsPerSample = 8;

    public String mSubChunk2ID = "data";
    public int mSubChunk2Size  = 0;
    
    public WavFileHeader() {
        
    }
    
    public WavFileHeader(int sampleRateInHz, int bitsPerSample, int channels) {          
        mSampleRate = sampleRateInHz;
        mBitsPerSample = (short)bitsPerSample;
        mNumChannel = (short)channels;                
        mByteRate = mSampleRate*mNumChannel*mBitsPerSample/8;
        mBlockAlign = (short)(mNumChannel*mBitsPerSample/8);
    }
}

具體每一個(gè)字段的含義,可以參考我上面給出的鏈接,下面我們?cè)倏纯慈绾巫x寫 wav 文件。

2. 讀寫 wav 文件


文章開頭已經(jīng)說過,其實(shí)說白了,wav 文件就是一段“文件頭”+“音頻二進(jìn)制數(shù)據(jù)”,因此:

(1)寫 wav 文件,其實(shí)就是先寫入一個(gè) wav 文件頭,然后再繼續(xù)寫入音頻二進(jìn)制數(shù)據(jù)即可

(2)讀 wav 文件,其實(shí)也就是先讀一個(gè) wav 文件頭,然后再繼續(xù)讀出音頻二進(jìn)制數(shù)據(jù)即可

那么,在動(dòng)手寫代碼之前,有兩點(diǎn)你需要搞清楚:

(1) wav 文件頭中,有哪些是“變化的”,哪些是“不變的”?

比如:文件頭開頭的“RIFF”字符串就是“不變的”部分,而用來(lái)記錄音頻數(shù)據(jù)總長(zhǎng)度的“Subchunk2Size”變量就是屬于“變化的”部分,因?yàn)椋僖纛l數(shù)據(jù)沒有徹底全部寫完之前,你是無(wú)法知道一共寫入了多少字節(jié)的音頻數(shù)據(jù)的,因此,這個(gè)部分,需要用一個(gè)變量記錄起來(lái),到全部寫完之后,再使用 Java 的“RandomAccessFile”類,將文件指針跳轉(zhuǎn)到“Subchunk2Size”字段,改寫一下默認(rèn)值即可。

(2) 如何把 int、short 變量與 byte[] 的轉(zhuǎn)換

因?yàn)?wav 文件都是二進(jìn)制的方式讀寫,因此,“WavFileHeader”類中定義的變量都需要轉(zhuǎn)換為byte字節(jié)流,具體轉(zhuǎn)換方法如下:

private static byte[] intToByteArray(int data) {
    return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(data).array();
}

private static byte[] shortToByteArray(short data) {
    return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(data).array();
} 

private static short byteArrayToShort(byte[] b) {
    return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getShort();
}
    
private static int byteArrayToInt(byte[] b) {
    return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getInt();
}

關(guān)于 wav 文件讀寫的類我已經(jīng)幫大家“封裝”好了,并且結(jié)合著前面幾篇文章給出的音頻采集和播放的代碼,完成了一個(gè) AudioDemo 程序,放在我的 Github 上了,歡迎大家下載運(yùn)行測(cè)試,然后結(jié)合著代碼具體學(xué)習(xí) Android 音頻相關(guān)技術(shù),代碼地址:

https://github.com/Jhuster/AudioDemo

注:本系列文章的所有代碼,以后都會(huì)并入到該 demo 項(xiàng)目中。

3. 小結(jié)

關(guān)于如何在 Android 平臺(tái)讀寫 wav 格式的文件就介紹到這兒了


網(wǎng)頁(yè)標(biāo)題:Android音頻開發(fā)(4):如何存儲(chǔ)和解析wav文件
分享地址:http://m.jcarcd.cn/article/ipdosi.html
主站蜘蛛池模板: 人成a大片在线观看 | 国产精品色综合 | 97在线人人| 日韩欧美亚洲大片 | 日韩午夜高清 | 日韩国产三区四区 | 日韩午夜禽兽视频 | 午夜日韩视频 | 国产理论片高清 | 国产精品国产片在 | 日韩欧美乱国产日 | 国产日韩在线视频 | 韩国视频一| www.色五月| 欧美日韩岛国 | 欧美亚洲精 | 日本高清无卡码一区 | 国内揄拍国| 午夜理论在线 | 日韩高清成 | 中文字幕乱伦视频 | 无码精品尤物一区二区三区 | 91精品污| 国语自产 | 96网友上传国产 | 国产91对白在 | 国产日韩精品影院 | 日韩精品视频老牛 | 91国语福利影院 | 三年在线 | 欧美在线一区视频 | 区三区四区 | 成人精品综合 | www.黄免费| 欧美亚洲性爱综 | 乱伦91欧 | 日韩在线视频第一页 | 日韩在线视频第一页 | 国产精品成人国 | 国产激情| 欧美性性性 |