protected virtual void InitModule(uint startPosition = 0) { track = startPosition; counter = 0; patternDelay = 0; samplesPerTick = 0; mixerPosition = 0; currentRow = 0; pattern = module[(int)track]; BPM = module.BPM; speed = module.tempo; moduleEnd = false; mixChannels.Clear(); for (int ch = 0; ch < module.numberOfChannels; ch++) { ModuleMixerChannel mc = CreateMixerChannel(); mc.instrumentIndex = 0; mc.instrumentLastIndex = 0; mixChannels.Add(mc); } SetBPM(); UpdateBPM(); }
private bool TickEffect2(ModuleMixerChannel mc) { mc.period = (uint)mc.portamentoStart; mc.periodInc = CalcClampPeriodIncrement(mc); mc.portamentoStart += mc.portamentoStep; return(true); }
private bool TickEffectA(ModuleMixerChannel mc) // Volume Slide tick { mc.channelVolume += mc.volumeSlideStep; mc.channelVolume = (mc.channelVolume < 0.0f) ? 0.0f : mc.channelVolume; mc.channelVolume = (mc.channelVolume > 1.0f) ? 1.0f : mc.channelVolume; return(true); }
private bool NoteEffect7(ModuleMixerChannel mc) // Tremolo { mc.tremoloCount = (mc.tremoloType <= 0x03) ? 0 : mc.tremoloCount; mc.tremoloStart = mc.channelVolume; mc.tremoloFreq = (mc.effectArgX != 0) ? (int)mc.effectArgX : 0; mc.tremoloAmp = (mc.effectArgY != 0) ? (int)mc.effectArgY : 0; return(true); }
private bool NoteEffect6(ModuleMixerChannel mc) // Continue Vibrato + Volume Slide { NoteEffectA(mc); mc.effectArgX = 0; mc.effectArgY = 0; NoteEffect4(mc); return(true); }
/* * var startTime = System.Diagnostics.Stopwatch.StartNew(); * startTime.Stop(); * var resultTime = startTime.Elapsed; * string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", * resultTime.Hours, * resultTime.Minutes, * resultTime.Seconds, * resultTime.Milliseconds); */ public float GetSampleValue(ModuleMixerChannel mc) { if (mc.instrumentIndex <= 0) { return(0.0f); } ModuleInstrument sampleData = module.Instruments[(int)mc.instrumentIndex - 1]; mc.instrumentPosition = sampleData.CalculateInstrumentPosition(mc.instrumentPosition); return(GetSampleValueSimple(mc)); }
private bool TickEffect4(ModuleMixerChannel mc) { mc.vibratoAdd = (mc.vibratoType % 4 == 0) ? ModuleConst.ModSinusTable[mc.vibratoCount] : mc.vibratoAdd; mc.vibratoAdd = (mc.vibratoType % 4 == 1) ? ModuleConst.ModRampDownTable[mc.vibratoCount] : mc.vibratoAdd; mc.vibratoAdd = (mc.vibratoType % 4 == 2) ? ModuleConst.ModSquareTable[mc.vibratoCount] : mc.vibratoAdd; mc.vibratoAdd = (mc.vibratoType % 4 == 3) ? ModuleConst.ModRandomTable[mc.vibratoCount] : mc.vibratoAdd; mc.periodInc = CalcPeriodIncrement((uint)mc.vibratoPeriod); mc.vibratoPeriod = mc.vibratoStart + (int)(mc.vibratoAdd * ((float)mc.vibratoAmp / 128.0f)); mc.vibratoCount = (mc.vibratoCount + mc.vibratoFreq) & 0x3F; return(true); }
private bool NoteEffectB(ModuleMixerChannel mc) // Position Jump { mc.patternNumToJump = mc.effectArgX * 16 + mc.effectArgY; if (mc.patternNumToJump > 0x7F) { mc.patternNumToJump = 0; } currentRow = 0; track = module.arrangement[(int)mc.patternNumToJump]; pattern = module.patterns[(int)module.arrangement[(int)track]]; return(true); }
private bool TickEffect7(ModuleMixerChannel mc) { mc.tremoloAdd = (mc.tremoloType % 4 == 0) ? ModuleConst.ModSinusTable[mc.tremoloCount] : mc.tremoloAdd; mc.tremoloAdd = (mc.tremoloType % 4 == 1) ? ModuleConst.ModRampDownTable[mc.tremoloCount] : mc.tremoloAdd; mc.tremoloAdd = (mc.tremoloType % 4 == 2) ? ModuleConst.ModSquareTable[mc.tremoloCount] : mc.tremoloAdd; mc.tremoloAdd = (mc.tremoloType % 4 == 3) ? ModuleConst.ModRandomTable[mc.tremoloCount] : mc.tremoloAdd; mc.channelVolume = mc.tremoloStart + ((float)mc.tremoloAdd / 64) * ((float)mc.tremoloAmp / 0x40); mc.channelVolume = (mc.channelVolume < 0.0f) ? 0.0f : mc.channelVolume; mc.channelVolume = (mc.channelVolume > 1.0f) ? 1.0f : mc.channelVolume; mc.tremoloCount = (mc.tremoloCount + mc.tremoloFreq) & 0x3F; return(true); }
private bool NoteEffectD(ModuleMixerChannel mc) // Pattern Break { mc.positionToJump = mc.effectArgX * 10 + mc.effectArgY; if (mc.positionToJump > 0x3F) { mc.positionToJump = 0; } track++; pattern = module.patterns[(int)module.arrangement[(int)track]]; currentRow = mc.positionToJump; return(true); }
private bool NoteEffectA(ModuleMixerChannel mc) // Volume Slide { mc.volumeSlideStep = 0; if (mc.effectArgX != 0) { mc.volumeSlideStep = (float)mc.effectArgX / 0x40; // Volume Slide up } else if (mc.effectArgY != 0) { mc.volumeSlideStep = -(float)mc.effectArgY / 0x40; // Volume Slide down } mc.channelVolume -= mc.volumeSlideStep; return(true); }
private bool NoteEffect3(ModuleMixerChannel mc) // Slide to note { if (mc.effectArg != 0) { mc.lastPortamentoStep = mc.portamentoStep; mc.portamentoStep = (mc.portamentoStart <= mc.portamentoEnd) ? (int)mc.effectArg : -(int)mc.effectArg; } else { mc.portamentoStep = mc.lastPortamentoStep; } return(true); }
protected virtual void MixData() { string ms = " channels " + module.numberOfChannels + " "; for (int pos = 0; pos < ModuleConst.MIX_LEN; pos++) { float mixValueR = 0; float mixValueL = 0; float mixValue = 0; for (int ch = 0; ch < module.numberOfChannels; ch++) { ModuleMixerChannel mc = mixChannels[ch]; //if (ch != 1) mc.muted = true; if (!mc.muted) { mixValue += GetSampleValue(mc); //if (ModuleConst.MIX_CHANNELS == ModuleConst.STEREO) { // mixValueL += (((ch & 0x03) == 0) || ((ch & 0x03) == 3)) ? mixValue * 0.75f : mixValue * 0.25f; // mixValueR += (((ch & 0x03) == 1) || ((ch & 0x03) == 2)) ? mixValue * 0.75f : mixValue * 0.25f; //} } mc.instrumentPosition += mc.periodInc; } if (ModuleConst.MIX_CHANNELS != ModuleConst.STEREO) { mixValue /= module.numberOfChannels; } //else { // mixValueL /= (module.numberOfChannels << 1); // mixValueR /= (module.numberOfChannels << 1); //} if (ModuleConst.MIX_CHANNELS != ModuleConst.STEREO) { waveStream.Write((short)mixValue); } //else { // waveStream.Write((short)mixValueL); // waveStream.Write((short)mixValueR); //} mixerPosition++; if (mixerPosition >= samplesPerTick) { SetBPM(); UpdateBPM(); } } }
protected override void ResetChannelInstrument(ModuleMixerChannel mc) { MOD_Instrument instrument = (MOD_Instrument)module.Instruments[(int)mc.instrumentIndex - 1]; mc.instrumentPosition = 2; mc.instrumentLength = instrument.length; mc.loopType = instrument.loopType; mc.instrumentLoopStart = instrument.repeatStart; mc.instrumentLoopEnd = instrument.repeatStop; mc.currentFineTune = instrument.fineTune; mc.vibratoCount = 0; mc.tremoloCount = 0; mc.arpeggioCount = 0; }
protected virtual float GetSampleValueLinear(ModuleMixerChannel mc) { ModuleInstrument sampleData = module.Instruments[(int)mc.instrumentIndex - 1]; int posInt = (int)mc.instrumentPosition; float posReal = mc.instrumentPosition - posInt; float a1 = sampleData[posInt]; if ((posInt + 1) >= mc.instrumentLength) { return(a1 * mc.channelVolume); } float a2 = sampleData[posInt + 1]; return((a1 + (a2 - a1) * posReal) * mc.channelVolume); }
//---------------------------------------------------------------------------------------------- private bool TickEffect0(ModuleMixerChannel mc) { if (mc.effectArg == 0) { return(false); } uint arpeggioPeriod = mc.arpeggioPeriod0; arpeggioPeriod = (mc.arpeggioCount == 1) ? mc.arpeggioPeriod1 : arpeggioPeriod; arpeggioPeriod = (mc.arpeggioCount == 2) ? mc.arpeggioPeriod2 : arpeggioPeriod; //mc.period = arpeggioPeriod; mc.periodInc = CalcPeriodIncrement(arpeggioPeriod); mc.arpeggioCount = (mc.arpeggioCount + 1) % 4; return(true); }
private bool NoteEffect0(ModuleMixerChannel mc) // Arpeggio { if (mc.effectArg == 0) { return(false); } mc.arpeggioCount = 0; mc.arpeggioIndex = mc.noteIndex; mc.arpeggioX = mc.arpeggioIndex + mc.effectArgX; mc.arpeggioY = mc.arpeggioIndex + mc.effectArgY; mc.arpeggioPeriod0 = GetNoteFreq(mc.arpeggioIndex, /*mc.currentFineTune*/ 0); mc.period = mc.arpeggioPeriod0; mc.arpeggioPeriod1 = (mc.arpeggioX < 60) ? GetNoteFreq(mc.arpeggioX, /*mc.currentFineTune*/ 0) : mc.arpeggioPeriod0; mc.arpeggioPeriod2 = (mc.arpeggioY < 60) ? GetNoteFreq(mc.arpeggioY, /*mc.currentFineTune*/ 0) : mc.arpeggioPeriod0; return(true); }
private bool TickEffect3(ModuleMixerChannel mc) { mc.period = (uint)mc.portamentoStart; mc.periodInc = CalcClampPeriodIncrement(mc); mc.portamentoStart += mc.portamentoStep; if (mc.portamentoStep < 0) { mc.portamentoStart = (mc.portamentoStart > mc.portamentoEnd) ? mc.portamentoStart : mc.portamentoEnd; } else { mc.portamentoStart = (mc.portamentoStart < mc.portamentoEnd) ? mc.portamentoStart : mc.portamentoEnd; } return(true); }
private bool NoteEffectF(ModuleMixerChannel mc) // SetSpeed { if ((mc.effectArg >= 0x20) && (mc.effectArg <= 0xFF)) { BPM = mc.effectArg; SetBPM(); } if ((mc.effectArg > 0) && (mc.effectArg <= 0x1F)) { speed = mc.effectArg; } //System.Diagnostics.Debug.WriteLine("Set BPM/speed -> " + BPM + " : " + speed); return(true); }
private bool NoteEffect4(ModuleMixerChannel mc) // Vibrato { mc.vibratoStart = (int)mc.period; mc.vibratoPeriod = mc.vibratoStart; if (mc.effectArgX != 0 && mc.effectArgY != 0) { mc.lastVibratoFreq = (int)mc.effectArgX; mc.lastVibratoAmp = (int)mc.effectArgY; mc.vibratoFreq = (int)mc.effectArgX; mc.vibratoAmp = (int)mc.effectArgY; mc.vibratoCount = 0; } else { mc.vibratoFreq = mc.lastVibratoFreq; mc.vibratoAmp = mc.lastVibratoAmp; mc.vibratoCount = 0; } return(true); }
protected virtual float GetSampleValueSpline(ModuleMixerChannel mc) { ModuleInstrument sampleData = module.Instruments[(int)mc.instrumentIndex - 1]; int posInt = (int)mc.instrumentPosition; float posReal = mc.instrumentPosition - posInt; float a2 = sampleData[posInt]; if (((posInt - 1) < 0) || ((posInt + 2) >= mc.instrumentLength)) { return(a2 * mc.channelVolume); } float a1 = sampleData[posInt - 1]; float a3 = sampleData[posInt + 1]; float a4 = sampleData[posInt + 2]; float b0 = a1 + a2 + a2 + a2 + a2 + a3; float b1 = -a1 + a3; float b2 = a1 - a2 - a2 + a3; float b3 = -a1 + a2 + a2 + a2 - a3 - a3 - a3 + a4; return((((b3 * posReal * 0.1666666f + b2 * 0.5f) * posReal + b1 * 0.5f) * posReal + b0 * 0.1666666f) * mc.channelVolume); }
private bool EffectEF(ModuleMixerChannel mc) { return(true); }
private bool EffectEE(ModuleMixerChannel mc) // Delay { patternDelay = mc.effectArgY; return(true); }
private bool EffectEC(ModuleMixerChannel mc) // Cut Sample { return(true); }
private bool EffectEB(ModuleMixerChannel mc) // Fine Volume Slide Down { mc.effect = 0x0A; mc.volumeSlideStep = -(float)mc.effectArgY / 0x40; return(true); }
private bool EffectE9(ModuleMixerChannel mc) // Retrigger Sample { return(true); }
private bool EffectE7(ModuleMixerChannel mc) { mc.tremoloType = mc.effectArgY & 0x7; return(true); }
private bool EffectE5(ModuleMixerChannel mc) { mc.currentFineTune = (int)mc.effectArgY; return(true); }
private bool EffectE4(ModuleMixerChannel mc) { mc.vibratoType = mc.effectArgY & 0x7; return(true); }
private bool EffectE2(ModuleMixerChannel mc) { mc.period += mc.effectArgY; mc.periodInc = CalcClampPeriodIncrement(mc); return(true); }