Bug? File data alignment error in AiffAudioFormatWriter


#1

Near the bottom of AiffFileHelpers::MarkChunk::create(), there's this gubbins:


                for (int i = 0; i < numCues; ++i)
                {

                    ...

                    out.writeShortBigEndian ((short) identifier);
                    out.writeIntBigEndian (offset);
                    const size_t labelLength = jmin ((size_t) 254, label.getNumBytesAsUTF8()); // seems to need null terminator even though it's a pstring
                    out.writeByte ((char) labelLength + 1);
                    out.write (label.toUTF8(), labelLength);
                    out.writeByte (0);
                }
                if ((out.getDataSize() & 1) != 0)
                    out.writeByte (0);

 

It's my opinion that the last two lines (which write a byte if necessary to keep short aligment) should be above the brace, so that alignment is performed after writing each cue label pstring rather than at the end of all the cue labels.

This would seem symmetrical with the loader code in AiffAudioFormatReader::AiffAudioFormatReader():


for (uint16 i = 0; i < numCues; ++i)
{
    uint16 identifier = (uint16) input->readShortBigEndian();
    uint32 offset = (uint32) input->readIntBigEndian();
    uint8 stringLength = (uint8) input->readByte();
    MemoryBlock textBlock;
    input->readIntoMemoryBlock (textBlock, stringLength);

    // if the stringLength is even then read one more byte as the
    // string needs to be an even number of bytes INCLUDING the
    // leading length character in the pascal string
    if ((stringLength & 1) == 0)
        input->readByte();

    const String prefixCue ("Cue" + String (i));
    metadataValues.set (prefixCue + "Identifier", String (identifier));
    metadataValues.set (prefixCue + "Offset", String (offset));
    const String prefixLabel ("CueLabel" + String (i));
    metadataValues.set (prefixLabel + "Identifier", String (identifier));
    metadataValues.set (prefixLabel + "Text", textBlock.toString());
}



Certainly, I found it necessary to do this whilst testing a 'round trip' AIFF read/write in Juce.  Without it, the written chunk (when read back in) had dodgy data, and Soundforge refused to recognise the cue points correctly.

I'm going to hypothesize further and say this may be the cause of the comment about needing a null terminator on a pstring, although I didn't bother trying to take that out in case that was to fix some problem with other AIFF reading software!

 

 

 


#2

This is fixed in the latest tip! Thank you for reporting.