NAudio Algorithm for playing a sine wave whose frequency can be changed smoothly in real time

So far, I have implemented the algorithm found on this blog with limited success.

The concept of my program is to initialize the sine wave, then change the frequency according to the position of the mouse on the screen - move the mouse up, and the sine wave will become higher and vice versa (in essence, this is an instrument such as a temporary type, a mouse).

The problem with what I have implemented so far is that when the sine wave frequency is updated, there is an audible click that instead of providing a smooth frequency sweep makes it sound like there are discrete frequencies, I searched high and low on the forums NAudio is here, but it doesn’t seem like anyone else is trying to do such things using NAudio, or, for that matter, any other sound module β€” all similar programs that run similarly to using equipment such as Kinect, using virtual GOVERNMENTAL midi-cable and an existing software module, but I would like to implement the same concept without relying on external software packages.

I posted a section of my code related to this issue on the NAudio forum here , and as you can see, I follow the MarkHeath recommendations here to try to find a solution to my problem.

+3
source share
1 answer

You need to avoid breaks in the output form (these are the clicks you hear). The easiest way to do this is a LUT-based signal generator - this works for any periodic waveform (i.e. not just pure sine waves). Typically, you use a fixed-point phase accumulator that increases for each new sample with a delta value that corresponds to the current output frequency. You can safely modify delta as you like, and the waveform will continue to be continuous.

Pseudocode (for one output sample):

const int LUT_SIZE; const int LUT[LUT_SIZE]; // waveform lookup table (typically 2^N, N >= 8) Fixed index; // current index into LUT (integer + fraction) Fixed delta; // delta controls output frequency output_value = LUT[(int)index]; // NB: for higher quality use the fractional part of index to interpolate // between LUT[(int)index] and LUT[(int)index + 1], rather than just // truncating the index and using LUT[(int)index] only. Depends on both // LUT_SIZE and required output quality. index = (index + delta) % LUT_SIZE; 


Note: to calculate delta for a given output frequency f and sampling frequency Fs :
 delta = FloatToFixed(LUT_SIZE * f / Fs); 
+9
source

Source: https://habr.com/ru/post/1393247/


All Articles