예제 #1
0
        /// <summary>
        /// writes PCM data onto WAV file
        /// </summary>
        public bool Write(BinaryWriter bw,
                          int numChannels,
                          int bitsPerSample,
                          int validBitsPerSample,
                          int sampleRate,
                          PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation,
                          long numFrames,
                          byte[] sampleArray)
        {
            if (0xffffffffL < sampleArray.LongLength + 36)
            {
                System.Diagnostics.Debug.Assert(false);
                return(false);
            }

            int dwChannelMask = 0;

            if (numChannels == 2)
            {
                dwChannelMask = 3;
            }

            mLL.RiffChunkWrite(bw, (int)(36 + sampleArray.LongLength));
            mLL.FmtChunkWriteExtensible(bw, (short)numChannels, (int)sampleRate,
                                        (short)bitsPerSample, (short)validBitsPerSample, sampleValueRepresentation, dwChannelMask);
            mLL.DataChunkWrite(bw, false, sampleArray);
            return(true);
        }
예제 #2
0
        public void FmtChunkWriteExtensible(BinaryWriter bw,
                                            short numChannels, int sampleRate, short bitsPerSample, short validBitsPerSample,
                                            PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation, int dwChannelMask)
        {
            FmtChunkWriteInternal(bw, numChannels, sampleRate, bitsPerSample, 40, WAVE_FORMAT_EXTENSIBLE);

            ushort cbSize = 22;

            bw.Write(cbSize);
            bw.Write(validBitsPerSample);
            bw.Write(dwChannelMask);

            byte[] guidByteArray = null;
            if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SInt)
            {
                var pcmGuid = Guid.Parse("00000001-0000-0010-8000-00aa00389b71");
                guidByteArray = pcmGuid.ToByteArray();
            }
            else if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SFloat)
            {
                var floatGuid = Guid.Parse("00000003-0000-0010-8000-00aa00389b71");
                guidByteArray = floatGuid.ToByteArray();
            }
            else
            {
                throw new ArgumentException("sampleValueRepresentation");
            }
            bw.Write(guidByteArray);
        }
예제 #3
0
        /// <summary>
        /// フォーマット設定から、
        /// Setup()に設定されうるビットフォーマットの候補の数を数えて戻す。
        /// </summary>
        /// <returns>Setup()に設定されうるビットフォーマットの候補の数</returns>
        static public int GetSetupSampleFormatCandidateNum(
            WasapiSharedOrExclusiveType sharedOrExclusive,
            BitsPerSampleFixType bitsPerSampleFixType,
            int validBitsPerSample,
            PcmDataLib.PcmData.ValueRepresentationType vrt)
        {
            if (bitsPerSampleFixType != BitsPerSampleFixType.AutoSelect ||
                sharedOrExclusive == WasapiSharedOrExclusiveType.Shared)
            {
                // 共有モードの場合 1通り
                // 排他モードで自動選択以外の選択肢の場合 1通り
                return(1);
            }

            // 排他モードのAutoSelect
            switch (validBitsPerSample)
            {
            case 16:
                return(mTryFormat16.Length);

            case 24:
            default:
                return(mTryFormat24.Length);

            case 32:
                return(mTryFormat32.Length);
            }
        }
예제 #4
0
        public bool Set(
            int numChannels,
            int bitsPerSample,
            int validBitsPerSample,
            int sampleRate,
            PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation,
            long numFrames,
            byte[] sampleArray)
        {
            mRcd = new RiffChunkDescriptor();

            if (0xffffffffL < sampleArray.LongLength + 36)
            {
                System.Diagnostics.Debug.Assert(false);
                return(false);
            }
            mRcd.Create((uint)(36 + sampleArray.LongLength));

            mFsc = new FmtSubChunk();
            mFsc.Create(numChannels, sampleRate, bitsPerSample, validBitsPerSample, sampleValueRepresentation);

            var dsc = new WavDataSubChunk();

            dsc.Create(numFrames, sampleArray);
            mDscList.Clear();
            mDscList.Add(dsc);
            return(true);
        }
예제 #5
0
        private static int ValueRepresentationToAudioFormat(PcmDataLib.PcmData.ValueRepresentationType vr)
        {
            switch (vr)
            {
            case PcmDataLib.PcmData.ValueRepresentationType.SInt:
                return(WavRWLib2.WavWriterLowLevel.WAVE_FORMAT_PCM);

            case PcmDataLib.PcmData.ValueRepresentationType.SFloat:
                return(WavRWLib2.WavWriterLowLevel.WAVE_FORMAT_IEEE_FLOAT);

            default:
                System.Diagnostics.Debug.Assert(false);
                return(WavRWLib2.WavWriterLowLevel.WAVE_FORMAT_PCM);
            }
        }
예제 #6
0
        public bool Create(
            int numChannels, int sampleRate, int bitsPerSample, int validBitsPerSample,
            PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation)
        {
            m_subChunk1Id    = new byte[4];
            m_subChunk1Id[0] = (byte)'f';
            m_subChunk1Id[1] = (byte)'m';
            m_subChunk1Id[2] = (byte)'t';
            m_subChunk1Id[3] = (byte)' ';

            m_subChunk1Size = 16;

            m_audioFormat = 1;

            System.Diagnostics.Debug.Assert(0 < numChannels);
            NumChannels = (ushort)numChannels;

            SampleRate   = (uint)sampleRate;
            m_byteRate   = (uint)(sampleRate * numChannels * bitsPerSample / 8);
            m_blockAlign = (ushort)(numChannels * bitsPerSample / 8);

            BitsPerSample      = (ushort)bitsPerSample;
            ValidBitsPerSample = (ushort)validBitsPerSample;
            ChannelMask        = 0;

            SampleValueRepresentationType = sampleValueRepresentation;
            if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SInt)
            {
                m_audioFormat = 1;
            }
            else if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SFloat)
            {
                m_audioFormat = 3;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            return(true);
        }
예제 #7
0
        private int WasapiSetup(
            int deviceId,
            bool isExclusive,
            bool isEventDriven,
            int sampleRate,
            int pcmDataBitsPerSample,
            int pcmDataValidBitsPerSample,
            PcmDataLib.PcmData.ValueRepresentationType vrt,
            int latencyMillisec)
        {
            int num = SampleFormatInfo.GetSetupSampleFormatCandidateNum(
                isExclusive ? WasapiSharedOrExclusiveType.Exclusive : WasapiSharedOrExclusiveType.Shared,
                BitsPerSampleFixType.AutoSelect,
                pcmDataValidBitsPerSample, vrt);

            int hr = -1;

            for (int i = 0; i < num; ++i)
            {
                SampleFormatInfo sf = SampleFormatInfo.CreateSetupSampleFormat(
                    isExclusive ? WasapiSharedOrExclusiveType.Exclusive : WasapiSharedOrExclusiveType.Shared,
                    BitsPerSampleFixType.AutoSelect,
                    pcmDataBitsPerSample,
                    pcmDataValidBitsPerSample, vrt, i);

                hr = wasapi.Setup(deviceId, WasapiCS.DeviceType.Play, WasapiCS.StreamType.PCM, sampleRate,
                                  sf.GetSampleFormatType(), 2, WasapiCS.MMCSSCallType.Enable, WasapiCS.MMThreadPriorityType.None,
                                  WasapiCS.SchedulerTaskType.ProAudio, WasapiCS.ShareMode.Exclusive,
                                  isEventDriven ? WasapiCS.DataFeedMode.EventDriven : WasapiCS.DataFeedMode.TimerDriven,
                                  latencyMillisec, 500, 10000);
                if (0 <= hr)
                {
                    m_sampleFormat = sf;
                    return(hr);
                }
            }
            wasapi.Unsetup();
            return(hr);
        }
예제 #8
0
        /// <summary>
        /// PcmDataの形式と、(共有・排他)、フォーマット固定設定から、
        /// デバイスに設定されるビットフォーマットを取得。
        ///
        /// これは、内容的にテーブルなので、テーブルにまとめたほうが良い。
        /// </summary>
        /// <returns>デバイスに設定されるビットフォーマット</returns>
        static public SampleFormatInfo CreateSetupSampleFormat(
            WasapiSharedOrExclusiveType sharedOrExclusive,
            BitsPerSampleFixType bitsPerSampleFixType,
            int bitsPerSample,
            int validBitsPerSample,
            PcmDataLib.PcmData.ValueRepresentationType vrt,
            int candidateId)
        {
            SampleFormatInfo sf = new SampleFormatInfo();

            if (sharedOrExclusive == WasapiSharedOrExclusiveType.Shared)
            {
                // 共有モード
                sf.bitsPerSample      = bitsPerSample;
                sf.validBitsPerSample = validBitsPerSample;
                sf.bitFormatType      = SampleFormatInfo.VrtToBft(vrt);
                return(sf);
            }

            // 排他モード
            switch (bitsPerSampleFixType)
            {
            case BitsPerSampleFixType.Sint16:
                sf.bitFormatType      = WasapiCS.BitFormatType.SInt;
                sf.bitsPerSample      = 16;
                sf.validBitsPerSample = 16;
                break;

            case BitsPerSampleFixType.Sint24:
                sf.bitFormatType      = WasapiCS.BitFormatType.SInt;
                sf.bitsPerSample      = 24;
                sf.validBitsPerSample = 24;
                break;

            case BitsPerSampleFixType.Sint32:
                sf.bitFormatType      = WasapiCS.BitFormatType.SInt;
                sf.bitsPerSample      = 32;
                sf.validBitsPerSample = 32;
                break;

            case BitsPerSampleFixType.Sint32V24:
                sf.bitFormatType      = WasapiCS.BitFormatType.SInt;
                sf.bitsPerSample      = 32;
                sf.validBitsPerSample = 24;
                break;

            case BitsPerSampleFixType.Sfloat32:
                sf.bitFormatType      = WasapiCS.BitFormatType.SFloat;
                sf.bitsPerSample      = 32;
                sf.validBitsPerSample = 32;
                break;

            case BitsPerSampleFixType.AutoSelect:
                WasapiCS.SampleFormatType sampleFormat = WasapiCS.SampleFormatType.Sint16;
                switch (validBitsPerSample)
                {
                case 16:
                    sampleFormat = mTryFormat16[candidateId];
                    break;

                case 24:
                default: /* ? */
                    sampleFormat = mTryFormat24[candidateId];
                    break;

                case 32:
                    sampleFormat = mTryFormat32[candidateId];
                    break;
                }

                sf.bitFormatType      = WasapiCS.BitFormatType.SInt;
                sf.bitsPerSample      = WasapiCS.SampleFormatTypeToUseBitsPerSample(sampleFormat);
                sf.validBitsPerSample = WasapiCS.SampleFormatTypeToValidBitsPerSample(sampleFormat);
                break;

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

            return(sf);
        }