0

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.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Grumpy
  • 1
  • 1
  • 2
    When stopping sound, do a linear fade of the amplitude to zero. When switching frequencies, control your phase to avoid discontinuity and/or crossfade from one tone buffer to another. – Reinderien Jul 03 '23 at 23:32

0 Answers0