@@ -0,0 +1,3444 @@
+package com.op1.aiff;%0A%0Aimport com.op1.iff.Chunk;%0Aimport com.op1.iff.IffReader;%0Aimport com.op1.iff.types.ID;%0Aimport com.op1.iff.types.SignedLong;%0Aimport com.op1.iff.types.UnsignedLong;%0Aimport com.op1.util.Check;%0A%0Aimport java.io.IOException;%0A%0Apublic class SoundDataChunk implements Chunk %7B%0A%0A    private final ID chunkId = ChunkType.SOUND_DATA.getId();%0A%0A    private SignedLong chunkSize;%0A    private UnsignedLong offset;%0A    private UnsignedLong blockSize;%0A%0A    // It is far more economical to store this data as bytes than in wrapper objects like SampleFrame and SamplePoint.%0A    // It does, however, expose a security hole in the getSampleData() method.%0A    private byte%5B%5D sampleData;%0A%0A    private SoundDataChunk() %7B%0A    %7D%0A%0A    private SoundDataChunk(SoundDataChunk chunk) %7B%0A        this.chunkSize = chunk.getChunkSize();%0A        this.offset = chunk.getOffset();%0A        this.blockSize = chunk.getBlockSize();%0A        this.sampleData = chunk.getSampleData();%0A    %7D%0A%0A    @Override%0A    public ID getChunkID() %7B%0A        return chunkId;%0A    %7D%0A%0A    public SignedLong getChunkSize() %7B%0A        return chunkSize;%0A    %7D%0A%0A    public UnsignedLong getOffset() %7B%0A        return offset;%0A    %7D%0A%0A    public UnsignedLong getBlockSize() %7B%0A        return blockSize;%0A    %7D%0A%0A    public byte%5B%5D getSampleData() %7B%0A        // TODO: Most of the references that gets passed around are immutable. This one isn't.%0A        return sampleData;%0A    %7D%0A%0A    public static class Builder %7B%0A%0A        private final SoundDataChunk instance;%0A%0A        public Builder() %7B%0A            instance = new SoundDataChunk();%0A        %7D%0A%0A        public SoundDataChunk build() %7B%0A            Check.notNull(instance.chunkId, %22Missing chunkId%22);%0A            Check.notNull(instance.chunkSize, %22Missing chunkSize%22);%0A            Check.notNull(instance.offset, %22Missing offset%22);%0A            Check.notNull(instance.blockSize, %22Missing blockSize%22);%0A            return new SoundDataChunk(instance);%0A        %7D%0A%0A        public Builder withChunkSize(SignedLong chunkSize) %7B%0A            instance.chunkSize = chunkSize;%0A            return this;%0A        %7D%0A%0A        public Builder withOffset(UnsignedLong offset) %7B%0A            instance.offset = offset;%0A            return this;%0A        %7D%0A%0A        public Builder withBlockSize(UnsignedLong blockSize) %7B%0A            instance.blockSize = blockSize;%0A            return this;%0A        %7D%0A%0A        public Builder withSampleData(byte%5B%5D sampleData) %7B%0A            instance.sampleData = sampleData;%0A            return this;%0A        %7D%0A    %7D%0A%0A    public static SoundDataChunk readSoundDataChunk(IffReader iffReader) throws IOException %7B%0A%0A        final SignedLong chunkSize = iffReader.readSignedLong();%0A%0A        final SoundDataChunk.Builder builder = new SoundDataChunk.Builder()%0A                .withChunkSize(chunkSize)%0A                .withOffset(iffReader.readUnsignedLong())%0A                .withBlockSize(iffReader.readUnsignedLong());%0A%0A        final int numSampleBytes = chunkSize.toInt() - 8;%0A        final byte%5B%5D sampleData = new byte%5BnumSampleBytes%5D;%0A        for (int i = 0; i %3C sampleData.length; i++) %7B%0A            sampleData%5Bi%5D = iffReader.readByte();%0A        %7D%0A        return builder.withSampleData(sampleData).build();%0A    %7D%0A%0A    public static class SoundDataChunkReader implements ChunkReader %7B%0A        @Override%0A        public Chunk readChunk(IffReader reader) throws IOException %7B%0A            return SoundDataChunk.readSoundDataChunk(reader);%0A        %7D%0A    %7D%0A%7D%0A

Create SoundDataChunk.java