case AUDIO_FORMAT_U32:
AUD_log (NULL, "U32");
break;
+ case AUDIO_FORMAT_F32:
+ AUD_log (NULL, "F32");
+ break;
default:
AUD_log (NULL, "invalid(%d)", as->fmt);
break;
case AUDIO_FORMAT_U16:
case AUDIO_FORMAT_S32:
case AUDIO_FORMAT_U32:
+ case AUDIO_FORMAT_F32:
break;
default:
invalid = 1;
static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *as)
{
- int bits = 8, sign = 0;
+ int bits = 8;
+ bool is_signed = false, is_float = false;
switch (as->fmt) {
case AUDIO_FORMAT_S8:
- sign = 1;
+ is_signed = true;
/* fall through */
case AUDIO_FORMAT_U8:
break;
case AUDIO_FORMAT_S16:
- sign = 1;
+ is_signed = true;
/* fall through */
case AUDIO_FORMAT_U16:
bits = 16;
break;
+ case AUDIO_FORMAT_F32:
+ is_float = true;
+ /* fall through */
case AUDIO_FORMAT_S32:
- sign = 1;
+ is_signed = true;
/* fall through */
case AUDIO_FORMAT_U32:
bits = 32;
}
return info->freq == as->freq
&& info->nchannels == as->nchannels
- && info->sign == sign
+ && info->is_signed == is_signed
+ && info->is_float == is_float
&& info->bits == bits
&& info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
}
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
{
- int bits = 8, sign = 0, mul;
+ int bits = 8, mul;
+ bool is_signed = false, is_float = false;
switch (as->fmt) {
case AUDIO_FORMAT_S8:
- sign = 1;
+ is_signed = true;
/* fall through */
case AUDIO_FORMAT_U8:
mul = 1;
break;
case AUDIO_FORMAT_S16:
- sign = 1;
+ is_signed = true;
/* fall through */
case AUDIO_FORMAT_U16:
bits = 16;
mul = 2;
break;
+ case AUDIO_FORMAT_F32:
+ is_float = true;
+ /* fall through */
case AUDIO_FORMAT_S32:
- sign = 1;
+ is_signed = true;
/* fall through */
case AUDIO_FORMAT_U32:
bits = 32;
info->freq = as->freq;
info->bits = bits;
- info->sign = sign;
+ info->is_signed = is_signed;
+ info->is_float = is_float;
info->nchannels = as->nchannels;
info->bytes_per_frame = as->nchannels * mul;
info->bytes_per_second = info->freq * info->bytes_per_frame;
return;
}
- if (info->sign) {
+ if (info->is_signed || info->is_float) {
memset(buf, 0x00, len * info->bytes_per_frame);
}
else {
total += isamp;
}
- if (!hw->pcm_ops->volume_in) {
+ if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
mixeng_volume (sw->buf, ret, &sw->vol);
}
if (swlim) {
sw->conv (sw->buf, buf, swlim);
- if (!sw->hw->pcm_ops->volume_out) {
+ if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) {
mixeng_volume (sw->buf, swlim, &sw->vol);
}
}
#ifdef DEBUG_AUDIO
static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
{
- dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n",
- cap, info->bits, info->sign, info->freq, info->nchannels);
+ dolog("%s: bits %d, sign %d, float %d, freq %d, nchan %d\n",
+ cap, info->bits, info->is_signed, info->is_float, info->freq,
+ info->nchannels);
}
#endif
}
}
-int AUD_get_buffer_size_out (SWVoiceOut *sw)
+int AUD_get_buffer_size_out(SWVoiceOut *sw)
{
- return sw->hw->mix_buf->size * sw->hw->info.bytes_per_frame;
+ return sw->hw->samples * sw->hw->info.bytes_per_frame;
}
void AUD_set_active_out (SWVoiceOut *sw, int on)
while (live) {
size_t size, decr, proc;
void *buf = hw->pcm_ops->get_buffer_out(hw, &size);
- if (!buf) {
- /* retrying will likely won't help, drop everything. */
- hw->mix_buf->pos = (hw->mix_buf->pos + live) % hw->mix_buf->size;
- return clipped + live;
+ if (!buf || size == 0) {
+ break;
}
decr = MIN(size / hw->info.bytes_per_frame, live);
}
}
+ if (hw->pcm_ops->run_buffer_out) {
+ hw->pcm_ops->run_buffer_out(hw);
+ }
+
return clipped;
}
}
assert(start >= 0 && start < hw->size_emul);
- *size = MIN(hw->pending_emul, hw->size_emul - start);
+ *size = MIN(*size, hw->pending_emul);
+ *size = MIN(*size, hw->size_emul - start);
return hw->buf_emul + start;
}
hw->pending_emul -= size;
}
+void audio_generic_run_buffer_out(HWVoiceOut *hw)
+{
+ while (hw->pending_emul) {
+ size_t write_len, written;
+ ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
+
+ if (start < 0) {
+ start += hw->size_emul;
+ }
+ assert(start >= 0 && start < hw->size_emul);
+
+ write_len = MIN(hw->pending_emul, hw->size_emul - start);
+
+ written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len);
+ hw->pending_emul -= written;
+
+ if (written < write_len) {
+ break;
+ }
+ }
+}
+
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
if (unlikely(!hw->buf_emul)) {
return hw->buf_emul + hw->pos_emul;
}
-size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf,
- size_t size)
+size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
{
assert(buf == hw->buf_emul + hw->pos_emul &&
size + hw->pending_emul <= hw->size_emul);
return size;
}
-size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
-{
- audio_generic_put_buffer_out_nowrite(hw, buf, size);
-
- while (hw->pending_emul) {
- size_t write_len, written;
- ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
- if (start < 0) {
- start += hw->size_emul;
- }
- assert(start >= 0 && start < hw->size_emul);
-
- write_len = MIN(hw->pending_emul, hw->size_emul - start);
-
- written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len);
- hw->pending_emul -= written;
-
- if (written < write_len) {
- break;
- }
- }
-
- /*
- * fake we have written everything. non-written data remain in pending_emul,
- * so we do not have to clip them multiple times
- */
- return size;
-}
-
size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
{
size_t dst_size, copy_size;
size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
{
- size_t src_size, copy_size;
- void *src = hw->pcm_ops->get_buffer_in(hw, &src_size);
- copy_size = MIN(size, src_size);
+ void *src = hw->pcm_ops->get_buffer_in(hw, &size);
- memcpy(buf, src, copy_size);
- hw->pcm_ops->put_buffer_in(hw, src, copy_size);
- return copy_size;
-}
+ memcpy(buf, src, size);
+ hw->pcm_ops->put_buffer_in(hw, src, size);
+ return size;
+}
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
bool msg, Audiodev *dev)
cap->buf = g_malloc0_n(hw->mix_buf->size, hw->info.bytes_per_frame);
- hw->clip = mixeng_clip
- [hw->info.nchannels == 2]
- [hw->info.sign]
- [hw->info.swap_endianness]
- [audio_bits_to_index (hw->info.bits)];
+ if (hw->info.is_float) {
+ hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
+ } else {
+ hw->clip = mixeng_clip
+ [hw->info.nchannels == 2]
+ [hw->info.is_signed]
+ [hw->info.swap_endianness]
+ [audio_bits_to_index(hw->info.bits)];
+ }
QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
CASE(ALSA, alsa, Alsa);
CASE(COREAUDIO, coreaudio, Coreaudio);
CASE(DSOUND, dsound, );
+ CASE(JACK, jack, Jack);
CASE(OSS, oss, Oss);
CASE(PA, pa, Pa);
CASE(SDL, sdl, );
case AUDIO_FORMAT_U32:
case AUDIO_FORMAT_S32:
+ case AUDIO_FORMAT_F32:
return 4;
case AUDIO_FORMAT__MAX: