@@ -0,0 +1,1535 @@
+package com.op1.aiff;%0A%0Aimport com.op1.iff.IffReader;%0Aimport com.op1.iff.types.ID;%0A%0Aimport java.io.IOException;%0A%0Apublic class AiffReader %7B%0A%0A    private final IffReader iffReader;%0A%0A    public AiffReader(IffReader iffReader) %7B%0A        this.iffReader = iffReader;%0A    %7D%0A%0A    public Aiff readAiff() throws IOException %7B%0A%0A        final Aiff.Builder builder = new Aiff.Builder()%0A                .withChunkId(iffReader.readID())%0A                .withChunkSize(iffReader.readSignedLong())%0A                .withFormat(iffReader.readID());%0A%0A        readChunks(builder);%0A        return builder.build();%0A    %7D%0A%0A    private void readChunks(Aiff.Builder builder) throws IOException %7B%0A%0A        while (true) %7B%0A            try %7B%0A                final ID id = iffReader.readID();%0A                System.out.println(String.format(%22Found chunk: %25s%22, id.getName()));%0A%0A                if (ChunkType.isKnownChunk(id.getName())) %7B%0A                    readKnownChunk(builder, id);%0A%0A                %7D else %7B%0A                    builder.withChunk(id, UnknownChunk.readUnknownChunk(iffReader, id));%0A                %7D%0A%0A            %7D catch (Exception e) %7B%0A                // TODO: don't use exceptions to control expected flow.%0A                System.out.println(%22Reached end of stream%22);%0A                break;%0A            %7D%0A        %7D%0A    %7D%0A%0A    private void readKnownChunk(Aiff.Builder builder, ID id) throws IOException %7B%0A        final ChunkType chunkType = ChunkType.fromName(id.getName());%0A        builder.withChunk(id, chunkType.readChunk(iffReader));%0A    %7D%0A%7D%0A

Create AiffReader.java