gpt4 book ai didi

android - 如何在android中生成准确的频率

转载 作者:行者123 更新时间:2023-11-29 02:37:53 24 4
gpt4 key购买 nike

为了在 android 中通过数字生成所需的频率,我知道 2 种方法,每种方法都有自己的大问题。

第一种方式是 PCM_16_bit:

    frequency = (int) frequency;
final int numberOfSamples = duration * sampleRate;
final byte[] generatedSnd = new byte[numberOfSamples * 2];
double dVal;

int idx = 0;
for (int i = 0; i < numberOfSamples; ++i) {
dVal = Math.sin(2 * Math.PI * i / (sampleRate / frequency));

// convert to 16 bit pcm sound array
// assumes the sample buffer is normalised.

// scale to maximum amplitude
short val = (short) ((dVal * 32767));

// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

}

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,
AudioTrack.MODE_STATIC);

audioTrack.write(generatedSnd, 0, generatedSnd.length);

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
loudnessEnhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());

loudnessEnhancer.setTargetGain(maxFrequency - (int) frequency);

}

这仅适用于短值,因此没有精确数字且振幅有限,因此需要依赖于 android 4.4 的 LoudnessEnhancer,这会增加增益并降低质量。

第二种方式是:

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final int numberOfSamples = duration * sampleRate * 4;
final float[] generatedSnd = new float[numberOfSamples];

float amplitude = 2;//Increase in amplitude has a relation with increase in noise.

for (int i = 0; i < numberOfSamples; ++i)
generatedSnd[i] = (float) (Math.sin((2 * Math.PI * i * frequency) / sampleRate)) * amplitude;

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_FLOAT, generatedSnd.length,
AudioTrack.MODE_STATIC);

audioTrack.write(generatedSnd, 0, generatedSnd.length, AudioTrack.WRITE_BLOCKING);

它只增加了一个精度,但为我解决了振幅问题,但它需要低效的 android 5,而且 1 个精度对于像第二钢琴 Octave 这样的非常低的音符是不够的。

是否可以制作更精确的频率?还有其他方法吗?

最佳答案

试试这个,我觉得没问题:

  isPlaying = true;
int sampleRate = 44100;// 44.1 KHz
double dnumSamples = (double) duration * sampleRate;
dnumSamples = Math.ceil(dnumSamples);
int numSamples = (int) dnumSamples;
double[] sample = new double[numSamples];
byte[] generatedSnd = new byte[2 * numSamples];
for (int i = 0; i < numSamples; ++i) { // Fill the sample array
sample[i] = Math.sin(freq * 2 * Math.PI * i / (sampleRate));
}

// convert to 16 bit pcm sound array
// assumes the sample buffer is normalized.
// convert to 16 bit pcm sound array
// assumes the sample buffer is normalised.
int idx = 0;
int i;

int ramp = numSamples / 20; // Amplitude ramp as a percent of sample count

for (i = 0; i < ramp; ++i) { // Ramp amplitude up (to avoid clicks)
// Ramp up to maximum
final short val = (short) (sample[i] * 32767 * i / ramp);
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}

for (i = ramp; i < numSamples - ramp;
++i) { // Max amplitude for most of the samples
// scale to maximum amplitude
final short val = (short) (sample[i] * 32767);
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}

for (i = numSamples - ramp; i < numSamples; ++i) { // Ramp amplitude down
// Ramp down to zero
final short val = (short) (sample[i] * 32767 * (numSamples - i) / ramp);
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}

try {
int bufferSize = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
audioTrack =
new AudioTrack(AudioManager.STREAM_SYSTEM, sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);

audioTrack.setNotificationMarkerPosition(numSamples);
audioTrack.setPlaybackPositionUpdateListener(
new AudioTrack.OnPlaybackPositionUpdateListener() {
@Override public void onPeriodicNotification(AudioTrack track) {
// nothing to do
}

@Override public void onMarkerReached(AudioTrack track) {
// toneStoppedListener.onToneStopped();
}
});

// Sanity Check for max volume, set after write method to handle issue in android
// v 4.0.3
float maxVolume = AudioTrack.getMaxVolume();

if (volume > maxVolume) {
volume = maxVolume;
} else if (volume < 0) {
volume = 0;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
audioTrack.setVolume(volume);
} else {
audioTrack.setStereoVolume(volume, volume);
}

audioTrack.play(); // Play the track
audioTrack.write(generatedSnd, 0, generatedSnd.length); // Load the track
} catch (Exception e) {
e.printStackTrace();
}

关于android - 如何在android中生成准确的频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45965431/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com