package jp.sourceforge.ocmml.android; import java.nio.DoubleBuffer; import jp.sourceforge.ocmml.android.modulators.FCNoise; import jp.sourceforge.ocmml.android.modulators.GBLongNoise; import jp.sourceforge.ocmml.android.modulators.GBShortNoise; import jp.sourceforge.ocmml.android.modulators.GBWave; import jp.sourceforge.ocmml.android.modulators.Modulator; import jp.sourceforge.ocmml.android.modulators.Noise; import jp.sourceforge.ocmml.android.modulators.Pulse; public class Channel { public static final int OUTPUT_DEFAULT = 0; public static final int OUTPUT_OVERWRITE = 1; public static final int OUTPUT_ADD = 2; public static final int PITCH_RESOLUTION = 100; public static void initialize(int sampleLength) { if (!sInitialized) { int i = 0; sSampleLength = sampleLength; sSamples = DoubleBuffer.allocate(sampleLength); int fl = sFrequencyLength = sFrequencyMap.length; for (i = 0; i < fl; i++) sFrequencyMap[i] = Sample.FREQUENCY_BASE * Math.pow(2.0, (i - 69.0 * PITCH_RESOLUTION) / (12.0 * PITCH_RESOLUTION)); sVolumeMap[0] = 0.0; for (i = 1; i < 128; i++) sVolumeMap[i] = Math.pow(10.0, (i - 127) * (48.0 / (127 * 20.0))); sInitialized = true; } } public static void release() { sPipeArray = null; sSamples = null; } public static void createPipes(int number) { sPipeArray = new double[number][]; sPipeArrayLength = number; int sl = sSampleLength; for (int i = 0; i < number; i++) { sPipeArray[i] = new double[sl]; for (int j = 0; j < sl; j++) sPipeArray[i][j] = 0; } } public static double getFrequencyFromIndex(int index) { index = Math.min(Math.max(index, 0), Math.max(sFrequencyLength, 1) - 1); return sFrequencyMap[index]; } public Channel() { mVCO = new Envelope(0.0, 60.0 / 127.0, 30.0 / 127, 1.0 / 127.0); mVCF = new Envelope(0.0, 30.0 / 127.0, 0.0, 1.0); mOsc1 = new Oscillator(); mMod1 = mOsc1.getCurrentModulator(); mOsc2 = new Oscillator(); mOsc2.makeAsLFO(); mMod2 = mOsc2.getCurrentModulator(); mFilter = new Filter(); mOsc2Connect = mEnableFilter = false; mFormant = new Formant(); mVolumeMode = 0; mExpression = 0; mOnCounter = 0; mLFODelay = 0; mLFODepth = 0; mLFOEnd = 0; mLPFAmount = 0; mLPFFrequency = 0; mLPFResonance = 0; setPan(64); setExpression(127); setVelocity(100); mFrequencyIndex = 0; setInput(new int[] { Track.EVENT_TYPE_INPUT, 0, 0, 0 }); setOutput(new int[] { Track.EVENT_TYPE_OUTPUT, 0, OUTPUT_DEFAULT, 0 }); } public void enableNote(int[] arg) { int index = arg[Track.EVENT_DELTA + 1], velocity = arg[Track.EVENT_DELTA + 2]; setNoteIndex(index); mVCO.trigger(false); mVCF.trigger(true); mMod1.resetPhase(); mMod2.resetPhase(); mFilter.reset(); mOnCounter = 0; setVelocity(velocity); FCNoise fcNoise = (FCNoise) mOsc1 .getModulatorFromForm(Oscillator.FC_NOISE); fcNoise.setNoiseFrequencyIndex(index); GBLongNoise longNoise = (GBLongNoise) mOsc1 .getModulatorFromForm(Oscillator.GB_LONG_NOISE); longNoise.setNoiseFrequencyIndex(index); GBShortNoise shortNoise = (GBShortNoise) mOsc1 .getModulatorFromForm(Oscillator.GB_SHORT_NOISE); shortNoise.setNoiseFrequencyIndex(index); } public void disableNote() { mVCO.release(); mVCF.release(); } public void close() { disableNote(); mFilter.setSwitch(Filter.NONE); } public void setLFO(int[] arg, double frequency) { int mainForm = arg[Track.EVENT_DELTA + 1] - 1; mOsc2.setForm(mainForm); mMod2 = mOsc2.getModulatorFromForm(mainForm); mOsc2Sign = arg[Track.EVENT_DELTA + 7] == 1 ? -1.0 : 1.0; if (mainForm >= Oscillator.MAX) mOsc2Connect = false; if (mainForm == Oscillator.GB_WAVE) { GBWave wave = (GBWave) mOsc2.getModulatorFromForm(mainForm); wave.setWaveIndex(arg[1]); } mLFODepth = arg[Track.EVENT_DELTA + 3]; mOsc2Connect = mLFODepth == 0 ? false : true; mMod2.setFrequency(frequency); mMod2.resetPhase(); Noise noise = (Noise) mOsc2.getModulatorFromForm(Oscillator.NOISE); noise.setNoiseFrequency(frequency / Sample.RATE); mLFODelay = arg[Track.EVENT_DELTA + 5]; int time = arg[Track.EVENT_DELTA + 6]; mLFOEnd = time > 0 ? mLFODelay + time : 0; } public void getSamples(DoubleBuffer samples, int start, int delta, int max) { int end = Math.min(start + delta, max), frequencyIndex = 0; if (!mVCO.isPlaying()) { for (int i = start; i < end; i++) sSamples.put(i, 0); } else if (mInSens < 0.000001) { if (!mOsc2Connect) { mMod1.getSamples(sSamples, start, end); if (mVolumeMode == 0) mVCO.getAmplitudeSamplesLinear(sSamples, start, end, mAmplitudeLevel); else mVCO.getAmplitudeSamplesNonLinear(sSamples, start, end, mAmplitudeLevel); } else { int s = start, e = 0; do { e = Math.min(s + sLFODelta, end); frequencyIndex = mFrequencyIndex; if (mOnCounter >= mLFODelay && (mLFOEnd == 0 || mOnCounter < mLFOEnd)) { frequencyIndex += (int) (mMod2.getNextSample() * mOsc2Sign * mLFODepth); mMod2.addPhase(e - s - 1); } mMod1.setFrequency(Channel .getFrequencyFromIndex(frequencyIndex)); mMod1.getSamples(sSamples, s, e); if (mVolumeMode == 0) mVCO.getAmplitudeSamplesLinear(sSamples, s, e, mAmplitudeLevel); else mVCO.getAmplitudeSamplesNonLinear(sSamples, s, e, mAmplitudeLevel); mOnCounter += e - s; s = e; } while (s < end); } } else { if (!mOsc2Connect) { mMod1.setFrequency(Channel .getFrequencyFromIndex(mFrequencyIndex)); for (int i = start; i < end; i++) sSamples .put( i, mMod1 .getNextSampleOfs((int) (sPipeArray[mInPipe][i] * mInSens))); if (mVolumeMode == 0) mVCO.getAmplitudeSamplesLinear(sSamples, start, end, mAmplitudeLevel); else mVCO.getAmplitudeSamplesNonLinear(sSamples, start, end, mAmplitudeLevel); } else { for (int i = start; i < end; i++) { frequencyIndex = mFrequencyIndex; if (mOnCounter >= mLFODelay && (mLFOEnd == 0 || mOnCounter < mLFOEnd)) frequencyIndex += (int) (mMod2.getNextSample() * mOsc2Sign * mLFODepth); mMod1.setFrequency(Channel .getFrequencyFromIndex(frequencyIndex)); sSamples .put( i, mMod1 .getNextSampleOfs((int) (sPipeArray[mInPipe][i] * mInSens))); mOnCounter++; } if (mVolumeMode == 0) mVCO.getAmplitudeSamplesLinear(sSamples, start, end, mAmplitudeLevel); else mVCO.getAmplitudeSamplesNonLinear(sSamples, start, end, mAmplitudeLevel); } } double key = mMod1.getFrequency(); mFormant.getSample(sSamples, start, end); mFilter.setEnvelope(mVCF); mFilter.setFrequency(mLPFFrequency); mFilter.setAmount(mLPFAmount); mFilter.setResonance(mLPFResonance); mFilter.setKey(key); mFilter.getSample(sSamples, start, end); switch (mOutMode) { case OUTPUT_DEFAULT: default: for (int i = start; i < end; i++) { int nl = i; //int nr = nl + 1; double amplitude = sSamples.get(i); samples.put(nl, samples.get(nl) + amplitude * mPanLeft); //samples.put(nr, samples.get(nr) + amplitude * mPanRight); } break; case OUTPUT_OVERWRITE: for (int i = start; i < end; i++) sPipeArray[mOutPipe][i] = sSamples.get(i); break; case OUTPUT_ADD: for (int i = start; i < end; i++) sPipeArray[mOutPipe][i] = sPipeArray[mOutPipe][i] + sSamples.get(i); break; } } public void setASDRForVCO(int[] arg) { double multiply = 1.0 / 127; mVCO.setASDR(arg[Track.EVENT_DELTA + 1] * multiply, arg[Track.EVENT_DELTA + 2] * multiply, arg[Track.EVENT_DELTA + 3] * multiply, arg[Track.EVENT_DELTA + 4] * multiply); } public void setASDRForVCF(int[] arg) { double multiply = 1.0 / 127; mVCF.setASDR(arg[Track.EVENT_DELTA + 1] * multiply, arg[Track.EVENT_DELTA + 2] * multiply, arg[Track.EVENT_DELTA + 3] * multiply, arg[Track.EVENT_DELTA + 4] * multiply); } public void setForm(int[] arg) { int mainForm = arg[Track.EVENT_DELTA + 1]; mOsc1.setForm(mainForm); mMod1 = mOsc1.getModulatorFromForm(mainForm); if (mainForm == Oscillator.GB_WAVE) { GBWave wave = (GBWave) mOsc1.getModulatorFromForm(mainForm); wave.setWaveIndex(arg[Track.EVENT_DELTA + 2]); } } public void setLPF(int[] arg) { int sw = arg[Track.EVENT_DELTA + 1]; if (sw >= Filter.HPF_QUALITY && sw <= Filter.LPF_QUALITY && !mEnableFilter) { mEnableFilter = true; mFilter.setSwitch(sw); } mLPFAmount = Math.min(Math.max(arg[Track.EVENT_DELTA + 2], -127), 127) * PITCH_RESOLUTION; int frequencyIndex = arg[Track.EVENT_DELTA + 3]; frequencyIndex = Math.min(Math.max(frequencyIndex, 0), 127); mLPFFrequency = frequencyIndex * PITCH_RESOLUTION; mLPFResonance = Math.min(Math.max(arg[Track.EVENT_DELTA + 4] * (1.0 / 127.0), 0.0), 1.0); } public void setInput(int[] arg) { mInSens = (1 << (arg[Track.EVENT_DELTA + 1] - 1)) * (1.0 / 8.0) * Modulator.PHASE_LENGTH; mInPipe = arg[Track.EVENT_DELTA + 2]; } public void setOutput(int[] arg) { mOutMode = arg[Track.EVENT_DELTA + 1]; mOutPipe = Math.min(Math.max(arg[Track.EVENT_DELTA + 2], 0), sPipeArrayLength); } public void setNoteIndex(int value) { mNoteIndex = value; setModulatorFrequency(); } public void setDetune(int value) { mDetune = value; setModulatorFrequency(); } public void setNoiseFrequency(double value) { Noise noise = (Noise) mOsc1.getModulatorFromForm(Oscillator.NOISE); noise.setNoiseFrequency(1.0 - value * (1.0 / 128)); } public void setPWM(int value) { Pulse pulse; if (mOsc1.getForm() != Oscillator.FC_PULSE) { pulse = (Pulse) mOsc1.getModulatorFromForm(Oscillator.PULSE); pulse.setPWM(value * (1.0 / 100.0)); } else { pulse = (Pulse) mOsc1.getModulatorFromForm(Oscillator.FC_PULSE); pulse.setPWM(0.125 * value); } } public void setPan(int value) { mPanRight = Math.max((value - 1) * (0.25 / 63.0), 0.0); mPanLeft = (2.0 * 0.25) - mPanRight; } public void setFormantVowel(int value) { mFormant.setVowel(value); } public void setVolumeMode(int value) { mVolumeMode = value; } public void setVelocity(int value) { int velocity = Math.min(Math.max(value, 0), 127); mVelocity = mVolumeMode > 0 ? sVolumeMap[velocity] : velocity / 127.0; mAmplitudeLevel = mVelocity * mExpression; } public void setExpression(int value) { int expression = Math.min(Math.max(value, 0), 127); mExpression = mVolumeMode > 0 ? sVolumeMap[expression] : expression / 127.0; mAmplitudeLevel = mVelocity * mExpression; } private void setModulatorFrequency() { mFrequencyIndex = mNoteIndex * PITCH_RESOLUTION + mDetune; mMod1.setFrequency(getFrequencyFromIndex(mFrequencyIndex)); } private static Boolean sInitialized = false; private static double[] sFrequencyMap = new double[128 * PITCH_RESOLUTION]; private static int sFrequencyLength = 0; private static double[] sVolumeMap = new double[128]; private static DoubleBuffer sSamples = null; private static int sSampleLength = 0; private static double[][] sPipeArray = null; private static int sPipeArrayLength = 0; private static int sLFODelta = 128; private Envelope mVCO; private Envelope mVCF; private Modulator mMod1; private Oscillator mOsc1; private Modulator mMod2; private Oscillator mOsc2; private int mNoteIndex; private int mDetune; private int mFrequencyIndex; private Boolean mOsc2Connect; private double mOsc2Sign; private Filter mFilter; private Boolean mEnableFilter; private Formant mFormant; private double mExpression; private double mVelocity; private double mAmplitudeLevel; private double mPanLeft; private double mPanRight; private int mOnCounter; private int mLFODelay; private double mLFODepth; private int mLFOEnd; private double mLPFAmount; private double mLPFFrequency; private double mLPFResonance; private int mVolumeMode; private double mInSens; private int mInPipe; private int mOutMode; private int mOutPipe; }