Help to address pop at end of buffer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



alsa-project/alsa-lib issue #417 was opened 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



[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux