package jp.sourceforge.ocmml.android; import java.nio.DoubleBuffer; import java.util.ArrayList; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Process; public class Sequencer implements Runnable { public static final int BUFFER_SIZE = 8192; private static final int STEP_PRE = 0; private static final int STEP_TRACK = 1; private static final int STEP_POST = 2; public Sequencer(int multiply) { mTracks = new ArrayList(); mMultiple = multiply; mBufferSize = BUFFER_SIZE * multiply; setMasterVolume(100); Channel.initialize(mBufferSize); } public void clearTracks() { mTracks.clear(); } public void addTrack(Track track) { mTracks.add(track); } public void createPipes(int number) { Channel.createPipes(number); } public int getMasterVolume() { return mMasterVolume; } public void setMasterVolume(int value) { mMasterVolume = value; } public void run() { DoubleBuffer samples = DoubleBuffer.allocate(mBufferSize); short[] audioData = new short[BUFFER_SIZE]; int multiply = mMultiple, count = 0, audioDataSize = audioData.length; AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, Sample.RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE, AudioTrack.MODE_STREAM); track.play(); mLoop = true; getSamples(samples); Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO); while (mLoop) { int index = count * BUFFER_SIZE; for (int i = 0; i < BUFFER_SIZE; i++) { double b = samples.get(index + i); short s = (short)(b * 16384); audioData[i] = s; } track.write(audioData, 0, audioDataSize); count++; if (multiply == count) { getSamples(samples); if (mTracks.get(Track.TEMPO_TRACK).isEnd()) mLoop = false; } } track.stop(); } public void stop() { mLoop = false; } private void getSamples(DoubleBuffer samples) { Boolean loop = true; int offset = 0, step = STEP_PRE, trackIndex = 0, trackCount = mTracks.size(); while (loop) { switch (step) { case STEP_PRE: if (trackCount > 0) { mTracks.get(Track.TEMPO_TRACK).getSamples(samples, 0, BUFFER_SIZE, false); } step = STEP_TRACK; trackIndex = Track.FIRST_TRACK; offset = 0; break; case STEP_TRACK: if (trackIndex >= trackCount) step = STEP_POST; else { mTracks.get(trackIndex).getSamples(samples, offset, offset + BUFFER_SIZE, true); offset += BUFFER_SIZE; if (offset >= mBufferSize) { offset = 0; trackIndex++; } } break; case STEP_POST: default: loop = false; break; } } } private ArrayList mTracks; private Boolean mLoop; private int mMultiple; private int mBufferSize; private int mMasterVolume; }