Search code examples
androidgeneratorwavesoundpooltrigonometry

Generate Sine Wave between 10 and 20000Hz using SoundPool


I attempted to generate a Sine Wave using AudioTrack initially. The result was not satisfactory. I then moved to the Soundpool class. I used Audacity to create audiofiles of 1 second and then modified the playback speed (.5 - 2.0) to get the desired frequencies. (Arrays, as there are also saw and triangle wavefiles)

    sig10000[0]=soundPool01.load(context,R.raw.sine10000,1);
    sig2500[0]=soundPool01.load(context,R.raw.sine2500,1);
    sig625[0]=soundPool01.load(context,R.raw.sine625,1);
    sig157[0]=soundPool01.load(context,R.raw.sine156,1);
    sig40[0]=soundPool01.load(context,R.raw.sine40,1);

I then, depending on the chosen frequency, play the audio:

    public void play(){

    Signal s=null;
    float factor;
    for(int i=0;i<this.size();i++){
        s=this.get(i);
            if(s.getFreq()>4999){
                factor = s.getFreq()/10000f;
                s.setStreamID(soundPool01.play(sig10000[s.getWaveType()],.99f,.99f,0,-1,factor));                   
            }else if(s.getFreq()>1249){
                factor = s.getFreq()/2500f;
                s.setStreamID(soundPool01.play(sig2500[s.getWaveType()],.99f,.99f,0,-1,factor));
            }else if(s.getFreq()>312){
                factor = s.getFreq()/625f;
                s.setStreamID(soundPool01.play(sig625[s.getWaveType()],.99f,.99f,0,-1,factor));
            }else if(s.getFreq()>77){
                factor = s.getFreq()/156f;
                s.setStreamID(soundPool01.play(sig157[s.getWaveType()],.99f,.99f,0,-1,factor));
            }else {
                factor = s.getFreq()/40f;
                s.setStreamID(soundPool01.play(sig40[s.getWaveType()],.99f,.99f,0,-1,factor));
            }

    }
}

Now as I see it, the method works fine except for the range 5000-20000 Hz. I'm breaking my head over this, not sure why its not working and I can't find any patterns to the problem.

Is there some fundamental problem with this method?

Thanking you in advance

Edit: "not working explained" When I play sine waves in the range 5000-20000 Hz it is very obvious that the frequency is inaccurate. This means the pitch is way off. E.g. 19000 Hz is too low and easily detectable by ear. What I can say is that 10000 Hz (as does 5000Hz- my mistake), so normal playback rate, is correct. At around 14kHz the signal pitch is no longer correct.

Thoughts/Possible Causes(?): (A) How many steps are there for the playbackspeed (SoundPool)? The documentation says 0.5-2.0 is it possible that this means there is 15 different playbackspeeds? (B) I used Audacity to generate the .ogg files. When I zoom in on the 10000Hz sine I can see it is not too smooth (sample rate 44100) and the wave does not precisely start and end at 0. Could this superposition unwanted signals?


Solution

  • My first guess is physics, not programming.

    There's very little chance that your test device will have a speaker that's physically capable of producing clean 19 Khz output, as that's pretty much senseless. As a result, it will produce other, unintended frequencies if you try to drive it with a 19 Khz signal sampled at 44 Khz.