aboutsummaryrefslogtreecommitdiff
path: root/audio/audio.c
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-02-17 22:19:29 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-02-17 22:19:29 +0000
commitf941aa256f2254c3f35f00fcf5d7f20dba55a5b7 (patch)
tree7e92c23171d665c8841d2afb7765ac45c94b70aa /audio/audio.c
parentb93aebecb0844b220c1652b79e698db2afe3bbab (diff)
Qemu support for S32 and U32 alsa output, by Vassili Karpov.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2427 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'audio/audio.c')
-rw-r--r--audio/audio.c110
1 files changed, 94 insertions, 16 deletions
diff --git a/audio/audio.c b/audio/audio.c
index 556e6fdbcb..5d3c7f15f0 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -80,7 +80,8 @@ static struct {
{
44100, /* freq */
2, /* nchannels */
- AUD_FMT_S16 /* fmt */
+ AUD_FMT_S16, /* fmt */
+ AUDIO_HOST_ENDIANNESS
}
},
@@ -91,7 +92,8 @@ static struct {
{
44100, /* freq */
2, /* nchannels */
- AUD_FMT_S16 /* fmt */
+ AUD_FMT_S16, /* fmt */
+ AUDIO_HOST_ENDIANNESS
}
},
@@ -166,6 +168,25 @@ int audio_bug (const char *funcname, int cond)
}
#endif
+static inline int audio_bits_to_index (int bits)
+{
+ switch (bits) {
+ case 8:
+ return 0;
+
+ case 16:
+ return 1;
+
+ case 32:
+ return 2;
+
+ default:
+ audio_bug ("bits_to_index", 1);
+ AUD_log (NULL, "invalid bits %d\n", bits);
+ return 0;
+ }
+}
+
void *audio_calloc (const char *funcname, int nmemb, size_t size)
{
int cond;
@@ -227,6 +248,12 @@ const char *audio_audfmt_to_string (audfmt_e fmt)
case AUD_FMT_S16:
return "S16";
+
+ case AUD_FMT_U32:
+ return "U32";
+
+ case AUD_FMT_S32:
+ return "S32";
}
dolog ("Bogus audfmt %d returning S16\n", fmt);
@@ -243,6 +270,10 @@ audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
*defaultp = 0;
return AUD_FMT_U16;
}
+ else if (!strcasecmp (s, "u32")) {
+ *defaultp = 0;
+ return AUD_FMT_U32;
+ }
else if (!strcasecmp (s, "s8")) {
*defaultp = 0;
return AUD_FMT_S8;
@@ -251,6 +282,10 @@ audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
*defaultp = 0;
return AUD_FMT_S16;
}
+ else if (!strcasecmp (s, "s32")) {
+ *defaultp = 0;
+ return AUD_FMT_S32;
+ }
else {
dolog ("Bogus audio format `%s' using %s\n",
s, audio_audfmt_to_string (defval));
@@ -538,6 +573,8 @@ static int audio_validate_settings (audsettings_t *as)
case AUD_FMT_U8:
case AUD_FMT_S16:
case AUD_FMT_U16:
+ case AUD_FMT_S32:
+ case AUD_FMT_U32:
break;
default:
invalid = 1;
@@ -563,6 +600,12 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
case AUD_FMT_U16:
bits = 16;
break;
+
+ case AUD_FMT_S32:
+ sign = 1;
+ case AUD_FMT_U32:
+ bits = 32;
+ break;
}
return info->freq == as->freq
&& info->nchannels == as->nchannels
@@ -573,7 +616,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
{
- int bits = 8, sign = 0;
+ int bits = 8, sign = 0, shift = 0;
switch (as->fmt) {
case AUD_FMT_S8:
@@ -585,6 +628,14 @@ void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
sign = 1;
case AUD_FMT_U16:
bits = 16;
+ shift = 1;
+ break;
+
+ case AUD_FMT_S32:
+ sign = 1;
+ case AUD_FMT_U32:
+ bits = 32;
+ shift = 2;
break;
}
@@ -592,7 +643,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
info->bits = bits;
info->sign = sign;
info->nchannels = as->nchannels;
- info->shift = (as->nchannels == 2) + (bits == 16);
+ info->shift = (as->nchannels == 2) + shift;
info->align = (1 << info->shift) - 1;
info->bytes_per_second = info->freq << info->shift;
info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
@@ -608,22 +659,49 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
memset (buf, 0x00, len << info->shift);
}
else {
- if (info->bits == 8) {
+ switch (info->bits) {
+ case 8:
memset (buf, 0x80, len << info->shift);
- }
- else {
- int i;
- uint16_t *p = buf;
- int shift = info->nchannels - 1;
- short s = INT16_MAX;
+ break;
- if (info->swap_endianness) {
- s = bswap16 (s);
+ case 16:
+ {
+ int i;
+ uint16_t *p = buf;
+ int shift = info->nchannels - 1;
+ short s = INT16_MAX;
+
+ if (info->swap_endianness) {
+ s = bswap16 (s);
+ }
+
+ for (i = 0; i < len << shift; i++) {
+ p[i] = s;
+ }
}
+ break;
+
+ case 32:
+ {
+ int i;
+ uint32_t *p = buf;
+ int shift = info->nchannels - 1;
+ int32_t s = INT32_MAX;
+
+ if (info->swap_endianness) {
+ s = bswap32 (s);
+ }
- for (i = 0; i < len << shift; i++) {
- p[i] = s;
+ for (i = 0; i < len << shift; i++) {
+ p[i] = s;
+ }
}
+ break;
+
+ default:
+ AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
+ info->bits);
+ break;
}
}
}
@@ -1811,7 +1889,7 @@ CaptureVoiceOut *AUD_add_capture (
[hw->info.nchannels == 2]
[hw->info.sign]
[hw->info.swap_endianness]
- [hw->info.bits == 16];
+ [audio_bits_to_index (hw->info.bits)];
LIST_INSERT_HEAD (&s->cap_head, cap, entries);
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);