示例#1
0
        public static int ReadWavFile(string path, out AudioData ad)
        {
            ad = new AudioData();

            using (var br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {
                var reader = new WavRWLib2.WavReader();
                if (!reader.ReadHeaderAndSamples(br, 0, -1))
                {
                    MessageBox.Show(
                        string.Format("Error: Failed to read WAV file: {0}", path));
                    return(-1);
                }

                ad.meta              = new WWFlacRWCS.Metadata();
                ad.meta.albumStr     = reader.AlbumName;
                ad.meta.artistStr    = reader.ArtistName;
                ad.meta.titleStr     = reader.Title;
                ad.meta.pictureBytes = reader.PictureBytes;
                ad.picture           = reader.PictureData;
                ad.meta.totalSamples = reader.NumFrames;
                ad.meta.channels     = reader.NumChannels;
                ad.meta.sampleRate   = reader.SampleRate;

                var interleaved    = reader.GetSampleLargeArray();
                int bytesPerSample = reader.BitsPerSample / 8;

                ad.pcm = new List <AudioDataPerChannel>();
                for (int ch = 0; ch < reader.NumChannels; ++ch)
                {
                    var pcmOneChannel = new WWUtil.LargeArray <byte>(reader.NumFrames * bytesPerSample);
                    for (long i = 0; i < reader.NumFrames; ++i)
                    {
                        for (int b = 0; b < reader.BitsPerSample / 8; ++b)
                        {
                            pcmOneChannel.Set(bytesPerSample * i + b,
                                              interleaved.At(bytesPerSample * (reader.NumChannels * i + ch) + b));
                        }
                    }

#if true
                    var adp = new AudioDataPerChannel();
                    adp.mData                    = pcmOneChannel;
                    adp.mOffsBytes               = 0;
                    adp.mBitsPerSample           = reader.BitsPerSample;
                    adp.mValueRepresentationType = reader.SampleValueRepresentationType;
#else
                    var pcm32 = PcmDataLib.PcmDataUtil.ConvertTo32bitInt(reader.BitsPerSample, reader.NumFrames,
                                                                         reader.SampleValueRepresentationType, pcmOneChannel);

                    var adp = new AudioDataPerChannel();
                    adp.mData                    = pcm32;
                    adp.mOffsBytes               = 0;
                    adp.mBitsPerSample           = 32;
                    adp.mValueRepresentationType = PcmDataLib.PcmData.ValueRepresentationType.SInt;
#endif
                    adp.mTotalSamples = ad.meta.totalSamples;
                    ad.pcm.Add(adp);
                }

                ad.meta.bitsPerSample  = reader.BitsPerSample;
                ad.preferredSaveFormat = WWAFUtil.FileFormatType.FLAC;
                if (24 < ad.meta.bitsPerSample)
                {
                    ad.preferredSaveFormat = WWAFUtil.FileFormatType.WAVE;
                }
                return(0);
            }
        }
示例#2
0
        public static int WriteWavFile(ref AudioData ad, string path)
        {
            int rv = 0;

            int audioFormat = ValueRepresentationToAudioFormat(ad.writeValueRepresentation);

            using (var bw = new BinaryWriter(File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Write))) {
                bool bRf64 = (2000 * 1000 * 1000 < ad.meta.PcmBytes);
                if (bRf64)
                {
                    // RF64形式で保存する。
                    WavRWLib2.WavWriter.WriteRF64Header(bw, ad.meta.channels, ad.meta.bitsPerSample, audioFormat, ad.meta.sampleRate, ad.meta.totalSamples);
                    int padBytes = ((ad.meta.PcmBytes & 1) == 1) ? 1 : 0;

                    int bytesPerSample = ad.meta.bitsPerSample / 8;
                    var buff           = new byte[bytesPerSample];

                    for (long i = 0; i < ad.meta.totalSamples; ++i)
                    {
                        for (int ch = 0; ch < ad.meta.channels; ++ch)
                        {
                            var from = ad.pcm[ch].mData;
                            for (int b = 0; b < bytesPerSample; ++b)
                            {
                                buff[b] = from.At(i * bytesPerSample + b);
                            }
                            bw.Write(buff);
                        }
                    }

                    if (1 == padBytes)
                    {
                        // チャンクの終わりが偶数になるようにパッドを入れる。
                        byte zero = 0;
                        bw.Write(zero);
                    }
                }
                else
                {
                    var sampleArray = new byte[ad.meta.PcmBytes];

                    int bytesPerSample = ad.meta.bitsPerSample / 8;
                    int toPos          = 0;
                    for (int i = 0; i < ad.meta.totalSamples; ++i)
                    {
                        for (int ch = 0; ch < ad.meta.channels; ++ch)
                        {
                            var from = ad.pcm[ch].mData;
                            for (int b = 0; b < bytesPerSample; ++b)
                            {
                                sampleArray[toPos++] = from.At(i * bytesPerSample + b);
                            }
                        }
                    }

                    WavRWLib2.WavWriter.Write(bw, ad.meta.channels, ad.meta.bitsPerSample, audioFormat,
                                              ad.meta.sampleRate, ad.meta.totalSamples, sampleArray);
                }
            }

            return(rv);
        }
示例#3
0
        public static int ReadDsfFile(string path, out AudioData ad)
        {
            ad = new AudioData();

            using (var br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {
                var reader = new WWDsfRW.WWDsfReader();

                PcmDataLib.PcmData header;
                var readResult = reader.ReadHeader(br, out header);
                if (readResult != WWDsfRW.WWDsfReader.ResultType.Success)
                {
                    MessageBox.Show(string.Format("Error: Failed to read DSF file: {0} {1}", path, readResult));
                    return(-1);
                }

                // DoP DSDデータとしての形式が出てくる。
                ad.meta              = new WWFlacRWCS.Metadata();
                ad.meta.albumStr     = reader.AlbumName;
                ad.meta.artistStr    = reader.ArtistName;
                ad.meta.titleStr     = reader.TitleName;
                ad.meta.pictureBytes = reader.PictureBytes;
                ad.picture           = reader.PictureData;
                ad.meta.totalSamples = reader.OutputFrames; // PCMのフレーム数が出る。
                ad.meta.channels     = reader.NumChannels;
                ad.meta.sampleRate   = reader.SampleRate;   // DSDレートが出る。
            }

            using (var br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {
                var reader = new WWDsfRW.WWDsfReader();

                PcmDataLib.PcmData pcm;
                reader.ReadStreamBegin(br, out pcm);

                var sampleData = new WWUtil.LargeArray <byte> [ad.meta.channels];

                for (int ch = 0; ch < ad.meta.channels; ++ch)
                {
                    // 24bit == 3bytes per channelのDoPから
                    // 16bitを抽出するので、1サンプルあたり2バイト。
                    sampleData[ch] = new WWUtil.LargeArray <byte>(ad.meta.totalSamples * 2);
                }

                const int FRAGMENT_SAMPLES = 1048576;

                // 1チャンネル、1サンプルあたり2バイト入っている。
                for (long sample = 0; sample < ad.meta.totalSamples; sample += FRAGMENT_SAMPLES)
                {
                    // DoPのフレームが出てくる。リトルエンディアン、3バイトのうち下位2バイトがDSDデータ。

                    int fragmentSamples = FRAGMENT_SAMPLES;
                    if (ad.meta.totalSamples < sample + FRAGMENT_SAMPLES)
                    {
                        fragmentSamples = (int)(ad.meta.totalSamples - sample);
                    }

                    var buff = reader.ReadStreamReadOne(br, fragmentSamples);

                    // ここで全チャンネルがインターリーブされた、1サンプル3バイトのデータが出てくる。
                    // 3バイト目はマーカーバイト。
                    for (int i = 0; i < fragmentSamples; ++i)
                    {
                        for (int ch = 0; ch < ad.meta.channels; ++ch)
                        {
                            // DoPデータはデータがビッグエンディアン詰めされている。
                            // ここでバイトオーダーを入れ替えて、1バイトごとに読めば順にデータが出てくるようにする。
                            // 1バイト内のビットの並びはMSBから古い順にデータが詰まっている。
                            sampleData[ch].Set((sample + i) * 2 + 0, buff[(ad.meta.channels * i + ch) * 3 + 1]);
                            sampleData[ch].Set((sample + i) * 2 + 1, buff[(ad.meta.channels * i + ch) * 3 + 0]);
                        }
                    }
                }

                // DSDデータとして書き込む。
                ad.meta.totalSamples  *= 16;
                ad.meta.bitsPerSample  = 1;
                ad.preferredSaveFormat = WWAFUtil.FileFormatType.DSF;
                ad.pcm = new List <AudioDataPerChannel>();

                // AudioDataPerChannelには本当のサンプル数、量子化ビット数をセットする。
                for (int ch = 0; ch < ad.meta.channels; ++ch)
                {
                    var adp = new AudioDataPerChannel();
                    adp.mData                    = sampleData[ch];
                    adp.mOffsBytes               = 0;
                    adp.mBitsPerSample           = 1;
                    adp.mValueRepresentationType = PcmDataLib.PcmData.ValueRepresentationType.SInt;
                    adp.mTotalSamples            = ad.meta.totalSamples;
                    adp.mDataFormat              = AudioDataPerChannel.DataFormat.Sdm1bit;
                    ad.pcm.Add(adp);
                }
            }

            return(0);
        }
示例#4
0
        public static int ReadFlacFile(string path, out AudioData ad)
        {
            ad = new AudioData();

            var flac = new WWFlacRWCS.FlacRW();
            int rv   = flac.DecodeAll(path);

            if (rv < 0)
            {
                MessageBox.Show(
                    string.Format("Error: Failed to read FLAC file: {0}", path));
                return(rv);
            }

            rv = flac.GetDecodedMetadata(out ad.meta);
            if (rv < 0)
            {
                return(rv);
            }

            rv = flac.GetDecodedPicture(out ad.picture, ad.meta.pictureBytes);
            if (rv < 0)
            {
                return(rv);
            }

            // ad.pcmにPCMデータを入れる。

            int bpf             = ad.meta.BytesPerFrame;
            int bps             = ad.meta.BytesPerSample;
            int fragmentSamples = 4096;
            int fragmentBytes   = fragmentSamples * bps;
            var fragment        = new byte[fragmentBytes];

            ad.pcm = new List <AudioDataPerChannel>();
            for (int ch = 0; ch < ad.meta.channels; ++ch)
            {
                // ■■■ 1チャンネル分のpcmを取り出す。■■■

                long oneChannelPcmBytes = ad.meta.totalSamples * bps;
                var  pcm = new WWUtil.LargeArray <byte>(oneChannelPcmBytes);

                for (long posS = 0; posS < ad.meta.totalSamples;)
                {
                    // copySamples : コピーするサンプル数を決定する。
                    int copySamples = fragmentSamples;
                    if (ad.meta.totalSamples < posS + fragmentSamples)
                    {
                        copySamples = (int)(ad.meta.totalSamples - posS);
                    }

                    copySamples = flac.GetPcmOfChannel(ch, posS, ref fragment, copySamples);
                    if (copySamples < 0)
                    {
                        return(copySamples);
                    }

                    // fragmentに入っているPCMデータのサイズはcopySamples * bpsバイト。
                    pcm.CopyFrom(fragment, 0, posS * bps, copySamples * bps);
                    posS += copySamples;
                }

                var pcm24 = PcmDataLib.PcmDataUtil.ConvertTo24bit(ad.meta.bitsPerSample,
                                                                  ad.meta.totalSamples, PcmDataLib.PcmData.ValueRepresentationType.SInt, pcm);

                var adp = new AudioDataPerChannel();
                adp.mDataFormat              = AudioDataPerChannel.DataFormat.Pcm;
                adp.mData                    = pcm24;
                adp.mOffsBytes               = 0;
                adp.mBitsPerSample           = 24;
                adp.mValueRepresentationType = PcmDataLib.PcmData.ValueRepresentationType.SInt;
                adp.mTotalSamples            = ad.meta.totalSamples;
                ad.pcm.Add(adp);
            }

            // converted to 24bit
            ad.meta.bitsPerSample  = 24;
            ad.preferredSaveFormat = WWAFUtil.FileFormatType.FLAC;

            flac.DecodeEnd();

            return(0);
        }
        private int SetupResultPcm(AudioData from, List <FilterBase> filters, out AudioData to,
                                   WWAFUtil.FileFormatType toFileFormat, WWAFUtil.AFSampleFormat toSampleFormat)
        {
            to = new AudioData();
            to.preferredSaveFormat = toFileFormat;

            var fmt = FilterSetup(from, 0, filters);

            if (null == fmt)
            {
                return(-1);
            }

            to.meta                     = new WWFlacRWCS.Metadata(from.meta);
            to.meta.sampleRate          = fmt.SampleRate;
            to.meta.totalSamples        = fmt.NumSamples;
            to.meta.channels            = fmt.NumChannels;
            to.writeValueRepresentation = PcmDataLib.PcmData.ValueRepresentationType.SInt;

            switch (toSampleFormat)
            {
            case WWAFUtil.AFSampleFormat.Auto:
                // auto selection.
                switch (toFileFormat)
                {
                case WWAFUtil.FileFormatType.FLAC:
                    to.meta.bitsPerSample = 24;
                    break;

                case WWAFUtil.FileFormatType.WAVE:
                    to.meta.bitsPerSample = 32;
                    break;

                case WWAFUtil.FileFormatType.DSF:
                    to.meta.bitsPerSample = 1;
                    break;
                }
                break;

            case WWAFUtil.AFSampleFormat.PcmInt16:
                to.meta.bitsPerSample = 16;
                break;

            case WWAFUtil.AFSampleFormat.PcmInt24:
                to.meta.bitsPerSample = 24;
                break;

            case WWAFUtil.AFSampleFormat.PcmInt32:
                to.meta.bitsPerSample = 32;
                break;

            case WWAFUtil.AFSampleFormat.PcmFloat32:
                to.meta.bitsPerSample       = 32;
                to.writeValueRepresentation = PcmDataLib.PcmData.ValueRepresentationType.SFloat;
                break;

            case WWAFUtil.AFSampleFormat.PcmInt64:
                to.meta.bitsPerSample = 64;
                break;

            case WWAFUtil.AFSampleFormat.PcmFloat64:
                to.meta.bitsPerSample       = 64;
                to.writeValueRepresentation = PcmDataLib.PcmData.ValueRepresentationType.SFloat;
                break;
            }

            if (from.picture != null)
            {
                to.picture = new byte[from.picture.Length];
                System.Array.Copy(from.picture, to.picture, to.picture.Length);
            }

            // allocate "to" pcm data
            to.pcm = new List <AudioDataPerChannel>();
            for (int ch = 0; ch < to.meta.channels; ++ch)
            {
                WWUtil.LargeArray <byte> data;

                // set silent sample values to output buffer
                switch (toFileFormat)
                {
                case WWAFUtil.FileFormatType.DSF:
                    data = new WWUtil.LargeArray <byte>((to.meta.totalSamples + 7) / 8);
                    for (long i = 0; i < data.LongLength; ++i)
                    {
                        data.Set(i, 0x69);
                    }
                    break;

                case WWAFUtil.FileFormatType.FLAC:
                    if (655350 < to.meta.sampleRate)
                    {
                        return((int)WWFlacRWCS.FlacErrorCode.InvalidSampleRate);
                    }
                    data = new WWUtil.LargeArray <byte>(to.meta.totalSamples * (to.meta.bitsPerSample / 8));
                    break;

                case WWAFUtil.FileFormatType.WAVE:
                    data = new WWUtil.LargeArray <byte>(to.meta.totalSamples * (to.meta.bitsPerSample / 8));
                    break;

                default:
                    System.Diagnostics.Debug.Assert(false);
                    data = null;
                    break;
                }

                var adp = new AudioDataPerChannel();
                adp.mDataFormat              = AudioDataPerChannel.DataFormat.Pcm;
                adp.mData                    = data;
                adp.mBitsPerSample           = to.meta.bitsPerSample;
                adp.mValueRepresentationType = to.writeValueRepresentation;
                adp.mTotalSamples            = to.meta.totalSamples;
                to.pcm.Add(adp);
            }
            return(0);
        }