Back to project page Modulo.
The source code is released under:
GNU General Public License
If you think the Android project Modulo listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.modulo; //from w w w .j ava 2 s .co m import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; public class Oscillator { public Oscillator() { // 440hz = "concert A", standard pitch frequency = 440; volume = 50; isPlaying = false; bufferSize = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); buffer = new short[bufferSize]; sample = new short[sampleRate]; audioTrack = initializeAudioTrack(); // Waveform arrays sqr = new short[sampleRate]; sin = new short[sampleRate]; tri = new short[sampleRate]; saw = new short[sampleRate]; // Pre-generates the lookup tables for each waveform, allows instant // waveform switching sqr = generateSqr(); sin = generateSin(); tri = generateTri(); saw = generateSaw(); // Sine wave is default sample = sin; } public void pause() { // Checks if audioTrack is initialized and if so, immediately pauses and // flushes the audio data if (audioTrack.getState() == AudioTrack.STATE_INITIALIZED) { setIsPlaying(false); audioTrack.pause(); audioTrack.flush(); } } // Sets up an AudioTrack public AudioTrack initializeAudioTrack() { AudioTrack returnTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, buffer.length, AudioTrack.MODE_STREAM); Float scaled = (float)(volume/100.0f); returnTrack.setStereoVolume(AudioTrack.getMaxVolume() * scaled, AudioTrack.getMaxVolume() * scaled); return returnTrack; } public void play() { if (audioTrack.getState() != AudioTrack.STATE_INITIALIZED) { audioTrack = initializeAudioTrack(); } setIsPlaying(true); fillBuffer(); audioTrack.play(); } public void stop() { if (audioTrack.getState() == AudioTrack.STATE_INITIALIZED) { setIsPlaying(false); audioTrack.pause(); audioTrack.flush(); audioTrack.release(); } } public void setFreq(int freq) { frequency = freq; } public int getFreq() { return frequency; } public void setIsPlaying(boolean boo) { isPlaying = boo; } public boolean getIsPlaying() { return isPlaying; } public void setVolume(int vol) { volume = vol; Float scaled = (float) (volume / 100.0f); audioTrack.setStereoVolume(AudioTrack.getMaxVolume() * scaled, AudioTrack.getMaxVolume() * scaled); } public int getVolume() { return volume; } // Generates the sine wave lookup table private short[] generateSin() { short[] returnArray = new short[sampleRate]; for (int i = 0; i < sampleRate; i++) { returnArray[i] = (short) ((float) Short.MIN_VALUE * (Math.sin((2.0f * (float) Math.PI * ((float) i)) / ((float) sampleRate)))); } return returnArray; } // Generates the sawtooth wave lookup table private short[] generateSaw() { short[] returnArray = new short[sampleRate]; for (int i = 0; i < sampleRate; i++) { returnArray[i] = (short) ((float) Short.MIN_VALUE + (((float) i * (2.0f * (float) Short.MAX_VALUE)) / (float) sampleRate)); } return returnArray; } // Generates the triangle wave lookup table private short[] generateTri() { short[] returnArray = new short[sampleRate]; for (int i = 0; i < sampleRate; i++) { // First quarter of the waveform lookup table if (i < (sampleRate / 4)) { returnArray[i] = (short) (((float) i * (4.0f * (float) Short.MAX_VALUE)) / (float) sampleRate); } // Last quarter of the waveform lookup table else if (i > (3 * (sampleRate / 4))) { returnArray[i] = (short) ((((float) i * (4.0f * (float) Short.MAX_VALUE)) / (float) sampleRate) - 2.0f * Short.MAX_VALUE); } // Middle two sections of the waveform lookup table else { returnArray[i] = (short) ((float) 2.0f * Short.MAX_VALUE - (((float) i * (4.0f * (float) Short.MAX_VALUE)) / (float) sampleRate)); } } return returnArray; } // Generates the square wave lookup table private short[] generateSqr() { short[] returnArray = new short[sampleRate]; // The square wave is represented by two values (Short.MAX_VALUE and // Short.MIN_VALUE) // with the max value for the first half of the waveform, and the min // for the second for (int i = 0; i < sampleRate; i++) { if (i < (sampleRate / 2)) { returnArray[i] = Short.MAX_VALUE; } else { returnArray[i] = Short.MIN_VALUE; } } return returnArray; } public void fillBuffer() { for (int i = 0; i < buffer.length; i++) { // Causes phase to wrap around to the front of the lookup table // when it exceeds its length phase %= sample.length; // Sets the short at buffer[i] to the value found in the lookup // table // of the current waveform sample buffer[i] = sample[phase]; // Increments the phase by the current frequency, allowing it to // step // through the table at the correct speed and resulting in a change // of pitch phase += frequency; } // Writes the buffer to the audioTrack audioTrack.write(buffer, 0, buffer.length); } // Changes the waveform public void setWave(int pos) { switch (pos) { case 0: sample = sin; break; case 1: sample = saw; break; case 2: sample = sqr; break; case 3: sample = tri; break; default: sample = sin; break; } } private int frequency; public static final int MAX_FREQUENCY = 20000; public static final int MIN_FREQUENCY = 20; private boolean isPlaying; private AudioTrack audioTrack; private int volume; private final int sampleRate = 44100; private int bufferSize; private short[] sample, buffer, sin, sqr, tri, saw; private int phase; }