Commit f941aa256f2254c3f35f00fcf5d7f20dba55a5b7

Authored by ths
1 parent b93aebec

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
audio/alsaaudio.c
... ... @@ -157,6 +157,12 @@ static int aud_to_alsafmt (audfmt_e fmt)
157 157 case AUD_FMT_U16:
158 158 return SND_PCM_FORMAT_U16_LE;
159 159  
  160 + case AUD_FMT_S32:
  161 + return SND_PCM_FORMAT_S32_LE;
  162 +
  163 + case AUD_FMT_U32:
  164 + return SND_PCM_FORMAT_U32_LE;
  165 +
160 166 default:
161 167 dolog ("Internal logic error: Bad audio format %d\n", fmt);
162 168 #ifdef DEBUG_AUDIO
... ... @@ -199,6 +205,26 @@ static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
199 205 *fmt = AUD_FMT_U16;
200 206 break;
201 207  
  208 + case SND_PCM_FORMAT_S32_LE:
  209 + *endianness = 0;
  210 + *fmt = AUD_FMT_S32;
  211 + break;
  212 +
  213 + case SND_PCM_FORMAT_U32_LE:
  214 + *endianness = 0;
  215 + *fmt = AUD_FMT_U32;
  216 + break;
  217 +
  218 + case SND_PCM_FORMAT_S32_BE:
  219 + *endianness = 1;
  220 + *fmt = AUD_FMT_S32;
  221 + break;
  222 +
  223 + case SND_PCM_FORMAT_U32_BE:
  224 + *endianness = 1;
  225 + *fmt = AUD_FMT_U32;
  226 + break;
  227 +
202 228 default:
203 229 dolog ("Unrecognized audio format %d\n", alsafmt);
204 230 return -1;
... ...
audio/audio.c
... ... @@ -80,7 +80,8 @@ static struct {
80 80 {
81 81 44100, /* freq */
82 82 2, /* nchannels */
83   - AUD_FMT_S16 /* fmt */
  83 + AUD_FMT_S16, /* fmt */
  84 + AUDIO_HOST_ENDIANNESS
84 85 }
85 86 },
86 87  
... ... @@ -91,7 +92,8 @@ static struct {
91 92 {
92 93 44100, /* freq */
93 94 2, /* nchannels */
94   - AUD_FMT_S16 /* fmt */
  95 + AUD_FMT_S16, /* fmt */
  96 + AUDIO_HOST_ENDIANNESS
95 97 }
96 98 },
97 99  
... ... @@ -166,6 +168,25 @@ int audio_bug (const char *funcname, int cond)
166 168 }
167 169 #endif
168 170  
  171 +static inline int audio_bits_to_index (int bits)
  172 +{
  173 + switch (bits) {
  174 + case 8:
  175 + return 0;
  176 +
  177 + case 16:
  178 + return 1;
  179 +
  180 + case 32:
  181 + return 2;
  182 +
  183 + default:
  184 + audio_bug ("bits_to_index", 1);
  185 + AUD_log (NULL, "invalid bits %d\n", bits);
  186 + return 0;
  187 + }
  188 +}
  189 +
169 190 void *audio_calloc (const char *funcname, int nmemb, size_t size)
170 191 {
171 192 int cond;
... ... @@ -227,6 +248,12 @@ const char *audio_audfmt_to_string (audfmt_e fmt)
227 248  
228 249 case AUD_FMT_S16:
229 250 return "S16";
  251 +
  252 + case AUD_FMT_U32:
  253 + return "U32";
  254 +
  255 + case AUD_FMT_S32:
  256 + return "S32";
230 257 }
231 258  
232 259 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)
243 270 *defaultp = 0;
244 271 return AUD_FMT_U16;
245 272 }
  273 + else if (!strcasecmp (s, "u32")) {
  274 + *defaultp = 0;
  275 + return AUD_FMT_U32;
  276 + }
246 277 else if (!strcasecmp (s, "s8")) {
247 278 *defaultp = 0;
248 279 return AUD_FMT_S8;
... ... @@ -251,6 +282,10 @@ audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
251 282 *defaultp = 0;
252 283 return AUD_FMT_S16;
253 284 }
  285 + else if (!strcasecmp (s, "s32")) {
  286 + *defaultp = 0;
  287 + return AUD_FMT_S32;
  288 + }
254 289 else {
255 290 dolog ("Bogus audio format `%s' using %s\n",
256 291 s, audio_audfmt_to_string (defval));
... ... @@ -538,6 +573,8 @@ static int audio_validate_settings (audsettings_t *as)
538 573 case AUD_FMT_U8:
539 574 case AUD_FMT_S16:
540 575 case AUD_FMT_U16:
  576 + case AUD_FMT_S32:
  577 + case AUD_FMT_U32:
541 578 break;
542 579 default:
543 580 invalid = 1;
... ... @@ -563,6 +600,12 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
563 600 case AUD_FMT_U16:
564 601 bits = 16;
565 602 break;
  603 +
  604 + case AUD_FMT_S32:
  605 + sign = 1;
  606 + case AUD_FMT_U32:
  607 + bits = 32;
  608 + break;
566 609 }
567 610 return info->freq == as->freq
568 611 && info->nchannels == as->nchannels
... ... @@ -573,7 +616,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
573 616  
574 617 void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
575 618 {
576   - int bits = 8, sign = 0;
  619 + int bits = 8, sign = 0, shift = 0;
577 620  
578 621 switch (as->fmt) {
579 622 case AUD_FMT_S8:
... ... @@ -585,6 +628,14 @@ void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
585 628 sign = 1;
586 629 case AUD_FMT_U16:
587 630 bits = 16;
  631 + shift = 1;
  632 + break;
  633 +
  634 + case AUD_FMT_S32:
  635 + sign = 1;
  636 + case AUD_FMT_U32:
  637 + bits = 32;
  638 + shift = 2;
588 639 break;
589 640 }
590 641  
... ... @@ -592,7 +643,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
592 643 info->bits = bits;
593 644 info->sign = sign;
594 645 info->nchannels = as->nchannels;
595   - info->shift = (as->nchannels == 2) + (bits == 16);
  646 + info->shift = (as->nchannels == 2) + shift;
596 647 info->align = (1 << info->shift) - 1;
597 648 info->bytes_per_second = info->freq << info->shift;
598 649 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)
608 659 memset (buf, 0x00, len << info->shift);
609 660 }
610 661 else {
611   - if (info->bits == 8) {
  662 + switch (info->bits) {
  663 + case 8:
612 664 memset (buf, 0x80, len << info->shift);
613   - }
614   - else {
615   - int i;
616   - uint16_t *p = buf;
617   - int shift = info->nchannels - 1;
618   - short s = INT16_MAX;
  665 + break;
619 666  
620   - if (info->swap_endianness) {
621   - s = bswap16 (s);
  667 + case 16:
  668 + {
  669 + int i;
  670 + uint16_t *p = buf;
  671 + int shift = info->nchannels - 1;
  672 + short s = INT16_MAX;
  673 +
  674 + if (info->swap_endianness) {
  675 + s = bswap16 (s);
  676 + }
  677 +
  678 + for (i = 0; i < len << shift; i++) {
  679 + p[i] = s;
  680 + }
622 681 }
  682 + break;
  683 +
  684 + case 32:
  685 + {
  686 + int i;
  687 + uint32_t *p = buf;
  688 + int shift = info->nchannels - 1;
  689 + int32_t s = INT32_MAX;
  690 +
  691 + if (info->swap_endianness) {
  692 + s = bswap32 (s);
  693 + }
623 694  
624   - for (i = 0; i < len << shift; i++) {
625   - p[i] = s;
  695 + for (i = 0; i < len << shift; i++) {
  696 + p[i] = s;
  697 + }
626 698 }
  699 + break;
  700 +
  701 + default:
  702 + AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
  703 + info->bits);
  704 + break;
627 705 }
628 706 }
629 707 }
... ... @@ -1811,7 +1889,7 @@ CaptureVoiceOut *AUD_add_capture (
1811 1889 [hw->info.nchannels == 2]
1812 1890 [hw->info.sign]
1813 1891 [hw->info.swap_endianness]
1814   - [hw->info.bits == 16];
  1892 + [audio_bits_to_index (hw->info.bits)];
1815 1893  
1816 1894 LIST_INSERT_HEAD (&s->cap_head, cap, entries);
1817 1895 LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
... ...
audio/audio.h
... ... @@ -33,7 +33,9 @@ typedef enum {
33 33 AUD_FMT_U8,
34 34 AUD_FMT_S8,
35 35 AUD_FMT_U16,
36   - AUD_FMT_S16
  36 + AUD_FMT_S16,
  37 + AUD_FMT_U32,
  38 + AUD_FMT_S32
37 39 } audfmt_e;
38 40  
39 41 #ifdef WORDS_BIGENDIAN
... ...
audio/audio_template.h
... ... @@ -164,7 +164,7 @@ static int glue (audio_pcm_sw_init_, TYPE) (
164 164 [sw->info.nchannels == 2]
165 165 [sw->info.sign]
166 166 [sw->info.swap_endianness]
167   - [sw->info.bits == 16];
  167 + [audio_bits_to_index (sw->info.bits)];
168 168  
169 169 sw->name = qemu_strdup (name);
170 170 err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
... ... @@ -288,7 +288,7 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
288 288 [hw->info.nchannels == 2]
289 289 [hw->info.sign]
290 290 [hw->info.swap_endianness]
291   - [hw->info.bits == 16];
  291 + [audio_bits_to_index (hw->info.bits)];
292 292  
293 293 if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
294 294 goto err1;
... ...
audio/coreaudio.c
... ... @@ -294,7 +294,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
294 294 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
295 295 UInt32 propertySize;
296 296 int err;
297   - int bits = 8;
298 297 const char *typ = "playback";
299 298 AudioValueRange frameRange;
300 299  
... ... @@ -305,10 +304,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
305 304 return -1;
306 305 }
307 306  
308   - if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
309   - bits = 16;
310   - }
311   -
312 307 audio_pcm_init_info (&hw->info, as);
313 308  
314 309 /* open default output device */
... ...
audio/mixeng.c
... ... @@ -82,6 +82,7 @@
82 82 #undef IN_T
83 83 #undef SHIFT
84 84  
  85 +/* Unsigned 16 bit */
85 86 #define IN_T uint16_t
86 87 #define IN_MIN 0
87 88 #define IN_MAX USHRT_MAX
... ... @@ -101,26 +102,72 @@
101 102 #undef IN_T
102 103 #undef SHIFT
103 104  
104   -t_sample *mixeng_conv[2][2][2][2] = {
  105 +/* Signed 32 bit */
  106 +#define IN_T int32_t
  107 +#define IN_MIN INT32_MIN
  108 +#define IN_MAX INT32_MAX
  109 +#define SIGNED
  110 +#define SHIFT 32
  111 +#define ENDIAN_CONVERSION natural
  112 +#define ENDIAN_CONVERT(v) (v)
  113 +#include "mixeng_template.h"
  114 +#undef ENDIAN_CONVERT
  115 +#undef ENDIAN_CONVERSION
  116 +#define ENDIAN_CONVERSION swap
  117 +#define ENDIAN_CONVERT(v) bswap32 (v)
  118 +#include "mixeng_template.h"
  119 +#undef ENDIAN_CONVERT
  120 +#undef ENDIAN_CONVERSION
  121 +#undef SIGNED
  122 +#undef IN_MAX
  123 +#undef IN_MIN
  124 +#undef IN_T
  125 +#undef SHIFT
  126 +
  127 +/* Unsigned 16 bit */
  128 +#define IN_T uint32_t
  129 +#define IN_MIN 0
  130 +#define IN_MAX UINT32_MAX
  131 +#define SHIFT 32
  132 +#define ENDIAN_CONVERSION natural
  133 +#define ENDIAN_CONVERT(v) (v)
  134 +#include "mixeng_template.h"
  135 +#undef ENDIAN_CONVERT
  136 +#undef ENDIAN_CONVERSION
  137 +#define ENDIAN_CONVERSION swap
  138 +#define ENDIAN_CONVERT(v) bswap32 (v)
  139 +#include "mixeng_template.h"
  140 +#undef ENDIAN_CONVERT
  141 +#undef ENDIAN_CONVERSION
  142 +#undef IN_MAX
  143 +#undef IN_MIN
  144 +#undef IN_T
  145 +#undef SHIFT
  146 +
  147 +t_sample *mixeng_conv[2][2][2][3] = {
105 148 {
106 149 {
107 150 {
108 151 conv_natural_uint8_t_to_mono,
109   - conv_natural_uint16_t_to_mono
  152 + conv_natural_uint16_t_to_mono,
  153 + conv_natural_uint32_t_to_mono
110 154 },
111 155 {
112 156 conv_natural_uint8_t_to_mono,
113   - conv_swap_uint16_t_to_mono
  157 + conv_swap_uint16_t_to_mono,
  158 + conv_swap_uint32_t_to_mono,
114 159 }
115 160 },
116 161 {
117 162 {
118 163 conv_natural_int8_t_to_mono,
119   - conv_natural_int16_t_to_mono
  164 + conv_natural_int16_t_to_mono,
  165 + conv_natural_int32_t_to_mono
120 166 },
121 167 {
122 168 conv_natural_int8_t_to_mono,
123   - conv_swap_int16_t_to_mono
  169 + conv_swap_int16_t_to_mono,
  170 + conv_swap_int32_t_to_mono
124 171 }
125 172 }
126 173 },
... ... @@ -128,46 +175,54 @@ t_sample *mixeng_conv[2][2][2][2] = {
128 175 {
129 176 {
130 177 conv_natural_uint8_t_to_stereo,
131   - conv_natural_uint16_t_to_stereo
  178 + conv_natural_uint16_t_to_stereo,
  179 + conv_natural_uint32_t_to_stereo
132 180 },
133 181 {
134 182 conv_natural_uint8_t_to_stereo,
135   - conv_swap_uint16_t_to_stereo
  183 + conv_swap_uint16_t_to_stereo,
  184 + conv_swap_uint32_t_to_stereo
136 185 }
137 186 },
138 187 {
139 188 {
140 189 conv_natural_int8_t_to_stereo,
141   - conv_natural_int16_t_to_stereo
  190 + conv_natural_int16_t_to_stereo,
  191 + conv_natural_int32_t_to_stereo
142 192 },
143 193 {
144 194 conv_natural_int8_t_to_stereo,
145   - conv_swap_int16_t_to_stereo
  195 + conv_swap_int16_t_to_stereo,
  196 + conv_swap_int32_t_to_stereo,
146 197 }
147 198 }
148 199 }
149 200 };
150 201  
151   -f_sample *mixeng_clip[2][2][2][2] = {
  202 +f_sample *mixeng_clip[2][2][2][3] = {
152 203 {
153 204 {
154 205 {
155 206 clip_natural_uint8_t_from_mono,
156   - clip_natural_uint16_t_from_mono
  207 + clip_natural_uint16_t_from_mono,
  208 + clip_natural_uint32_t_from_mono
157 209 },
158 210 {
159 211 clip_natural_uint8_t_from_mono,
160   - clip_swap_uint16_t_from_mono
  212 + clip_swap_uint16_t_from_mono,
  213 + clip_swap_uint32_t_from_mono
161 214 }
162 215 },
163 216 {
164 217 {
165 218 clip_natural_int8_t_from_mono,
166   - clip_natural_int16_t_from_mono
  219 + clip_natural_int16_t_from_mono,
  220 + clip_natural_int32_t_from_mono
167 221 },
168 222 {
169 223 clip_natural_int8_t_from_mono,
170   - clip_swap_int16_t_from_mono
  224 + clip_swap_int16_t_from_mono,
  225 + clip_swap_int32_t_from_mono
171 226 }
172 227 }
173 228 },
... ... @@ -175,21 +230,25 @@ f_sample *mixeng_clip[2][2][2][2] = {
175 230 {
176 231 {
177 232 clip_natural_uint8_t_from_stereo,
178   - clip_natural_uint16_t_from_stereo
  233 + clip_natural_uint16_t_from_stereo,
  234 + clip_natural_uint32_t_from_stereo
179 235 },
180 236 {
181 237 clip_natural_uint8_t_from_stereo,
182   - clip_swap_uint16_t_from_stereo
  238 + clip_swap_uint16_t_from_stereo,
  239 + clip_swap_uint32_t_from_stereo
183 240 }
184 241 },
185 242 {
186 243 {
187 244 clip_natural_int8_t_from_stereo,
188   - clip_natural_int16_t_from_stereo
  245 + clip_natural_int16_t_from_stereo,
  246 + clip_natural_int32_t_from_stereo
189 247 },
190 248 {
191 249 clip_natural_int8_t_from_stereo,
192   - clip_swap_int16_t_from_stereo
  250 + clip_swap_int16_t_from_stereo,
  251 + clip_swap_int32_t_from_stereo
193 252 }
194 253 }
195 254 }
... ...
audio/mixeng.h
... ... @@ -37,8 +37,8 @@ typedef void (t_sample) (st_sample_t *dst, const void *src,
37 37 int samples, volume_t *vol);
38 38 typedef void (f_sample) (void *dst, const st_sample_t *src, int samples);
39 39  
40   -extern t_sample *mixeng_conv[2][2][2][2];
41   -extern f_sample *mixeng_clip[2][2][2][2];
  40 +extern t_sample *mixeng_conv[2][2][2][3];
  41 +extern f_sample *mixeng_clip[2][2][2][3];
42 42  
43 43 void *st_rate_start (int inrate, int outrate);
44 44 void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
... ...
audio/wavaudio.c
... ... @@ -41,7 +41,8 @@ static struct {
41 41 {
42 42 44100,
43 43 2,
44   - AUD_FMT_S16
  44 + AUD_FMT_S16,
  45 + AUDIO_HOST_ENDIANNESS
45 46 },
46 47 "qemu.wav"
47 48 };
... ... @@ -131,6 +132,11 @@ static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
131 132 case AUD_FMT_U16:
132 133 bits16 = 1;
133 134 break;
  135 +
  136 + case AUD_FMT_S32:
  137 + case AUD_FMT_U32:
  138 + dolog ("WAVE files can not handle 32bit formats\n");
  139 + return -1;
134 140 }
135 141  
136 142 hdr[34] = bits16 ? 0x10 : 0x08;
... ...
audio/wavcapture.c
... ... @@ -37,15 +37,15 @@ static void wav_destroy (void *opaque)
37 37 if (wav->f) {
38 38 le_store (rlen, rifflen, 4);
39 39 le_store (dlen, datalen, 4);
40   -
  40 +
41 41 qemu_fseek (wav->f, 4, SEEK_SET);
42 42 qemu_put_buffer (wav->f, rlen, 4);
43   -
  43 +
44 44 qemu_fseek (wav->f, 32, SEEK_CUR);
45 45 qemu_put_buffer (wav->f, dlen, 4);
46 46 qemu_fclose (wav->f);
47 47 }
48   -
  48 +
49 49 qemu_free (wav->path);
50 50 }
51 51  
... ...