mirror of
https://github.com/RaySollium99/libpicofe.git
synced 2025-09-04 14:37:46 -04:00
support multiple sound drivers, add sdl
This commit is contained in:
parent
20b143089c
commit
26d3ca0d29
6 changed files with 294 additions and 6 deletions
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include "sndout_oss.h"
|
#include "sndout_oss.h"
|
||||||
|
|
||||||
|
int sndout_oss_frag_frames = 1;
|
||||||
|
|
||||||
static int sounddev = -1, mixerdev = -1;
|
static int sounddev = -1, mixerdev = -1;
|
||||||
static int can_write_safe;
|
static int can_write_safe;
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ void sndout_oss_stop(void)
|
||||||
sounddev = -1;
|
sounddev = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sndout_oss_start(int rate, int stereo, int frames_in_frag)
|
int sndout_oss_start(int rate, int stereo)
|
||||||
{
|
{
|
||||||
static int s_oldrate = 0, s_oldstereo = 0;
|
static int s_oldrate = 0, s_oldstereo = 0;
|
||||||
int frag, bsize, bits, ret;
|
int frag, bsize, bits, ret;
|
||||||
|
@ -69,10 +71,11 @@ int sndout_oss_start(int rate, int stereo, int frames_in_frag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to fit frames_in_frag frames worth of data in fragment
|
// try to fit sndout_oss_frag_frames (video) frames
|
||||||
|
// worth of sound data in OSS fragment
|
||||||
// ignore mono because it's unlikely to be used and
|
// ignore mono because it's unlikely to be used and
|
||||||
// both GP2X and Wiz mixes mono to stereo anyway.
|
// both GP2X and Wiz mixes mono to stereo anyway.
|
||||||
bsize = (frames_in_frag * rate / 50) * 4;
|
bsize = (sndout_oss_frag_frames * rate / 50) * 4;
|
||||||
|
|
||||||
for (frag = 0; bsize; bsize >>= 1, frag++)
|
for (frag = 0; bsize; bsize >>= 1, frag++)
|
||||||
;
|
;
|
||||||
|
@ -164,8 +167,9 @@ int sndout_oss_can_write(int bytes)
|
||||||
return bi.bytes - bi.fragsize >= bytes ? 1 : 0;
|
return bi.bytes - bi.fragsize >= bytes ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sndout_oss_sync(void)
|
void sndout_oss_wait(void)
|
||||||
{
|
{
|
||||||
|
// FIXME?
|
||||||
ioctl(sounddev, SOUND_PCM_SYNC, 0);
|
ioctl(sounddev, SOUND_PCM_SYNC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
int sndout_oss_init(void);
|
int sndout_oss_init(void);
|
||||||
int sndout_oss_start(int rate, int stereo, int frames_in_frag);
|
int sndout_oss_start(int rate, int stereo);
|
||||||
void sndout_oss_stop(void);
|
void sndout_oss_stop(void);
|
||||||
int sndout_oss_write(const void *buff, int len);
|
int sndout_oss_write(const void *buff, int len);
|
||||||
int sndout_oss_write_nb(const void *buff, int len);
|
int sndout_oss_write_nb(const void *buff, int len);
|
||||||
int sndout_oss_can_write(int bytes);
|
int sndout_oss_can_write(int bytes);
|
||||||
void sndout_oss_sync(void);
|
void sndout_oss_wait(void);
|
||||||
void sndout_oss_setvol(int l, int r);
|
void sndout_oss_setvol(int l, int r);
|
||||||
void sndout_oss_exit(void);
|
void sndout_oss_exit(void);
|
||||||
|
|
||||||
|
/* make oss fragment size to fit this much video frames */
|
||||||
|
extern int sndout_oss_frag_frames;
|
||||||
|
|
80
sndout.c
Normal file
80
sndout.c
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* (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 <string.h>
|
||||||
|
|
||||||
|
#include "linux/sndout_oss.h"
|
||||||
|
#include "sndout_sdl.h"
|
||||||
|
#include "sndout.h"
|
||||||
|
|
||||||
|
static int sndout_null_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sndout_null_exit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sndout_null_start(int rate, int stereo)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sndout_null_stop(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sndout_null_wait(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sndout_null_write_nb(const void *data, int bytes)
|
||||||
|
{
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SNDOUT_DRIVER(name) { \
|
||||||
|
#name, \
|
||||||
|
sndout_##name##_init, \
|
||||||
|
sndout_##name##_exit, \
|
||||||
|
sndout_##name##_start, \
|
||||||
|
sndout_##name##_stop, \
|
||||||
|
sndout_##name##_wait, \
|
||||||
|
sndout_##name##_write_nb, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sndout_driver sndout_avail[] =
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SDL
|
||||||
|
SNDOUT_DRIVER(sdl),
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_OSS
|
||||||
|
SNDOUT_DRIVER(oss),
|
||||||
|
#endif
|
||||||
|
SNDOUT_DRIVER(null)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sndout_driver sndout_current;
|
||||||
|
|
||||||
|
void sndout_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(sndout_avail) / sizeof(sndout_avail[0]); i++) {
|
||||||
|
if (sndout_avail[i].init() == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&sndout_current, &sndout_avail[i], sizeof(sndout_current));
|
||||||
|
printf("using %s audio output driver\n", sndout_current.name);
|
||||||
|
}
|
43
sndout.h
Normal file
43
sndout.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef LIBPICOFE_SNDOUT_H
|
||||||
|
#define LIBPICOFE_SNDOUT_H
|
||||||
|
|
||||||
|
struct sndout_driver {
|
||||||
|
const char *name;
|
||||||
|
int (*init)(void);
|
||||||
|
void (*exit)(void);
|
||||||
|
int (*start)(int rate, int stereo);
|
||||||
|
void (*stop)(void);
|
||||||
|
void (*wait)(void);
|
||||||
|
int (*write_nb)(const void *data, int bytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct sndout_driver sndout_current;
|
||||||
|
|
||||||
|
void sndout_init(void);
|
||||||
|
|
||||||
|
static inline void sndout_exit(void)
|
||||||
|
{
|
||||||
|
sndout_current.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int sndout_start(int rate, int stereo)
|
||||||
|
{
|
||||||
|
return sndout_current.start(rate, stereo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sndout_stop(void)
|
||||||
|
{
|
||||||
|
sndout_current.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sndout_wait(void)
|
||||||
|
{
|
||||||
|
sndout_current.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int sndout_write_nb(const void *data, int bytes)
|
||||||
|
{
|
||||||
|
return sndout_current.write_nb(data, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LIBPICOFE_SNDOUT_H
|
151
sndout_sdl.c
Normal file
151
sndout_sdl.c
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* (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 <SDL.h>
|
||||||
|
#include "sndout_sdl.h"
|
||||||
|
|
||||||
|
// ~1/3s at 44kHz
|
||||||
|
// set this to power of 2
|
||||||
|
#define BUF_LEN 32768
|
||||||
|
#define BUF_MASK (BUF_LEN - 1)
|
||||||
|
|
||||||
|
static short buf[BUF_LEN];
|
||||||
|
static int buf_w, buf_r;
|
||||||
|
static int started;
|
||||||
|
|
||||||
|
static void callback(void *userdata, Uint8 *stream, int len)
|
||||||
|
{
|
||||||
|
int have = (buf_w - buf_r) & BUF_MASK;
|
||||||
|
int buf_left = BUF_LEN - buf_r;
|
||||||
|
|
||||||
|
len /= 2;
|
||||||
|
if (have > len)
|
||||||
|
have = len;
|
||||||
|
if (have > 0) {
|
||||||
|
if (have > buf_left) {
|
||||||
|
memcpy(stream, buf + buf_r, buf_left * 2);
|
||||||
|
stream += buf_left * 2;
|
||||||
|
buf_r = 0;
|
||||||
|
have -= buf_left;
|
||||||
|
len -= buf_left;
|
||||||
|
}
|
||||||
|
memcpy(stream, buf + buf_r, have * 2);
|
||||||
|
stream += have * 2;
|
||||||
|
buf_r = (buf_r + have) & BUF_MASK;
|
||||||
|
len -= have;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
// put in some silence..
|
||||||
|
memset(stream, 0, len * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sndout_sdl_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
if (ret != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sndout_sdl_start(int rate, int stereo)
|
||||||
|
{
|
||||||
|
SDL_AudioSpec desired;
|
||||||
|
int samples, shift;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (started)
|
||||||
|
sndout_sdl_stop();
|
||||||
|
|
||||||
|
desired.freq = rate;
|
||||||
|
desired.format = AUDIO_S16LSB;
|
||||||
|
desired.channels = stereo ? 2 : 1;
|
||||||
|
desired.callback = callback;
|
||||||
|
desired.userdata = NULL;
|
||||||
|
|
||||||
|
samples = rate * 4 * 16 / 1000;
|
||||||
|
for (shift = 8; (1 << shift) < samples; shift++)
|
||||||
|
;
|
||||||
|
desired.samples = 1 << shift;
|
||||||
|
|
||||||
|
ret = SDL_OpenAudio(&desired, NULL);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_w = buf_r = 0;
|
||||||
|
|
||||||
|
SDL_PauseAudio(0);
|
||||||
|
started = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndout_sdl_stop(void)
|
||||||
|
{
|
||||||
|
SDL_PauseAudio(1);
|
||||||
|
SDL_CloseAudio();
|
||||||
|
started = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndout_sdl_wait(void)
|
||||||
|
{
|
||||||
|
int left;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
left = (buf_r - buf_w - 2) & BUF_MASK;
|
||||||
|
if (left >= BUF_LEN / 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
SDL_Delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sndout_sdl_write_nb(const void *samples, int len)
|
||||||
|
{
|
||||||
|
int maxlen = (buf_r - buf_w - 2) & BUF_MASK;
|
||||||
|
int buf_left = BUF_LEN - buf_w;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
len /= 2;
|
||||||
|
if (len > maxlen)
|
||||||
|
// not enough space
|
||||||
|
len = maxlen;
|
||||||
|
if (len == 0)
|
||||||
|
// totally full
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
retval = len;
|
||||||
|
|
||||||
|
if (len > buf_left) {
|
||||||
|
memcpy(buf + buf_w, samples, buf_left * 2);
|
||||||
|
samples = (const short *)samples + buf_left;
|
||||||
|
len -= buf_left;
|
||||||
|
buf_w = 0;
|
||||||
|
}
|
||||||
|
memcpy(buf + buf_w, samples, len * 2);
|
||||||
|
buf_w = (buf_w + len) & BUF_MASK;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndout_sdl_exit(void)
|
||||||
|
{
|
||||||
|
if (started)
|
||||||
|
sndout_sdl_stop();
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
}
|
7
sndout_sdl.h
Normal file
7
sndout_sdl.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
int sndout_sdl_init(void);
|
||||||
|
int sndout_sdl_start(int rate, int stereo);
|
||||||
|
void sndout_sdl_stop(void);
|
||||||
|
void sndout_sdl_wait(void);
|
||||||
|
int sndout_sdl_write_nb(const void *buff, int len);
|
||||||
|
void sndout_sdl_exit(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue