aboutsummaryrefslogtreecommitdiff
path: root/audio/audio.c
diff options
context:
space:
mode:
authorKővágó, Zoltán <dirty.ice.hu@gmail.com>2019-10-13 21:58:02 +0200
committerGerd Hoffmann <kraxel@redhat.com>2019-10-18 08:14:05 +0200
commit2b9cce8c8c37b95290c48c037e51e001985124d1 (patch)
tree82fbbf3fff30c561215cada4c3f2a97f8cda1dbb /audio/audio.c
parentcecc1e79bf9ad9a0e2d3ce513d4f71792a0985f6 (diff)
audio: replace shift in audio_pcm_info with bytes_per_frame
The bit shifting trick worked because the number of bytes per frame was always a power-of-two (since QEMU only supports mono, stereo and 8, 16 and 32 bit samples). But if we want to add support for surround sound, this no longer holds true. Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com> Message-id: 1351fd9bcce0ff20d81850c5292722194329de02.1570996490.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'audio/audio.c')
-rw-r--r--audio/audio.c74
1 files changed, 37 insertions, 37 deletions
diff --git a/audio/audio.c b/audio/audio.c
index f1c145dfcd..c00f4deddd 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -299,12 +299,13 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *a
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
{
- int bits = 8, sign = 0, shift = 0;
+ int bits = 8, sign = 0, mul;
switch (as->fmt) {
case AUDIO_FORMAT_S8:
sign = 1;
case AUDIO_FORMAT_U8:
+ mul = 1;
break;
case AUDIO_FORMAT_S16:
@@ -312,7 +313,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
/* fall through */
case AUDIO_FORMAT_U16:
bits = 16;
- shift = 1;
+ mul = 2;
break;
case AUDIO_FORMAT_S32:
@@ -320,7 +321,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
/* fall through */
case AUDIO_FORMAT_U32:
bits = 32;
- shift = 2;
+ mul = 4;
break;
default:
@@ -331,9 +332,8 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
info->bits = bits;
info->sign = sign;
info->nchannels = as->nchannels;
- info->shift = (as->nchannels == 2) + shift;
- info->align = (1 << info->shift) - 1;
- info->bytes_per_second = info->freq << info->shift;
+ info->bytes_per_frame = as->nchannels * mul;
+ info->bytes_per_second = info->freq * info->bytes_per_frame;
info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
}
@@ -344,26 +344,25 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
}
if (info->sign) {
- memset (buf, 0x00, len << info->shift);
+ memset(buf, 0x00, len * info->bytes_per_frame);
}
else {
switch (info->bits) {
case 8:
- memset (buf, 0x80, len << info->shift);
+ memset(buf, 0x80, len * info->bytes_per_frame);
break;
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++) {
+ for (i = 0; i < len * info->nchannels; i++) {
p[i] = s;
}
}
@@ -373,14 +372,13 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
{
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++) {
+ for (i = 0; i < len * info->nchannels; i++) {
p[i] = s;
}
}
@@ -558,7 +556,7 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
while (len) {
st_sample *src = hw->mix_buf->samples + pos;
- uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift);
+ uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
@@ -607,7 +605,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
return 0;
}
- samples = size >> sw->info.shift;
+ samples = size / sw->info.bytes_per_frame;
if (!live) {
return 0;
}
@@ -642,7 +640,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
sw->clip (buf, sw->buf, ret);
sw->total_hw_samples_acquired += total;
- return ret << sw->info.shift;
+ return ret * sw->info.bytes_per_frame;
}
/*
@@ -715,7 +713,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
}
wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
- samples = size >> sw->info.shift;
+ samples = size / sw->info.bytes_per_frame;
dead = hwsamples - live;
swlim = ((int64_t) dead << 32) / sw->ratio;
@@ -759,13 +757,13 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
dolog (
"%s: write size %zu ret %zu total sw %zu\n",
SW_NAME (sw),
- size >> sw->info.shift,
+ size / sw->info.bytes_per_frame,
ret,
sw->total_hw_samples_mixed
);
#endif
- return ret << sw->info.shift;
+ return ret * sw->info.bytes_per_frame;
}
#ifdef DEBUG_AUDIO
@@ -882,7 +880,7 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size)
int AUD_get_buffer_size_out (SWVoiceOut *sw)
{
- return sw->hw->mix_buf->size << sw->hw->info.shift;
+ return sw->hw->mix_buf->size * sw->hw->info.bytes_per_frame;
}
void AUD_set_active_out (SWVoiceOut *sw, int on)
@@ -998,10 +996,10 @@ static size_t audio_get_avail (SWVoiceIn *sw)
ldebug (
"%s: get_avail live %d ret %" PRId64 "\n",
SW_NAME (sw),
- live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
+ live, (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame
);
- return (((int64_t) live << 32) / sw->ratio) << sw->info.shift;
+ return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
}
static size_t audio_get_free(SWVoiceOut *sw)
@@ -1025,10 +1023,11 @@ static size_t audio_get_free(SWVoiceOut *sw)
#ifdef DEBUG_OUT
dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n",
SW_NAME (sw),
- live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
+ live, dead, (((int64_t) dead << 32) / sw->ratio) *
+ sw->info.bytes_per_frame);
#endif
- return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
+ return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;
}
static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
@@ -1047,7 +1046,7 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
while (n) {
size_t till_end_of_hw = hw->mix_buf->size - rpos2;
size_t to_write = MIN(till_end_of_hw, n);
- size_t bytes = to_write << hw->info.shift;
+ size_t bytes = to_write * hw->info.bytes_per_frame;
size_t written;
sw->buf = hw->mix_buf->samples + rpos2;
@@ -1082,10 +1081,11 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
return clipped + live;
}
- decr = MIN(size >> hw->info.shift, live);
+ decr = MIN(size / hw->info.bytes_per_frame, live);
audio_pcm_hw_clip_out(hw, buf, decr);
- proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >>
- hw->info.shift;
+ proc = hw->pcm_ops->put_buffer_out(hw, buf,
+ decr * hw->info.bytes_per_frame) /
+ hw->info.bytes_per_frame;
live -= proc;
clipped += proc;
@@ -1234,16 +1234,16 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
while (samples) {
size_t proc;
- size_t size = samples << hw->info.shift;
+ size_t size = samples * hw->info.bytes_per_frame;
void *buf = hw->pcm_ops->get_buffer_in(hw, &size);
- assert((size & hw->info.align) == 0);
+ assert(size % hw->info.bytes_per_frame == 0);
if (size == 0) {
hw->pcm_ops->put_buffer_in(hw, buf, size);
break;
}
- proc = MIN(size >> hw->info.shift,
+ proc = MIN(size / hw->info.bytes_per_frame,
conv_buf->size - conv_buf->pos);
hw->conv(conv_buf->samples + conv_buf->pos, buf, proc);
@@ -1251,7 +1251,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
samples -= proc;
conv += proc;
- hw->pcm_ops->put_buffer_in(hw, buf, proc << hw->info.shift);
+ hw->pcm_ops->put_buffer_in(hw, buf, proc * hw->info.bytes_per_frame);
}
return conv;
@@ -1325,7 +1325,7 @@ static void audio_run_capture (AudioState *s)
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
cb->ops.capture (cb->opaque, cap->buf,
- to_capture << hw->info.shift);
+ to_capture * hw->info.bytes_per_frame);
}
rpos = (rpos + to_capture) % hw->mix_buf->size;
live -= to_capture;
@@ -1378,7 +1378,7 @@ void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
ssize_t start;
if (unlikely(!hw->buf_emul)) {
- size_t calc_size = hw->conv_buf->size << hw->info.shift;
+ size_t calc_size = hw->conv_buf->size * hw->info.bytes_per_frame;
hw->buf_emul = g_malloc(calc_size);
hw->size_emul = calc_size;
hw->pos_emul = hw->pending_emul = 0;
@@ -1414,7 +1414,7 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
if (unlikely(!hw->buf_emul)) {
- size_t calc_size = hw->mix_buf->size << hw->info.shift;
+ size_t calc_size = hw->mix_buf->size * hw->info.bytes_per_frame;
hw->buf_emul = g_malloc(calc_size);
hw->size_emul = calc_size;
@@ -1833,7 +1833,7 @@ CaptureVoiceOut *AUD_add_capture(
audio_pcm_init_info (&hw->info, as);
- cap->buf = g_malloc0_n(hw->mix_buf->size, 1 << hw->info.shift);
+ cap->buf = g_malloc0_n(hw->mix_buf->size, hw->info.bytes_per_frame);
hw->clip = mixeng_clip
[hw->info.nchannels == 2]
@@ -2153,14 +2153,14 @@ size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ticks = now - rate->start_ticks;
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
- samples = (bytes - rate->bytes_sent) >> info->shift;
+ samples = (bytes - rate->bytes_sent) / info->bytes_per_frame;
if (samples < 0 || samples > 65536) {
AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", samples);
audio_rate_start(rate);
samples = 0;
}
- ret = MIN(samples << info->shift, bytes_avail);
+ ret = MIN(samples * info->bytes_per_frame, bytes_avail);
rate->bytes_sent += ret;
return ret;
}