GUACAMOLE-934: Correct waveform calculation. Switch to triangle wave to reduce aliasing distortion.
diff --git a/src/protocols/rdp/beep.c b/src/protocols/rdp/beep.c
index 46e80fd..8fb5001 100644
--- a/src/protocols/rdp/beep.c
+++ b/src/protocols/rdp/beep.c
@@ -46,29 +46,30 @@
  * @param buffer_size
  *     The number of bytes of PCM data to write to the given buffer.
  */
-static void guac_rdp_beep_fill_square_wave(unsigned char* buffer,
+static void guac_rdp_beep_fill_triangle_wave(unsigned char* buffer,
         int frequency, int rate, int buffer_size) {
 
-    int remaining = buffer_size;
-    int current_value = GUAC_RDP_BEEP_AMPLITUDE;
-    int pulse_width = rate / frequency / 2;
+    /* With the distance between each positive/negative peak and zero being the
+     * amplitude, and with the "bounce" between those peaks occurring once
+     * every two periods, the number of distinct states that the triangle wave
+     * function goes through is twice the peak-to-peak amplitude, or four times
+     * the overall amplitude */
+    const int wave_period = GUAC_RDP_BEEP_AMPLITUDE * 4;
 
-    /* Repeatedly write pulses (whose widths are determined by the desired
-     * frequency) until buffer space is exhausted */
-    while (remaining > 0) {
+    /* With the number of distinct states being the wave_period defined above,
+     * the "bounce" point within that period is half the period */
+    const int wave_bounce_offset = wave_period / 2;
 
-        /* Truncate pulse if insufficient space remains */
-        int block_size = pulse_width;
-        if (block_size > remaining)
-            block_size = remaining;
+    for (int position = 0; position < buffer_size; position++) {
 
-        /* Write blocks, alternating the sign of the amplitude of each
-         * successive block */
-        memset(buffer, current_value, block_size);
-        current_value = -current_value;
+        /* Calculate relative position within the repeating portion of the wave
+         * (the portion with wave_period unique states) */
+        int wave_position = (position * frequency * wave_period / rate) % wave_period;
 
-        buffer += block_size;
-        remaining -= block_size;
+        /* Calculate state of the triangle wave function at the calculated
+         * offset, knowing in advance the relative location that the function
+         * should "bounce" */
+        *(buffer++) = abs(wave_position - wave_bounce_offset) - GUAC_RDP_BEEP_AMPLITUDE;
 
     }
 
@@ -95,8 +96,8 @@
     int buffer_size = audio->rate * duration / 1000;
     unsigned char* buffer = malloc(buffer_size);
 
-    /* Beep for given frequency/duration using a simple square wave */
-    guac_rdp_beep_fill_square_wave(buffer, frequency, audio->rate, buffer_size);
+    /* Beep for given frequency/duration using a simple triangle wave */
+    guac_rdp_beep_fill_triangle_wave(buffer, frequency, audio->rate, buffer_size);
     guac_audio_stream_write_pcm(audio, buffer, buffer_size);
 
     free(buffer);