New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Coreaudio_exclusive only work with audio-format=s16 on a 24bit external DAC #4478
Comments
From the logs, when you select -audio-format=s24, it looks like where it is erroring out in the code is in ao_coreaudio_exclusive.c: My initial response would be to change the return of af_fmt_to_bytes for AF_FORMAT_S24 to 4. But I don't know whether that might break things elsewhere. So I don't know what the appropriate fix should be. |
Thanks, @downthomas . I did some test according to your suggestion, but it still failed. The only change I made was After this change, I noted that although BytesPerFrame matched my device ([8bpp][1fbp][8bpf][2ch]), the requested bit depth became 32bit The log file is here. http://sprunge.us/IVDL Not sure whether the following information would be helpful.
|
That change will definitely break. CAF isn't the API. "24 bit" in 32 bit with data in high bytes is S32 in mpv. 24 bit support should probably somehow be redone, though it's all a pain. I'd argue AOs should always take 32 bit samples for 24 bit, and "reduce" the data themselves if needed. |
@wm4 Just wondering whether there is a way to change BytesPerFrame to ([8bpp][1fbp][8bpf][2ch]) while still keeping 24bit? |
Not sure what you mean. Anyway, does any of you want to change the code so that it accepts 32 bit samples instead of S24? I think I need to remove the S24 sample format from mpv anyway. |
Sorry about my English. As downthomas pointed out, Coreaudio_exclusive doesn't work with 24 bit audio because the Bytes per packet, Frames per packet and Bytes per frame doesn't match that of my device. For 16 bit, since [4bpp][1fbp][4bpf] matches my device format, it works. Currently, for 24 bit audio, mpv delivers [6bpp][1fbp][6bpf]. However, the device requires [8bpp][1fbp][8bpf]. The method downthomas suggested did change to [8bpp][1fbp][8bpf], but result in 32bit. I guess if [8bpp][1fbp][8bpf] and 24bit can be achieved at same time, perhaps it will work. That's why I raised that question. I also found another reference, http://kaniini.dereferenced.org/2014/08/31/CoreAudio-sucks.html. It says,
|
Well, since changing the return of af_fmt_to_bytes didn't fix the problem, that indicates there would still be a problem in the CoreAudio exclusive code recognizing the format. So maybe changing the CoreAudio code to recognize 24bit audio in 6 byte and 8 byte formats would allow it to work. This change appeared to work for me. Try using the function in the attached patch for audio/out/ao_coreaudio_utils.c instead: |
mpv's S24 is always 3 bytes, so the format mapping within ao_coreaudio is the problem. I probably never tested this - AFAIK coreaudio used to accept only float for a while? |
That's what CoreAudio looks like it is still using behind the scenes once it starts playing. It is a problem with the format mapping within ao_coreaudio. And thinking about it some more, I don't believe CoreAudio is ever going to offer a 24bit format with 6bpp/bpf. So maybe a better change would be to change ca_fill_asbd_raw to fill S24 with 8bpp/bpf instead. |
I was under the impression that coreaudio does support 24 bit per samples, at least in theory (on the API level). I'm not sure why that format would be a special case. If it's not supported, it wouldn't appear anywhere in this file at all. And it would mean either ca_fill_asbd_raw or ca_asbd_equals has a bug, because it uses CA's generic format description wrong. |
I believe your impression is correct. As for why it is a special case, I think I've found the answer.
So it looks like the root of the problem are the CoreAudio_utils code not supporting both packed and unpacked 24 bit samples. Packed S24 will be 6bpp, unpacked S24 will be 8bpp. |
@downthomas Tried both of your patches, still not working.
logfile: patch_1_mp_asbd.mBytesPerPacket_3.log
Unfortunately my device can't handle the physical format of 32 bit. In fact, most of the external DACs can't. But in Audirvana, I can see a virtual format of "2 ch Mixable linear PCM Interleaved 32 little endian Float 96kHz". logfile: patch_1_mp_asbd.mBytesPerPacket_4.log
Is it possible that the failure is due to the mismatch of the "number before [8bpp]"?
Logfile: patch_2_S24_with_8bpp_bpf.log |
Yeah, I think the continued failure is due to the AudioStreamBasicDescription mFormatFlags (the numbers in square brackets) being improperly set. There were three problems I saw:
But at the end of it, the 'hardware format not supported' message is still because the format wasn't being set. This patch should set the appropriate mFormatFlags, compare those flags accurately so the appropriate format should be recognized, and set the right bpp/bpf. Try it out and see if works. |
@downthomas There is no sound and it keeps popping up that error message until I terminate it manually. The log file: http://sprunge.us/SagF. I also upload the altered ao_coreaudio_utils.c in case that I accidentally messed up something during the alteration. ao_coreaudio_utils_altered.c BTW, I saw this in /audio/out/ao_coreaudio_exclusive.c
|
That 24 bit special case in the patch still makes no sense, and it probably the reason for the unaligned read message (indicates that mpv is working with 3 byte samples while CA wants 4 bytes). |
@downthomas Built-in output deviceAccording to Audirvana Plus, the built-in output device has 4 virtual formats, which are all 32-bit float. Also, the built-in output device isn’t compatible with the Integer Mode.
In mpv with Log file: http://sprunge.us/OAai External 24-bit DACAudirvana Plus shows there are 18 virtual formats:
When Integer Mode is off, it shows
My hardware can’t handle actual 32-bit audio, but now the music is still playable. So, I’m guessing perhaps it is due to 32-bit Float virtual format. When integer mode is on, it shows
I believe your pervious patch is a foundation of 24-bit Integer Mode. I once read, Integer Mode means an integer physical format. At least, Audirvana applies unpacked 24-bit to achieve Integer Mode. In mpv, I never saw 32-bit virtual format with my external DAC. Sorry if I made any mistakes. It is purely deduction from my observations. |
The s24 mpv sample format just stopped existing (for other reasons). But whatever the underlying problem is, it probably still exists. |
@wm4 The problem does still exist. CoreAudio can deal with 32-bit while CoreAudio Exclusive can't. |
Sorry for the radio silence, I looked at the problem for a while, dug into understanding Core Audio, then got busy, and didn't come back with what I was thinking. There are two problems in the code that I've identified so far:
Try using the ao_coreaudio_utils_diff.txt I linked to earlier, along with changing, in format.c, the return of af_fmt_to_bytes for AF_FORMAT_S24 to 4, and see if that works. Unfortunately, I don't have a USB Sound output to test this out on my own. The first problem in the code is what prevents mpv from recognizing 24 bit output. Technically, mBytesPerPacket/mBytesPerFrame is supposed to be number_of_channels * sizeof(ContainerDataType), not number_of_channels * mBitsPerChannel. For hardware purposes, CoreAudio only supports unpacked 24 bit audio, so the container size will be 32 bit (4 bytes). The second problem is harder to deal with conceptually, because I'm not sure if AF_FORMAT_24 is supported to represent the data size or the container size. More later. |
It's alright, @downthomas. I am and will always be grateful for your help. I modified "ao_coreaudio_utils_diff.txt" patch from:
to
ao_coreaudio_utils.c: https://0x0.st/GbQ.c Now it works on my external DAC as well as on the build-in audio device. However, there is one regression. 24-bit WAV/AIFF can only be played in Exclusive Mode. To play in Shared Mode, we need to specify |
Well, I'm glad that it's working, because that shows it can work. The ASBD (Audio Stream Basic Description) is still wrong however, and the code which selects which ASBD format to output to is still wrong. That's a third problem I identified: if you specify a specific format, like s24, the code is written to still prefer s32 or float if it is available. Now, it just thinks the s24 is an s32, so it is using that. That's why to get it to play in Shared Mode, you have to specify float, because the ao_coreaudio_utils is used by both shared and exclusive. And in shared mode, audio is mixable, so mpv should feed it to CoreAudio in 32-bit float, because even if it didn't, CoreAudio would convert it (losslessly) to 32-bit float itself. |
Thanks for your detailed explanation. My observation is if we don't use It seems the problem is AO-dependent. As you said, in shared mode, audio must be true 32-bit for mixing. I tested, --audio-format=float, floatp, s32p, all works, as long as it's not s32. It makes sense, because I specifically defined "s32" to be "24-bit in 32-bit container". Maybe we could temporarily bypass this issue by first determining the current AO, that is
I'm not sure whether it is feasible in terms of implementation. |
How can I reproduce any of these problems? |
Additionally, With the help of Apple's HALLab and Audirvana Plus, I came to the following conclusion. b.) With a proper hardware, mpv's CoreAudio Exclusive Mode is actually "Exclusive + Integer" Mode c.) If Apple's HALLab shows virtual format is "Mixable 2 channel 32 Bit Float Point" while physical format is "Mixable 2 channel 24 Bit Signed Integer Aligned Low in 32 Bits", that means "Exclusive + Float" Mode. As explained by downthomas, CoreAudio would convert it (losslessly) to 32-bit float itself in order to be mixable. It' been confirmed by both mpv playing with Mac's build-in audio device (my Mac's build-in audio device has no unmixable format hence can't achieve Integer Mode, mpv log shows coreaudio_exclusive receives float point) and playing with Audirvana Plus (Integer Mode: OFF, log shows play in standard float point mode). d.) Apple provides a
Now the log can show whether the physical format is Mixable or not. |
Ah, I doubt I have hardware for this. What's the minimum required OSX version? I only have Sierra. Is the entire API exclusive mode uses even still needed? |
I'm on Sierra as well. Integer Mode was taken out from Lion and brought back since Mavericks. So only Lion and Mountain Lion don't have Integer Mode. Unfortunately, I have no idea about any API changes. I basically understand why this issue happens. In Shared Mode, Audio format must be "true 32-bit" for mixing. However, my patch specifically defines "s32" to be "24-bit". So, when playing "s32" in Shared Mode, the byte doesn't match up. Maybe we could temporarily bypass this issue by first determining the current AO, that is
Alternatively, we can get rid of the Integer Mode (Personally, I prefer keeping Integer Mode). |
why? was this issue solved? |
Nah, I just open a new issue, including some thoughts and updates. Please see, #6750 |
@downthomas You're right, The ASBD was indeed incorrect. mpv's format is actually 24 Bit aligned high in 32 Bit. If we don't specify
Another issue I am worry about is the high/low alignment, that is our format being aligned high while the hardware format being aligned low. In exclusive mode where no format conversion is performed, I am worried about losing fidelity. mpv has already constructed a function called |
From my reading, coreaudio_exclusive assigns
as a physical format. I'm not sure if the requisite byte shepherding can be accomplished by CoreAudio, or if that has to be handled client side via a call by |
@badgerkin Your device is packed 24 Bit, which is different from mine. Does my patch work on your device? If not, we might need to make you a special case, too. I'm not sure if the requisite byte shepherding can be accomplished by CoreAudio either, but worthy trying. CoreAudio is smarter than we though. Sometimes, it's just we setting too many hurdles in |
Your patch gets coreaudio_exclusive to work in mixable float mode. When playing a 24/48 sample the console logs:
|
Can you try this file? Previously, I set Integer Mode off if the physical format's highest bit is 24. Edit: It still probably gonna fail. Things need to change (and maybe in different combinations): return and maybe also REMINDER, wrong alignment can cause very sharp noise. Make sure you reduce the volume before testing. OR, a simpler solution, just use the original mpv git files and do the following changes in ca_asbd_equals/ao_coreaudio_utils.c. |
@badgerkin Hi, can you try this patch? As suggested by you and @wm4 , I changed from |
It works, thank you! I had to set |
I'm glad it's working and thanks for your feedback. I tried to combine packed and unpacked cases, but lack of devices for testing. Could you please test this patch? If not working, could you please upload a full log? |
This patch fails with:
Full log here. |
I think I made a mistake here. This should fix it. Can you give a go? |
That works. Alternatively, you could check for |
You're right. Thanks for reminding. |
@badgerkin Hi, sorry to trouble you again. Could you please help to test the following code?
Basically, I did my best to fix all the bugs I introduced and make the code as concise as I can. If there is no problem on your device, I will open a PR. If possible, please upload a full log as last time and focus on,
|
mpv version and platform
MacOS 10.12.5 (16F73), MPV Git 7e889e5
Reproduction steps
Run with
-no-config -audio-format=s16 -audio-exclusive=yes
and-no-config -audio-format=s24 -audio-exclusive=yes
The specification of my DAC. It is 24 bit compatible.
"[ 0.292][v][ao/coreaudio_exclusive] - 192000.0Hz 24bit mcpl [4][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 176400.0Hz 24bit mcpl [4][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 96000.0Hz 24bit mcpl [4][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 88200.0Hz 24bit mcpl [4][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 48000.0Hz 24bit mcpl [4][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 44100.0Hz 24bit mcpl [4][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 192000.0Hz 16bit mcpl [12][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 176400.0Hz 16bit mcpl [12][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 96000.0Hz 16bit mcpl [12][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 88200.0Hz 16bit mcpl [12][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 48000.0Hz 16bit mcpl [12][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 44100.0Hz 16bit mcpl [12][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 192000.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 176400.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 96000.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 88200.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 48000.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 44100.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 0.292][v][ao/coreaudio_exclusive] - 192000.0Hz 16bit mcpl [76][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 176400.0Hz 16bit mcpl [76][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 96000.0Hz 16bit mcpl [76][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 88200.0Hz 16bit mcpl [76][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 48000.0Hz 16bit mcpl [76][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)
[ 0.292][v][ao/coreaudio_exclusive] - 44100.0Hz 16bit mcpl [76][4bpp][1fbp][4bpf][2ch] int LE S packed (s16)"
Expected behavior
Both
audio-format=s16
andaudio-format=s24
should work properlyActual behavior
audio-format=s16
works fine.audio-format=s24
terminates.Error message:
"[ 1.009][v][ao/coreaudio_exclusive] virtual format 96000.0Hz 24bit mcpl [68][8bpp][1fbp][8bpf][2ch] int LE S (-)
[ 1.009][e][ao/coreaudio_exclusive] hardware format not supported
[ 1.009][e][ao] Failed to initialize audio driver 'coreaudio'
[ 1.009][e][cplayer] Could not open/initialize audio device -> no sound.
[ 1.009][v][ad] Uninit audio decoder.
[ 1.009][v][af] Removing filter lavrresample
[ 1.010][i][cplayer] Audio: no audio
[ 1.010][v][cplayer] playback restart complete
[ 1.010][v][cplayer] EOF code: 1
[ 1.010][v][vd] Uninit video.
[ 1.010][v][cplayer] finished playback, audio output initialization failed (reason 4)"
Log file
s16.log
s24.log
Sample files
Sample files needed to reproduce this issue can be uploaded to https://0x0.st/
or similar sites. (Only needed if the issue cannot be reproduced without it.)
The text was updated successfully, but these errors were encountered: