Exemplo n.º 1
0
        public AWCFile(Stream stream)
        {
            this.Stream = stream;

            Structs.AWCHeader header = new Structs.AWCHeader(stream);

            if ((header.Flags >> 8) != 0xFF)
            {
                throw new Exception("Unsupported flag");
            }

            // first bit - means that there are unknown word for each stream after this header
            // second bit - I think that it means that not all the tags are in the start of the file, but all the tags of a stream are near the data tag
            // third bit - Multi channel audio
            if ((header.Flags & 0xF8) != 0)
            {
                throw new Exception("Unsupported flag");
            }

            MultiChannel = ((header.Flags & 4) == 4);

            // 0x10 - Header size
            int audioInfoStart = 0x10 + ((header.Flags & 1) == 1 ? (2 * header.StreamsCount) : 0);

            stream.Seek(audioInfoStart, SeekOrigin.Begin);
            List <Structs.StreamInfo> info = new List <Structs.StreamInfo>();
            Dictionary <int, Dictionary <byte, Structs.ChunkInfo> > streamsChunks = new Dictionary <int, Dictionary <byte, Structs.ChunkInfo> >();

            for (int i = 0; i < header.StreamsCount; ++i)
            {
                info.Add(new Structs.StreamInfo(Stream, header.BigEndian));
            }

            for (int i = 0; i < header.StreamsCount; ++i)
            {
                streamsChunks[info[i].Id] = new Dictionary <byte, Structs.ChunkInfo>();
                for (int j = 0; j < info[i].TagsCount; ++j)
                {
                    Structs.ChunkInfo chunk = new Structs.ChunkInfo(stream, header.BigEndian);
                    streamsChunks[info[i].Id][chunk.Tag] = chunk;
                }
            }

            if (MultiChannel)
            {
                List <Structs.ChannelsInfoChunkItem> streamsInfo = new List <Structs.ChannelsInfoChunkItem>();
                Structs.ChannelsInfoChunkHeader      channelsInfoHeader;
                // Haven't figured out that hash yet
                // stream with id 0 is just info on the other channels
                using (Stream chunkReader = new ChunkStream(this.Stream, streamsChunks[0][Tag(0x81F95048)]))
                {
                    channelsInfoHeader = new Structs.ChannelsInfoChunkHeader(chunkReader, header.BigEndian);
                    if (channelsInfoHeader.ChannelsCount != header.StreamsCount - 1)
                    {
                        throw new Exception("Unexcepted number of channels");
                    }

                    for (int i = 0; i < channelsInfoHeader.ChannelsCount; ++i)
                    {
                        streamsInfo.Add(new Structs.ChannelsInfoChunkItem(chunkReader, header.BigEndian));
                        AudioIds.Add(info[i + 1].Id);
                    }
                }

                AudioStreams.Add(new MultiChannelAudio(new ChunkStream(this.Stream, streamsChunks[0][Tag("data")]), channelsInfoHeader, streamsInfo, header.BigEndian));
            }
            else
            {
                List <Structs.FormatChunk> streamsInfo = new List <Structs.FormatChunk>();
                for (int i = 0; i < header.StreamsCount; ++i)
                {
                    using (Stream chunkReader = new ChunkStream(this.Stream, streamsChunks[info[i].Id][Tag("format")]))
                    {
                        AudioStreams.Add(new Audio(new ChunkStream(this.Stream, streamsChunks[info[i].Id][Tag("data")]), new Structs.FormatChunk(chunkReader, header.BigEndian)));
                        AudioIds.Add(info[i].Id);
                    }
                }
            }

            // note: there is fourth unknown 0x21E86A3 tag
        }
Exemplo n.º 2
0
        public MultiChannelAudio(Stream data, Structs.ChannelsInfoChunkHeader channelsInfoHeader, List <Structs.ChannelsInfoChunkItem> channelsInfo, bool bigEndian)
        {
            int chunkSize = 0x800;

            List <Stream>[]            channelsStreams = new List <Stream> [channelsInfoHeader.ChannelsCount];
            List <Tuple <int, int> >[] samples         = new List <Tuple <int, int> > [channelsInfoHeader.ChannelsCount];

            for (int i = 0; i < channelsInfoHeader.ChannelsCount; ++i)
            {
                channelsStreams[i] = new List <Stream>();
                samples[i]         = new List <Tuple <int, int> >();
            }

            while (data.Position != data.Length)
            {
                int   totalChunks  = 0;
                long  startPos     = data.Position;
                long  pos          = startPos;
                int[] dataSizes    = new int[channelsInfoHeader.ChannelsCount];
                int[] firstNewData = new int[channelsInfoHeader.ChannelsCount];
                for (int i = 0; i < channelsInfoHeader.ChannelsCount; ++i)
                {
                    Structs.ChannelChunkHeader header = new Structs.ChannelChunkHeader(data, bigEndian);
                    dataSizes[i] = header.DataSize;
                    totalChunks += header.Chunks;

                    samples[i].Add(Tuple.Create(header.SamplesSkip, (int)header.Samples - header.SamplesSkip));
                }

                int headerSize = totalChunks * 4 + channelsInfoHeader.ChannelsCount * Structs.ChannelChunkHeader.Size;
                headerSize += (((-headerSize) % chunkSize) + chunkSize) % chunkSize;

                pos += headerSize;
                for (int i = 0; i < channelsInfoHeader.ChannelsCount; ++i)
                {
                    channelsStreams[i].Add(new PartialStream(data, pos, dataSizes[i]));

                    if (channelsInfo[i].RoundSize != 0)
                    {
                        dataSizes[i] += (((-dataSizes[i]) % channelsInfo[i].RoundSize) + channelsInfo[i].RoundSize) % channelsInfo[i].RoundSize;
                    }
                    pos += dataSizes[i];
                }

                if (pos - startPos > channelsInfoHeader.BigChunkSize)
                {
                    throw new Exception("Chunks too big");
                }

                if (totalChunks == 0 || startPos + channelsInfoHeader.BigChunkSize > data.Length)
                {
                    throw new Exception("Unexpected value");
                }

                // After each chunk, there is header's size zeros block
                data.Seek(startPos + channelsInfoHeader.BigChunkSize, SeekOrigin.Begin);
            }

            for (int i = 0; i < channelsInfoHeader.ChannelsCount; ++i)
            {
                Channels.Add(new SplittedAudio(channelsStreams[i], samples[i], channelsInfo[i].Samples, channelsInfo[i].SamplesPerSecond));
            }

            // following the headers, there is a seek table: For each chunk, there is the dword - which is the first sample in the block
        }