alsa-project/alsa-lib issue #417 was edited from charlesmulder:
Hi.
Apologies for asking for help here. I don't know where else to go.
I'm working on a wavetable project for college.
I've managed to create a wavetable containing a sine wave. The pitch can be altered via a frequency variable (f).
There is an audible popping sound when the sound loops. I have noticed that increasing the buffer size, postpones the pop.
I've been reading up on `buffer > period > frames`, but I don't know how to go about removing the pop.
Would really appreciate some guidance.
Thanks C
``` #include <stdio.h> #include <alsa/asoundlib.h> #include <math.h>
unsigned char sinuc( float );
#define TWOPI 2*M_PI #define ALSA_INFO 1
static char *device = "default"; /* playback device */ unsigned char buffer[24*1024];
int main(void) {
// ALSA playback related int err; snd_pcm_t *playback_handle; // pcm snd_pcm_hw_params_t *hw_params; unsigned int val, val2; int dir; snd_pcm_uframes_t period_size; snd_pcm_format_t format;
// Wavetable related unsigned int N = 1024; float f = 440; // A4 note //float f = 261.626; // C4 note unsigned int fs = 44100;
// playback if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { printf("Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); }
// ALSA configuration
/* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&hw_params);
/* Fill it in with default values. */ snd_pcm_hw_params_any(playback_handle, hw_params);
/* Set the desired hardware parameters. */
/* Interleaved mode */ snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Unsigned 8-bit little-endian format */ snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_U8);
/* Two channels (stereo) */ snd_pcm_hw_params_set_channels(playback_handle, hw_params, 1);
/* 44100 bits/second sampling rate (CD quality) */ snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &fs, &dir);
/* Set period size to 32 frames. */ period_size = 32; snd_pcm_hw_params_set_period_size_near(playback_handle, hw_params, &period_size, &dir);
/* Write the parameters to the driver */ err = snd_pcm_hw_params(playback_handle, hw_params); if (err < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(err)); exit(1); }
// Wavetable init unsigned char wavetable[N]; // wavetable buffer float angle_inc = TWOPI/(float)N; // sine wave angle increment float index_inc = N*f/(float)fs; // wavetable index increment
// Populate wavetable with a sine wave for( int n = 0; n < N; n++ ) { wavetable[n] = sinuc( angle_inc * n ); // 0 - 255 range }
// ALSA Sample Buffer // period = 940 frames // buffer = 15052 frames float n = 0; for (int i = 0; i < sizeof(buffer)/sizeof(char); i++) { buffer[i] = wavetable[(int)n]; //printf("%d\n",buffer[i]); n = n+index_inc; if( (int)n >= N ) { n = 0; } }
if ((err = snd_pcm_prepare (playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); }
//for (int i = 0; i < 16; i++) { while(1) { period_size = snd_pcm_writei(playback_handle, buffer, sizeof(buffer)); if (period_size < 0) period_size = snd_pcm_recover(playback_handle, period_size, 0); if (period_size < 0) { printf("snd_pcm_writei failed: %s\n", snd_strerror(period_size)); break; } if (period_size > 0 && period_size < (long)sizeof(buffer)) printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), period_size); }
// pass the remaining samples, otherwise they're dropped in close err = snd_pcm_drain(playback_handle); if (err < 0) printf("snd_pcm_drain failed: %s\n", snd_strerror(err));
//snd_pcm_hw_params_free(hw_params); snd_pcm_close(playback_handle);
return 0; }
/** * Sine unsigned char. * Scales sine output to a char * Original range -1 to 1. * New range 0 - 255. */ unsigned char sinuc( float angle ) { return (sinf( angle ) * 255 + 255) / 2; }
```
Issue URL : https://github.com/alsa-project/alsa-lib/issues/417 Repository URL: https://github.com/alsa-project/alsa-lib