예제 #1
0
        public ITask CreateExtractSng()
        {
            return(Build("Extract SNG", task =>
            {
                var files = GetInputFiles(task);
                if (!files.Any())
                {
                    task.Message = "No input files.";
                    return false;
                }

                ParallelProgress(task, files, file =>
                {
                    using (var input = OpenRead(task, file))
                    {
                        foreach (var entry in _xboxSngStreamReader.Read(input))
                        {
                            if (entry.Song != null)
                            {
                                var sound = _imaAdpcmDecoder.Decode(new ImaAdpcmChunk
                                {
                                    Channels = 2,
                                    ChannelSamplesPerFrame = 64,
                                    Data = entry.Song,
                                    Rate = 44100
                                }).Single();

                                var encoded = _riffPcm16SoundEncoder.Encode(sound);
                                using (var outStream = OpenWriteMulti(task, file, i => $"{entry.Name}.wav"))
                                {
                                    _riffStreamWriter.Write(outStream, encoded);
                                    outStream.Flush();
                                }
                            }

                            if (entry.Preview != null)
                            {
                                var sound = _imaAdpcmDecoder.Decode(new ImaAdpcmChunk
                                {
                                    Channels = 2,
                                    ChannelSamplesPerFrame = 64,
                                    Data = entry.Preview,
                                    Rate = 44100
                                }).Single();

                                var encoded = _riffPcm16SoundEncoder.Encode(sound);
                                using (var outStream = OpenWriteMulti(task, file, i => $"{entry.Name}-preview.wav"))
                                {
                                    _riffStreamWriter.Write(outStream, encoded);
                                    outStream.Flush();
                                }
                            }
                        }
                    }
                });

                return true;
            }));
        }
예제 #2
0
        public ISound Decode(Stream stream)
        {
            var riff = _riffStreamReader.Read(stream);

            if (riff.Format != "WAVE")
            {
                throw new RhythmCodexException("RIFF type must be WAVE.");
            }

            var fmt = riff.Chunks.FirstOrDefault(c => c.Id == "fmt ");

            if (fmt == null)
            {
                throw new RhythmCodexException("RIFF must contain the fmt chunk.");
            }
            var format = _waveFmtDecoder.Decode(fmt);

            var data = riff.Chunks.FirstOrDefault(c => c.Id == "data");

            if (data == null)
            {
                throw new RhythmCodexException("RIFF must contain the data chunk.");
            }

            var result = new Sound
            {
                [NumericData.Rate] = format.SampleRate,
                Samples            = new List <ISample>()
            };

            switch (format.Format)
            {
            case 0x0001:     // raw PCM
            {
                float[] decoded;
                switch (format.BitsPerSample)
                {
                case 8:
                    decoded = _pcmDecoder.Decode8Bit(data.Data);
                    break;

                case 16:
                    decoded = _pcmDecoder.Decode16Bit(data.Data);
                    break;

                case 24:
                    decoded = _pcmDecoder.Decode24Bit(data.Data);
                    break;

                case 32:
                    decoded = _pcmDecoder.Decode32Bit(data.Data);
                    break;

                default:
                    throw new RhythmCodexException("Invalid bits per sample.");
                }

                foreach (var channel in decoded.Deinterleave(1, format.Channels))
                {
                    result.Samples.Add(new Sample
                        {
                            [NumericData.Rate] = format.SampleRate,
                            Data = channel
                        });
                }

                break;
            }

            case 0x0002:     // Microsoft ADPCM
            {
                var exFormat = new MicrosoftAdpcmFormat(format.ExtraData);
                var decoded  = _microsoftAdpcmDecoder.Decode(data.Data.AsSpan(), format, exFormat);

                foreach (var sample in decoded.Samples)
                {
                    result.Samples.Add(sample);
                }

                break;
            }

            case 0x0003:     // 32-bit float
            {
                var decoded = _pcmDecoder.DecodeFloat(data.Data);

                foreach (var channel in decoded.Deinterleave(1, format.Channels))
                {
                    result.Samples.Add(new Sample
                        {
                            [NumericData.Rate] = format.SampleRate,
                            Data = channel
                        });
                }

                break;
            }

            case 0x0011:     // IMA ADPCM
            {
                var exFormat = new ImaAdpcmFormat(format.ExtraData);
                var decoded  = _imaAdpcmDecoder.Decode(new ImaAdpcmChunk
                    {
                        Channels = format.Channels,
                        Rate     = format.SampleRate,
                        Data     = data.Data,
                        ChannelSamplesPerFrame = exFormat.SamplesPerBlock
                    });

                foreach (var sample in decoded.SelectMany(s => s.Samples))
                {
                    result.Samples.Add(sample);
                }

                break;
            }
            }

            return(result);
        }
예제 #3
0
        private ISound DecodeSound(XwbSound sound)
        {
            var result = new Sound();
            var format = sound.Info.Format;

            switch (format.FormatTag)
            {
            case XwbConstants.WavebankminiformatTagPcm:
            {
                float[] decoded;
                switch (format.BitsPerSample)
                {
                case 8:
                    decoded = _pcmDecoder.Decode8Bit(sound.Data);
                    break;

                case 16:
                    decoded = _pcmDecoder.Decode16Bit(sound.Data);
                    break;

                case 24:
                    decoded = _pcmDecoder.Decode24Bit(sound.Data);
                    break;

                case 32:
                    decoded = _pcmDecoder.Decode32Bit(sound.Data);
                    break;

                default:
                    return(null);
                }

                foreach (var channel in decoded.Deinterleave(1, format.Channels))
                {
                    result.Samples.Add(new Sample
                        {
                            [NumericData.Rate] = format.SampleRate,
                            Data = channel
                        });
                }

                return(result);
            }

            case XwbConstants.WavebankminiformatTagXma:
            {
                return(_imaAdpcmDecoder.Decode(new ImaAdpcmChunk
                    {
                        Channels = format.Channels,
                        ChannelSamplesPerFrame = format.AdpcmSamplesPerBlock,
                        Data = sound.Data,
                        Rate = format.SampleRate
                    }).SingleOrDefault());
            }

            case XwbConstants.WavebankminiformatTagAdpcm:
            {
                return(_microsoftAdpcmDecoder.Decode(
                           sound.Data,
                           format,
                           new MicrosoftAdpcmFormat
                    {
                        Coefficients = new int[0],
                        SamplesPerBlock = format.AdpcmSamplesPerBlock
                    }));
            }

            default:
            {
                return(null);
            }
            }
        }