我正在制作一个带有一系列频率值(即440Hz,880Hz,1760Hz)的类,并播放它们如何组合成单个AudioTrack的声音.我不是一个合理的程序员,所以我自己写这篇文章很困难,我认为对于经验丰富的声音程序员来说这是一个相对容易的问题.以下是play方法中的一些代码:
public void play() {
// Get array of frequencies with their relative strengths
double[][] soundData = getData();
// TODO
// Perform a calculation to fill an array with the mixed sound - then play it in an infinite loop
// Need an AudioTrack that will play calculated loop
// Track sample info
int numOfSamples = DURATION * SAMPLE_RATE;
double sample[] = new double[numOfSamples];
byte sound[] = new byte[2 * numOfSamples];
// fill out the array
for (int i = 0; i < numOfSamples; ++i) {
sample[i] = Math.sin(2 * Math.PI * i / (SAMPLE_RATE / 440));
}
int i = 0;
for (double dVal : sample) {
// scale to maximum amplitude
final short val = (short) ((dVal * 32767));
// in 16 bit wav PCM,first byte is the low order byte
sound[i++] = (byte) (val & 0x00ff);
sound[i++] = (byte) ((val & 0xff00) >>> 8);
}
// Obtain a minimum buffer size
int minBuffer = AudioTrack.getMinBufferSize(SAMPLE_RATE,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);
if (minBuffer > 0) {
// Create an AudioTrack
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,SAMPLE_RATE,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT,numOfSamples,AudioTrack.MODE_STATIC);
// Write audio data to track
track.write(sound,sound.length);
// Begin playing track
track.play();
}
// Once everything has successfully begun,indicate such.
isPlaying = true;
}
现在,这段代码只播放音乐会A(440Hz).这是测试此代码是否有效.现在,我需要采取一堆频率,执行某种计算,并编写样本数据.
最佳答案
好的,所以答案确实是一个简单的求和循环.在这里,只需将原始循环替换为for循环:
// fill out the array
for (int i = 0; i < numOfSamples; ++i) {
double valueSum = 0;
for (int j = 0; j < soundData.length; j++) {
valueSum += Math.sin(2 * Math.PI * i / (SAMPLE_RATE / soundData[j][0]));
}
sample[i] = valueSum / soundData.length;
}
现在,这样做只需要采用所有可能的频率,将它们一起添加到变量valueSum中,然后将其除以频率数组的长度soundData,这是一个简单的平均值.这产生了任意长的频率阵列的良好正弦波混合.