qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

coreaudio: fix coreaudio playback

There are reports that since commit 2ceb8240fa "coreaudio: port
to the new audio backend api" audio playback with CoreAudio is
broken. This patch reverts some parts the commit.

Because of changes in the audio subsystem the audio clip
function in v4.1.0 of coreaudio.c had to be moved to mixeng.c
and the generic buffer management code needed a hint about the
size of the float type.

This patch is based on a patch from Zoltán Kővágó found at
https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg02142.html.

Fixes: 2ceb8240fa "coreaudio: port to the new audio backend api"

Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
Message-id: 20200202140641.4737-1-vr_qemu@t-online.de
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

authored by

Volker Rümelin and committed by
Gerd Hoffmann
180b044f fb35c2ce

+69 -23
+7
audio/audio_template.h
··· 276 276 goto err1; 277 277 } 278 278 279 + if (s->dev->driver == AUDIODEV_DRIVER_COREAUDIO) { 280 + #ifdef DAC 281 + hw->clip = clip_natural_float_from_stereo; 282 + #else 283 + hw->conv = conv_natural_float_to_stereo; 284 + #endif 285 + } else 279 286 #ifdef DAC 280 287 hw->clip = mixeng_clip 281 288 #else
+9 -23
audio/coreaudio.c
··· 471 471 return 0; 472 472 } 473 473 474 - static UInt32 coreaudio_get_flags(struct audio_pcm_info *info, 475 - struct audsettings *as) 476 - { 477 - UInt32 flags = info->sign ? kAudioFormatFlagIsSignedInteger : 0; 478 - if (as->endianness) { /* 0 = little, 1 = big */ 479 - flags |= kAudioFormatFlagIsBigEndian; 480 - } 481 - 482 - if (flags == 0) { /* must not be 0 */ 483 - flags = kAudioFormatFlagsAreAllClear; 484 - } 485 - return flags; 486 - } 487 - 488 474 static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, 489 475 void *drv_opaque) 490 476 { ··· 496 482 Audiodev *dev = drv_opaque; 497 483 AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out; 498 484 int frames; 485 + struct audsettings fake_as; 499 486 500 487 /* create mutex */ 501 488 err = pthread_mutex_init(&core->mutex, NULL); ··· 504 491 return -1; 505 492 } 506 493 494 + /* 495 + * The canonical audio format for CoreAudio on macOS is float. Currently 496 + * there is no generic code for AUDIO_FORMAT_F32 in qemu. Here we select 497 + * AUDIO_FORMAT_S32 instead because only the sample size has to match. 498 + */ 499 + fake_as = *as; 500 + as = &fake_as; 501 + as->fmt = AUDIO_FORMAT_S32; 507 502 audio_pcm_init_info (&hw->info, as); 508 503 509 504 status = coreaudio_get_voice(&core->outputDeviceID); ··· 572 567 573 568 /* set Samplerate */ 574 569 core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq; 575 - core->outputStreamBasicDescription.mFormatID = kAudioFormatLinearPCM; 576 - core->outputStreamBasicDescription.mFormatFlags = 577 - coreaudio_get_flags(&hw->info, as); 578 - core->outputStreamBasicDescription.mBytesPerPacket = 579 - core->outputStreamBasicDescription.mBytesPerFrame = 580 - hw->info.nchannels * hw->info.bits / 8; 581 - core->outputStreamBasicDescription.mFramesPerPacket = 1; 582 - core->outputStreamBasicDescription.mChannelsPerFrame = hw->info.nchannels; 583 - core->outputStreamBasicDescription.mBitsPerChannel = hw->info.bits; 584 570 585 571 status = coreaudio_set_streamformat(core->outputDeviceID, 586 572 &core->outputStreamBasicDescription);
+48
audio/mixeng.c
··· 267 267 } 268 268 }; 269 269 270 + void conv_natural_float_to_stereo(struct st_sample *dst, const void *src, 271 + int samples) 272 + { 273 + float *in = (float *)src; 274 + #ifndef FLOAT_MIXENG 275 + const float scale = UINT_MAX; 276 + #endif 277 + 278 + while (samples--) { 279 + #ifdef FLOAT_MIXENG 280 + dst->l = *in++; 281 + dst->r = *in++; 282 + #else 283 + dst->l = *in++ * scale; 284 + dst->r = *in++ * scale; 285 + #endif 286 + dst++; 287 + } 288 + } 289 + 290 + void clip_natural_float_from_stereo(void *dst, const struct st_sample *src, 291 + int samples) 292 + { 293 + float *out = (float *)dst; 294 + #ifndef FLOAT_MIXENG 295 + #ifdef RECIPROCAL 296 + const float scale = 1.f / UINT_MAX; 297 + #else 298 + const float scale = UINT_MAX; 299 + #endif 300 + #endif 301 + 302 + while (samples--) { 303 + #ifdef FLOAT_MIXENG 304 + *out++ = src->l; 305 + *out++ = src->r; 306 + #else 307 + #ifdef RECIPROCAL 308 + *out++ = src->l * scale; 309 + *out++ = src->r * scale; 310 + #else 311 + *out++ = src->l / scale; 312 + *out++ = src->r / scale; 313 + #endif 314 + #endif 315 + src++; 316 + } 317 + } 270 318 271 319 void audio_sample_to_uint64(void *samples, int pos, 272 320 uint64_t *left, uint64_t *right)
+5
audio/mixeng.h
··· 41 41 extern t_sample *mixeng_conv[2][2][2][3]; 42 42 extern f_sample *mixeng_clip[2][2][2][3]; 43 43 44 + void conv_natural_float_to_stereo(struct st_sample *dst, const void *src, 45 + int samples); 46 + void clip_natural_float_from_stereo(void *dst, const struct st_sample *src, 47 + int samples); 48 + 44 49 void *st_rate_start (int inrate, int outrate); 45 50 void st_rate_flow(void *opaque, st_sample *ibuf, st_sample *obuf, 46 51 size_t *isamp, size_t *osamp);