如何在 Android 中轻松生成合成和弦声音?

发布于 2024-10-24 04:38:52 字数 1492 浏览 2 评论 0原文

如何在 Android 中轻松生成合成和弦声音? 我希望能够使用 8 位动态生成游戏中的音乐。 尝试过使用AudioTrack,但尚未获得良好的声音效果。

有什么例子吗?

我尝试过以下代码但没有成功:

public class BitLoose {
    private final int duration = 1; // seconds
    private final int sampleRate = 4200;
    private final int numSamples = duration * sampleRate;
    private final double sample[] = new double[numSamples];

    final AudioTrack audioTrack;

    public BitLoose() {
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_8BIT, numSamples,
                AudioTrack.MODE_STREAM);
        audioTrack.play();
    }

    public void addTone(final int freqOfTone) {
        // fill out the array
        for (int i = 0; i < numSamples; ++i) {
            sample[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));
        }

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        final byte generatedSnd[] = new byte[numSamples];

        int idx = 0;
        for (final double dVal : sample) {
            // scale to maximum amplitude
            final short val = (short) ((((dVal * 255))) % 255);
            // in 16 bit wav PCM, first byte is the low order byte
            generatedSnd[idx++] = (byte) (val);
        }
        audioTrack.write(generatedSnd, 0, sampleRate);
    }

    public void stop() {
        audioTrack.stop();
    }

How to easily Generate Synth Chords Sounds in Android?
I wanna be able to generate dynamically an in game Music using 8bit.
Tried with AudioTrack, but did not get good results of nice sounds yet.

Any examples out there?

I have tried the following code without success:

public class BitLoose {
    private final int duration = 1; // seconds
    private final int sampleRate = 4200;
    private final int numSamples = duration * sampleRate;
    private final double sample[] = new double[numSamples];

    final AudioTrack audioTrack;

    public BitLoose() {
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_8BIT, numSamples,
                AudioTrack.MODE_STREAM);
        audioTrack.play();
    }

    public void addTone(final int freqOfTone) {
        // fill out the array
        for (int i = 0; i < numSamples; ++i) {
            sample[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));
        }

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        final byte generatedSnd[] = new byte[numSamples];

        int idx = 0;
        for (final double dVal : sample) {
            // scale to maximum amplitude
            final short val = (short) ((((dVal * 255))) % 255);
            // in 16 bit wav PCM, first byte is the low order byte
            generatedSnd[idx++] = (byte) (val);
        }
        audioTrack.write(generatedSnd, 0, sampleRate);
    }

    public void stop() {
        audioTrack.stop();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

猫九 2024-10-31 04:38:52

我认为声音不好是由于音频格式造成的:AudioFormat.ENCODING_PCM_8BIT 使用无符号样本,因此 1 和 -1 之间的正弦必须转换为 0-255 字节值,请尝试以下操作:

for (final double dVal : sample) {
    final short val = (short) ((dVal + 1) / 2 * 255) ;
    generatedSnd[idx++] = (byte) val;
}

尝试将采样率更改为 11025,因为 4200某些设备可能不支持:

private final int sampleRate = 11025;

I think that bad sound is due to audio format: AudioFormat.ENCODING_PCM_8BIT uses unsigned samples, so a sine between 1 and -1 must be converted to 0-255 byte values, try this:

for (final double dVal : sample) {
    final short val = (short) ((dVal + 1) / 2 * 255) ;
    generatedSnd[idx++] = (byte) val;
}

Try also to change sample rate to 11025, because 4200 may be unsupported on some devices:

private final int sampleRate = 11025;
樱&纷飞 2024-10-31 04:38:52

除了答案 1 之外,您还应该使用:
样本[i] = Math.sin(2 * Math.PI * i / ((double)sampleRate / freqOfTone));
而不是
样本[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));

Apart from answer 1 you should use:
sample[i] = Math.sin(2 * Math.PI * i / ((double) sampleRate / freqOfTone));
instead of
sample[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文