公司項目裏想添加一個聽力測試的小功能,主要目的就是增加用戶的新鮮感,增加軟件的用戶黏度,同時有了聽力測試又可以衍生一些其他業務,譬如爲贊助商推廣藥品什麼的,當然是保健藥,哈哈,你懂的~
廢話不多說,直接實現。首先,我們需要一個能夠根據輸入頻率獲取播放的數據,有了可播放的數據,我們就可以播放了,我這裏使用的是AudioTrack進行播放的,具體的實現代碼,用一個類就可以解決掉了,實現代碼如下:
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;
/**
* 生成聲音數據
* @author 袁劍
*
*/
public class GenerVoiceData {
public static final float DURATION=0.1f;
public static final float LISTEN_SAMP_AMP=16000.0f;
public static final int LISTEN_SAMP_RATE=48000;
public static GenerVoiceData instance=null;
AudioTrack audio;
public static GenerVoiceData getInstance(){
if(instance==null){
instance=new GenerVoiceData();
}
return instance;
}
/**
* 根據輸入的頻率,返回播放的數據
* @param f 想要播放的頻率
* @return
*/
/*DURATION=0.1,LISTEN_SAMP_AMP=16000.0,LISTEN_SAMP_RATE=48000,此三值可以根據需要修改 48K採樣率播放*/
public short[] GetFreqData(double f)
{
int zq_num=(int)(DURATION*f+0.5);
double t=zq_num/f;
int data_len=(int)(t*LISTEN_SAMP_RATE);
short[] pdata=new short[data_len];
if(pdata==null)
return null;
;
for(int i=0;i<data_len;i++)
pdata[i]=(short)(LISTEN_SAMP_AMP*Math.sin(Math.PI*2*i*f/LISTEN_SAMP_RATE)+0.5);
//dlen=data_len;
return pdata;
}
/**
* 播放制定頻率的聲音
* @param f 指定頻率
*/
public void playDefineFreqData(double f){
stopPlay();
int minBufSize = AudioTrack.getMinBufferSize(48000,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
audio = new AudioTrack(
AudioManager.STREAM_MUSIC, // 指定在流的類型
48000, // 設置音頻數據的採樣率 48k,如果是44.1k就是44100
AudioFormat.CHANNEL_OUT_MONO, // 設置輸出聲道爲雙聲道立體聲,而CHANNEL_OUT_MONO類型是單聲道
AudioFormat.ENCODING_PCM_16BIT, // 設置音頻數據塊是8位還是16位,這裏設置爲16位。好像現在絕大多數的音頻都是16位的了
minBufSize,
AudioTrack.MODE_STREAM // 設置模式類型,在這裏設置爲流類型,另外一種MODE_STATIC貌似沒有什麼效果
);
audio.play(); // 啓動音頻設備,下面就可以真正開始音頻數據的播放了
// 打開mp3文件,讀取數據,解碼等操作省略 ...
short[]tempdata=GetFreqData(f);
short playdata[]=new short[tempdata.length*30];
for(int i=0;i<30;i++){
for(int j=0;j<tempdata.length;j++){
playdata[i*tempdata.length+j]=tempdata[j];
}
}
short[] buffer = new short[2048];
Log.d("LISTENTEST", "長度爲:"+playdata.length);
int count=0;
while(true)
{
// 最關鍵的是將解碼後的數據,從緩衝區寫入到AudioTrack對象中
//audio.write(buffer, 0, 4096);
for(int i=0;i<2048;i++){
buffer[i]=playdata[count*2048+i];
}
audio.write(buffer, 0, 2048);
count++;
if((count+1)*2048>=playdata.length) break;
}
// 最後別忘了關閉並釋放資源
audio.stop();
audio.release();
}
/**
* 停止播放,並釋放資源
*/
public void stopPlay(){
if(audio!=null){
try {
audio.stop();
audio.release();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
有了輸入頻率播放的方法我們接下來就是儘量減少用戶聽的不同頻率的聲波的次數,畢竟3000HZ以上的聲音是很刺耳的,長時間聽我可受不了,這也不是我們需要的用戶體驗,實現思想如下:
- 從20HZ開始去測試,頻率逐漸往上增,第一次聽到聲音對應的頻率就是我們可以聽到的最低頻率;
- 聽到最低頻率後,播放的頻率從20000HZ往下走進行測試,能聽到的頻率就是我們能聽到的最高頻率;
- 最低頻率到最高頻率的區間就是我們能聽到的頻率範圍,測試就完成了。
Demo 項目地址如下:http://download.csdn.net/detail/omrleft123/9715608,使用的環境是AndroidStudio。