註冊 登錄
Android 台灣中文網 返回首頁

jianrupan的個人空間 https://apk.tw/?1180935 [收藏] [複製] [分享] [RSS]

日誌

固定頻率聲音輸出

已有 244 次閱讀2020-10-21 17:34 |個人分類:軟體應用| 固定, 頻率, 聲音, 輸出


驗證程序
sineWave.SetRate(440, 3); // db 自動轉為負值
sineWave.SetVolume((float)0.5); // 注意波形變形
sineWave.Start();
sineWave.Play();

// 固定聲音頻率輸出
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));
    }
}

路過

雞蛋

鮮花

握手

雷人

評論 (0 個評論)

facelist

您需要登錄後才可以評論 登錄 | 註冊