Question

i have been trying to generate a linear Chirp signal using smartphone speakers. i wrote a code following this equation that i found here.

the equation looks logical to me but when i tried to test on high frequencies like 24KHz or 26KHz the sound is still audible and gets out of the speakers though my smartphone doesnt support frequencies over 22KHz.

Please if you notice anything wrong with my code, you will be giving me a great help.

public class MainActivity extends Activity {  

int duration=1;
int sampleRate=44100;
int numSample=duration*sampleRate;
double sample[]=new double[numSample];
double freq1=23000;
double freq2=24000;
byte[] generatedSnd= new byte[2*numSample];
Handler handler=new Handler();


@Override 
 protected void onCreate(Bundle savedInstanceState) {  

 super.onCreate(savedInstanceState);  
 setContentView(R.layout.activity_main);

 Thread thread=new Thread(new Runnable(){
           public void run(){
                    try {
                         genTone();
                        } 
                   catch (IOException e) {
        // TODO Auto-generated catch block                                                                                                                                                                                          
                        e.printStackTrace();
                                         }
          handler.post(new Runnable(){
                 public void run(){
                   playSound();
      }


   });

  }
  });



 thread.start();

  }    

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

}
void genTone() throws IOException{

  double instfreq=0, numerator;
for (int i=0;i<numSample; i++ )
    {
    numerator=(double)(i)/(double)numSample;
    instfreq    =freq1+(numerator*(freq2-freq1));
     if ((i % 1000) == 0) {
               Log.e("Current Freq:", String.format("Freq is:  %f at loop %d of %d", instfreq, i, numSample));
            }
    sample[i]=Math.sin(2*Math.PI*i/(sampleRate/instfreq));

    }
    int idx = 0;
        for (final double dVal : sample) {
            // scale to maximum amplitude
            final short val = (short) ((dVal * 32767)); // max positive sample for signed 16 bit integers is 32767
            // in 16 bit wave PCM, first byte is the low order byte (pcm: pulse control modulation)
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);


        }
 void playSound(){
    AudioTrack audioTrack= null;
        try{
            audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, AudioTrack.MODE_STATIC);
            audioTrack.write(generatedSnd, 0, generatedSnd.length);
        audioTrack.play();
Was it helpful?

Solution

What you are experiencing is a phenomenon known as aliasing. For more information, read about the Nyquist Theorem. Essentially what this means is that you can reproduce any frequency up to 1/2 of the sample rate. But once you cross that threshold, the frequency begins folding back such that a sine at sample rate plus 1kHz is indistinguishable from a sine at sample rate minus 1kHz, and so on. It's very similar to something you might have seen on film where a car wheel appears to stop or even move backward (the wagon wheel effect). The best solution to your problem is to prevent the user from entering a frequency greater than half the sample rate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top