mirror of https://github.com/encounter/SDL.git
bsdaudio: first shot at audio capture support!
(untested, uncompiled...for now.)
This commit is contained in:
parent
d30a2f5ad8
commit
9dd8477a21
|
@ -63,13 +63,17 @@ BSDAUDIO_Status(_THIS)
|
||||||
#ifdef DEBUG_AUDIO
|
#ifdef DEBUG_AUDIO
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
audio_info_t info;
|
audio_info_t info;
|
||||||
|
const audio_prinfo *prinfo;
|
||||||
|
|
||||||
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
|
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
|
||||||
fprintf(stderr, "AUDIO_GETINFO failed.\n");
|
fprintf(stderr, "AUDIO_GETINFO failed.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prinfo = this->iscapture ? &info.play : &info.record;
|
||||||
|
|
||||||
fprintf(stderr, "\n"
|
fprintf(stderr, "\n"
|
||||||
"[play/record info]\n"
|
"[%s info]\n"
|
||||||
"buffer size : %d bytes\n"
|
"buffer size : %d bytes\n"
|
||||||
"sample rate : %i Hz\n"
|
"sample rate : %i Hz\n"
|
||||||
"channels : %i\n"
|
"channels : %i\n"
|
||||||
|
@ -83,18 +87,19 @@ BSDAUDIO_Status(_THIS)
|
||||||
"waiting : %s\n"
|
"waiting : %s\n"
|
||||||
"active : %s\n"
|
"active : %s\n"
|
||||||
"",
|
"",
|
||||||
info.play.buffer_size,
|
this->iscapture ? "record" : "play",
|
||||||
info.play.sample_rate,
|
prinfo->buffer_size,
|
||||||
info.play.channels,
|
prinfo->sample_rate,
|
||||||
info.play.precision,
|
prinfo->channels,
|
||||||
info.play.encoding,
|
prinfo->precision,
|
||||||
info.play.seek,
|
prinfo->encoding,
|
||||||
info.play.samples,
|
prinfo->seek,
|
||||||
info.play.eof,
|
prinfo->samples,
|
||||||
info.play.pause ? "yes" : "no",
|
prinfo->eof,
|
||||||
info.play.error ? "yes" : "no",
|
prinfo->pause ? "yes" : "no",
|
||||||
info.play.waiting ? "yes" : "no",
|
prinfo->error ? "yes" : "no",
|
||||||
info.play.active ? "yes" : "no");
|
prinfo->waiting ? "yes" : "no",
|
||||||
|
prinfo->active ? "yes" : "no");
|
||||||
|
|
||||||
fprintf(stderr, "\n"
|
fprintf(stderr, "\n"
|
||||||
"[audio info]\n"
|
"[audio info]\n"
|
||||||
|
@ -209,6 +214,57 @@ BSDAUDIO_GetDeviceBuf(_THIS)
|
||||||
return (this->hidden->mixbuf);
|
return (this->hidden->mixbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
BSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
|
||||||
|
{
|
||||||
|
Uint8 *buffer = (Uint8 *) _buffer;
|
||||||
|
int br, p = 0;
|
||||||
|
|
||||||
|
/* Write the audio data, checking for EAGAIN on broken audio drivers */
|
||||||
|
do {
|
||||||
|
br = read(this->hidden->audio_fd, buffer + p, buflen - p);
|
||||||
|
if (br > 0)
|
||||||
|
p += br;
|
||||||
|
if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
|
||||||
|
/* Non recoverable error has occurred. It should be reported!!! */
|
||||||
|
perror("audio");
|
||||||
|
return p ? p : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_AUDIO
|
||||||
|
fprintf(stderr, "Captured %d bytes of audio data\n", br);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (p < buflen
|
||||||
|
|| ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) {
|
||||||
|
SDL_Delay(1); /* Let a little CPU time go by */
|
||||||
|
}
|
||||||
|
} while (p < buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BSDAUDIO_FlushCapture(_THIS)
|
||||||
|
{
|
||||||
|
audio_info_t info;
|
||||||
|
size_t remain;
|
||||||
|
Uint8 buf[512];
|
||||||
|
|
||||||
|
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
|
||||||
|
return; /* oh well. */
|
||||||
|
}
|
||||||
|
|
||||||
|
remain = (size_t) (info.record.samples * (SDL_AUDIO_BITSIZE(this->spec.format) / 8));
|
||||||
|
while (remain > 0) {
|
||||||
|
const size_t len = SDL_min(sizeof (buf), remain);
|
||||||
|
const int br = read(this->hidden->audio_fd, buf, len);
|
||||||
|
if (br <= 0) {
|
||||||
|
return; /* oh well. */
|
||||||
|
}
|
||||||
|
remain -= br;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
BSDAUDIO_CloseDevice(_THIS)
|
BSDAUDIO_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
|
@ -227,9 +283,10 @@ BSDAUDIO_CloseDevice(_THIS)
|
||||||
static int
|
static int
|
||||||
BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
{
|
{
|
||||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
|
||||||
SDL_AudioFormat format = 0;
|
SDL_AudioFormat format = 0;
|
||||||
audio_info_t info;
|
audio_info_t info;
|
||||||
|
audio_prinfo *prinfo = iscapture ? &info.play : &info.record;
|
||||||
|
|
||||||
/* We don't care what the devname is...we'll try to open anything. */
|
/* We don't care what the devname is...we'll try to open anything. */
|
||||||
/* ...but default to first name in the list... */
|
/* ...but default to first name in the list... */
|
||||||
|
@ -260,7 +317,7 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
SDL_CalculateAudioSpec(&this->spec);
|
SDL_CalculateAudioSpec(&this->spec);
|
||||||
|
|
||||||
/* Set to play mode */
|
/* Set to play mode */
|
||||||
info.mode = AUMODE_PLAY;
|
info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
|
||||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
|
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
|
||||||
BSDAUDIO_CloseDevice(this);
|
BSDAUDIO_CloseDevice(this);
|
||||||
return SDL_SetError("Couldn't put device into play mode");
|
return SDL_SetError("Couldn't put device into play mode");
|
||||||
|
@ -271,28 +328,28 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
format; format = SDL_NextAudioFormat()) {
|
format; format = SDL_NextAudioFormat()) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case AUDIO_U8:
|
case AUDIO_U8:
|
||||||
info.play.encoding = AUDIO_ENCODING_ULINEAR;
|
prinfo->encoding = AUDIO_ENCODING_ULINEAR;
|
||||||
info.play.precision = 8;
|
prinfo->precision = 8;
|
||||||
break;
|
break;
|
||||||
case AUDIO_S8:
|
case AUDIO_S8:
|
||||||
info.play.encoding = AUDIO_ENCODING_SLINEAR;
|
prinfo->encoding = AUDIO_ENCODING_SLINEAR;
|
||||||
info.play.precision = 8;
|
prinfo->precision = 8;
|
||||||
break;
|
break;
|
||||||
case AUDIO_S16LSB:
|
case AUDIO_S16LSB:
|
||||||
info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
|
prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
|
||||||
info.play.precision = 16;
|
prinfo->precision = 16;
|
||||||
break;
|
break;
|
||||||
case AUDIO_S16MSB:
|
case AUDIO_S16MSB:
|
||||||
info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
|
prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
|
||||||
info.play.precision = 16;
|
prinfo->precision = 16;
|
||||||
break;
|
break;
|
||||||
case AUDIO_U16LSB:
|
case AUDIO_U16LSB:
|
||||||
info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
|
prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
|
||||||
info.play.precision = 16;
|
prinfo->precision = 16;
|
||||||
break;
|
break;
|
||||||
case AUDIO_U16MSB:
|
case AUDIO_U16MSB:
|
||||||
info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
|
prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
|
||||||
info.play.precision = 16;
|
prinfo->precision = 16;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
@ -311,26 +368,29 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
this->spec.format = format;
|
this->spec.format = format;
|
||||||
|
|
||||||
AUDIO_INITINFO(&info);
|
AUDIO_INITINFO(&info);
|
||||||
info.play.channels = this->spec.channels;
|
prinfo->channels = this->spec.channels;
|
||||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
|
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
|
||||||
this->spec.channels = 1;
|
this->spec.channels = 1;
|
||||||
}
|
}
|
||||||
AUDIO_INITINFO(&info);
|
AUDIO_INITINFO(&info);
|
||||||
info.play.sample_rate = this->spec.freq;
|
prinfo->sample_rate = this->spec.freq;
|
||||||
info.blocksize = this->spec.size;
|
info.blocksize = this->spec.size;
|
||||||
info.hiwat = 5;
|
info.hiwat = 5;
|
||||||
info.lowat = 3;
|
info.lowat = 3;
|
||||||
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
|
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
|
||||||
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
|
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
|
||||||
this->spec.freq = info.play.sample_rate;
|
this->spec.freq = prinfo->sample_rate;
|
||||||
/* Allocate mixing buffer */
|
|
||||||
this->hidden->mixlen = this->spec.size;
|
if (!iscapture) {
|
||||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
/* Allocate mixing buffer */
|
||||||
if (this->hidden->mixbuf == NULL) {
|
this->hidden->mixlen = this->spec.size;
|
||||||
BSDAUDIO_CloseDevice(this);
|
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||||
return SDL_OutOfMemory();
|
if (this->hidden->mixbuf == NULL) {
|
||||||
|
BSDAUDIO_CloseDevice(this);
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||||
}
|
}
|
||||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
|
||||||
|
|
||||||
BSDAUDIO_Status(this);
|
BSDAUDIO_Status(this);
|
||||||
|
|
||||||
|
@ -348,7 +408,10 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||||
impl->WaitDevice = BSDAUDIO_WaitDevice;
|
impl->WaitDevice = BSDAUDIO_WaitDevice;
|
||||||
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
|
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
|
||||||
impl->CloseDevice = BSDAUDIO_CloseDevice;
|
impl->CloseDevice = BSDAUDIO_CloseDevice;
|
||||||
|
impl->CaptureFromDevice = BSDAUDIO_CaptureFromDevice;
|
||||||
|
impl->FlushCapture = BSDAUDIO_FlushCapture;
|
||||||
|
|
||||||
|
impl->HasCaptureSupport = SDL_TRUE;
|
||||||
impl->AllowsArbitraryDeviceNames = 1;
|
impl->AllowsArbitraryDeviceNames = 1;
|
||||||
|
|
||||||
return 1; /* this audio target is available. */
|
return 1; /* this audio target is available. */
|
||||||
|
|
Loading…
Reference in New Issue