Skip to content

Add AIFF-C subformats for twos,in24,in32,42ni,23ni - #916

Open
madah81pnz1 wants to merge 3 commits into
xiph:masterfrom
madah81pnz1:add-more-aiff-c-formats
Open

Add AIFF-C subformats for twos,in24,in32,42ni,23ni#916
madah81pnz1 wants to merge 3 commits into
xiph:masterfrom
madah81pnz1:add-more-aiff-c-formats

Conversation

@madah81pnz1

Copy link
Copy Markdown
Contributor

Added new option --force-aiff-c-format=FORMAT

Added new option --force-aiff-c-format=FORMAT
Comment thread src/flac/encode.c
; /* nothing to do, we already default to big-endian */
}
else {
flac__utils_printf(stderr, 1, "%s: ERROR: can't handle AIFF-C compression type \"%c%c%c%c\"\n", e->inbasefilename, (char)(xx>>24), (char)((xx>>16)&8), (char)((xx>>8)&8), (char)(xx&8));

@madah81pnz1 madah81pnz1 Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This & 8 seems to be a very old bug, all the way from the original implementation in 2005 (commit 15acb69).
It would print either a NUL character or a BS (backspace) character.

I added get_printable_char() to avoid printing garbage characters to the terminal or log file, as this could potentially be exploited in some way wit, e.g. unicode right-to-left override or escape sequence.

Comment thread src/test_streams/main.c
if(!generate_unsigned_raw(fn, channels, bits_per_sample/8, nsamples[samples]))
return 1;
if(bits_per_sample <= 24) {
/* unsigned 32 bps raw does not work */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raw unsigned test fails for 32 bits per sample. Note that I increased it to 32 and the max value tested was only up to 24 before.

Comment thread man/flac.md Outdated
: Instruct the decoder to output an AIFF-C file with format NONE and
sowt respectively.

**\--force-aiff-c-format**={none\|sowt\|twos\|in24\|42ni\|in32\|23ni}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other format types would be 'raw ', but seems to be very rarely used.

'in16'/'61ni' is another one for 16-bit audio, which seems to be used only internally in CoreAudio, but very rarely in actual AIFF-C files.

@H2Swine

H2Swine commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

raw is 8-bit signed. Easily produced with ffmpeg -c:a copy , and to those who are not aware the signedness of every format, it could very well show up. I would suppose it isn't hard to handle, but that _en_coding support might be more interesting.

@madah81pnz1

Copy link
Copy Markdown
Contributor Author

raw is 8-bit signed. Easily produced with ffmpeg -c:a copy , and to those who are not aware the signedness of every format, it could very well show up. I would suppose it isn't hard to handle, but that _en_coding support might be more interesting.

I had it initially, but decided to not include it, due to it being rare, and its endianess is ambigious beyond 8 bits.
It's easy to add back, but then I think I'll restrict it to 8 bits only, same as 'in24' is restricted to 24 bits only.

You have to have both encode and decode support, otherwise foreign metadata is not able to restore the original file back.

@madah81pnz1

Copy link
Copy Markdown
Contributor Author

raw is 8-bit signed. Easily produced with ffmpeg -c:a copy , and to those who are not aware the signedness of every format, it could very well show up. I would suppose it isn't hard to handle, but that _en_coding support might be more interesting.

But I realized now this contradicts the findings here: https://hydrogenaudio.org/index.php/topic,127436.25.html
afconvert with -d UI8 will write 'raw ' as unsigned 8-bit, not signed?

If flac is going to support 'raw ', it should be unsigned then, to atleast keep in sync with afconvert. I can push another commit with these changes.

The problem then becomes if there is ever a need to support both signed and unsigned for 'raw '. If so that means flac must store some additional metadata, since there is nothing itself in the AIFF-C format (and flac's foreign metadata of it) that can recover the signedness of the audio.

@H2Swine

H2Swine commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

1: you are right I was dumb, 2: what about ... something that does the bit depth for the user?

raw is 8-bit signed.

But I realized now this contradicts the findings here: https://hydrogenaudio.org/index.php/topic,127436.25.html afconvert with -d UI8 will write 'raw ' as unsigned 8-bit, not signed?

Thanks for arresting thoughtless swiney me being too dumb to think twice. raw is 8-bit unsigned like WAVE 8-bit (but unlike the traditional AIFF which like AU/SND writes 8-bit as signed).
Yeah, treat it as "8 bits only".

.

  1. Here is the problem: User needs to know the bit depth, and that is unnecessary. Consider instead:
    --force-aiff-c-format=in and --force-aiff-c-format=ni or
    --force-aiff-c-in-format and --force-aiff-c-ni-format without options.
    Let the decoder put in 24/42 etc, and in help file explain that "in" means the trad-AIFF endian with new type designations that Apple seems to write, while "ni" means WAVE endian (unsigned 'raw' in case of 8-bit).

Also, what is the capitalization in the AIFF files?

@madah81pnz1

Copy link
Copy Markdown
Contributor Author
2. Here is the problem: User needs to know the bit depth, and that is unnecessary. Consider instead:
   `--force-aiff-c-format=in` and `--force-aiff-c-format=ni` or
   `--force-aiff-c-in-format` and `--force-aiff-c-ni-format` without options.
   Let the decoder put in 24/42 etc, and in help file explain that "in" means the trad-AIFF endian with new type designations that Apple seems to write, while "ni" means WAVE endian (unsigned 'raw' in case of 8-bit).

Yes, it is a good idea. I was more thinking of a =le and =be syntax, since it is not obvious what =ni and =in stands for.
An example:

8 16 24 32 others
in NONE NONE in24 in32 NONE
ni sowt sowt 42ni 23ni sowt
  • = any other bit depth, e.g. 20 bits

But then what if you want 'twos' instead of 'NONE'? And 'raw ' for 8 bit, or if you don't want 'raw '. Seems we need some kind of profile mapping for this, e.g. a list of preferred AIFC compression types and what bits they should be used for.
This is why I opted to not do this as part of this commit, just add support as a first step and then see how it pans out.

(There's also 'in16'/'61ni' for 16-bits, but I don't want to promote or make flac legitimate its usage further.)

Also, what is the capitalization in the AIFF files?

Only 'NONE' is upper-case, everything else is (supposedly) lower-case.
But then for other formats such as 'fl32', 'ulaw' and 'alaw', it seems common to also handle 'FL32', 'ULAW' and 'ALAW' as the same. https://www.mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html

@H2Swine

H2Swine commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Uh-oh, stop press. According to https://developer.apple.com/documentation/avfaudio/avaudiocommonformat/pcmformatint16
, "in" is native endianness, not big endian.

QuickTime doc does not cite endianness for these. It does for twos and sowt. Of course when https://developer.apple.com/standards/qtff-2001.pdf was issued, endianness would default to Big. But now there is a source saying native. Also here is how ffmpeg mishandled little-endian in24 in .mov. Of course AIFC lacks the QuickTime format's endianness atom: https://trac.ffmpeg.org/ticket/1881

This found by asking AI engines to get a pseudo-confirmation on what is supposed to be right about 8-bit ... this was a byproduct.

@madah81pnz1

Copy link
Copy Markdown
Contributor Author

Uh-oh, stop press. According to https://developer.apple.com/documentation/avfaudio/avaudiocommonformat/pcmformatint16 , "in" is native endianness, not big endian.

QuickTime doc does not cite endianness for these. It does for twos and sowt. Of course when https://developer.apple.com/standards/qtff-2001.pdf was issued, endianness would default to Big. But now there is a source saying native. Also here is how ffmpeg mishandled little-endian in24 in .mov. Of course AIFC lacks the QuickTime format's endianness atom: https://trac.ffmpeg.org/ticket/1881

This found by asking AI engines to get a pseudo-confirmation on what is supposed to be right about 8-bit ... this was a byproduct.

An interesting point. When ffmpeg does a codec copy, does it also retain the 'enda' chunk? So you could for example have two .mov files with 'in24', and 'enda' specified as little-endian in one and big-endian in the other. A plain codec copy would copy the data as-is, but one file would for sure be interpreted wrongly in most (if not all) players and software. Unless ffmpeg switches from 'in24' to '42ni' for one file?

The main purpose of doing this in flac is to increase interoperability with existing tools (e.g. sox, ffmpeg, libsndfile), and if they all agree that 'in24' is big-endian and '42ni' is little-endian, then that problem is solved, as it has already become the de facto standard way to write AIFF-C files.

@H2Swine

H2Swine commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Edit: ... erruhm ... "native" maybe still means "big" and Apple didn't even change it? Others started speaking of "network endian" if they had an "n" to explain ...

Anyway,:
Of course, this doesn't address AIFF directly - heck I cannot even fathom if it addresses files or streams that aren't for interchange. E.g. it says that float is supposed to be in native endian. And there is nothing there about the "ni" nor about 24.

Here is support for your notion, but it is a wiki entry, not official and even if correct once, obsolete the moment Apple decides to fart in another general direction: https://wiki.multimedia.cx/index.php/PCM#Apple_QuickTime_Identifiers

So what then? --force-aiff-c-big-in-format and --force-aiff-c-little-ni-format?

The main purpose of doing this in flac is to increase interoperability with existing tools (e.g. sox, ffmpeg, libsndfile), and if they all agree that 'in24' is big-endian and '42ni' is little-endian, then that problem is solved, as it has already become the de facto standard way to write AIFF-C files.

  • Hm, do they ever need these? Even if they write them, does that mean flac has to force output to these except when selected through foreign metadata (then you have to "do" the same thing, but you don't have to call the command option anything "big").
  • Do they use the in16? 16 bits is so common a format that you should think twice before supporting in but not in16.

Also I see that Apple for QuickTime expects NONE to be deprecated in favour of raw, so is there really any signed 8-bit left? twos is for 16, NONE would be signed but is now supposedly unsigned, ...? Meh. Fruitcake.

@madah81pnz1

Copy link
Copy Markdown
Contributor Author
* Hm, do they ever _need_ these? Even if they write them, does that mean flac has to force output to these except when selected through foreign metadata (then you have to "do" the same thing, but you don't have to call the command option anything "big").

* Do they use the in16? 16 bits is so common a format that you should think twice before supporting in but not in16.

I don't think anything outside Apple supports 'in16'/'61ni'.
I did a small manual no-AI survey of source code for some popular libraries:

sox_ng

https://codeberg.org/sox_ng/sox_ng/src/branch/main/src/aiff.c#L991
Writes 'NONE' for 8-bit signed, and then either 'twos','in24','in32' or 'sowt','42ni','23ni' depending on endianess.
When reading, it seems to accept any of these and uses sample_size for the actual bits, so sox_ng is able to decode for example 'in24' even as 16-bits.
An interesting detail is that sox_ng does not support 'raw '.

libsndfile

Reads 'NONE', 'raw ', 'twos'/'sowt', 'in24'/'42ni', 'in32'/'23ni':
https://github.com/libsndfile/libsndfile/blob/master/src/aiff.c#L1089
When writing, 'twos'/'sowt' is used for 8-bit signed and also 16-bit, while 'in24'/'42ni' for 24-bit and 'in32'/'23ni' for 32-bit. 8-bit unsigned uses 'raw '. It never writes 'NONE'.
https://github.com/libsndfile/libsndfile/blob/master/src/aiff.c#L1268

ffmpeg

Uses 'NONE' for signed 8-bit and 'raw ' for unsigned 8-bit. 'NONE' can also be used for big-endian 16/24/32-bit, and 'in24'/'in32' for 24/32-bit big-endian only.
https://git.ffmpeg.org/gitweb/ffmpeg.git/blob/refs/heads/master:/libavformat/aiff.c
When reading, it seems to go through that same table here:
https://git.ffmpeg.org/gitweb/ffmpeg.git/blob/refs/heads/master:/libavformat/aiffdec.c#l141
So 'NONE' and 'twos' ends up as AV_CODEC_ID_PCM_S16BE, and then later on line 148 there is a check for bits_per_coded_sample that remaps the codec_id to one of AV_CODEC_ID_PCM_S{8|16BE|24BE|32BE}.

But I don't see such check for 'sowt', so 'sowt' only works for 16-bit.
There's no support for '42ni' and '23ni' either, so no little-endian support for anything 24/32-bit, from what I can glean from the source.

WavPack

Able to read 'NONE', 'twos', 'sowt' and 'raw '. 'raw ' is unsigned, but beyond 8-bits I think it is treated as signed.
https://github.com/dbry/WavPack/blob/master/cli/aiff.c#L185

Worth noting is that WavPack handles 'none', 'TWOS', 'SOWT', and 'RAW ' also. I haven't seen any other software do this. When writing, WavPack only writes 'NONE' and 'sowt', never 'raw ' or 'twos':
https://github.com/dbry/WavPack/blob/master/cli/aiff_write.c#L113

@H2Swine

H2Swine commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Good detective work. Did you check whether libsndfile interprets 8-bit NONE as signed when reading it?

In view of this picture, we have at least some support for an option that for 24 and 32 covers "in" as BE and "ni" as LE, while for 8 and 16:

  • corresponding to in/BE, writes "twos" but with a "WARNING:" or maybe an "INFO:" saying "for compatibility, this option currently writes 'twos' for 8/16 bits. This could change in the future." Whether that message is thrown for 24/32 ...
  • corresponding to ni/LE, writes "raw " for 8-bit and "sowt" for 16-bit; and with the similar WARNING/INFO. This obsoletes the kinda-broken --force-aiff-c-sowt-format (you don't want sowt for other than 16 bits, maybe there should be a WARNING on that, but I guess that is a separate PR).

Allowing "twos" for 8-bit has some support in the 2001 QuickTime doc https://developer.apple.com/standards/qtff-2001.pdf: it says (page 103) about "twos" that
"sample values range from -128 to 127 for 8-bit audio, and -32768 to 32767 for 16-bit audio; 0 is always silence"
... note it says not the latter for "sowt"! Then if we might interpret the subsequent
"These samples are stored in 16-bit big-endian format."
to mean In case of 16-bit they are stored as big-endian, we have a case for 8-bit "twos".

Above suggestion does not write any "NONE", presuming that those who want it would just keep using --force-aiff-c-none-format as is. That option's behaviour does violate that 2001 QuickTime doc, on its suggestion that NONE is to be interpreted as "raw " when encountered in 8-bits, but I don't know whether any application actually does this when it comes to AIFC. Haven't checked libsndfile, am not on appropriate computer, but if libsndfile reads 8-bit NONE as signed, we have a case for the opinion that --force-aiff-c-none-format is not "broken" and does not need to be obsoleted, while --force-aiff-c-sowt-format should be.

As goes WavPack's "raw ", support introduced out of my pointing out that ffmpeg would write it. That WavPack also supports "in case someone does it wrong" for cases and >8 raw, isn't much of an indication than "whatever stupid application might write", since WavPack will reconstruct files warts-and-all but AFAIK offers no option to otherwise force-select between AIFF versions or WAVE versions. These flac options for the latter situation which WavPack doesn't really provide for. No reason to support wrong-case as a chosen option.

Tasks?

  • Verify whether libsndfile reads 8-bit "NONE" as unsigned/signed. If it reads as signed, then fine, I'd say ignore the statement from the QuickTime document which after all is not directly about AIFC.
  • Once content of the options is set: Decide on name for the new options. The other --force-blahblahblah-format options cannot take arguments, so I'd say that neither should these!
  • Take stand on WARNING/INFO for these new options, taking into account the possibility of users working with --warnings-as-errors, and whether to throw WARNING/INFO for all formats or only 8/16 or even only 16.
  • Take stand on a PR (likely a separate one?) for amending WARNING into --force-aiff-c-sowt-format and when for it to be INFO and when to be WARNING.

@madah81pnz1

madah81pnz1 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Good detective work. Did you check whether libsndfile interprets 8-bit NONE as signed when reading it?

Yes, 'NONE' is always signed (SF_FORMAT_PCM_S8), and support any bit depth. 'raw ' is unsigned 8-bit only (SF_FORMAT_PCM_U8):

s_bitwidth_to_subformat (int bits)
{	static int array [] =
	{	SF_FORMAT_PCM_S8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
		} ;
...
subformat = s_bitwidth_to_subformat (comm_fmt->sampleSize) ;
...
	{	case NONE_MARKER :
				psf->sf.format = (SF_FORMAT_AIFF | subformat) ;
				break ;
...
		case raw_MARKER :
				psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_PCM_U8) ;
				break ;

but if libsndfile reads 8-bit NONE as signed, we have a case for the opinion that --force-aiff-c-none-format is not "broken" and does not need to be obsoleted, while --force-aiff-c-sowt-format should be.

For 8-bit signed, since the endianess doesn't matter (the data is encoded identically), it makes sense to prefer 'NONE' rather than 'sowt' or 'twos'. This is maybe how 'sowt' became known as 16-bit only, since before 24-bit audio was common, there was only 16-bit that 'sowt' could be used for (to select little-endian).

This was also one of things I wanted to take a closer look at; how 8-bit is handled. Atleast it seems that 'raw ' is always unsigned 8-bit, and 'NONE' is signed big-endian for any bit depth.

Most software agrees on 16-bit 'NONE' big-endian and 'sowt' little-endian.

What differs is how 24/32-bit audio should be handled. There is no solution that works for everything; best practice I can recommended (based on ffmpeg and wavpack as the lowest common denominators) is to use 'NONE' for everything; since ffmpeg doesn't support arbitrary bit depths for 'sowt', and wavpack doesn't support 'in24' and 'in32'.

Then there's also how 16/24/32-bit audio in 'raw ', there is no consensus, best practice seems to be "don't do it".

As goes WavPack's "raw ", support introduced out of my pointing out that ffmpeg would write it. That WavPack also supports "in case someone does it wrong" for cases and >8 raw, isn't much of an indication than "whatever stupid application might write", since WavPack will reconstruct files warts-and-all but AFAIK offers no option to otherwise force-select between AIFF versions or WAVE versions. These flac options for the latter situation which WavPack doesn't really provide for. No reason to support wrong-case as a chosen option.

I thought WavPack could always decode back to .wav, atleast I think that's a nice feature in flac.
If the encoder is wrong about the signedness, that would decrease compression, same applies to endianess. You could always restore back to the original file, but you could never decode back to another format.

Tasks?

* [ ]  Verify whether libsndfile _reads_ 8-bit "NONE" as unsigned/signed. If it reads as signed, then fine, I'd say ignore the statement from the QuickTime document which after all is not directly about AIFC.

I think this is done then? 'NONE' seems to always be signed in all software I have checked.

* [ ]  Once _content_ of the options is set: Decide on name for the new options. The other --force-blahblahblah-format options cannot take arguments, so I'd say that neither should these!

The reason I added arguments for the new --force-aiff-format was that I dislike having too many separate options; I prefer to have a single option with many arguments instead. It improves documentation and discoverability.

For comparison, what if --bps=# was separate options: --bps-8, --bps-16, --bps-24 and so on. If someone tries --bps-40, it is harder to give a meaningful error message that the max supported bps is 32, compared to --bps=40.

* [ ]  Take stand on WARNING/INFO for these new options, taking into account the possibility of users working with `--warnings-as-errors`, and whether to throw WARNING/INFO for all formats or only 8/16 or even only 16.

* [ ]  Take stand on a PR (likely a separate one?) for amending WARNING into `--force-aiff-c-sowt-format` and when for it to be INFO and when to be WARNING.

I think for the existing NONE/sowt you don't need a warning.

Edit: To clarify, I mean that the --force-*-format options are expert options, e.g. "do exactly what I asked". It would be like if --force (Force overwriting of output files) still printed a warning if the output file existed.

A better or smarter AIFF-C compression type selection is maybe not even possible. If we always need to print a warning whenever 24-bit audio is used, some users will be unhappy about it.

If we think about this, when do you really need to use 'sowt' and little-endian? Even a quick and dirty AIFF reader would certainly implement support for 'NONE' and big-endian, since that is that the only thing that the original AIFF (not AIFC) supports. It would be rare to have a AIFC reader that only supports little-endian audio.

But the same could be said for --force-extensible-wave-format, as historically there are far too many WAV readers that doesn't correctly handle the 'fmt ' chunk being either 16, 18 or 40 bytes.

@H2Swine

H2Swine commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Reason why I advocated "twos" is that there is already a --force-aiff-c-none-format which can be used if you want NONE. There is no --force-aiff-c-twos-format (of course that can be added), but there is a --force-aiff-c-sowt-format that is "broken" in the sense that it outputs sowt when sowt is not generally readable and was maybe not implemented.

Most software agrees on 16-bit 'NONE' big-endian and 'sowt' little-endian.

I don't even know a counterexample.

What differs is how 24/32-bit audio should be handled. There is no solution that works for everything; best practice I can recommended (based on ffmpeg and wavpack as the lowest common denominators) is to use 'NONE' for everything; since ffmpeg doesn't support arbitrary bit depths for 'sowt', and wavpack doesn't support 'in24' and 'in32'.

... and that - NONE for all - we have an option for.

Then there's also how 16/24/32-bit audio in 'raw ', there is no consensus, best practice seems to be "don't do it".

Never seen one.

I thought WavPack could always decode back to .wav,

Yes, and you can choose AIFF/AIFC too, but you cannot select among AIFC flavours. wvunpack has
--aif for legacy AIFF (not AIFC)
--aif-le for AIFC-sowt
--caf-le and --caf-be for both endianness CAF
-w64 for Wave64
-w or equivalently --wav: write WAVE, that is WAVE_FORMAT_EXTENSIBLE for multichannel, and that also means RF64 for > 4 GiB.

(... and choices for DSD too.)

The reason I added arguments for the new --force-aiff-format was that I dislike having too many separate options; I prefer to have a single option with many arguments instead. It improves documentation and discoverability.

That choice has I think been made already, as there are
--force-aiff-format --force-rf64-format --force-wave64-format --force-legacy-wave-format --force-extensible-wave-format --force-aiff-c-none-format --force-aiff-c-sowt-format

Let's stay consistent. I think there should be a --force-aiff-c-format that takes no argument but where decoder chooses AIFC flavour.
(And I think flac -d infile.flac -o outfile.aifc should write same decoder chooses AIFC too. Right now it writes WAVE.)

@madah81pnz1

Copy link
Copy Markdown
Contributor Author

I thought WavPack could always decode back to .wav,

Yes, and you can choose AIFF/AIFC too, but you cannot select among AIFC flavours. wvunpack has --aif for legacy AIFF (not AIFC) --aif-le for AIFC-sowt --caf-le and --caf-be for both endianness CAF -w64 for Wave64 -w or equivalently --wav: write WAVE, that is WAVE_FORMAT_EXTENSIBLE for multichannel, and that also means RF64 for > 4 GiB.

(... and choices for DSD too.)

wvunpack also has this rather surprising feature:

wvunpack in.wv out.wav

out.wav is not always a WAVE file, it is whatever format the original file was (in this case CAF).

Similarly, this gives no errors and no warnings, but doesn't do what you think it does (as you've found out):

flac -d in.flac -o out.aifc

Both wavpack and flac really need some warning if the output file extension doesn't match the actual format used.

The reason I added arguments for the new --force-aiff-format was that I dislike having too many separate options; I prefer to have a single option with many arguments instead. It improves documentation and discoverability.

That choice has I think been made already, as there are --force-aiff-format --force-rf64-format --force-wave64-format --force-legacy-wave-format --force-extensible-wave-format --force-aiff-c-none-format --force-aiff-c-sowt-format

Let's stay consistent.

Alright, I agree with you on consistency. But then I assume you don't want all these options?

--force-aiff-c-none-format
--force-aiff-c-raw-format
--force-aiff-c-sowt-format
--force-aiff-c-twos-format
--force-aiff-c-in24-format
--force-aiff-c-in32-format
--force-aiff-c-42ni-format
--force-aiff-c-23ni-format

Maybe could repurpose --sign=unsigned if someone really wanted 'raw ' for 8-bits, and use --endian=little or --endian=big to select between the two groups:

bits --endian=big --endian=little --sign=unsigned
8 'NONE' 'NONE' 'raw '
16 'twos' 'sowt' -
24 'in24' '42ni' -
32 'in32' '23ni' -

But maybe this complicates it even further, so let's go back to your original suggestion about --force-aiff-c-in-format and --force-aiff-c-ni-format. We could disallow 'raw ' from being used (but still accept encoding from it and restoring via foreign metadata). Or add --force-aiff-c-raw-format.

The existing --force-aiff-c-sowt-format can still be used for force 'sowt' for everything, but with a warning about compatibility for bits != 16.

--force-aiff-c-none-format would remain as-is with no such warning, since it seems most existing software can handle arbitrary bit depths for 'NONE', atleast when reading.

I think there should be a --force-aiff-c-format that takes no argument but where decoder chooses AIFC flavour. (And I think flac -d infile.flac -o outfile.aifc should write same decoder chooses AIFC too. Right now it writes WAVE.)

The only safe decoder chooses format would be 'NONE', since that is the only one that seems to work across bit depths.
Since some software doesn't implement 'in24', and some only supports 'sowt' for 16-bits.

@H2Swine

H2Swine commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Maybe could repurpose --sign=unsigned if someone really wanted 'raw ' for 8-bits,

Uh-oh. That's raw PCM, not AIFC with "raw " fourcc. Don't mix that up.

I was assuming that if the user asks for a "little-endian option" they would want what WAVE uses, which for 8-bit is unsigned. Like this

. 24/32 16 8
'big'/'in' in twos twos or maybe NONE
'little'/'ni' ni sowt raw

Argument against "NONE" is that there is the --force-aifc-none-format already (and easier to remember). No strong opinions (and mine is hardly carrying much weight).

The only safe decoder chooses format would be 'NONE', since that is the only one that seems to work across bit depths. Since some software doesn't implement 'in24', and some only supports 'sowt' for 16-bits.

I tend to agree although it isn't a given that a decoder chooses would have to choose one and the same for all signals. Decoder doesn't do that upon -o filename.wav, it chooses WAVE_FORMAT_EXTENSIBLE for > 2 channels or > 16 bits I think it is (too lazy to look up detail, point is it does not choose one and the same always).
Foreign metadata should override.

@madah81pnz1

Copy link
Copy Markdown
Contributor Author

Maybe could repurpose --sign=unsigned if someone really wanted 'raw ' for 8-bits,

Uh-oh. That's raw PCM, not AIFC with "raw " fourcc. Don't mix that up.

Yes that was my conclusion as well.

But considering supporting future formats such as CAF that also comes in little- or big-endian, it might be a better user experience to have one single command line option to select the endianess across all formats (or atleast those that supports this), not just for raw PCM.

(As another example, --force-extensible-wave-format is already a bit limited in that you can't use it to affect the 'fmt ' chunk for WAVE64 or RF64. Adding more options like --force-rf64-extensible-format and --force-wave64-extensible-format would add unnecessary complexity in my opinion. Better then to have a separate option that affects the 'fmt ' chunk size and format independently for WAV/RF64/WAVE64. YAGNI also applies here, any software that supports RF64/WAVE64 probably also supports all 'fmt ' chunk variants.)

I was assuming that if the user asks for a "little-endian option" they would want what WAVE uses, which for 8-bit is unsigned. Like this
. 24/32 16 8
'big'/'in' in twos twos or maybe NONE
'little'/'ni' ni sowt raw

'raw ' is a bit of an odd format in AIFF though, I don't think it should be the default option for 8-bit. The original AIFF is signed only, even CAF is signed only.
Also, if selecting endianess also affects signedness for 8-bit (where endianess doesn't matter), that would be a bit surprising, e.g. principle of least astonishment (POLA).

Argument against "NONE" is that there is the --force-aifc-none-format already (and easier to remember). No strong opinions (and mine is hardly carrying much weight).

The only safe decoder chooses format would be 'NONE', since that is the only one that seems to work across bit depths. Since some software doesn't implement 'in24', and some only supports 'sowt' for 16-bits.

I tend to agree although it isn't a given that a decoder chooses would have to choose one and the same for all signals. Decoder doesn't do that upon -o filename.wav, it chooses WAVE_FORMAT_EXTENSIBLE for > 2 channels or > 16 bits I think it is (too lazy to look up detail, point is it does not choose one and the same always). Foreign metadata should override.

My point was that there is no such safe format for 24/32-bit in AIFF-C: Not all software supports 'inXX', not all software supports 24-bit 'sowt', not all software supports 'twos'; so what we're left with is 'NONE'.
Foreign metadata always takes precedence.

@H2Swine

H2Swine commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

But considering supporting future formats such as CAF that also comes in little- or big-endian, it might be a better user experience to have one single command line option to select the endianess across all formats (or atleast those that supports this), not just for raw PCM.

(As another example, --force-extensible-wave-format is already a bit limited in that you can't use it to affect the 'fmt ' chunk for WAVE64 or RF64. Adding more options like --force-rf64-extensible-format and --force-wave64-extensible-format would add unnecessary complexity in my opinion.

Warning for (honest) whining:

I agree with you that --force-enormously-many-different-such-options-without-argument is a meh, and I even dislike that those start with "--force" as --force is used for overwrite.
Maybe come a 1.6 the dev team could discuss whether to obsolete (of course not remove) them by a new --format= or --outformat= that takes the file type as argument. Maybe even a long argument like--outformat="aifc-raw,wavex,raw-le,caf23ni" to force any 8-bit to decode to aifc-raw, 16-bit to extensible wave, 24-bit to little-endian raw, and 32-bit to caf23ni ... is that a name? Anyway my point is, a new option to obsolete the others could be discussed more tabula rasa.

But for now ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants