Madwin74

Harmonist effect

May 8th, 2023 (edited)
895
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.62 KB | Source Code | 0 0
  1. /***********************************************************
  2.  **                                                       **
  3.  **   Codesnippets written by Madwin for MMP 2023         **
  4.  **                                                       **
  5.  **   Not to be used freely. the code still has errors    **
  6.  **   It's intended to be used as starting point.         **
  7.  **   Code has not been checked and might still need      **
  8.  **   (a lot of) work.                                    **
  9.  **                                                       **
  10.  **   © MadMedia Productions 2023                         **
  11.  **                                                       **
  12.  ***********************************************************/
  13.  
  14.  
  15.  
  16.  
  17.  
  18. // C# class Harmonist effect in real-time
  19.  
  20. using NAudio.Wave;
  21. using NAudio.Wasapi;
  22.  
  23. public class HarmonistEffect
  24. {
  25.     private WasapiCapture capture;
  26.     private WasapiOut output;
  27.     private BufferedWaveProvider waveBuffer;
  28.     private TDHSolaProvider pitchShifter;
  29.     private MixingWaveProvider32 mixer;
  30.     private WaveFormat format;
  31.     private int bufferMilliseconds;
  32.     private float harmonyLevel;
  33.     private float harmonyInterval;
  34.     private float harmonyDetune;
  35.  
  36.     public HarmonistEffect(int sampleRate, int channels, int bufferMilliseconds, float harmonyLevel, float harmonyInterval, float harmonyDetune)
  37.     {
  38.         this.format = new WaveFormat(sampleRate, 16, channels);
  39.         this.bufferMilliseconds = bufferMilliseconds;
  40.         this.harmonyLevel = harmonyLevel;
  41.         this.harmonyInterval = harmonyInterval;
  42.         this.harmonyDetune = harmonyDetune;
  43.  
  44.         // Initialize wave buffer with the specified buffer size and sample rate
  45.         this.waveBuffer = new BufferedWaveProvider(format) {
  46.             BufferDuration = TimeSpan.FromMilliseconds(bufferMilliseconds)
  47.         };
  48.  
  49.         // Create a TDHSolaProvider with the desired detune and interval
  50.         float frequencyShift = (float) Math.Pow(2, harmonyInterval / 12);
  51.         this.pitchShifter = new TDHSolaProvider(waveBuffer.ToWaveProvider(), frequencyShift, harmonyDetune);
  52.  
  53.         // Create a mixing wave provider to combine the input signal with the pitch shifted signal
  54.         this.mixer = new MixingWaveProvider32();
  55.         mixer.AddInputStream(waveBuffer.ToWaveProvider()); // add input signal
  56.         mixer.AddInputStream(pitchShifter); // add pitch shifted signal
  57.  
  58.         // Adjust the level of the harmony effect
  59.         this.mixer.Volume = harmonyLevel;
  60.     }
  61.  
  62.     public void Start()
  63.     {
  64.         // Initialize WasapiCapture and WasapiOut with the specified format and buffer size
  65.         this.capture = new WasapiCapture(AudioClientShareMode.Shared, false, bufferMilliseconds) {
  66.             WaveFormat = format
  67.         };
  68.         this.output = new WasapiOut(AudioClientShareMode.Shared, false, bufferMilliseconds) {
  69.             LatencyMilliseconds = 100 // add some extra latency to avoid buffer underruns
  70.         };
  71.  
  72.         // Set up event handlers to process audio input and output
  73.         capture.DataAvailable += OnDataAvailable;
  74.         output.Play();
  75.         capture.StartRecording();
  76.     }
  77.  
  78.     public void Stop()
  79.     {
  80.         // Stop and dispose of WasapiCapture and WasapiOut
  81.         capture?.StopRecording();
  82.         capture?.Dispose();
  83.         output?.Stop();
  84.         output?.Dispose();
  85.     }
  86.  
  87.     private void OnDataAvailable(object sender, WaveInEventArgs e)
  88.     {
  89.         // Add the new audio samples to the wave buffer
  90.         waveBuffer.AddSamples(e.Buffer, 0, e.BytesRecorded);
  91.  
  92.         // Read the mixed and processed audio samples from the mixing wave provider
  93.         byte[] buffer = new byte[e.BytesRecorded];
  94.         int bytesRead = mixer.Read(buffer, 0, e.BytesRecorded);
  95.  
  96.         // Write the processed audio samples to WasapiOut
  97.         output?.Write(buffer, 0, bytesRead);
  98.     }
  99. }
  100. /*
  101.  
  102. You can create an instance of the HarmonistEffect class
  103. with the desired parameters (sample rate, buffer size,
  104. harmony level, interval, and detune) and call the Start()
  105. method to begin processing live audio input. You can call
  106. the Stop() method to stop processing and release resources.
  107.  
  108.  
  109. Note that the TDHSolaProvider may introduce some latency,
  110. especially if the pitch shift interval is large. To minimize
  111. latency, you can set the LatencyMilliseconds property of the
  112. WasapiOut object to a small value, but be aware that this may
  113. increase the risk of buffer underruns. You can also experiment
  114. with different pitch shift intervals and buffer sizes to find
  115. a balance between latency and quality.
  116.  
  117.  
  118. Here's an example usage:
  119.  
  120. // Create a HarmonistEffect object with the desired parameters
  121. HarmonistEffect harmonist = new HarmonistEffect(
  122.     sampleRate: 44100,
  123.     channels: 2,
  124.     bufferMilliseconds: 100,
  125.     harmonyLevel: 0.5f,
  126.     harmonyInterval: 7, // pitch shift up by a perfect fifth (7 semitones)
  127.     harmonyDetune: 5 // detune the harmony by 5 cents
  128. );
  129.  
  130. // Start processing live audio input
  131. harmonist.Start();
  132.  
  133. // Wait for user input to stop processing
  134. Console.WriteLine("Press any key to stop...");
  135. Console.ReadKey();
  136.  
  137. // Stop processing and release resources
  138. harmonist.Stop();
  139.  
  140. /*
  141. This example creates a HarmonistEffect object that pitches up
  142. the input signal by a perfect fifth (7 semitones) and detunes
  143. the harmony by 5 cents. The harmonyLevel parameter controls the
  144. level of the harmony effect relative to the input signal. The
  145. Start() method begins processing live audio input from the
  146. default audio input device, and the Stop() method stops
  147. processing and releases resources when the user presses any key.
  148. */
  149.  
  150.  
  151.  
  152.  
  153.  
Advertisement
Add Comment
Please, Sign In to add comment