Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /***********************************************************
- ***********************************************************
- ** **
- ** Codesnippets written by Madwin for MMP 2023 **
- ** **
- ** Not to be used freely. the code still has errors **
- ** It's intended to be used as starting point. **
- ** Code has not been checked and might still need **
- ** (a lot of) work. **
- ** **
- ** ℗ & © MadMedia Productions 2023 **
- ** **
- ***********************************************************
- ***********************************************************
- ** **
- ** -- Disclaimer: -- **
- ** **
- ** If code is used in private projects and/or for **
- ** study purposes please mention resource. Any other **
- ** use -whether commercial or non-commercial- is not **
- ** condoned by the author and violates his intent. **
- ** **
- ** [email protected] **
- ** **
- ***********************************************************
- ***********************************************************/
- using CSCore;
- using CSCore.Codecs.WAV;
- using CSCore.DSP;
- using CSCore.SoundIn;
- using CSCore.Streams;
- using System;
- public enum SlicerMode
- {
- Single,
- Dual,
- Tremolo,
- Harmonica,
- SFX
- }
- public class SlicerEmulator
- {
- private const int BufferSize = 8192;
- private ISoundIn soundIn;
- private IWaveSource waveSource;
- private ISampleSource sampleSource;
- private BiQuadFilter[] filters;
- private WaveBuffer buffer;
- public bool IsEnabled { get; set; }
- public float Level { get; set; }
- public float Rate { get; set; }
- public float Depth { get; set; }
- public float Balance { get; set; }
- public float Tempo { get; set; }
- public float Attack { get; set; }
- public float Duty { get; set; }
- public float Variaties { get; set; }
- public SlicerMode Mode { get; set; }
- public SlicerEmulator()
- {
- IsEnabled = false;
- Level = 0.5f;
- Rate = 1.0f;
- Depth = 0.5f;
- Balance = 0.0f;
- Tempo = 1.0f;
- Attack = 0.5f;
- Duty = 0.5f;
- Variaties = 0.5f;
- Mode = SlicerMode.Single;
- filters = new BiQuadFilter[2];
- filters[0] = BiQuadFilter.LowpassFilter(44100, 10000, 0.707f);
- filters[1] = BiQuadFilter.HighpassFilter(44100, 100, 0.707f);
- buffer = new WaveBuffer(BufferSize);
- }
- public void Initialize()
- {
- soundIn = new WasapiCapture();
- soundIn.Initialize();
- soundIn.DataAvailable += SoundIn_DataAvailable;
- waveSource = soundIn.ToSampleSource().ToStereo();
- sampleSource = waveSource.ToWaveSource();
- soundIn.Start();
- }
- public void Stop()
- {
- soundIn.Stop();
- soundIn.Dispose();
- }
- private void SoundIn_DataAvailable(object sender, DataAvailableEventArgs e)
- {
- var count = e.ByteCount / 4; // 4 bytes per float sample
- sampleSource.Read(buffer, 0, count);
- var balance = (Balance + 1.0f) / 2.0f;
- var leftDelayTime = 0.003f + balance * 0.004f;
- var rightDelayTime = 0.003f + (1.0f - balance) * 0.004f;
- var rate = Rate * 10.0f;
- var depth = Depth * 0.5f;
- var level = Level * 0.5f;
- var offset = (float)(Math.Sin(rate * Math.PI * sampleSource.Position / sampleSource.Length) * depth);
- for (int i = 0; i < count; i += 2)
- {
- var inputLeft = buffer.ShortBuffer[i] / 32768f;
- var inputRight = buffer.ShortBuffer[i + 1] / 32768f;
- var leftOutput = inputLeft;
- var rightOutput = inputRight;
- // Apply slicing effect based on the selected mode
- switch (Mode)
- {
- case SlicerMode.Single:
- leftOutput = ProcessSingle(inputLeft, offset, level);
- rightOutput = ProcessSingle(inputRight, offset, level);
- break;
- case SlicerMode.Dual:
- leftOutput = ProcessDual(inputLeft, offset, level, leftDelayTime, rightDelayTime);
- rightOutput = ProcessDual(inputRight, offset, level, rightDelayTime, leftDelayTime);
- break;
- case SlicerMode.Tremolo:
- leftOutput = ProcessTremolo(inputLeft, offset, level, leftDelayTime, rightDelayTime);
- rightOutput = ProcessTremolo(inputRight, offset, level, rightDelayTime, leftDelayTime);
- break;
- case SlicerMode.Harmonica:
- leftOutput = ProcessHarmonica(inputLeft, offset, level, leftDelayTime, rightDelayTime);
- rightOutput = ProcessHarmonica(inputRight, offset, level, rightDelayTime, leftDelayTime);
- break;
- case SlicerMode.SFX:
- leftOutput = ProcessSFX(inputLeft, offset, level, leftDelayTime, rightDelayTime);
- rightOutput = ProcessSFX(inputRight, offset, level, rightDelayTime, leftDelayTime);
- break;
- }
- buffer.ShortBuffer[i] = (short)(leftOutput * 32768f);
- buffer.ShortBuffer[i + 1] = (short)(rightOutput * 32768f);
- }
- e.Data = buffer.ByteBuffer;
- }
- private float ProcessSingle(float input, float offset, float level)
- {
- var output = input + offset * level;
- return output;
- }
- private float ProcessDual(float input, float offset, float level, float delayTime1, float delayTime2)
- {
- var delayed1 = filters[0].Process(input);
- var delayed2 = filters[1].Process(input);
- var output = input + offset * level * (1.0f - delayTime1) + delayed1 * level * delayTime1 + delayed2 * level * delayTime2;
- return output;
- }
- private float ProcessTremolo(float input, float offset, float level, float delayTime1, float delayTime2)
- {
- var delayed1 = filters[0].Process(input);
- var delayed2 = filters[1].Process(input);
- var tremoloRate = 4.0f * Tempo;
- var tremoloDepth = 0.5f * Variaties;
- var tremoloOffset = (float)(Math.Sin(tremoloRate * Math.PI * sampleSource.Position / sampleSource.Length) * tremoloDepth);
- var output = input + (offset + tremoloOffset) * level * (1.0f - delayTime1) + delayed1 * level * delayTime1 + delayed2 * level * delayTime2;
- return output;
- }
- private float ProcessHarmonica(float input, float offset, float level, float delayTime1, float delayTime2)
- {
- var harmonicaRate = 0.5f * Tempo;
- var harmonicaDepth = 0.2f * Variaties;
- var harmonicaOffset = (float)(Math.Sin(harmonicaRate * Math.PI * sampleSource.Position / sampleSource.Length) * harmonicaDepth);
- var output = input + (offset + harmonicaOffset) * level * (1.0f - delayTime1) + input * level * delayTime1 + input * level * delayTime2;
- return output;
- }
- private float ProcessSFX(float input, float offset, float level, float delayTime1, float delayTime2)
- {
- var sfxRate = 2.0f * Tempo;
- var sfxDepth = 0.8f * Variaties;
- var sfxOffset = (float)(Math.Sin(sfxRate * Math.PI * sampleSource.Position / sampleSource.Length) * sfxDepth);
- var output = input + (offset + sfxOffset) * level * (1.0f - delayTime1) + input * level * delayTime1 + input * level * delayTime2;
- return output;
- }
- }
- /*
- The `SlicerEmulator` class includes the controls: `Balance` for adjusting the stereo balance, `Tempo` for
- controlling the tempo of the effect, `Attack` for setting the attack time, `Duty` for adjusting the duty
- cycle, and `Variaties` for controlling variations in the effect. It also introduces five different modes:
- `Single`, `Dual`, `Tremolo`, `Harmonica`, and `SFX`, each with its own processing logic.
- The class processes the audio in real-time, handling the input and output through the `SoundIn_DataAvailable`
- event. The processed audio is then assigned back to the `Data` property of the `DataAvailableEventArgs` object.
- Remember to include the necessary dependencies and configure the audio input and output accordingly in
- your application to make use of this class effectively.
- */
Advertisement
Add Comment
Please, Sign In to add comment