2

I'm currently writing a android app for mobile phones to control 2 servo motors.

Therefore I need to create a square wave at 50hz with a high amplitude. I alread had a look at some example code of the AudioManager and AudioTrack class, but I dont really get the clue on how to achieve a basic square wave at 50hz with a hearable amplitude.

Here's what i got so far:

package com.example.rollerball;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.support.v7.app.ActionBarActivity;

public class ToneGenerator
{   
    Thread t;
    int sr = 44100;
    boolean isRunning = true;

    public void startTone()
    {
        isRunning = true;
        t = new Thread() {
            public void run() {
                // set process priority
                setPriority(Thread.MAX_PRIORITY);
                int buffsize = AudioTrack.getMinBufferSize(sr,
                        AudioFormat.CHANNEL_OUT_MONO,
                        AudioFormat.ENCODING_PCM_16BIT);
                // create an audiotrack object
                AudioTrack audioTrack = new AudioTrack(
                        AudioManager.STREAM_MUSIC, sr,
                        AudioFormat.CHANNEL_OUT_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, buffsize,
                        AudioTrack.MODE_STREAM);

                short samples[] = new short[buffsize];
                int amp = 10000;
                double twopi = 8. * Math.atan(1.);
                double fr = 440.f;
                double ph = 0.0;
                // start audio
                audioTrack.play();

                while (isRunning) {

                    for (int i = 0; i < buffsize; i++) {
                        samples[i] = (short) (amp * Math.sin(ph));
                        ph += twopi * fr / sr;
                    }
                    audioTrack.write(samples, 0, buffsize);
                }
                audioTrack.stop();
                audioTrack.release();
            }
        };
        t.start();
    }

    public void stopTone(){   
           isRunning = false;
           try {
             t.join();
           } catch (InterruptedException e) {
             e.printStackTrace();
           }    
          t = null;
        }
}

Maybe some of you guys out there can help me!

Thanks in Advance!

Nop0x
  • 173
  • 1
  • 14

2 Answers2

3

As it stands your code generates a nice clean sine wave with peak amplitude of ±10000. The maximum sample value that can be represented in 16-bit PCM is ±1^15-1 = ±32767 which is ~-10dB of FSD.

You want a square-wave. The code below achieves it (not particularly efficiently).

for (int i = 0; i < buffsize; i++) {
    short s = (amp * Math.sin(ph));
    if (s > 0.0) {
        sample[i] = 32767;
    };

    if (s < 0.0) {
        sample[i] = -32767;
    }
    ph += twopi * fr / sr;
}
marko
  • 9,029
  • 4
  • 30
  • 46
0

I have a code sample from my project. The start/end of the generated tone is controlled by a switch. I think the Thread part would be useful for you.

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Switch;
import android.widget.CompoundButton;

public class MainActivity extends AppCompatActivity {

    Thread t; //Object that hold the audio processing thread
    int sr = 44100; //sampling rate
    boolean isRunning = true; //means of switching on and off

    public Switch switch1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //switch
        switch1 = (Switch) findViewById(R.id.switch1);

        //attach a listener to it
        switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    isRunning = true;
                    t = createToneThread();
                    t.start();
                } else {
                    isRunning = false;
                }
            }
        });

    }

    Thread createToneThread()
    {
        t = new Thread() {
        public void run() {
            //set process priority to maximum to get good performance
            setPriority(Thread.MAX_PRIORITY);
            //set the buffer size
            int buffsize = AudioTrack.getMinBufferSize(sr, AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);
            //create an audiotrack  object
            AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sr,
                    AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, buffsize,
                    AudioTrack.MODE_STREAM);

            //create signal buffer and define the parameters
            short samples[] = new short[buffsize];
            short amp = 10000;

            for (int i = 0; i < buffsize; i+=4) {
                samples[i]   = (short)-amp;
                samples[i+1] = (short)-amp;
                samples[i+2] =  amp;
                samples[i+3] =  amp;
            }

            //start audio
            audioTrack.play();

            //define the synthesis loop
            while (isRunning) {

                audioTrack.write(samples, 0, buffsize);
            }
            //closing  of the audio device
            audioTrack.stop();
            audioTrack.release();

            }
        };
        return t;
    }
}
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96