public override EffectLayer Render(IGameState gamestate) { EffectLayer gradient_layer = new EffectLayer(); //If Wave Size 0 Gradiant Stop Moving Animation if (Properties.GradientConfig.gradient_size == 0) { Properties.GradientConfig.shift_amount += ((Utils.Time.GetMillisecondsSinceEpoch() - Properties.GradientConfig.last_effect_call) / 1000.0f) * 5.0f * Properties.GradientConfig.speed; Properties.GradientConfig.shift_amount = Properties.GradientConfig.shift_amount % Effects.canvas_biggest; Properties.GradientConfig.last_effect_call = Utils.Time.GetMillisecondsSinceEpoch(); Color selected_color = Properties.GradientConfig.brush.GetColorSpectrum().GetColorAt(Properties.GradientConfig.shift_amount, Effects.canvas_biggest); gradient_layer.Set(Properties.Sequence, selected_color); } else if (Properties.Sequence.type == KeySequenceType.Sequence) { using var temp_layer = new EffectLayer("Color Zone Effect", LayerEffects.GradientShift_Custom_Angle, Properties.GradientConfig); foreach (var key in Properties.Sequence.keys) { gradient_layer.Set(key, temp_layer.Get(key)); } } else { gradient_layer.DrawTransformed( Properties.Sequence, g => { var rect = new RectangleF(0, 0, Effects.canvas_width, Effects.canvas_height); using var temp_layer_bitmap = new EffectLayer("Color Zone Effect", LayerEffects.GradientShift_Custom_Angle, Properties.GradientConfig, rect).GetBitmap(); g.DrawImage(temp_layer_bitmap, rect, rect, GraphicsUnit.Pixel); } ); } return(gradient_layer); }
public override EffectLayer Render(IGameState gamestate) { try { //if (current_device != null) //current_device.Dispose(); CheckForDeviceChange(); // The system sound as a value between 0.0 and 1.0 float system_sound_normalized = default_device.AudioEndpointVolume.MasterVolumeLevelScalar; // Scale the Maximum amplitude with the system sound if enabled, so that at 100% volume the max_amp is unchanged. // Replaces all Properties.MaxAmplitude calls with the scaled value float scaled_max_amplitude = Properties.MaxAmplitude * (Properties.ScaleWithSystemVolume ? system_sound_normalized : 1); float[] freqs = Properties.Frequencies.ToArray(); //Defined Frequencies double[] freq_results = new double[freqs.Length]; if (previous_freq_results == null || previous_freq_results.Length < freqs.Length) { previous_freq_results = new float[freqs.Length]; } //Maintain local copies of fft, to prevent data overwrite Complex[] _local_fft = new List <Complex>(_ffts).ToArray(); Complex[] _local_fft_previous = new List <Complex>(_ffts_prev).ToArray(); EffectLayer equalizer_layer = new EffectLayer(); bool BgEnabled = false; switch (Properties.BackgroundMode) { case EqualizerBackgroundMode.EnabledOnSound: foreach (var bin in _local_fft) { if (bin.X > 0.0005 || bin.X < -0.0005) { BgEnabled = true; break; } } break; case EqualizerBackgroundMode.AlwaysOn: BgEnabled = true; break; } // Use the new transform render method to draw the equalizer layer equalizer_layer.DrawTransformed(Properties.Sequence, g => { // Here we draw the equalizer relative to our source rectangle and the DrawTransformed method handles sizing and positioning it correctly for us // Draw a rectangle background over the entire source rect if bg is enabled if (BgEnabled) { g.FillRectangle(new SolidBrush(Properties.DimColor), sourceRect); } g.CompositingMode = CompositingMode.SourceCopy; int wave_step_amount = _local_fft.Length / (int)sourceRect.Width; switch (Properties.EQType) { case EqualizerType.Waveform: var halfHeight = sourceRect.Height / 2f; for (int x = 0; x < (int)sourceRect.Width; x++) { float fft_val = _local_fft.Length > x * wave_step_amount ? _local_fft[x * wave_step_amount].X : 0.0f; Brush brush = GetBrush(fft_val, x, sourceRect.Width); var yOff = -Math.Max(Math.Min(fft_val / scaled_max_amplitude * 1000.0f, halfHeight), -halfHeight); g.DrawLine(new Pen(brush), x, halfHeight, x, halfHeight + yOff); } break; case EqualizerType.Waveform_Bottom: for (int x = 0; x < (int)sourceRect.Width; x++) { float fft_val = _local_fft.Length > x * wave_step_amount ? _local_fft[x * wave_step_amount].X : 0.0f; Brush brush = GetBrush(fft_val, x, sourceRect.Width); g.DrawLine(new Pen(brush), x, sourceRect.Height, x, sourceRect.Height - Math.Min(Math.Abs(fft_val / scaled_max_amplitude) * 1000.0f, sourceRect.Height)); } break; case EqualizerType.PowerBars: //Perform FFT again to get frequencies FastFourierTransform.FFT(false, (int)Math.Log(fftLength, 2.0), _local_fft); while (flux_array.Count < freqs.Length) { flux_array.Add(0.0f); } int startF = 0; int endF = 0; float threshhold = 300.0f; for (int x = 0; x < freqs.Length - 1; x++) { startF = freqToBin(freqs[x]); endF = freqToBin(freqs[x + 1]); float flux = 0.0f; for (int j = startF; j <= endF; j++) { float curr_fft = (float)Math.Sqrt(_local_fft[j].X * _local_fft[j].X + _local_fft[j].Y * _local_fft[j].Y); float prev_fft = (float)Math.Sqrt(_local_fft_previous[j].X * _local_fft_previous[j].X + _local_fft_previous[j].Y * _local_fft_previous[j].Y); float value = curr_fft - prev_fft; float flux_calc = (value + Math.Abs(value)) / 2; if (flux < flux_calc) { flux = flux_calc; } flux = flux > threshhold ? 0.0f : flux; } flux_array[x] = flux; } //System.Diagnostics.Debug.WriteLine($"flux max: {flux_array.Max()}"); float bar_width = sourceRect.Width / (float)(freqs.Length - 1); for (int f_x = 0; f_x < freq_results.Length - 1; f_x++) { float fft_val = flux_array[f_x] / scaled_max_amplitude; fft_val = Math.Min(1.0f, fft_val); if (previous_freq_results[f_x] - fft_val > 0.10) { fft_val = previous_freq_results[f_x] - 0.15f; } float x = f_x * bar_width; float y = sourceRect.Height; float height = fft_val * sourceRect.Height; previous_freq_results[f_x] = fft_val; Brush brush = GetBrush(-(f_x % 2), f_x, freq_results.Length - 1); g.FillRectangle(brush, x, y - height, bar_width, height); } break; } }, sourceRect); var hander = NewLayerRender; if (hander != null) { hander.Invoke(equalizer_layer.GetBitmap()); } return(equalizer_layer); } catch (Exception exc) { Global.logger.Error("Error encountered in the Equalizer layer. Exception: " + exc.ToString()); return(new EffectLayer()); } }