Android 台灣中文網

標題: 固定頻率聲音輸出 [打印本頁]

作者: jianrupan    時間: 2020-10-21 17:35
標題: 固定頻率聲音輸出
驗證程序
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 = (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));
    }
}



作者: johngameboy    時間: 2021-8-3 18:08
正弦波資料陣列更新聲音的分貝




歡迎光臨 Android 台灣中文網 (https://apk.tw/) Powered by Discuz! X3.1