예제 #1
0
파일: AudReader.cs 프로젝트: CastleJing/d2
            protected override bool BufferData(Stream baseStream, Queue <byte> data)
            {
                if (dataSize <= 0)
                {
                    return(true);
                }

                var chunk = ImaAdpcmChunk.Read(baseStream);

                for (var n = 0; n < chunk.CompressedSize; n++)
                {
                    var b = baseStream.ReadUInt8();

                    var t = ImaAdpcmReader.DecodeImaAdpcmSample(b, ref index, ref currentSample);
                    data.Enqueue((byte)t);
                    data.Enqueue((byte)(t >> 8));
                    baseOffset += 2;

                    if (baseOffset < outputSize)
                    {
                        /* possible that only half of the final byte is used! */
                        t = ImaAdpcmReader.DecodeImaAdpcmSample((byte)(b >> 4), ref index, ref currentSample);
                        data.Enqueue((byte)t);
                        data.Enqueue((byte)(t >> 8));
                        baseOffset += 2;
                    }
                }

                dataSize -= 8 + chunk.CompressedSize;

                return(dataSize <= 0);
            }
예제 #2
0
        // Reference: https://github.com/dbry/adpcm-xq/blob/master/adpcm-lib.c

        public IList <ISound> Decode(ImaAdpcmChunk chunk)
        {
            var sounds    = new List <ISound>();
            var buffer    = new float[chunk.ChannelSamplesPerFrame];
            var channels  = chunk.Channels;
            var frameSize = (chunk.ChannelSamplesPerFrame * chunk.Channels / 2) + (chunk.Channels * 4);
            var max       = (chunk.Data.Length / frameSize) * frameSize;
            var output    = Enumerable.Range(0, channels).Select(i => new List <float>()).ToArray();

            for (var offset = 0; offset < max; offset += frameSize)
            {
                var mem = chunk.Data.AsSpan(offset, frameSize);
                for (var channel = 0; channel < channels; channel++)
                {
                    DecodeFrame(mem, buffer, channel, channels);
                    output[channel].AddRange(buffer);
                }
            }

            sounds.Add(new Sound
            {
                Samples = output.Select(s => new Sample {
                    Data = s
                }).Cast <ISample>().ToList()
            });

            return(sounds);
        }
        public void TestXboxAdpcm()
        {
            var decoder = Resolve <IImaAdpcmDecoder>();
            var encoder = Resolve <IRiffPcm16SoundEncoder>();
            var writer  = Resolve <IRiffStreamWriter>();

            var data = GetArchiveResource($"ImaAdpcm.RawXboxAdpcm.zip")
                       .First()
                       .Value;

            var ima = new ImaAdpcmChunk
            {
                Channels = 2,
                ChannelSamplesPerFrame = 64,
                Data = data,
                Rate = 44100
            };

            var decoded = decoder.Decode(ima);
            var index   = 0;

            foreach (var sound in decoded)
            {
                sound[NumericData.Rate] = ima.Rate;
                var encoded   = encoder.Encode(sound);
                var outfolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "ima");
                if (!Directory.Exists(outfolder))
                {
                    Directory.CreateDirectory(outfolder);
                }

                using (var outStream = new MemoryStream())
                {
                    writer.Write(outStream, encoded);
                    outStream.Flush();
                    File.WriteAllBytes(Path.Combine(outfolder, $"{index:000}.wav"), outStream.ToArray());
                    index++;
                }
            }
        }