如何生成特定的声音频率?

16

我正在开发一款安卓应用程序,我想产生1KHz到20KHz之间的频率范围内的声音。是否有任何方法可以生成特定频率的声音。


1
您所描述的范围不是超声波。也就是说,它仍然可以被听到。 - Sjoerd
3
只是挑刺一下:超声波从20千赫兹开始。你想要的频率范围属于声学范畴。 - Ted Hopp
1
@alextsc,如果涉及到BlackBerry或Java-ME,欢迎回答。 - Lucifer
请查看android.media.ToneGenerator - Ted Hopp
公平地说,大多数成年人听不到18khz以上的声音(参加了太多的摇滚音乐会)。 - Reid
1个回答

21

我在另一个SO帖子中找到了这段代码。据我所知,它仍然有些错误,但应该可以解决这个问题。

public class PlaySound extends Activity {
    // originally from http://marblemice.blogspot.com/2010/04/generate-and-play-tone-in-android.html
    // and modified by Steve Pomeroy <steve@staticfree.info>
    private final int duration = 3; // seconds
    private final int sampleRate = 8000;
    private final int numSamples = duration * sampleRate;
    private final double sample[] = new double[numSamples];
    private final double freqOfTone = 440; // hz

    private final byte generatedSnd[] = new byte[2 * numSamples];

    Handler handler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Use a new tread as this can take a while
        final Thread thread = new Thread(new Runnable() {
            public void run() {
                genTone();
                handler.post(new Runnable() {

                    public void run() {
                        playSound();
                    }
                });
            }
        });
        thread.start();
    }

    void genTone(){
        // 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.
        int idx = 0;
        for (final 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
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

        }
    }

    void playSound(){
        final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, numSamples,
                AudioTrack.MODE_STATIC);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);
        audioTrack.play();
    }
}

嘿,我刚在这里找到了同样的东西(http://marblemice.blogspot.com/2010/04/generate-and-play-tone-in-android.html)。据说那个链接上的代码已经更新以修复漏洞。 - Ted Hopp
是的,但根据评论,它仍然有一些问题...无论如何,这是一个很好的基础。 - Reid
1
这段代码存在问题,即使将sampleRate设置为44100,它仍无法回放超过17000Hz的任何内容。例如,在Flash中,这些算法可以正常工作,而且当这些频率来自文件时,我使用的手机也可以播放它们。有人知道如何解决这个问题吗? - Igor Čordaš
@Reid 很遗憾,这段代码已经无法在较新版本的Android上运行。 - SparkyNZ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接