/// <summary> /// Get the default BFXR parameters. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters Default() { var p = new BfxrParameters(); foreach (PropertyInfo prop in typeof(BfxrParameters).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var attr = prop.GetCustomAttribute <ParamAttribute>(); if (attr != null) { prop.SetValue(p, attr.Default); } } return(p); }
/// <summary> /// Generate parameters for a random explosion sound. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters Explosion() { var p = BfxrParameters.Default(); p.Wave = BfxrWave.Noise; if (rand.NextDouble() < 0.5) { p.StartFrequency = randFloat(0.1, 0.4); p.Slide = randFloat(-0.5, -0.1); } else { p.StartFrequency = randFloat(0.2, 0.7); p.Slide = randFloat(-0.4, -0.2); } p.StartFrequency = p.StartFrequency * p.StartFrequency; if (rand.NextDouble() < 0.2) { p.Slide = 0; } if (rand.NextDouble() < 0.33) { p.RepeatSpeed = randFloat(0.3, 0.8); } p.SustainTime = randFloat(0.1, 0.4); p.DecayTime = randFloat(0, 0.5); p.SustainPunch = randFloat(0.2, 0.8); if (rand.NextDouble() < 0.5) { p.FlangerOffset = randFloat(-0.3, 0.6); p.FlangerSweep = randFloat(-0.3, 0); } if (rand.NextDouble() < 0.33) { p.ChangeSpeed = randFloat(0.6, 0.9); p.ChangeAmount = randFloat(-0.8, 0.8); } return(p); }
/// <summary> /// Generate parameters for a random coin pickup sound. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters PickupCoin() { var p = BfxrParameters.Default(); p.StartFrequency = randFloat(0.4, 0.9); p.SustainTime = randFloat(0, 0.1); p.DecayTime = randFloat(0.1, 0.5); p.SustainPunch = randFloat(0.3, 0.6); if (rand.NextDouble() < 0.5) { p.ChangeSpeed = randFloat(0.5, 0.7); int numer = rand.Next(1, 8); int denom = numer + rand.Next(2, 9); p.ChangeAmount = (double)numer / (double)denom; } return(p); }
/// <summary> /// Deserialize a set of parameters from the BFXR tool. /// </summary> /// <param name="data">The BFXR parameterss, serialized as a string.</param> public static BfxrParameters Deserialize(string data) { string[] fieldText = data.Split(new char[] { ',' }); var p = new BfxrParameters(); foreach (PropertyInfo prop in typeof(BfxrParameters).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var attr = prop.GetCustomAttribute <ParamAttribute>(); if (attr == null) { continue; } object value = attr.Default; string s = attr.Order < fieldText.Length ? fieldText[attr.Order] : null; if (s != null && s.Length > 0) { double v; if (!double.TryParse(s, out v)) { Console.WriteLine("Warning: Cannot parse value for {0}: {1}", prop.Name, s); } else { var cattr = attr as ContinuousParamAttribute; if (cattr != null) { double nv = Math.Max(cattr.Minimum, Math.Min(cattr.Maximum, v)); if (nv != v) { Console.WriteLine("Warning: Value {0} out of range for {1}, should be {2} .. {3}", v, prop.Name, cattr.Minimum, cattr.Maximum); } value = nv; } else { value = (BfxrWave)(Math.Max(0, Math.Min(8, (int)v))); } } } prop.SetValue(p, value); } return(p); }
/// <summary> /// Deserialize a set of parameters from the BFXR tool. /// </summary> /// <param name="data">The BFXR parameterss, serialized as a string.</param> public static BfxrParameters Deserialize(string data) { string[] fieldText = data.Split(new char[]{ ',' }); var p = new BfxrParameters(); foreach (PropertyInfo prop in typeof(BfxrParameters).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var attr = prop.GetCustomAttribute<ParamAttribute>(); if (attr == null) continue; object value = attr.Default; string s = attr.Order < fieldText.Length ? fieldText[attr.Order] : null; if (s != null && s.Length > 0) { double v; if (!double.TryParse(s, out v)) { Console.WriteLine("Warning: Cannot parse value for {0}: {1}", prop.Name, s); } else { var cattr = attr as ContinuousParamAttribute; if (cattr != null) { double nv = Math.Max(cattr.Minimum, Math.Min(cattr.Maximum, v)); if (nv != v) { Console.WriteLine("Warning: Value {0} out of range for {1}, should be {2} .. {3}", v, prop.Name, cattr.Minimum, cattr.Maximum); } value = nv; } else { value = (BfxrWave)(Math.Max(0, Math.Min(8, (int)v))); } } } prop.SetValue(p, value); } return p; }
/// <summary> /// Get the default BFXR parameters. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters Default() { var p = new BfxrParameters(); foreach (PropertyInfo prop in typeof(BfxrParameters).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var attr = prop.GetCustomAttribute<ParamAttribute>(); if (attr != null) { prop.SetValue(p, attr.Default); } } return p; }
/// <summary> /// Generate parameters for a random laser shoot sound. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters LaserShoot() { var p = BfxrParameters.Default(); switch (rand.Next(0, 12) / 5) { case 0: p.Wave = BfxrWave.Square; break; case 1: p.Wave = BfxrWave.Saw; break; case 2: p.Wave = BfxrWave.Sine; break; } p.StartFrequency = randFloat(0.5, 1.0); p.MinFrequency = Math.Max(0.2, p.StartFrequency - randFloat(0.2, 0.8)); p.Slide = randFloat(-0.35, -0.15); if (rand.NextDouble() < 0.33) { p.StartFrequency = randFloat(0, 0.6); p.MinFrequency = randFloat(0, 0.1); p.Slide = randFloat(-0.65, -0.35); } if (p.Wave == BfxrWave.Square) { if (rand.NextDouble() < 0.5) { p.SquareDuty = randFloat(0, 0.5); p.DutySweep = randFloat(0, 0.2); } else { p.SquareDuty = randFloat(0.4, 0.9); p.DutySweep = randFloat(-0.7, 0); } } p.SustainTime = randFloat(0.1, 0.3); p.DecayTime = randFloat(0, 0.4); if (rand.NextDouble() < 0.5) { p.SustainPunch = randFloat(0, 0.3); } if (rand.NextDouble() < 0.33) { p.FlangerOffset = randFloat(0, 0.2); p.FlangerSweep = randFloat(-0.2, 0); } if (rand.NextDouble() < 0.5) { p.HPFilterCutoff = randFloat(0, 0.3); } return(p); }
/// <summary> /// Generate parameters for a random hit or hurt sound. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters HitHurt() { var p = BfxrParameters.Default(); return(p); }
/// <summary> /// Generate parameters for a random powerup sound. /// </summary> /// <returns>BFXR parameters.</returns> public static BfxrParameters Powerup() { var p = BfxrParameters.Default(); return(p); }
public BfxrGenerator(BfxrParameters p) { this.rand = new Random(); this.state.period = 100.0 / (p.StartFrequency * p.StartFrequency + 0.001); this.state.maxPeriod = 100.0 / (p.MinFrequency * p.MinFrequency + 0.001); this.state.slide = 1.0 - 0.01 * p.Slide * p.Slide * p.Slide; this.state.deltaSlide = -0.000001 * p.DeltaSlide * p.DeltaSlide * p.DeltaSlide; this.state.squareDuty = 0; this.state.dutySweep = 0; if (p.Wave == BfxrWave.Square) { this.state.squareDuty = 0.5 - 0.5 * p.SquareDuty; this.state.dutySweep = -0.00005 * p.DutySweep; } this.state.changePeriod = (int)((1.1 - p.ChangeRepeat) * (20000 / 1.1) + 32); this.state.changePeriodTime = 0; this.state.changeAmount = p.ChangeAmount > 0 ? 1.0 - 0.9 * p.ChangeAmount * p.ChangeAmount : 1.0 + 10.0 * p.ChangeAmount * p.ChangeAmount; this.state.changeAmount2 = p.ChangeAmount2 > 0 ? 1.0 - 0.9 * p.ChangeAmount2 * p.ChangeAmount2 : 1.0 + 10.0 * p.ChangeAmount2 * p.ChangeAmount2; this.state.changeTime = 0; this.state.changeTime2 = 0; this.state.changeLimit = p.ChangeSpeed == 1.0 ? 0 : (int)(((1.0 - p.ChangeSpeed) * (1.0 - p.ChangeSpeed) * 20000 + 32) * (1.0 - p.ChangeRepeat + 0.1) / 1.1); this.state.changeLimit2 = p.ChangeSpeed2 == 1.0 ? 0 : (int)(((1.0 - p.ChangeSpeed2) * (1.0 - p.ChangeSpeed2) * 20000 + 32) * (1.0 - p.ChangeRepeat + 0.1) / 1.1); this.initState = this.state; this.pinkGenerator = new PinkGenerator(this.rand); this.masterVolume = p.MasterVolume * p.MasterVolume; this.wave = p.Wave; double attackTime = Math.Max(0, p.AttackTime); double sustainTime = Math.Max(0.01, p.SustainTime); double decayTime = Math.Max(0, p.DecayTime); double totalTime = attackTime + sustainTime + decayTime; if (totalTime < MinLength) { double fac = MinLength / totalTime; attackTime *= fac; sustainTime *= fac; decayTime *= fac; } this.sustainPunch = p.SustainPunch; this.phase = 0; this.minFrequency = p.MinFrequency; this.muted = false; this.overtones = (int)(p.Overtones * 10); this.overtoneFalloff = p.OvertoneFalloff; this.bitcrushFreq = 1 - Math.Pow(p.BitCrush, 1.0 / 3.0); this.bitcrushFreqSweep = -0.000015 * p.BitCrushSweep; this.bitcrushPhase = 0; this.bitcrushLast = 0; this.compressionFactor = 1 / (1 + 4 * p.CompressionAmount); this.filters = p.LPFilterCutoff != 1.0 || p.HPFilterCutoff != 0.0; this.lpFilterOn = p.LPFilterCutoff != 1.0; this.lpFilterPos = 0.0; this.lpFilterDeltaPos = 0.0; this.lpFilterCutoff = 0.1 * p.LPFilterCutoff * p.LPFilterCutoff * p.LPFilterCutoff; this.lpFilterDeltaCutoff = 1.0 + 0.0001 * p.LPFilterCutoffSweep; this.lpFilterDamping = 1.0 - 5.0 / (1.0 + 20 * p.LPFilterResonance * p.LPFilterResonance) * (0.01 + this.lpFilterCutoff); this.hpFilterPos = 0.0; this.hpFilterCutoff = 0.1 * p.HPFilterCutoff * p.HPFilterCutoff; this.hpFilterDeltaCutoff = 1.0 + 0.0003 * p.HPFilterCutoffSweep; this.vibratoPhase = 0; this.vibratoSpeed = 0.01 * p.VibratoSpeed * p.VibratoSpeed; this.vibratoAmplitude = 0.5 * p.VibratoDepth; this.envelopeVolume = 0; this.envelopeStage = 0; this.envelopeTime = 0; this.envelopeLength0 = (int)(100000 * attackTime * attackTime); this.envelopeLength1 = (int)(100000 * sustainTime * sustainTime); this.envelopeLength2 = (int)(100000 * decayTime * decayTime + 10); this.envelopeLength = this.envelopeLength0; this.envelopeFullLength = this.envelopeLength0 + this.envelopeLength1 + this.envelopeLength2; this.envelopeInvLength0 = 1.0 / this.envelopeLength0; this.envelopeInvLength1 = 1.0 / this.envelopeLength1; this.envelopeInvLength2 = 1.0 / this.envelopeLength2; this.flanger = p.FlangerOffset != 0.0 || p.FlangerSweep != 0.0; this.flangerOffset = 1020.0 * p.FlangerOffset * p.FlangerOffset * (p.FlangerOffset > 0 ? 1 : -1); this.flangerDeltaOffset = 0.2 * p.FlangerSweep * p.FlangerSweep * p.FlangerSweep; this.flangerPos = 0; this.flangerBuffer = new float[1024]; this.noiseBuffer = new float[32]; this.pinkNoiseBuffer = new float[32]; this.loResNoiseBuffer = new float[32]; for (int i = 0; i < this.noiseBuffer.Length; i++) { this.noiseBuffer[i] = 2.0f * (float)this.rand.NextDouble() - 1.0f; } for (int i = 0; i < this.pinkNoiseBuffer.Length; i++) { this.pinkNoiseBuffer[i] = this.pinkGenerator.Next(); } float val = 0.0f; for (int i = 0; i < this.loResNoiseBuffer.Length; i++) { if ((i % LoResNoisePeriod) == 0) { val = 2.0f * (float)this.rand.NextDouble() - 1.0f; } this.loResNoiseBuffer[i] = val; } this.repeatTime = 0; this.repeatLimit = p.RepeatSpeed == 0.0 ? 0 : (int)((1.0 - p.RepeatSpeed) * (1.0 - p.RepeatSpeed) * 20000) + 32; }