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;
}
next 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.