mirror of
https://github.com/RaySollium99/libpicofe.git
synced 2025-09-03 06:17:44 -04:00
add preliminary alsa driver too
This commit is contained in:
parent
26d3ca0d29
commit
32d23d03ac
3 changed files with 150 additions and 0 deletions
139
linux/sndout_alsa.c
Normal file
139
linux/sndout_alsa.c
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* (C) notaz, 2013
|
||||
*
|
||||
* This work is licensed under the terms of any of these licenses
|
||||
* (at your option):
|
||||
* - GNU GPL, version 2 or later.
|
||||
* - GNU LGPL, version 2.1 or later.
|
||||
* - MAME license.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sndout_alsa.h"
|
||||
|
||||
static snd_pcm_t *handle;
|
||||
static snd_pcm_uframes_t buffer_size, period_size;
|
||||
static unsigned int channels;
|
||||
static void *silent_period;
|
||||
|
||||
int sndout_alsa_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sndout_alsa_start(int rate_, int stereo)
|
||||
{
|
||||
snd_pcm_hw_params_t *hwparams = NULL;
|
||||
unsigned int rate = rate_;
|
||||
int samples, shift;
|
||||
int ret;
|
||||
|
||||
samples = rate * 40 / 1000;
|
||||
for (shift = 8; (1 << shift) < samples; shift++)
|
||||
;
|
||||
period_size = 1 << shift;
|
||||
buffer_size = 8 * period_size;
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
ret = snd_pcm_hw_params_any(handle, hwparams);
|
||||
ret |= snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
ret |= snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE);
|
||||
ret |= snd_pcm_hw_params_set_channels(handle, hwparams, stereo ? 2 : 1);
|
||||
ret |= snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0);
|
||||
ret |= snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
|
||||
ret |= snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, NULL);
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "sndout_alsa: failed to set hwparams\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = snd_pcm_hw_params(handle, hwparams);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "sndout_alsa: failed to apply hwparams: %d\n",
|
||||
ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
|
||||
snd_pcm_hw_params_get_period_size(hwparams, &period_size, NULL);
|
||||
snd_pcm_hw_params_get_channels(hwparams, &channels);
|
||||
|
||||
silent_period = realloc(silent_period, period_size * 2 * channels);
|
||||
if (silent_period != NULL)
|
||||
memset(silent_period, 0, period_size * 2 * channels);
|
||||
|
||||
ret = snd_pcm_prepare(handle);
|
||||
ret |= snd_pcm_start(handle);
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "sndout_alsa: failed to start pcm: %d\n",
|
||||
ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sndout_alsa_stop(void)
|
||||
{
|
||||
// nothing?
|
||||
}
|
||||
|
||||
void sndout_alsa_wait(void)
|
||||
{
|
||||
snd_pcm_sframes_t left;
|
||||
|
||||
while (1)
|
||||
{
|
||||
left = snd_pcm_avail(handle);
|
||||
if (left < 0 || left >= buffer_size / 2)
|
||||
break;
|
||||
|
||||
usleep(4000);
|
||||
}
|
||||
}
|
||||
|
||||
int sndout_alsa_write_nb(const void *samples, int len)
|
||||
{
|
||||
snd_pcm_sframes_t left;
|
||||
int ret;
|
||||
|
||||
len /= 2;
|
||||
if (channels == 2)
|
||||
len /= 2;
|
||||
|
||||
left = snd_pcm_avail(handle);
|
||||
if (left >= 0 && left < len)
|
||||
return 0;
|
||||
|
||||
ret = snd_pcm_writei(handle, samples, len);
|
||||
if (ret < 0) {
|
||||
ret = snd_pcm_recover(handle, ret, 1);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "sndout_alsa snd_pcm_recover: %d\n", ret);
|
||||
|
||||
if (silent_period)
|
||||
snd_pcm_writei(handle, silent_period, period_size);
|
||||
snd_pcm_writei(handle, samples, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void sndout_alsa_exit(void)
|
||||
{
|
||||
snd_pcm_close(handle);
|
||||
handle = NULL;
|
||||
}
|
7
linux/sndout_alsa.h
Normal file
7
linux/sndout_alsa.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
int sndout_alsa_init(void);
|
||||
int sndout_alsa_start(int rate, int stereo);
|
||||
void sndout_alsa_stop(void);
|
||||
void sndout_alsa_wait(void);
|
||||
int sndout_alsa_write_nb(const void *samples, int len);
|
||||
void sndout_alsa_exit(void);
|
4
sndout.c
4
sndout.c
|
@ -13,6 +13,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "linux/sndout_oss.h"
|
||||
#include "linux/sndout_alsa.h"
|
||||
#include "sndout_sdl.h"
|
||||
#include "sndout.h"
|
||||
|
||||
|
@ -58,6 +59,9 @@ static struct sndout_driver sndout_avail[] =
|
|||
#ifdef HAVE_SDL
|
||||
SNDOUT_DRIVER(sdl),
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
SNDOUT_DRIVER(alsa),
|
||||
#endif
|
||||
#ifdef HAVE_OSS
|
||||
SNDOUT_DRIVER(oss),
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue