To control the EMGRobotics Audio Dual Motor Controller Board (ADMCB ) and the EMGRobotics Audio Dual Servo Controller Board (ADSCB) you need to generate tones between the frequencies of 1000hz to 10000hz.

This is easily done in Android using the AudioTrack class.  The AudioTrack class lets you play pcm data from a memory buffer.  PCM is un-encoded audio.  It is very easy to produce pure tones in PCM using trigonometry, specifically, the sine function.

Click on above image for source of image.

The formula for a sinewave is (from Wikipedia)

y(t) = A \cdot \sin(2 \pi f t + \phi) = A \cdot \sin(\omega t + \phi)

where:

  • A, the amplitude, is the peak deviation of the function from zero.
  • f, the ordinary frequency, is the number of oscillations (cycles) that occur each second of time.
  • ω = 2πf, the angular frequency, is the rate of change of the function argument in units of radians per second
  • φ, the phase, specifies (in radians) where in its cycle the oscillation is at t = 0.
    • When φ is non-zero, the entire waveform appears to be shifted in time by the amount φ/ω seconds. A negative value represents a delay, and a positive value represents an advance.

 

Using the Android Math.sin() function we can generate a pure sinewave in a memory buffer, then use the AudioTrack class to play the sinewave out the headphone jack.  The following Android Java code creates a pure tone (sinewave) at the Frequency specified, storing it in the buffer called GeneratedSound[].  This code generates a stereo signal with the exact same tone on both channels.  It is possible to play different tones on different channels.

    // http://stackoverflow.com/questions/2413426/playing-an-arbitrary-ton...

    // originally from http://marblemice.blogspot.com/2010/04/generate-and-play-tone-in-an...

    // and modified by Steve Pomeroy <steve@staticfree.info>

    void genTone( double Frequency, byte GeneratedSound[] )

    {

        // fill out the array

        for (int i = 0; i < (numSamples); ++i) {

            sample[i] = Math.sin(2 * Math.PI * i / (sampleRate/Frequency));

        }

        

        // 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 - Stereo

            GeneratedSound[idx++] = (byte) (val & 0x00ff);

            GeneratedSound[idx++] = (byte) ((val & 0xff00) >>> 8);

            GeneratedSound[idx++] = (byte) (val & 0x00ff);

            GeneratedSound[idx++] = (byte) ((val & 0xff00) >>> 8);

        }

    }

Use the Android AudioTrack class to play the contents of the buffer out the audio jack.

The sinewave buffer is written to the AudioTrack class using the write() method.  This method is blocking.  It does not return until the AudioTrack class is ready to except a new buffer.  To avoid blocking the primary thread, a new thread is created.  The write() is executed within this new thread.

    Handler handler = new Handler();

    

    final AudioTrack audioTrack = new AudioTrack(

                                                                                      AudioManager.STREAM_MUSIC,

                                                                                     (int)sampleRate,

                                                                                    AudioFormat.CHANNEL_OUT_STEREO,

                                                                                    AudioFormat.ENCODING_PCM_16BIT,

                                                                                    8*AudioTrack.getMinBufferSize (

                                                                                                                              (int)sampleRate,

                                                                                                                             AudioFormat.CHANNEL_OUT_STEREO,

                                                                                                                             AudioFormat.ENCODING_PCM_16BIT),

                                                                                 AudioTrack.MODE_STREAM);    

//------------------------------------------------------------------------------------------

//

//  Tone Generating Code

//

//------------------------------------------------------------------------------------------

    void PlayStream()

    {

   // mPosition = Scalar(Xpos,Ypos,LastX,ObjectArea)

    

   // Use a new tread as this can take a while

        final Thread thread = new Thread(new Runnable() 

        {

                    public void run() 

                    {

                               while( KeepRunning )

                    {

                    if( mPosition.val[0] > 0 )

                              audioTrack.write(ForwardSnd, 0, ForwardSnd.length);

                    else

                    {

                             if( mPosition.val[2] > mCenter )

                                      audioTrack.write(LeftSnd, 0, LeftSnd.length);

                           else if( mPosition.val[2] > 0 )

                                     audioTrack.write(RightSnd, 0, RightSnd.length);

                    }

              

                    try { Thread.sleep(50);

                            } catch (InterruptedException e) {

                                // TODO Auto-generated catch block

                                e.printStackTrace();

                            }

                    }

                    }

        });

        thread.start();

    }

 

//------------------------------------------------------------------------------------------

//

//  Tracking

//

//------------------------------------------------------------------------------------------    

    private Scalar mPosition;

    

//------------------------------------------------------------------------------------------

//

//  Tone Generating Code

//

//------------------------------------------------------------------------------------------    

    private final double duration = 0.1; // seconds

    private final double sampleRate = 44100.0;

    private final int numSamples = (int)(duration * sampleRate);

    private final double sample[] = new double[numSamples];

    private boolean KeepRunning = true;

    

    private final byte ForwardSnd[] = new byte[4 * numSamples];

    private final byte RightSnd[]   = new byte[4 * numSamples];

    private final byte LeftSnd[]    = new byte[4 * numSamples];

Views: 8685

Comment

You need to be a member of buildsmartrobots to add comments!

EMGRobotics

© 2017   Created by eric gregori.   Powered by

Badges  |  Report an Issue  |  Terms of Service