All of lore.kernel.org
 help / color / mirror / Atom feed
From: Charles Mulder <charlesmulder@tutamail.com>
To: alsa-devel@alsa-project.org
Subject: Help to solve pop when sound loops
Date: Fri, 25 Oct 2024 18:03:25 +0200 (GMT+02:00)	[thread overview]
Message-ID: <OA3PlJI--B-9@tutamail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 614 bytes --]

Hi.

I hope this is the correct place to ask for help relating to ALSA's C lib?

I'm working on a wavetable project for college. Please see attached. 

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

-- 
 Sent with Tuta; enjoy secure & ad-free emails: 
 https://tuta.com

[-- Attachment #2: basic_alsa_wavetable.c --]
[-- Type: text/x-csrc, Size: 6471 bytes --]

#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];              /* some random data */

/**
 * = ALSA  Frames
 * Frame is container for sending simultaneous samples.
 *  - Mono frame contains 1 sample.
 *  - Stereo frame contains 2 samples.
 *
 * = ALSA Ring Buffer
 * Store outgoing (playback) and incoming (capture, record) samples.
 * == Two pointers
 *  - current processed sample by hardware
 *  - last processed sample by application.
 */
int main(void) {

	// ALSA playback related
	int err; 
	snd_pcm_t *playback_handle; // pcm
	snd_pcm_hw_params_t *hw_params;
	unsigned int sbits, subformat, tick_time, access, channels, buffer_time, buffer_size, periods, period_time, rate, rate_num, rate_den, val, val2; // @todo more descriptive vars
	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);
	}

	/* Display information about the PCM interface */
	if( ALSA_INFO == 1) {
		printf("PCM playback_handle name = '%s'\n", snd_pcm_name(playback_handle));

		printf("PCM state = %s\n",
				snd_pcm_state_name(snd_pcm_state(playback_handle)));

		snd_pcm_hw_params_get_access(hw_params, &access);
		printf("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)access));

		snd_pcm_hw_params_get_format(hw_params, &format);
		printf("format = '%s' (%s)\n",
				snd_pcm_format_name((snd_pcm_format_t)format),
				snd_pcm_format_description(
					(snd_pcm_format_t)format));

		snd_pcm_hw_params_get_subformat(hw_params, (snd_pcm_subformat_t *)&subformat);
		printf("subformat = '%s' (%s)\n",
				snd_pcm_subformat_name((snd_pcm_subformat_t)subformat),
				snd_pcm_subformat_description( (snd_pcm_subformat_t)subformat) );

		snd_pcm_hw_params_get_channels(hw_params, &channels);
		printf("channels = %d\n", channels);

		snd_pcm_hw_params_get_rate(hw_params, &rate, NULL);
		printf("rate = %d bps\n", rate);

		snd_pcm_hw_params_get_period_time(hw_params, &period_time, NULL);
		printf("period time = %d us\n", period_time);

		snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);
		printf("period size = %d frames\n", (int)period_size);

		snd_pcm_hw_params_get_buffer_time(hw_params, &buffer_time, &dir);
		printf("buffer time = %d us\n", buffer_time);

		snd_pcm_hw_params_get_buffer_size(hw_params, (snd_pcm_uframes_t *) &buffer_size);
		printf("buffer size = %d frames\n", buffer_size);

		snd_pcm_hw_params_get_periods(hw_params, &periods, &dir);
		printf("periods per buffer = %d frames\n", periods);

		// rate numerator and denominator
		snd_pcm_hw_params_get_rate_numden(hw_params, &rate_num, &rate_den);
		printf("exact rate = %d/%d bps\n", rate_num, rate_den);

		sbits = snd_pcm_hw_params_get_sbits(hw_params);
		printf("significant bits = %d\n", sbits);

	}

	// 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
									 //printf("angle inc: %.4f\n", angle_inc);
									 //printf("index inc: %.4f\n", index_inc);

									 // Populate wavetable with a sine wave
	for( int n = 0; n < N; n++ ) {
		//wavetable[n] = sin( angle_inc * n ); // 0 - 1 range
		wavetable[n] = sinuc( angle_inc * n ); // 0 - 255 range
											   //printf("%d\n", wavetable[n]);
	}

	// 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;
}


             reply	other threads:[~2024-10-28 16:43 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-25 16:03 Charles Mulder [this message]
     [not found] <1730889959056958199-webhooks-bot@alsa-project.org>
2024-11-06 10:46 ` Help to solve pop when sound loops GitHub issues - edited
     [not found] <1729870300826364279-webhooks-bot@alsa-project.org>
2024-10-25 15:31 ` GitHub issues - edited

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=OA3PlJI--B-9@tutamail.com \
    --to=charlesmulder@tutamail.com \
    --cc=alsa-devel@alsa-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.