I am working on a beeper that makes simple wave sounds in order to use it in sorting visualizer program. The beeper can make simple waves. The problem is that I want to eliminate the clicking sound when stopping the sound or changing the frequency.
Here is the source code of the beeper.
Beeper.h
#include <SDL2/SDL.h>
#ifndef BEEPER_H
#define BEEPER_H
#define AMPLITUDE 32000
#define CHANNELS 1
#define SAMPLE_RATE 44100
#define BUFFER_SIZE 4096
#define DEFAULT_TONE 440.0f
typedef struct Beeper
{
int buffer;
int amplitude;
int sample_rate;
int channels;
float tone;
float target_tone;
Uint64 sample_played;
SDL_AudioDeviceID device;
} Beeper;
Beeper *InitializeBepper(int buffer, int amplitude, int sample_rate, int channel, float tone);
int RequestDevice(Beeper *beeper);
void AddTone(Beeper *beeper, float freq);
void PlaySounds(Beeper *beeper, int duration);
void AudioCallBack(void *beeper, Uint8 *stream, int len);
void DetroyBeeper(Beeper *beeper);
#endif
Beeper.c
#include <SDL2/SDL.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "beeper.h"
Beeper *InitializeBepper(int buffer, int amplitude, int sample_rate, int channel, float tone)
{
Beeper *beeper = (Beeper *)malloc(sizeof(Beeper));
if (beeper == NULL)
{
return NULL;
}
beeper->amplitude = amplitude;
beeper->buffer = buffer;
beeper->sample_rate = sample_rate;
beeper->channels = channel;
beeper->tone = beeper->target_tone = tone;
beeper->sample_played = 0;
if (RequestDevice(beeper) == -1)
return NULL;
return beeper;
}
int RequestDevice(Beeper *beeper)
{
SDL_AudioSpec desired;
SDL_zero(desired);
desired.freq = beeper->sample_rate;
desired.channels = beeper->channels;
desired.format = AUDIO_S16SYS;
desired.samples = beeper->buffer;
desired.userdata = beeper;
desired.callback = AudioCallBack;
beeper->device = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, 0);
if (beeper->device == 0)
{
printf("Failed to request audio device.\n%s.\n", SDL_GetError());
SDL_CloseAudio();
return -1;
}
return 0;
SDL_PauseAudioDevice(beeper->device, 1);
}
void AddTone(Beeper *beeper, float freq)
{
beeper->target_tone = freq;
}
static void AddSamples(Beeper *beeper, Sint16 *stream, int len)
{
int samples = len / sizeof(Sint16);
float tone_step = (beeper->target_tone - beeper->tone) / samples;
for (int i = 0; i < samples; i++)
{
double time = 2.0 * M_PI * (beeper->sample_played + i) / beeper->sample_rate;
stream[i] = (Sint16)(beeper->amplitude * sin(time * beeper->tone));
beeper->tone += tone_step;
}
beeper->sample_played += samples;
beeper->tone = beeper->target_tone;
}
void AudioCallBack(void *user_data, Uint8 *stream, int len)
{
AddSamples((Beeper *)user_data, (Sint16 *)stream, len);
}
void DetroyBeeper(Beeper *beeper)
{
SDL_CloseAudio();
free(beeper);
}
I tried to smooth the sound by adding a tone step variable to increment the tone to the next target tone.