GUACAMOLE-934: Correct waveform calculation. Switch to triangle wave to reduce aliasing distortion.

This commit is contained in:
Michael Jumper 2020-01-21 00:03:42 -08:00
parent b8148b0daf
commit b21d19d37d

View File

@ -46,29 +46,30 @@
* @param buffer_size * @param buffer_size
* The number of bytes of PCM data to write to the given buffer. * 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 frequency, int rate, int buffer_size) {
int remaining = buffer_size; /* With the distance between each positive/negative peak and zero being the
int current_value = GUAC_RDP_BEEP_AMPLITUDE; * amplitude, and with the "bounce" between those peaks occurring once
int pulse_width = rate / frequency / 2; * 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 /* With the number of distinct states being the wave_period defined above,
* frequency) until buffer space is exhausted */ * the "bounce" point within that period is half the period */
while (remaining > 0) { const int wave_bounce_offset = wave_period / 2;
/* Truncate pulse if insufficient space remains */ for (int position = 0; position < buffer_size; position++) {
int block_size = pulse_width;
if (block_size > remaining)
block_size = remaining;
/* Write blocks, alternating the sign of the amplitude of each /* Calculate relative position within the repeating portion of the wave
* successive block */ * (the portion with wave_period unique states) */
memset(buffer, current_value, block_size); int wave_position = (position * frequency * wave_period / rate) % wave_period;
current_value = -current_value;
buffer += block_size; /* Calculate state of the triangle wave function at the calculated
remaining -= block_size; * 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 @@ static void guac_rdp_beep_write_pcm(guac_audio_stream* audio,
int buffer_size = audio->rate * duration / 1000; int buffer_size = audio->rate * duration / 1000;
unsigned char* buffer = malloc(buffer_size); unsigned char* buffer = malloc(buffer_size);
/* Beep for given frequency/duration using a simple square wave */ /* Beep for given frequency/duration using a simple triangle wave */
guac_rdp_beep_fill_square_wave(buffer, frequency, audio->rate, buffer_size); guac_rdp_beep_fill_triangle_wave(buffer, frequency, audio->rate, buffer_size);
guac_audio_stream_write_pcm(audio, buffer, buffer_size); guac_audio_stream_write_pcm(audio, buffer, buffer_size);
free(buffer); free(buffer);