0

i am creating a small hearing test application for a university project. I have been using some of the code found in: Playing an arbitrary tone with Android

So far i have a button set with a switch statement, so each time it is clicked, it will play tones of increasing frequency. however, when it reaches 4000Hz the sound will no longer play, does anyone have any ideas? Thanks!

public class AutoTest extends MainActivity {

private final int duration = 5; // seconds
private final int sampleRate = 8000;
private final int numSamples = duration * sampleRate;
private final double sample[] = new double[numSamples];
private  double freqOfTone = 250; // hz
private int inc=0;
int count = 0;

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

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


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

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

    for (int i = 0; i < ramp; i++) {
        // scale to maximum amplitude
        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 (int i = ramp; i < numSamples - ramp; i++) {
        // 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 (int i = numSamples - ramp; i < numSamples; i++) {
        // scale to maximum amplitude
        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);

    }
}

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

public void playTone(View view)

{

    //switch statement - auto - increment
    switch(count) {
        case 0:
            break;
        case 1:
            inc+=250;
            break;
        case 2:
            inc+=500;
            break;
        case 3:
            inc+=1000;
            break;

        case 4:
            inc+=2000;
            break;
        case 5:
            inc+=2000;
            break;
        case 6:
            inc+=2000;
            break;


        default:
            Log.d("Values","error message");
            break;
    }
    genTone();
    playSound();
    Log.d("Values","This is the value of count"+ count);
    count++;

here is my code, i would greatly appreciate any help!

Community
  • 1
  • 1
hgzy
  • 11
  • 8

1 Answers1

1

Your sample rate is 8 kHz -

private final int sampleRate = 8000;

Due to the sampling theorem, all frequencies above sample-rate/2 will start aliasing. This means that at 4000 Hz you're actually hearing 0 Hz. At 4001 Hz, you're hearing 1 Hz. etc etc. Here's the wiki page if you're interested in learning more signal processing in the future: Wikipedia - Aliasing

Try changing your sample rate to a higher one (standard 44.1 kHz), that should solve it!

yun
  • 1,243
  • 11
  • 30
  • yeahh i had come to that conclusion myself there! but when i raise the sample rate to 44.1khz, the app will play the first sound at 250hz then crash for some reason! – hgzy Feb 25 '16 at 15:23
  • Weird, what have you seen when you debug it? – yun Feb 25 '16 at 15:26
  • this is the error in logcat: FATAL EXCEPTION: main Process: com.example.lewis.finalproject, PID: 15804 java.lang.IllegalStateException: play() called on uninitialized AudioTrack. at android.media.AudioTrack.play(AudioTrack.java:1141) – hgzy Feb 25 '16 at 15:28
  • Well looks like you're initializing `AudioTrack` incorrectly. I'm not too familiar with the library so I can't help you all the way, but I'm guessing changing the sample rate had something to do with it. – yun Feb 25 '16 at 15:33
  • Thanks, I will look into that now! – hgzy Feb 25 '16 at 15:35
  • Fixed, changing the audio track form AudioTrack.MODE_STREAM to MODE_STATIC + using the 44.1Khz sample rate sorted it out thanks. – hgzy Feb 25 '16 at 15:44