Android 纯音生成方法
因项目需要在 APP 中播放纯音,耳机测听的需求,理解在 Android 系统中,纯音播放有两种方式,一种是在程序中模拟出一个波形满足正弦波的音频数据,另一种就是事前准备好多个音频文件而后直接播放。若使用事前准备的音频,效果是可以达到(且可能更好),但需要准备各种分贝、频率的音频文件,算下来,要制作上百个,所以这里探讨通过程序模拟生成纯音。

所有声音都是有正弦波组成,只不过纯音是固定频率的正弦波。主要思路就是,可以使用 sin 函数 实现想要的频率的正弦波,而后再用AudioTrack类来实现声音的播放。
一、简单纯音计算
首先正弦波的高度设置为 127,由于这里使用 8 位的采样率,2 的 8 次方就应该是 256,所以正弦波的波峰就应该是 127 了。
/** 正弦波的高度 **/ public static final int HEIGHT = 127; /** 2PI **/ public static final double TWOPI = 2 * 3.1415; /** * 生成正弦波 * @param wave * @param waveLen 每段正弦波的长度 * @param length 总长度 * @return */ public static byte[] sin(byte[] wave, int waveLen, int length) { for (int i = 0; i < length; i++) { wave[i] = (byte) (HEIGHT * (1 - Math.sin(TWOPI * ((i % waveLen) * 1.00 / waveLen)))); } return wave; }初始化 AudioTrack 首先传入一个指定频率,这里先将声音总频率设置为 44100,而后计算出单个正弦波(也就是 2PI)的长度,最后将单个正弦波的长度乘以频率获得声波的实际频率,这样的是为了避免声波最后出现一段空的声波。 而后将参数传入上述的 sin 方法中获得正弦波。
AudioFormat.ENCODING_PCM_8BIT 就是指定 AudioTrack 使用 8 位采样率。
/** * 设置频率 * @param rate */public void start(int rate) { if (rate > 0) { Hz = rate; waveLen = 44100 / Hz; length = waveLen * Hz; audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO, // CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT, length, AudioTrack.MODE_STREAM); //生成正弦波 wave = SinWave.sin(wave, waveLen, length); if (audioTrack != null) { audioTrack.play(); } } else { return; }}AudioTrack.play() 是还不能播放声音的,由于这个时候 AudioTrack 里面还没有声波数据。下面这段代码喂数据才能真的播放声音:
audioTrack.write(wave, 0, length);这种生产的方法,在频率高的时候,就会产生误差,频率越高,误差越大。
二、生成不同分贝和频率的纯音
根据不同分贝,不同频率的生成纯音。
- 初始化 AudioTrack
- 播放 audioTrackz.play()
- 喂数据 AudioTrackZThread
private int sampleRateInHz = 16000; // 采样率,MAX 44100 private int mChannel = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 声道 :单声道 private int mSampBit = AudioFormat.ENCODING_PCM_16BIT;// 采样精度 :16bit private AudioTrackZThread audioTrackZThread; private boolean isRunning = false; private AudioTrack audioTrackz; public WaveOutZ() { int bufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, mChannel, mSampBit); audioTrackz = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, mChannel, mSampBit, bufferSize * 2, AudioTrack.MODE_STREAM); audioTrackz.setStereoVolume(1.0f, 1.0f); audioTrackz.play(); } public void palyWaveZ(float rate, int db) { if (audioTrackZThread==null) { audioTrackZThread = new AudioTrackZThread(); audioTrackZThread.start(); } audioTrackZThread.setDb(rate,db); } public void colseWaveZ() { if (audioTrackz != null) { if (!AudioTrackZThread.interrupted()) { isRunning = false; audioTrackZThread=null; } } } class AudioTrackZThread extends Thread { private short m_iAmp = Short.MAX_VALUE; private short m_bitDateZ[] = new short[44100]; private double x = 2.0 * Math.PI * 8250.0 / 44100.0; private int mM_bitDateZSize; public void setDb(float rate, int db) { x = 2.0 * Math.PI * rate / 44100.0; m_iAmp = (short) ((Math.pow(10.0, db / 20.0) * 1.414) * Short.MAX_VALUE); for (int i = 0; i < 44100; i++) { m_bitDateZ[i] = (short) (m_iAmp * Math.sin(x * i)); } mM_bitDateZSize = m_bitDateZ.length; } @Override public void run() { isRunning = true; do { audioTrackz.write(m_bitDateZ, 0, mM_bitDateZSize); } while (isRunning); super.run(); } }说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Android 纯音生成方法
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Android 纯音生成方法