// 固定聲音頻率輸出
public class SineWaveGenerator {
// 採樣頻率
private int RATE = 44100;
private final int LEFT = 1;
private final int RIGHT = 2;
private final int DOUBLE = 3;
// 輸出頻率
private int Hz;
// 輸出分貝
private int dB = 0;
// 輸出音量
private float volume;
AudioTrack audioTrack;
// 輸出聲道
private int channel;
// 資料長度
private int length;
// 一個正弦波長度
private int waveLen;
// 正弦波資料陣列
private byte[] wave;
public SineWaveGenerator() {
wave = new byte[RATE];
}
// 音量設定
public void SetVolume(float v) {
volume = v;
}
// 頻率分貝設定
public void SetRate(int hz, int db) {
this.Hz = hz;
this.dB = db;
updateDB(db);
}
// 啟動播放
public void Start() {
start(DOUBLE);
}
// 啟動播放
// @param channel 左, 右, 立體
private void start(int channel) {
Stop();
if (Hz > 0) {
waveLen = (RATE/Hz)*2; // 實測 頻率 為 Hz/2(440Hz=440/2)
length = waveLen * Hz;
audioTrack = new AudioTrack( AudioManager.STREAM_MUSIC, // streamType
RATE, // sampleRateInHz
AudioFormat.CHANNEL_OUT_STEREO, // channelConfig
AudioFormat.ENCODING_PCM_8BIT, // audioFormat
length, // bufferSizeInBytes
AudioTrack.MODE_STREAM // mode
);
// 聲道音量
switch (channel) {
case LEFT:
audioTrack.setStereoVolume(volume, 0f);
break;
case RIGHT:
audioTrack.setStereoVolume(0f, volume);
break;
case DOUBLE:
audioTrack.setStereoVolume(volume, volume);
break;
}
// 生成正弦波
wave = sineWave(waveLen, length);
if (audioTrack != null) {
audioTrack.play();
}
} else {
return;
}
}
private boolean isRun = false;
private boolean isStop = true;
// 開始播放(寫入數據)
public void Play() {
isRun = true;
isStop = false;
if (audioTrack != null) {
new Thread(new Runnable() {
@Override
public void run() {
while(isRun)
audioTrack.write(wave, 0, length);
isStop = true;
}
}).start();
}
}
// 停止播放
public void Stop() {
isRun = false;
try {
int limitCnt = 0;
while(!isStop)
{
limitCnt++;
if(limitCnt > 1000)
break;
Thread.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
isStop = true;
if (audioTrack != null) {
audioTrack.stop();
audioTrack.release();
audioTrack = null;
}
}
// 取得播放狀態
public boolean GetRunStatus() {
return isRun;
}
// 正弦波的高度
private final int ampMax = 127; // 8Bit編碼, 振幅最大 127
private int HEIGHT = ampMax;
// 2PI
private final double TWOPI = 2*Math.PI;
// 生成正弦波
// @param waveLen 每段正弦波的長度
// @param length 總長度
// @return
private byte[] sineWave(int waveLen, int length) {
byte[] bWave = new byte[length];
for(int i=0; i<length; i++)
bWave[i] = (byte)(HEIGHT*(1-Math.sin(TWOPI*((i%waveLen)*1.00/waveLen))));
return bWave;
}
// 更新聲音的分貝
// @param dB
public void updateDB(double dB) {
// db 自動轉為負值
if(dB > 0)
dB = 0-dB;
// 10 的 **次方
HEIGHT = (int)(ampMax*Math.pow(10.0, dB/10));
}
}