Пример #1
0
        /// <summary>
        /// FLACファイルからPCMデータを取り出し開始。
        /// </summary>
        /// <param name="flacFilePath">読み込むファイルパス。</param>
        /// <param name="skipFrames">ファイルの先頭からのスキップするフレーム数。0以外の値を指定するとMD5のチェックが行われなくなる。</param>
        /// <param name="pcmData">出てきたデコード後のPCMデータ。</param>
        /// <returns>0: 成功。負: 失敗。</returns>
        public int ReadStreamBegin(string flacFilePath, long skipFrames,
                                   out PcmDataLib.PcmData pcmData_return)
        {
            pcmData_return = new PcmDataLib.PcmData();
            mFlacRW        = new WWFlacRWCS.FlacRW();

            // ここでファイルをオープンし、メタデータ部分を読み込んで
            // ストリームデータの頭のところでFLACデコードを止める。
            int ercd = mFlacRW.DecodeStreamStart(flacFilePath);

            if (ercd < 0)
            {
                return(ercd);
            }

            CreatePcmData(flacFilePath, mFlacRW, out pcmData_return);

            mNumFrames     = pcmData_return.NumFrames;
            mBytesPerFrame = pcmData_return.BitsPerFrame / 8;

            // ストリームデータを頭出しする。
            if (0 < skipFrames)
            {
                mFlacRW.DecodeStreamSeekAbsolute(skipFrames);
            }

            if (CalcMD5 && skipFrames == 0)
            {
                md5           = new MD5CryptoServiceProvider();
                mMD5SumOfPcm  = new byte[MD5_BYTES];
                mMD5TmpBuffer = new byte[WWFlacRWCS.FlacRW.PCM_FRAGMENT_BUFFER_BYTES];
            }

            return(0);
        }
Пример #2
0
 public void LoadAddEnd(ContentList.AudioFile af)
 {
     SetSampleDataToWasapiEnd(af.Idx, mFlac);
     mLoadedGroupId = af.GroupId;
     mFlac.DecodeEnd();
     mFlac = null;
 }
Пример #3
0
 public void Setup(WWFlacRWCS.Metadata metaW, byte[] picture)
 {
     mFlacW = new WWFlacRWCS.FlacRW();
     mFlacW.EncodeInit(metaW);
     if (picture != null)
     {
         mFlacW.EncodeSetPicture(picture);
     }
 }
Пример #4
0
        public void ReadStreamAbort()
        {
            mFlacRW.DecodeEnd();
            mFlacRW = null;

            if (md5 != null)
            {
                md5.Dispose();
                md5           = null;
                mMD5TmpBuffer = null;
            }
        }
Пример #5
0
        private static int ReadFlacFile(string path, out AudioData ad)
        {
            ad = new AudioData();

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

            if (rv < 0)
            {
                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 = new List <AudioDataPerChannel>();
            for (int ch = 0; ch < ad.meta.channels; ++ch)
            {
                byte[] pcm;
                long   lrv = flac.GetDecodedPcmBytes(ch, 0, out pcm, ad.meta.totalSamples * (ad.meta.bitsPerSample / 8));
                if (lrv < 0)
                {
                    return((int)lrv);
                }

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

                var adp = new AudioDataPerChannel();
                adp.data          = pcm24;
                adp.offsBytes     = 0;
                adp.bitsPerSample = 24;
                adp.totalSamples  = ad.meta.totalSamples;
                ad.pcm.Add(adp);
            }

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

            flac.DecodeEnd();

            return(0);
        }
        /// <returns>負の値: FLACのエラー FlacErrorCode</returns>
        public int LoadAddStart(ContentList.AudioFile af)
        {
            mFlac = new WWFlacRWCS.FlacRW();
            int ercd = mFlac.DecodeStreamStart(af.Path);

            if (ercd < 0)
            {
                return(ercd);
            }

            SetSampleDataToWasapiStart(af.Idx, mFlac);
            return(ercd);
        }
        private void SetSampleDataToWasapiStart(int idx, WWFlacRWCS.FlacRW flac)
        {
            WWFlacRWCS.Metadata meta;
            flac.GetDecodedMetadata(out meta);

            mFromFormat = new DeviceFormat();
            mFromFormat.Set(meta.channels, meta.sampleRate,
                            WasapiCS.BitAndFormatToSampleFormatType(meta.bitsPerSample, meta.bitsPerSample, WasapiCS.BitFormatType.SInt));

            long totalBytes = meta.totalSamples * mDeviceFormat.BytesPerFrame();

            mWasapi.AddPlayPcmDataAllocateMemory(idx, totalBytes);

            mDecodedPcmOffs = 0;
        }
Пример #8
0
        private static int ReadFlacFile(string path, out AudioData ad)
        {
            ad = new AudioData();

            ad.fileFormat = FileFormatType.FLAC;

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

            if (rv < 0)
            {
                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 = new List <AudioDataPerChannel>();
            for (int ch = 0; ch < ad.meta.channels; ++ch)
            {
                byte[] data;
                long   lrv = flac.GetDecodedPcmBytes(ch, 0, out data, ad.meta.totalSamples * (ad.meta.bitsPerSample / 8));
                if (lrv < 0)
                {
                    return((int)lrv);
                }

                var adp = new AudioDataPerChannel();
                adp.data          = data;
                adp.offsBytes     = 0;
                adp.bitsPerSample = ad.meta.bitsPerSample;
                adp.totalSamples  = ad.meta.totalSamples;
                ad.pcm.Add(adp);
            }

            flac.DecodeEnd();

            return(0);
        }
Пример #9
0
        public int ReadEnd()
        {
            mFlacRW.DecodeEnd();
            mFlacRW = null;

            if (md5 != null)
            {
                md5.TransformFinalBlock(new byte[0], 0, 0);
                mMD5SumOfPcm = md5.Hash;
                md5.Dispose();
                md5           = null;
                mMD5TmpBuffer = null;
            }

            return(0);
        }
Пример #10
0
        /// <returns>負の値: FLACのエラー FlacErrorCode</returns>
        public int LoadAddStart(ContentList.AudioFile af)
        {
            mFlac = new WWFlacRWCS.FlacRW();
            int ercd = mFlac.DecodeStreamStart(af.Path);

            if (ercd < 0)
            {
                return(ercd);
            }

            int hr = SetSampleDataToWasapiStart(af.Idx, mFlac);

            if (hr < 0)
            {
                ercd = (int)WWFlacRWCS.FlacErrorCode.Other;
            }
            return(ercd);
        }
Пример #11
0
        private int SetSampleDataToWasapiStart(int idx, WWFlacRWCS.FlacRW flac)
        {
            int hr = 0;

            mDecodedPcmOffs = 0;

            WWFlacRWCS.Metadata meta;
            flac.GetDecodedMetadata(out meta);

            mFromFormat = new DeviceFormat();
            mFromFormat.Set(meta.channels, meta.sampleRate,
                            WasapiCS.BitAndFormatToSampleFormatType(
                                meta.bitsPerSample, meta.bitsPerSample, WasapiCS.BitFormatType.SInt),
                            WasapiCS.GetTypicalChannelMask(meta.channels));

            if (WasapiCS.ShareMode.Exclusive == mShareMode)
            {
                // 排他モードの時。サンプルレート変換しないので
                // サンプル数がFromと同じ。
                long totalBytes = meta.totalSamples * mDeviceFormat.BytesPerFrame();
                mWasapi.AddPlayPcmDataAllocateMemory(idx, totalBytes);
            }
            else
            {
                // 共有モードの時。サンプルレート変換する。
                long totalBytes = (meta.totalSamples * mDeviceFormat.SampleRate / mFromFormat.SampleRate) * mDeviceFormat.BytesPerFrame();
                mWasapi.AddPlayPcmDataAllocateMemory(idx, totalBytes);

                var resampleFrom = new WWMFResamplerCs.WWPcmFormat(WWMFResamplerCs.WWPcmFormat.SampleFormat.SF_Int,
                                                                   mFromFormat.NumChannels, mFromFormat.UseBitsPerSample(), mFromFormat.SampleRate,
                                                                   WasapiCS.GetTypicalChannelMask(mFromFormat.NumChannels), mFromFormat.ValidBitsPerSample());
                var resampleTo = new WWMFResamplerCs.WWPcmFormat(WWMFResamplerCs.WWPcmFormat.SampleFormat.SF_Float,
                                                                 mDeviceFormat.NumChannels, mDeviceFormat.UseBitsPerSample(), mDeviceFormat.SampleRate,
                                                                 mDeviceFormat.DwChannelMask, mDeviceFormat.ValidBitsPerSample());
                hr = mMfResampler.Init(resampleFrom, resampleTo, 60);
                if (hr < 0)
                {
                    Console.WriteLine("mMfResampler.Init() failed {0:X8}", hr);
                }
            }

            return(hr);
        }
Пример #12
0
        private void CreatePcmData(string path, WWFlacRWCS.FlacRW flacRW,
                                   out PcmDataLib.PcmData pcmData_return)
        {
            pcmData_return = new PcmDataLib.PcmData();

            WWFlacRWCS.Metadata m;
            flacRW.GetDecodedMetadata(out m);

            pcmData_return.SetFormat(m.channels, m.bitsPerSample, m.bitsPerSample,
                                     m.sampleRate, PcmDataLib.PcmData.ValueRepresentationType.SInt,
                                     m.totalSamples);
            pcmData_return.SampleDataType = PcmDataLib.PcmData.DataType.PCM;

            pcmData_return.DisplayName  = m.titleStr;
            pcmData_return.AlbumTitle   = m.albumStr;
            pcmData_return.ArtistName   = m.artistStr;
            pcmData_return.ComposerName = m.composerStr;
            pcmData_return.FullPath     = path;

            mMD5SumInMetadata = new byte[MD5_BYTES];
            Array.Copy(m.md5sum, mMD5SumInMetadata, MD5_BYTES);

            bool allZero = true;

            for (int i = 0; i < MD5_BYTES; ++i)
            {
                if (m.md5sum[i] != 0)
                {
                    allZero = false;
                    break;
                }
            }
            md5MetaAvailable = !allZero;

            if (0 < m.pictureBytes)
            {
                byte[] picture;
                flacRW.GetDecodedPicture(out picture, m.pictureBytes);
                pcmData_return.SetPicture(picture.Length, picture);
            }
        }
Пример #13
0
        private void SetSampleDataToWasapiEnd(int idx, WWFlacRWCS.FlacRW flac)
        {
            if (WasapiCS.ShareMode.Shared == mShareMode)
            {
                // 共有モードの場合。サンプルレート変換のFIFOをドレインする。
                byte[] toBytes = new byte[0];
                int    hr      = mMfResampler.Drain(out toBytes);
                if (hr < 0)
                {
                    Console.WriteLine("mMfResampler.Drain() failed {0:X8}", hr);
                    // ここでエラーが出ても特にすることは無い。
                }
                mWasapi.AddPlayPcmDataSetPcmFragment(idx, mDecodedPcmOffs, toBytes);
                mDecodedPcmOffs += toBytes.Length;

                mMfResampler.Term();
            }


            mFromFormat     = null;
            mDecodedPcmOffs = 0;
        }
Пример #14
0
        private void InspectOneFile(string path, int numFiles)
        {
            var flacrw = new WWFlacRWCS.FlacRW();
            var result = flacrw.CheckIntegrity(path);
            int ercd   = result.rv;

            lock (mBw) {
                if (ercd < 0)
                {
                    ++mBackgroundResult.corrupted;
                }
                else
                {
                    ++mBackgroundResult.ok;
                }

                ++mFinished;

                if (result.totalSamplesUnknown)
                {
                    mSbLog.AppendLine(string.Format("FLAC Metadata total_samples field is Unknown : {0}", path));
                }

                if (ercd < 0)
                {
                    mSbLog.AppendLine(string.Format("({0}/{1}) {2} : {3}\n",
                                                    mFinished, numFiles,
                                                    WWFlacRWCS.FlacRW.ErrorCodeToStr(ercd), path));
                }
                if (UPDATE_INTERVAL_MILLISEC < (mStopwatch.ElapsedMilliseconds - mLastUpdateMillisec))
                {
                    mLastUpdateMillisec = mStopwatch.ElapsedMilliseconds;

                    mBw.ReportProgress((int)(1000000L * mFinished / numFiles),
                                       new ReportProgressArgs("", 0, true));
                }
            }
        }
Пример #15
0
        private static int WriteFlacFile(ref AudioData ad, string path)
        {
            int rv;
            var flac = new WWFlacRWCS.FlacRW();

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

            rv = flac.EncodeSetPicture(ad.picture);
            if (rv < 0)
            {
                flac.EncodeEnd();
                return(rv);
            }

            for (int ch = 0; ch < ad.meta.channels; ++ch)
            {
                long lrv = flac.EncodeAddPcm(ch, ad.pcm[ch].data);
                if (lrv < 0)
                {
                    flac.EncodeEnd();
                    return((int)lrv);
                }
            }

            rv = flac.EncodeRun(path);
            if (rv < 0)
            {
                flac.EncodeEnd();
                return(rv);
            }

            flac.EncodeEnd();
            return(0);
        }
Пример #16
0
        /// <summary>
        /// この後ReadEndを呼んで終了して下さい。
        /// </summary>
        public int ReadHeader(string flacFilePath, out PcmDataLib.PcmData pcmData_return,
                              out List <WWFlacRWCS.FlacCuesheetTrack> cueSheet_return)
        {
            pcmData_return  = new PcmDataLib.PcmData();
            cueSheet_return = new List <WWFlacRWCS.FlacCuesheetTrack>();

            mFlacRW = new WWFlacRWCS.FlacRW();
            int ercd = mFlacRW.DecodeHeader(flacFilePath);

            if (ercd < 0)
            {
                return(ercd);
            }

            mFlacRW.GetDecodedCuesheet(out cueSheet_return);

            CreatePcmData(flacFilePath, mFlacRW, out pcmData_return);

            mBytesPerFrame = pcmData_return.BitsPerFrame / 8;
            mNumFrames     = pcmData_return.NumFrames;

            return(0);
        }
Пример #17
0
        // FLACからPCMのバイト列を取得し、最大値1のdouble型のサンプル値の配列を作る。
        private double[] InputSamples(WWFlacRWCS.FlacRW flacR, WWFlacRWCS.Metadata meta,
                                      int ch, long posSamples, int nSamples)
        {
            // 1ch分のnサンプルのPCMデータ。
            int nBytes = nSamples * meta.BytesPerSample;
            var pcm    = new byte[nBytes];

            nSamples = flacR.GetPcmOfChannel(ch, posSamples, ref pcm, nSamples);
            if (nSamples <= 0)
            {
                return(new double[0]);
            }
            double[] result = new double[nSamples];
            switch (meta.bitsPerSample)
            {
            case 16:
                for (int i = 0; i < nSamples; ++i)
                {
                    short v = (short)(pcm[i * 2] + (pcm[i * 2 + 1] << 8));
                    result[i] = v / 32768.0;
                }
                break;

            case 20:
            case 24:
                for (int i = 0; i < nSamples; ++i)
                {
                    int v = (int)((pcm[i * 3] << 8) + (pcm[i * 3 + 1] << 16) + (pcm[i * 3 + 2] << 24));
                    result[i] = v / 2147483648.0;
                }
                break;

            default:
                throw new NotSupportedException();
            }
            return(result);
        }
        private static int WriteFlacFile(ref AudioData ad, string path)
        {
            int rv;
            var flac = new WWFlacRWCS.FlacRW();
            rv = flac.EncodeInit(ad.meta);
            if (rv < 0) {
                return rv;
            }

            rv = flac.EncodeSetPicture(ad.picture);
            if (rv < 0) {
                flac.EncodeEnd();
                return rv;
            }

            for (int ch=0; ch < ad.meta.channels; ++ch) {
                long lrv = flac.EncodeAddPcm(ch, ad.pcm[ch].data);
                if (lrv < 0) {
                    flac.EncodeEnd();
                    return (int)lrv;
                }
            }

            rv = flac.EncodeRun(path);
            if (rv < 0) {
                flac.EncodeEnd();
                return rv;
            }

            flac.EncodeEnd();
            return 0;
        }
        private static int ReadFlacFile(string path, out AudioData ad)
        {
            ad = new AudioData();

            ad.fileFormat = FileFormatType.FLAC;

            var flac = new WWFlacRWCS.FlacRW();
            int rv = flac.DecodeAll(path);
            if (rv < 0) {
                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 = new List<AudioDataPerChannel>();
            for (int ch=0; ch < ad.meta.channels; ++ch) {
                byte [] data;
                long lrv = flac.GetDecodedPcmBytes(ch, 0, out data, ad.meta.totalSamples * (ad.meta.bitsPerSample / 8));
                if (lrv < 0) {
                    return (int)lrv;
                }

                var adp = new AudioDataPerChannel();
                adp.data = data;
                adp.offsBytes = 0;
                adp.bitsPerSample = ad.meta.bitsPerSample;
                adp.totalSamples = ad.meta.totalSamples;
                ad.pcm.Add(adp);
            }

            flac.DecodeEnd();

            return 0;
        }
Пример #20
0
        public RunWorkerCompletedResult BackgroundDoWorkImpl(DoWorkEventArgs e, string rootPath, bool background)
        {
            mContentList.Clear();

            var result = new RunWorkerCompletedResult();

            result.fileCount = 0;
            result.path      = rootPath;

            if (background)
            {
                mBw.ReportProgress(0, new ReportProgressArgs(string.Format(Properties.Resources.LogCountingFiles, rootPath)));
            }

            var flacList = WWUtil.DirectoryUtil.CollectFilesOnFolder(rootPath, ".FLAC");

            if (background)
            {
                mBw.ReportProgress(0, new ReportProgressArgs(string.Format(Properties.Resources.LogReportCount, flacList.Length)));
            }

            if (mBw.CancellationPending)
            {
                Console.WriteLine("D: BackgroundContentListBuilder::BackgroundDoWorkImpl() canceled 1");
                e.Cancel = true;
                return(result);
            }

            int finished = 0;

            mStopWatch.Start();

            // Parallel.Forにした時はforの中に持っていく必要あり。
            if (background)
            {
                System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Lowest;
            }

            try {
                for (int i = 0; i < flacList.Length; ++i)
                {
                    if (mBw.CancellationPending)
                    {
                        Console.WriteLine("D: BackgroundContentListBuilder::BackgroundDoWorkImpl() canceled 2");
                        e.Cancel = true;
                        return(result);
                    }

                    string path   = flacList[i];
                    var    flacrw = new WWFlacRWCS.FlacRW();
                    int    ercd   = flacrw.DecodeHeader(path);
                    lock (mBw) {
                        if (0 <= ercd)
                        {
                            ++result.fileCount;
                            var m = new WWFlacRWCS.Metadata();
                            flacrw.GetDecodedMetadata(out m);
                            var pic = new byte[0];
                            if (0 < m.pictureBytes)
                            {
                                pic = new byte[m.pictureBytes];
                                flacrw.GetDecodedPicture(out pic, m.pictureBytes);
                            }
                            mContentList.Add(path, m.titleStr, 1, m.albumStr, m.artistStr, pic,
                                             m.channels, m.bitsPerSample, m.sampleRate, m.PcmBytes / (m.channels * m.bitsPerSample / 8));
                        }
                        else
                        {
                            Console.WriteLine("FLAC decode failed {0} {1}", WWFlacRWCS.FlacRW.ErrorCodeToStr(ercd), path);
                        }
                        flacrw.DecodeEnd();

                        ++finished;

                        if (1000 < mStopWatch.ElapsedMilliseconds)
                        {
                            if (background)
                            {
                                var text = string.Format(Properties.Resources.LogCreatingMusicList,
                                                         100 * finished / flacList.Length);
                                mBw.ReportProgress((int)(1000000L * finished / flacList.Length),
                                                   new ReportProgressArgs(text));
                            }

                            mStopWatch.Restart();
                        }
                    }
                }
            } catch (System.IO.IOException ex) {
                //Console.WriteLine(ex);
            } catch (System.Exception ex) {
                Console.WriteLine(ex);
            }

            mStopWatch.Stop();
            return(result);
        }
 private void SetSampleDataToWasapiEnd(int idx, WWFlacRWCS.FlacRW flac)
 {
     mFromFormat     = null;
     mDecodedPcmOffs = 0;
 }
Пример #22
0
        private void LoadPcm_DoWork(object sender, DoWorkEventArgs e)
        {
            string path = (string)e.Argument;
            var    r    = new LoadPcmResult();

            r.path    = path;
            r.result  = false;
            r.pcmData = null;

            mPlayPcmData = null;
            try {
                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) &&
                        reader.NumChannels == NUM_CHANNELS)
                    {
                        var b = reader.GetSampleLargeArray();
                        r.pcmData = new PcmDataLib.PcmData();
                        r.pcmData.SetFormat(NUM_CHANNELS, reader.BitsPerSample, reader.ValidBitsPerSample,
                                            reader.SampleRate, reader.SampleValueRepresentationType, reader.NumFrames);
                        r.pcmData.SetSampleLargeArray(b);
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine(ex);
                r.pcmData = null;
            }

            if (r.pcmData == null)
            {
                try {
                    var flacRW = new WWFlacRWCS.FlacRW();
                    int rv     = flacRW.DecodeAll(r.path);
                    if (0 <= rv)
                    {
                        WWFlacRWCS.Metadata metaData;
                        flacRW.GetDecodedMetadata(out metaData);
                        if (metaData.channels == NUM_CHANNELS)
                        {
                            var pcmBytes = new LargeArray <byte>(metaData.PcmBytes);

                            int bytesPerSample = metaData.bitsPerSample / 8;
                            var fragment       = new byte[bytesPerSample];
                            for (long pos = 0; pos < metaData.totalSamples; ++pos)
                            {
                                for (int ch = 0; ch < NUM_CHANNELS; ++ch)
                                {
                                    flacRW.GetDecodedPcmBytes(ch, pos * bytesPerSample, out fragment, bytesPerSample);
                                    pcmBytes.CopyFrom(fragment, 0, (long)bytesPerSample * (NUM_CHANNELS * pos + ch), bytesPerSample);
                                }
                            }

                            r.pcmData = new PcmDataLib.PcmData();
                            r.pcmData.SetFormat(NUM_CHANNELS, metaData.bitsPerSample, metaData.bitsPerSample,
                                                metaData.sampleRate, PcmDataLib.PcmData.ValueRepresentationType.SInt, metaData.totalSamples);
                            r.pcmData.SetSampleLargeArray(pcmBytes);
                        }
                    }
                    flacRW.DecodeEnd();
                } catch (Exception ex) {
                    Console.WriteLine(ex);
                    r.pcmData = null;
                }
            }

            if (r.pcmData != null)
            {
                r.result = true;
            }
            else
            {
                r.result = false;
            }

            e.Result = r;
        }
Пример #23
0
        private static int ReadFlacFile(string path, out AudioData ad)
        {
            ad = new AudioData();

            var flac = new WWFlacRWCS.FlacRW();
            int rv = flac.DecodeAll(path);
            if (rv < 0) {
                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 = new List<AudioDataPerChannel>();
            for (int ch = 0; ch < ad.meta.channels; ++ch) {
                byte[] pcm;
                long lrv = flac.GetDecodedPcmBytes(ch, 0, out pcm, ad.meta.totalSamples * (ad.meta.bitsPerSample / 8));
                if (lrv < 0) {
                    return (int)lrv;
                }

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

                var adp = new AudioDataPerChannel();
                adp.data = pcm24;
                adp.offsBytes = 0;
                adp.bitsPerSample = 24;
                adp.totalSamples = ad.meta.totalSamples;
                ad.pcm.Add(adp);
            }

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

            flac.DecodeEnd();

            return 0;
        }
Пример #24
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);
        }
Пример #25
0
        public BWCompletedParam DoWork(BWStartParams param, ProgressReportDelegate ReportProgress)
        {
            int rv = 0;

            var flacR = new WWFlacRWCS.FlacRW();

            do
            {
                // FLACファイルからメタデータ、画像、音声を取り出す。
                WWFlacRWCS.Metadata metaR;
                rv = flacR.DecodeAll(param.inputFile);
                if (rv < 0)
                {
                    // do-whileを抜けたところでflacR.DecodeEndする。
                    break;
                }

                flacR.GetDecodedMetadata(out metaR);

                byte[] picture = null;
                if (0 < metaR.pictureBytes)
                {
                    rv = flacR.GetDecodedPicture(out picture, metaR.pictureBytes);
                    if (rv < 0)
                    {
                        // do-whileを抜けたところでflacR.DecodeEndする。
                        break;
                    }
                }

                // flacRはまだ使用するのでここではDecodeEndしない。

                long lcm             = WWMath.Functions.LCM(metaR.sampleRate, param.targetSampleRate);
                int  upsampleScale   = (int)(lcm / metaR.sampleRate);
                int  downsampleScale = (int)(lcm / param.targetSampleRate);

                // IIRフィルターを設計。

                // ストップバンド最小周波数fs。
                double fs = metaR.sampleRate / 2 * STOPBAND_FREQ_RATIO;
                if (param.targetSampleRate / 2 * STOPBAND_FREQ_RATIO < fs)
                {
                    fs = param.targetSampleRate / 2 * STOPBAND_FREQ_RATIO;
                }

                // カットオフ周波数fc。
                double fc = CUTOFF_STOPBAND_RATIO * fs;

                mIIRFilterDesign = new IIRFilterDesign();
                mIIRFilterDesign.Design(fc, fs, lcm, param.method);

                ReportProgress(CONVERT_START_PERCENT, new BWProgressParam(State.FilterDesigned,
                                                                          string.Format("Read FLAC completed.\nSource sample rate = {0}kHz.\nTarget sample rate = {1}kHz. ratio={2}/{3}\n",
                                                                                        metaR.sampleRate / 1000.0, param.targetSampleRate / 1000.0,
                                                                                        lcm / metaR.sampleRate, lcm / param.targetSampleRate)));

                double RESAMPLE_RATIO = param.targetSampleRate / metaR.sampleRate;

                mSw.Restart();

                // 書き込み準備。
                WWFlacRWCS.Metadata metaW = new WWFlacRWCS.Metadata(metaR);
                metaW.sampleRate    = param.targetSampleRate;
                metaW.pictureBytes  = metaR.pictureBytes;
                metaW.bitsPerSample = 24;
                metaW.totalSamples  = metaR.totalSamples * upsampleScale / downsampleScale;

                if (param.isTargetPcm)
                {
                    mFlacWrite = new FlacWrite();
                    mFlacWrite.Setup(metaW, picture);
                }
                else
                {
                    mDsfWrite = new DsfWrite();
                    mDsfWrite.Setup(metaW, picture);
                }

                var  stat = new SampleValueStatistics();
                long totalSamplesOfAllChannels = metaR.totalSamples * metaR.channels;
                long processedSamples          = 0;

                // Mathematica用の設定。
                WWComplex.imaginaryUnit = "I";

                // 変換する
                for (int ch = 0; ch < metaR.channels; ++ch)
                {
                    //Parallel.For(0, metaR.channels, (int ch) => {
                    var pcmW = new WWUtil.LargeArray <byte>(metaW.totalSamples * metaW.BytesPerSample);

#if USE_ZOH_UPSAMPLE
                    // 零次ホールドのハイ落ち補償フィルター。
# if USE_CPP
                    var zohCompensation = new WWFilterCpp();
                    zohCompensation.BuildZohCompensation();
# else
                    var zohCompensation = new WWIIRFilterDesign.ZohNosdacCompensation(33);
# endif