Ejemplo n.º 1
0
        public PcmData MonoToStereo()
        {
            System.Diagnostics.Debug.Assert(NumChannels == 1);

            // サンプルあたりビット数が8の倍数でないとこのアルゴリズムは使えない
            System.Diagnostics.Debug.Assert((BitsPerSample & 7) == 0);

            var newSampleArray = new WWUtil.LargeArray <byte>(mSampleLargeArray.LongLength * 2);

            {
                int bytesPerSample = BitsPerSample / 8;

                // sampleArrayのフレーム数はこれよりも少ないことがある。
                // 実際に存在するサンプル数sampleFramesだけ処理する。
                long sampleFrames = mSampleLargeArray.LongLength / bytesPerSample; // NumChannels==1なので。
                long fromPosBytes = 0;
                for (long frame = 0; frame < sampleFrames; ++frame)
                {
                    for (int offs = 0; offs < bytesPerSample; ++offs)
                    {
                        byte b = mSampleLargeArray.At(fromPosBytes + offs);
                        newSampleArray.Set(fromPosBytes * 2 + offs, b);
                        newSampleArray.Set(fromPosBytes * 2 + bytesPerSample + offs, b);
                    }
                    fromPosBytes += bytesPerSample;
                }
            }
            PcmData newPcmData = new PcmData();

            newPcmData.CopyHeaderInfoFrom(this);
            newPcmData.SetFormat(2, BitsPerSample, ValidBitsPerSample, SampleRate, SampleValueRepresentationType, NumFrames);
            newPcmData.SetSampleLargeArray(newSampleArray);

            return(newPcmData);
        }
Ejemplo n.º 2
0
 public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcm)
 {
     WWUtil.LargeArray <double> outPcm = new WWUtil.LargeArray <double>(inPcm.LongLength);
     for (long i = 0; i < outPcm.LongLength; ++i)
     {
         outPcm.Set(i, inPcm.At(inPcm.LongLength - i - 1));
     }
     return(outPcm);
 }
        public WWUtil.LargeArray <double> GetPcmInDoubleSdm1bit(long longCount)
        {
            // サンプル数 / 8 == バイト数。
            var result = new WWUtil.LargeArray <double>(longCount);

            if (mTotalSamples / 8 <= mOffsBytes || longCount == 0)
            {
                // 完全に範囲外の時。
                int writePos = 0;
                for (long i = 0; i < (longCount + 7) / 8; ++i)
                {
                    byte b = 0x69; // DSD silence

                    // 1バイト内のビットの並びはMSBから古い順にデータが詰まっている。
                    for (int bit = 7; 0 <= bit; --bit)
                    {
                        if (longCount <= writePos)
                        {
                            break;
                        }
                        result.Set(writePos++, ((b >> bit) & 1) == 1 ? 1.0 : -1.0);
                    }
                }

                return(result);
            }
            else
            {
                long copySamples = longCount;
                if (mTotalSamples < mOffsBytes * 8 + copySamples)
                {
                    copySamples = mTotalSamples - mOffsBytes * 8;
                }

                long toPos = 0;
                for (long remain = copySamples; 0 < remain;)
                {
                    int fragmentCount = WWUtil.LargeArray <byte> .ARRAY_FRAGMENT_LENGTH_NUM;
                    if (remain < fragmentCount)
                    {
                        fragmentCount = (int)remain;
                    }

                    var fragment = GetPcmInDoubleSdm1bit(fragmentCount);
                    result.CopyFrom(fragment, 0, toPos, fragmentCount);
                    fragment = null;

                    toPos  += fragmentCount;
                    remain -= fragmentCount;
                }

                return(result);
            }
        }
Ejemplo n.º 4
0
        private void SetupCoeffs() {
            var window = WWMath.WWWindowFunc.BlackmanWindow(UpsampledWindowLen);

            // ループ処理を簡単にするため最初と最後に0を置く。
            mCoeffs = new WWUtil.LargeArray<double>(1 + UpsampledWindowLen + 1);
            long center = UpsampledWindowLen / 2;

            for (long i = 0; i < UpsampledWindowLen / 2 + 1; ++i) {
                long numerator = i;
                int denominator = Factor;
                int numeratorReminder = (int)(numerator % (denominator*2));
                if (numerator == 0) {
                    mCoeffs.Set(1 + center + i, 1.0f);
                } else if (numerator % denominator == 0) {
                    // sinc(180 deg) == 0, sinc(360 deg) == 0, ...
                    mCoeffs.Set(1 + center + i, 0.0f);
                } else {
                    mCoeffs.Set(1 + center + i, Math.Sin(Math.PI * numeratorReminder / denominator)
                        / (Math.PI * numerator / denominator)
                        * window.At(center + i));
                }
                mCoeffs.Set(1 + center - i, mCoeffs.At(1 + center + i));
            }
        }
Ejemplo n.º 5
0
        Add(WWUtil.LargeArray <double> a, WWUtil.LargeArray <double> b)
        {
            if (a.LongLength != b.LongLength)
            {
                return(null);
            }

            var result = new WWUtil.LargeArray <double>(a.LongLength);

            for (long i = 0; i < a.LongLength; ++i)
            {
                result.Set(i, a.At(i) + b.At(i));
            }

            return(result);
        }
Ejemplo n.º 6
0
        Mul(WWUtil.LargeArray <WWComplex> a, WWUtil.LargeArray <WWComplex> b)
        {
            if (a.LongLength != b.LongLength)
            {
                return(null);
            }

            var result = new WWUtil.LargeArray <WWComplex>(a.LongLength);

            for (long i = 0; i < a.LongLength; ++i)
            {
                var t = a.At(i);
                result.Set(i, WWComplex.Mul(t, b.At(i)));
            }

            return(result);
        }
Ejemplo n.º 7
0
        private WWUtil.LargeArray <double> FFTFir(WWUtil.LargeArray <double> inPcm,
                                                  double[] coef, long fftLength)
        {
            var fft    = new WWMath.WWRadix2FftLargeArray(fftLength);
            var inTime = new WWUtil.LargeArray <WWComplex>(fftLength);

            for (long i = 0; i < mNumSamples; ++i)
            {
                inTime.Set(i, new WWComplex(inPcm.At(i), 0));
            }

            var inFreq = fft.ForwardFft(inTime);

            inTime = null;

            var coefTime = new WWUtil.LargeArray <WWComplex>(fftLength);

            for (long i = 0; i < mCoeffs[mChannelId * 2].Length; ++i)
            {
                coefTime.Set(i, new WWComplex(coef[i], 0));
            }

            var coefFreq = fft.ForwardFft(coefTime);

            coefTime = null;

            var mulFreq = Mul(inFreq, coefFreq);

            inFreq   = null;
            coefFreq = null;

            var mulTime = fft.InverseFft(mulFreq);

            mulFreq = null;

            var result = new WWUtil.LargeArray <double>(inPcm.LongLength);

            for (int i = 0; i < inPcm.LongLength; ++i)
            {
                result.Set(i, mulTime.At(i).real);
            }
            mulTime = null;

            return(result);
        }
Ejemplo n.º 8
0
        public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcm)
        {
            // この処理で出力するチャンネルはmChannelId
            // inPcmは使用しない。

            double maxMagnitude = SearchMaxMagnitude();
            double gain         = Magnitude / maxMagnitude;

            var s = mPcmAllChannels[mChannelId];

            var result = new WWUtil.LargeArray <double>(mNumSamples);

            for (long i = 0; i < mNumSamples; ++i)
            {
                result.Set(i, s.At(i) * gain);
            }

            return(result);
        }
Ejemplo n.º 9
0
        public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA)
        {
            var y = new WWUtil.LargeArray <double>(inPcmLA.LongLength);

            for (long pos = 0; pos < inPcmLA.LongLength; ++pos)
            {
                double x = inPcmLA.At(pos);

                x = mScale * x;

                foreach (var f in mF)
                {
                    x = f.Filter(x);
                }

                y.Set(pos, x);
            }

            return(y);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// サンプル値セット。フォーマットがSintの場合のみ使用可能。
        /// サンプル値は符号付32bit int値で、0x8000000 ~ 0x7fffffffの値。
        /// </summary>
        public void SetSampleValueInInt32(int ch, long pos, int val)
        {
            Debug.Assert(SampleValueRepresentationType == ValueRepresentationType.SInt);
            Debug.Assert(0 <= ch && ch < NumChannels);
            if (pos < 0 || NumFrames <= pos)
            {
                return;
            }

            long offset = pos * BitsPerFrame / 8 + ch * BitsPerSample / 8;

            switch (BitsPerSample)
            {
            case 16:
                mSampleLargeArray.Set(offset + 0, (byte)(0xff & (val >> 16)));
                mSampleLargeArray.Set(offset + 1, (byte)(0xff & (val >> 24)));
                return;

            case 24:
                mSampleLargeArray.Set(offset + 0, (byte)(0xff & (val >> 8)));
                mSampleLargeArray.Set(offset + 1, (byte)(0xff & (val >> 16)));
                mSampleLargeArray.Set(offset + 2, (byte)(0xff & (val >> 24)));
                return;

            case 32:
                switch (ValidBitsPerSample)
                {
                case 24:
                    mSampleLargeArray.Set(offset + 0, 0);
                    mSampleLargeArray.Set(offset + 1, (byte)(0xff & (val >> 8)));
                    mSampleLargeArray.Set(offset + 2, (byte)(0xff & (val >> 16)));
                    mSampleLargeArray.Set(offset + 3, (byte)(0xff & (val >> 24)));
                    return;

                case 32:
                    mSampleLargeArray.Set(offset + 0, (byte)(0xff & (val)));
                    mSampleLargeArray.Set(offset + 1, (byte)(0xff & (val >> 8)));
                    mSampleLargeArray.Set(offset + 2, (byte)(0xff & (val >> 16)));
                    mSampleLargeArray.Set(offset + 3, (byte)(0xff & (val >> 24)));
                    return;

                default:
                    System.Diagnostics.Debug.Assert(false);
                    return;
                }

            default:
                System.Diagnostics.Debug.Assert(false);
                return;
            }
        }
Ejemplo n.º 11
0
        public WWUtil.LargeArray <double> GetDoubleArray(int ch)
        {
            var r = new WWUtil.LargeArray <double>(NumFrames);

            if (SampleValueRepresentationType == ValueRepresentationType.SFloat)
            {
                switch (BitsPerSample)
                {
                case 32:
                    for (long i = 0; i < NumFrames; ++i)
                    {
                        float v = GetSampleValueInFloat(ch, i);
                        r.Set(i, v);
                    }
                    break;

                case 64:
                    for (long i = 0; i < NumFrames; ++i)
                    {
                        double v = GetSampleValueInDouble(ch, i);
                        r.Set(i, v);
                    }
                    break;

                default:
                    System.Diagnostics.Debug.Assert(false);
                    break;
                }
            }
            else
            {
                var  f        = GetSampleLargeArray();
                long readPos  = 0;
                long writePos = 0;

                switch (BitsPerSample)
                {
                case 16:
                    for (int i = 0; i < NumFrames; ++i)
                    {
                        for (int c = 0; c < NumChannels; ++c)
                        {
                            if (c == ch)
                            {
                                short v = (short)(f.At(readPos) + f.At(readPos + 1) << 8);
                                r.Set(writePos++, v / 32768.0);
                            }
                            readPos += 2;
                        }
                    }
                    break;

                case 24:
                    for (int i = 0; i < NumFrames; ++i)
                    {
                        for (int c = 0; c < NumChannels; ++c)
                        {
                            if (c == ch)
                            {
                                int v = (int)((f.At(readPos) << 8)
                                              + (f.At(readPos + 1) << 16)
                                              + (f.At(readPos + 2) << 24));
                                r.Set(writePos++, v / 2147483648.0);
                            }
                            readPos += 3;
                        }
                    }
                    break;

                case 32:
                    for (int i = 0; i < NumFrames; ++i)
                    {
                        for (int c = 0; c < NumChannels; ++c)
                        {
                            if (c == ch)
                            {
                                int v = (int)((f.At(readPos) << 0)
                                              + (f.At(readPos + 1) << 8)
                                              + (f.At(readPos + 2) << 16)
                                              + (f.At(readPos + 3) << 24));
                                r.Set(writePos++, v / 2147483648.0);
                            }
                            readPos += 4;
                        }
                    }
                    break;

                case 64:
                    // 16.48 fixed point numberを想定。
                    for (int i = 0; i < NumFrames; ++i)
                    {
                        for (int c = 0; c < NumChannels; ++c)
                        {
                            if (c == ch)
                            {
                                long v = (long)(
                                    (((long)f.At(readPos)) << 0)
                                    + ((long)(f.At(readPos + 1)) << 8)
                                    + ((long)(f.At(readPos + 2)) << 16)
                                    + ((long)(f.At(readPos + 3)) << 24)
                                    + ((long)(f.At(readPos + 4)) << 32)
                                    + ((long)(f.At(readPos + 5)) << 40)
                                    + ((long)(f.At(readPos + 6)) << 48)
                                    + ((long)(f.At(readPos + 7)) << 56)
                                    );
                                r.Set(writePos++, v / 65536.0 / 65536.0 / 65536.0);
                            }
                            readPos += 8;
                        }
                    }
                    break;

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

            return(r);
        }
Ejemplo n.º 12
0
        public PcmData ConvertChannelCount(int newCh)
        {
            if (NumChannels == newCh)
            {
                // 既に希望のチャンネル数である。
                return(this);
            }

            // サンプルあたりビット数が8の倍数でないとこのアルゴリズムは使えない
            System.Diagnostics.Debug.Assert((BitsPerSample & 7) == 0);

            // 新しいサンプルサイズ
            // NumFramesは総フレーム数。sampleArrayのフレーム数はこれよりも少ないことがある。
            // 実際に存在するサンプル数sampleFramesだけ処理する。
            int  bytesPerSample = BitsPerSample / 8;
            long sampleFrames   = mSampleLargeArray.LongLength / (BitsPerFrame / 8);
            var  newSampleArray = new WWUtil.LargeArray <byte>((long)newCh * bytesPerSample * sampleFrames);

            for (long frame = 0; frame < sampleFrames; ++frame)
            {
                int copyBytes = NumChannels * bytesPerSample;
                if (newCh < NumChannels)
                {
                    // チャンネル数が減る場合。
                    copyBytes = newCh * bytesPerSample;
                }

                newSampleArray.CopyFrom(mSampleLargeArray, (long)NumChannels * bytesPerSample * frame,
                                        (long)newCh * bytesPerSample * frame, copyBytes);

                if (SampleDataType == DataType.DoP &&
                    NumChannels < newCh)
                {
                    // 追加したチャンネルにDSD無音をセットする。
                    switch (bytesPerSample)
                    {
                    case 3:
                        for (int ch = NumChannels; ch < newCh; ++ch)
                        {
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 0, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 1, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 2, (byte)((frame & 1) == 1 ? 0xfa : 0x05));
                        }
                        break;

                    case 4:
                        for (int ch = NumChannels; ch < newCh; ++ch)
                        {
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 1, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 2, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 3, (byte)((frame & 1) == 1 ? 0xfa : 0x05));
                        }
                        break;
                    }
                }
            }

            PcmData newPcmData = new PcmData();

            newPcmData.CopyHeaderInfoFrom(this);
            newPcmData.SetFormat(newCh, BitsPerSample, ValidBitsPerSample, SampleRate, SampleValueRepresentationType, NumFrames);
            newPcmData.SetSampleLargeArray(newSampleArray);

            return(newPcmData);
        }
Ejemplo n.º 13
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);
            }
        }
Ejemplo n.º 14
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);
        }
        /// <param name="pcm">コピー元データ。先頭から全要素コピーする。</param>
        /// <param name="writePos">コピー先(この配列)先頭要素数。</param>
        public void SetPcmInDouble(double[] pcm, long writePos)
        {
            if (mBitsPerSample == 1 && 0 != (writePos & 7))
            {
                throw new ArgumentException("writeOffs must be multiple of 8");
            }

            int copyCount = pcm.Length;

            if (mTotalSamples < writePos + copyCount)
            {
                copyCount = (int)(mTotalSamples - writePos);
            }

            long writePosBytes;

            switch (mBitsPerSample)
            {
            case 1: {
                long readPos = 0;

                // set 1bit data (from LSB to MSB) into 8bit buffer
                writePosBytes = writePos / 8;
                for (long i = 0; i < copyCount / 8; ++i)
                {
                    byte sampleValue = 0;
                    for (int subPos = 0; subPos < 8; ++subPos)
                    {
                        byte bit = (0 <= pcm[readPos]) ? (byte)(1 << subPos) : (byte)0;
                        sampleValue |= bit;

                        ++readPos;
                    }
                    mData.Set(writePosBytes, sampleValue);
                    ++writePosBytes;
                }
            }
            break;

            case 16:
                writePosBytes = writePos * 2;
                for (long i = 0; i < copyCount; ++i)
                {
                    short  vS = 0;
                    double vD = pcm[i];
                    if (vD < -1.0f)
                    {
                        vS = -32768;

                        mOverflow = true;
                        if (mMaxMagnitude < Math.Abs(vD))
                        {
                            mMaxMagnitude = Math.Abs(vD);
                        }
                    }
                    else if (1.0f <= vD)
                    {
                        vS = 32767;

                        mOverflow = true;
                        if (mMaxMagnitude < Math.Abs(vD))
                        {
                            mMaxMagnitude = Math.Abs(vD);
                        }
                    }
                    else
                    {
                        vS = (short)(32768.0 * vD);
                    }

                    mData.Set(writePosBytes + 0, (byte)((vS) & 0xff));
                    mData.Set(writePosBytes + 1, (byte)((vS >> 8) & 0xff));

                    writePosBytes += 2;
                }
                break;

            case 24:
                writePosBytes = writePos * 3;
                for (long i = 0; i < copyCount; ++i)
                {
                    int    vI = 0;
                    double vD = pcm[i];
                    if (vD < -1.0f)
                    {
                        vI = Int32.MinValue;

                        mOverflow = true;
                        if (mMaxMagnitude < Math.Abs(vD))
                        {
                            mMaxMagnitude = Math.Abs(vD);
                        }
                    }
                    else if (1.0f <= vD)
                    {
                        vI = 0x7fffff00;

                        mOverflow = true;
                        if (mMaxMagnitude < Math.Abs(vD))
                        {
                            mMaxMagnitude = Math.Abs(vD);
                        }
                    }
                    else
                    {
                        vI = (int)(2147483648.0 * vD);
                    }

                    mData.Set(writePosBytes + 0, (byte)((vI >> 8) & 0xff));
                    mData.Set(writePosBytes + 1, (byte)((vI >> 16) & 0xff));
                    mData.Set(writePosBytes + 2, (byte)((vI >> 24) & 0xff));

                    writePosBytes += 3;
                }
                break;

            case 32:
                switch (mValueRepresentationType)
                {
                case PcmData.ValueRepresentationType.SInt:
                    // 32bit int.
                    writePosBytes = writePos * 4;
                    for (long i = 0; i < copyCount; ++i)
                    {
                        int    vI = 0;
                        double vD = pcm[i];
                        if (vD < -1.0f)
                        {
                            vI = Int32.MinValue;

                            mOverflow = true;
                            if (mMaxMagnitude < Math.Abs(vD))
                            {
                                mMaxMagnitude = Math.Abs(vD);
                            }
                        }
                        else if (1.0f <= vD)
                        {
                            vI = 0x7fffffff;

                            mOverflow = true;
                            if (mMaxMagnitude < Math.Abs(vD))
                            {
                                mMaxMagnitude = Math.Abs(vD);
                            }
                        }
                        else
                        {
                            vI = (int)(2147483648.0 * vD);
                        }

                        mData.Set(writePosBytes + 0, (byte)((vI >> 0) & 0xff));
                        mData.Set(writePosBytes + 1, (byte)((vI >> 8) & 0xff));
                        mData.Set(writePosBytes + 2, (byte)((vI >> 16) & 0xff));
                        mData.Set(writePosBytes + 3, (byte)((vI >> 24) & 0xff));

                        writePosBytes += 4;
                    }
                    break;

                case PcmData.ValueRepresentationType.SFloat:
                    // 32bit Float.
                    writePosBytes = writePos * 4;
                    for (long i = 0; i < copyCount; ++i)
                    {
                        double vD = pcm[i];
                        float  vF = (float)vD;
                        var    b4 = BitConverter.GetBytes(vF);
                        for (int j = 0; j < 4; ++j)
                        {
                            mData.Set(writePosBytes + j, b4[j]);
                        }
                        writePosBytes += 4;
                    }
                    break;
                }
                break;

            case 64:
                switch (mValueRepresentationType)
                {
                case PcmData.ValueRepresentationType.SInt:
                    //64bit int.
                    writePosBytes = writePos * 8;
                    for (long i = 0; i < copyCount; ++i)
                    {
                        long   vI = 0;
                        double vD = pcm[i];
                        // 16:48 fixed point number
                        if (vD < -32768.0)
                        {
                            vI = long.MinValue;

                            mOverflow = true;
                            if (mMaxMagnitude < Math.Abs(vD))
                            {
                                mMaxMagnitude = Math.Abs(vD);
                            }
                        }
                        else if (32768.0 <= vD)
                        {
                            vI = long.MaxValue;

                            mOverflow = true;
                            if (mMaxMagnitude < Math.Abs(vD))
                            {
                                mMaxMagnitude = Math.Abs(vD);
                            }
                        }
                        else
                        {
                            vI = (long)(65536.0 * 65536.0 * 65536.0 * vD);
                        }

                        for (int j = 0; j < 8; ++j)
                        {
                            mData.Set(writePosBytes + j, (byte)((vI >> (j * 8)) & 0xff));
                        }

                        writePosBytes += 8;
                    }
                    break;

                case PcmData.ValueRepresentationType.SFloat:
                    // 64bit float.
                    writePosBytes = writePos * 8;
                    for (long i = 0; i < copyCount; ++i)
                    {
                        double vD = pcm[i];
                        var    b8 = BitConverter.GetBytes(vD);
                        for (int j = 0; j < 8; ++j)
                        {
                            mData.Set(writePosBytes + j, b8[j]);
                        }
                        writePosBytes += 8;
                    }
                    break;
                }
                break;

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