Filling Audio Buffer to Generate Waves in the PSLab Android App

The PSLab Android App works as an oscilloscope and a wave generator using the audio jack of the Android device. The implementation of the oscilloscope in the Android device using the in-built mic has been discussed in the blog post “Using the Audio Jack to make an Oscilloscope in the PSLab Android App” and the same has been discussed in the context of wave generator in the blog post “Implement Wave Generation Functionality in the PSLab Android App”. This post is a continuation of the post related to the implementation of wave generation functionality in the PSLab Android App. In this post, the subject matter of discussion is the way to fill the audio buffer so that the resulting wave generated is either a Sine Wave, a Square Wave or a Sawtooth Wave. The resultant audio buffer would be played using the AudioTrack API of Android to generate the corresponding wave. The waves we are trying to generate are periodic waves. Periodic Wave: A wave whose displacement has a periodic variation with respect to time or distance, or both. Thus, the problem reduces to generating a pulse which will constitute a single time period of the wave. Suppose we want to generate a sine wave; if we generate a continuous stream of pulses as illustrated in the image below, we would get a continuous sine wave. This is the main concept that we shall try to implement using code. Initialise AudioTrack Object AudioTrack object is initialised using the following parameters: STREAM TYPE: Type of stream like STREAM_SYSTEM, STREAM_MUSIC, STREAM_RING, etc. For wave generation purposes we are using stream music. Every stream has its own maximum and minimum volume level.   SAMPLING RATE: It is the rate at which the source samples the audio signal. BUFFER SIZE IN BYTES: Total size of the internal buffer in bytes from where the audio data is read for playback. MODES: There are two modes- MODE_STATIC: Audio data is transferred from Java to the native layer only once before the audio starts playing. MODE_STREAM: Audio data is streamed from Java to the native layer as audio is being played. getMinBufferSize() returns the estimated minimum buffer size required for an AudioTrack object to be created in the MODE_STREAM mode. minTrackBufferSize = AudioTrack.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); audioTrack = new AudioTrack(       AudioManager.STREAM_MUSIC,       SAMPLING_RATE,       AudioFormat.CHANNEL_OUT_MONO,       AudioFormat.ENCODING_PCM_16BIT,       minTrackBufferSize,       AudioTrack.MODE_STREAM); Fill Audio Buffer to Generate Sine Wave Depending on the values in the audio buffer, the wave is generated by the AudioTrack object. Therefore, to generate a specific kind of wave, we need to fill the audio buffer with some specific values. The values are governed by the wave equation of the signal that we want to generate. public short[] createBuffer(int frequency) {   short[] buffer = new short[minTrackBufferSize];   double f = frequency;   double q = 0;   double level = 16384;   final double K = 2.0 * Math.PI / SAMPLING_RATE;   for (int i = 0; i < minTrackBufferSize; i++) {         f += (frequency - f) / 4096.0;         q += (q < Math.PI) ?…

Continue ReadingFilling Audio Buffer to Generate Waves in the PSLab Android App

Implement Wave Generation Functionality in The PSLab Android App

The PSLab Android App works as an Oscilloscope using the audio jack of Android device. The implementation for the scope using in-built mic is discussed in the post Using the Audio Jack to make an Oscilloscope in the PSLab Android App. Another application which can be implemented by hacking the audio jack is Wave Generation. We can generate different types of signals on the wires connected to the audio jack using the Android APIs that control the Audio Hardware. In this post, I will discuss about how we can generate wave by using the Android APIs for controlling the audio hardware. Configuration of Audio Jack for Wave Generation Simply cut open the wire of a cheap pair of earphones to gain control of its terminals and attach alligator pins by soldering or any other hack(jugaad) that you can think of. After you are done with the tinkering of the earphone jack, it should look something like shown in the image below. If your earphones had mic, it would have an extra wire for mic input. In any general pair of earphones the wire configuration is almost the same as shown in the image below. Android APIs for Controlling Audio Hardware AudioRecord and AudioTrack are the two classes in Android that manages recording and playback respectively. For Wave Generation application we only need AudioTrack class. Creating an AudioTrack object: We need the following parameters to initialise an AudioTrack object. STREAM TYPE: Type of stream like STREAM_SYSTEM, STREAM_MUSIC, STREAM_RING, etc. For wave generation purpose we are using stream music. Every stream has its own maximum and minimum volume level. SAMPLING RATE: it is the rate at which source samples the audio signal. BUFFER SIZE IN BYTES: total size in bytes of the internal buffer from where the audio data is read for playback. MODES: There are two modes MODE_STATIC: Audio data is transferred from Java to native layer only once before the audio starts playing. MODE_STREAM: Audio data is streamed from Java to native layer as audio is being played. getMinBufferSize() returns the estimated minimum buffer size required for an AudioTrack object to be created in the MODE_STREAM mode. private int minTrackBufferSize; private static final int SAMPLING_RATE = 44100; minTrackBufferSize = AudioTrack.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); audioTrack = new AudioTrack(       AudioManager.STREAM_MUSIC,       SAMPLING_RATE,       AudioFormat.CHANNEL_OUT_MONO,       AudioFormat.ENCODING_PCM_16BIT,       minTrackBufferSize,       AudioTrack.MODE_STREAM); Function createBuffer() creates the audio buffer that is played using the audio track object i.e audio track object would write this buffer on playback stream. Function below fills random values in the buffer due to which a random signal is generated. If we want to generate some specific wave like Square Wave, Sine Wave, Triangular Wave, we have to fill the buffer accordingly. public short[] createBuffer(int frequency) {   // generating a random buffer for now   short[] buffer = new short[minTrackBufferSize];   for (int i = 0; i < minTrackBufferSize; i++) {       buffer[i] = (short) (random.nextInt(32767) + (-32768));   }   return buffer; } We created a write() method and passed the audio buffer created in above step as an argument to…

Continue ReadingImplement Wave Generation Functionality in The PSLab Android App