コード例 #1
0
        /// <summary>
        /// 指定チャンネル番号のPCMデータを取り出す。
        /// DecodeAll()後に呼ぶ。
        /// </summary>
        /// <param name="copySamples">バイト換算で512MBくらいまで可能。</param>
        /// <returns>コピーされたサンプル数。</returns>
        public int GetPcmOfChannel(int ch, long posSamples, ref byte[] fragment, int copySamples)
        {
            System.Diagnostics.Debug.Assert(mDecodedMetadata != null);
            System.Diagnostics.Debug.Assert(mPcmAllBuffer != null);
            System.Diagnostics.Debug.Assert(0 <= ch && ch < mDecodedMetadata.channels);

            int bpf = mDecodedMetadata.BytesPerFrame;
            int bps = mDecodedMetadata.BytesPerSample;

            // copySamplesを決定します。
            long totalSamples = mPcmAllBuffer.LongLength / bpf;

            if (totalSamples < posSamples + copySamples)
            {
                copySamples = (int)(totalSamples - posSamples);
            }
            if (copySamples < 0)
            {
                copySamples = 0;
            }

            if (fragment.Length < copySamples * bps)
            {
                throw new ArgumentException("fragment is too small");
            }

            for (int i = 0; i < copySamples; ++i)
            {
                long fromPosBytes = (posSamples + i) * bpf + ch * bps;
                int  toPosBytes   = i * bps;
                mPcmAllBuffer.CopyTo(fromPosBytes, ref fragment, toPosBytes, bps);
            }

            return(copySamples);
        }
コード例 #2
0
        public static LargeArray <byte> ConvertTo32bitInt(
            int bitsPerSample, long numSamples,
            PcmData.ValueRepresentationType valueType, LargeArray <byte> data)
        {
            if (bitsPerSample == 32 && valueType == PcmData.ValueRepresentationType.SInt)
            {
                // すでに所望の形式。
                return(data);
            }

            var data32 = new LargeArray <byte>(numSamples * 4);

            switch (valueType)
            {
            case PcmData.ValueRepresentationType.SInt:
                switch (bitsPerSample)
                {
                case 16:
                    for (long i = 0; i < numSamples; ++i)
                    {
                        short v16 = (short)(
                            (uint)data.At(i * 2)
                            + ((uint)data.At(i * 2 + 1) << 8));
                        int v32 = v16;
                        v32 *= 65536;
                        data32.Set(i * 4 + 0, 0);
                        data32.Set(i * 4 + 1, 0);
                        data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16));
                        data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24));
                    }
                    return(data32);

                case 24:
                    for (long i = 0; i < numSamples; ++i)
                    {
                        int v32 = (int)(
                            ((uint)data.At(i * 3 + 0) << 8)
                            + ((uint)data.At(i * 3 + 1) << 16)
                            + ((uint)data.At(i * 3 + 2) << 24));
                        data32.Set(i * 4 + 0, 0);
                        data32.Set(i * 4 + 1, (byte)((v32 & 0x0000ff00) >> 8));
                        data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16));
                        data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24));
                    }
                    return(data32);

                case 32:
                    // 所望の形式。
                    System.Diagnostics.Debug.Assert(false);
                    return(null);

                case 64:
                    for (long i = 0; i < numSamples; ++i)
                    {
                        // 16.48 fixed point
                        int v32 = (int)(
                            ((uint)data.At(i * 8 + 2) << 0)
                            + ((uint)data.At(i * 8 + 3) << 8)
                            + ((uint)data.At(i * 8 + 4) << 16)
                            + ((uint)data.At(i * 8 + 5) << 24));
                        data32.Set(i * 4 + 0, (byte)((v32 & 0x000000ff) >> 0));
                        data32.Set(i * 4 + 1, (byte)((v32 & 0x0000ff00) >> 8));
                        data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16));
                        data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24));
                    }
                    return(data32);

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

            case PcmData.ValueRepresentationType.SFloat:
                for (long i = 0; i < numSamples; ++i)
                {
                    double v;
                    switch (bitsPerSample)
                    {
                    case 32: {
                        var b4 = new byte[4];
                        data.CopyTo(i * 4, ref b4, 0, 4);
                        v = BitConverter.ToSingle(b4, 0);
                    }
                    break;

                    case 64: {
                        var b8 = new byte[8];
                        data.CopyTo(i * 8, ref b8, 0, 8);
                        v = BitConverter.ToDouble(b8, 0);
                    }
                    break;

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

                    int v32 = 0;
                    if (1.0f <= v)
                    {
                        v32 = Int32.MaxValue;
                    }
                    else if (v < -1.0f)
                    {
                        v32 = Int32.MinValue;
                    }
                    else
                    {
                        long vMax = -((long)Int32.MinValue);

                        long v64 = (long)(v * vMax);
                        if (Int32.MaxValue < v64)
                        {
                            v64 = Int32.MaxValue;
                        }
                        v32 = (int)v64;
                    }

                    data32.Set(i * 4 + 0, (byte)((v32 & 0x000000ff) >> 0));
                    data32.Set(i * 4 + 1, (byte)((v32 & 0x0000ff00) >> 8));
                    data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16));
                    data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24));
                }
                return(data32);

            default:
                System.Diagnostics.Debug.Assert(false);
                return(null);
            }
        }
コード例 #3
0
        /// <summary>
        /// サンプルフォーマットがmMetadataのmPcmDataを
        /// Spatial Audio用のフォーマットにリサンプルして
        /// mResampledPcmByChannelに入れる。
        /// </summary>
        public int Resample()
        {
            int hr = 0;

            // 48000Hz 32bit floatに変換。
            var fromFmt = new WWPcmFormat(WWPcmFormat.SampleFormat.SF_Int, mMetadata.numChannels,
                                          mMetadata.bitsPerSample, mMetadata.sampleRate, DwChannelMask,
                                          mMetadata.bitsPerSample);

            var toFmt = new WWPcmFormat(WWPcmFormat.SampleFormat.SF_Float, mMetadata.numChannels,
                                        32, PlaySampleRate, DwChannelMask,
                                        32);

            var toBufList = new List <byte[]>();

            using (var resampler = new WWMFResampler()) {
                hr = resampler.Init(fromFmt, toFmt, RESAMPLE_QUALITY);
                if (hr < 0)
                {
                    return(hr);
                }

                long inPos   = 0;
                int  inBytes = 1024 * 1024 * fromFmt.FrameBytes;
                var  inBuf   = new byte[inBytes];
                do
                {
                    // 少しずつ変換。
                    if (mPcmData.LongLength < inPos + inBytes)
                    {
                        inBytes = (int)(mPcmData.LongLength - inPos);
                        inBuf   = new byte[inBytes];
                    }

                    mPcmData.CopyTo(inPos, ref inBuf, 0, inBytes);
                    inPos += inBytes;

                    byte[] outBuf;
                    hr = resampler.Resample(inBuf, out outBuf);
                    if (hr < 0)
                    {
                        return(hr);
                    }

                    if (0 < outBuf.Length)
                    {
                        toBufList.Add(outBuf);
                    }
                    outBuf = null;
                } while (inPos < mPcmData.LongLength);
                inBuf = null;

                {
                    byte[] outBuf;
                    hr = resampler.Drain(out outBuf);
                    if (hr < 0)
                    {
                        return(hr);
                    }

                    if (0 < outBuf.Length)
                    {
                        toBufList.Add(outBuf);
                    }
                    outBuf = null;
                }
            }

            // 整列する。
            long totalBytes = 0;

            foreach (var item in toBufList)
            {
                totalBytes += item.Length;
            }

            var fullPcm = WWUtil.ListUtils <byte> .GetLargeArrayFragment(toBufList, 0, totalBytes);

            toBufList.Clear();
            toBufList = null;

            // fullPcmからチャンネルごとのfloatデータを取得し、
            // mResampledPcmByChannelに入れる。
            mResampledPcmByChannel.Clear();

            int  sampleBytes = toFmt.bits / 8;
            int  nCh         = toFmt.nChannels;
            long numFrames   = totalBytes / (sampleBytes * nCh);

            for (int ch = 0; ch < nCh; ++ch)
            {
                var buf = new LargeArray <float>(numFrames);
                mResampledPcmByChannel.Add(buf);
            }

            {
                var buf4 = new byte[4];
                var f1   = new float[1];
                for (long b = 0; b < numFrames; ++b)
                {
                    for (int ch = 0; ch < nCh; ++ch)
                    {
                        fullPcm.CopyTo(sampleBytes * (nCh * b + ch), ref buf4, 0, 4);
                        var bufCh = mResampledPcmByChannel[ch];
                        f1[0] = BitConverter.ToSingle(buf4, 0);
                        bufCh.CopyFrom(f1, 0, b, 1);
                    }
                }
            }
            return(hr);
        }