Created
April 6, 2020 10:00
-
-
Save mchalain/3eb0a88251262488d2c00fa52c371916 to your computer and use it in GitHub Desktop.
Simple noise generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <alsa/asoundlib.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <sched.h> | |
snd_pcm_t *player_init(char *soundcard, int nbsamples) | |
{ | |
int ret; | |
snd_pcm_t *playback_handle; | |
snd_pcm_open(&playback_handle, soundcard, SND_PCM_STREAM_PLAYBACK, 0); | |
snd_pcm_hw_params_t *hw_params; | |
snd_pcm_hw_params_malloc(&hw_params); | |
snd_pcm_hw_params_any(playback_handle, hw_params); | |
int channels = 2; | |
snd_pcm_hw_params_set_channels(playback_handle, hw_params, channels); | |
snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); | |
snd_pcm_format_t pcm_format = SND_PCM_FORMAT_S16_LE; | |
snd_pcm_hw_params_set_format(playback_handle, hw_params, pcm_format); | |
unsigned int rate = 44100; | |
snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, NULL); | |
int periods = 3; | |
ret = snd_pcm_hw_params_set_periods(playback_handle, hw_params, periods, 0); | |
if (ret != 0) | |
printf("set_periods error %s\n", snd_strerror(ret)); | |
ret = snd_pcm_hw_params_set_period_size(playback_handle, hw_params, nbsamples, 0); | |
if (ret != 0) | |
printf("set_period_size error %s\n", snd_strerror(ret)); | |
ret = snd_pcm_hw_params_set_buffer_size(playback_handle, hw_params, nbsamples * periods); | |
if (ret != 0) | |
printf("set_buffer_size error %s\n", snd_strerror(ret)); | |
snd_pcm_hw_params(playback_handle, hw_params); | |
snd_pcm_uframes_t buffersize = 0; | |
snd_pcm_hw_params_get_buffer_size(hw_params, &buffersize); | |
snd_pcm_uframes_t periodsize = 0; | |
snd_pcm_hw_params_get_period_size(hw_params, &periodsize, 0); | |
snd_pcm_hw_params_get_periods(hw_params, &periods, 0); | |
printf("buffersize %ld, periodsize %ld, nb periods %d\n", buffersize, periodsize, periods); | |
snd_pcm_prepare(playback_handle); | |
snd_pcm_hw_params_free(hw_params); | |
return playback_handle; | |
} | |
int generator_init(void) | |
{ | |
unsigned int seed; | |
int fd = open("/dev/random", R_OK); | |
sched_yield(); | |
read(fd, &seed, sizeof(seed)); | |
close(fd); | |
srandom(seed); | |
} | |
void generator(int16_t *samples, int nbsamples, int16_t max) | |
{ | |
int i; | |
for (i = 0; i < nbsamples; i++) | |
{ | |
int16_t *left = &samples[i * 2]; | |
int16_t *right = &samples[i * 2 + 1]; | |
*left = random() * max / RAND_MAX; | |
*right = random() * max / RAND_MAX; | |
} | |
} | |
typedef void (*generator_t)(int16_t *samples, int nbsamples, int16_t max); | |
int player_run(snd_pcm_t *playback_handle, int nbsamples, generator_t generator) | |
{ | |
int run = 1; | |
int16_t *buffer = malloc(nbsamples * sizeof(int16_t) * 2); | |
generator_init(); | |
while (run) | |
{ | |
generator(buffer, nbsamples, INT16_MAX); | |
snd_pcm_writei(playback_handle, buffer, nbsamples); | |
} | |
free(buffer); | |
} | |
void player_finish(snd_pcm_t *handle) | |
{ | |
snd_pcm_drain(handle); | |
snd_pcm_close(handle); | |
} | |
int main(int argc, char **argv) | |
{ | |
snd_pcm_t *handle = player_init("default", 1024); | |
generator_init(); | |
player_run(handle, 1024, &generator); | |
player_finish(handle); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment