wav格式与PCM格式的关系,pcm格式数据播放设置参数解析

其实PCM格式数据加上一系列的数据头就成为了 Wav格式数据,数据部分是一样的
项目工程在我的下载里面 http://download.csdn.net/download/wangchao712217/10145696

 public class WaveOpeater
    {
        private byte[] riff;  //4   
        private byte[] riffSize; //4    
        private byte[] waveID; //4  
        private byte[] fmtID; //4   
        private byte[] notDefinition; //4   

        private byte[] waveType;  //2   
        private byte[] channel;  //2    
        private byte[] sample;  //4 
        private byte[] send;   //4  
        private byte[] blockAjust;  //2 
        private byte[] bitNum;  //2 

        private byte[] unknown; //2 
        private byte[] dataID;  //4 
        private byte[] dataLength;  //4 

        short[] data;
        private string longFileName;

        public string LongFileName
        {
            get { return longFileName; }
        }

        public string ShortFileName
        {
            get
            {
                int pos = LongFileName.LastIndexOf("\\");
                return LongFileName.Substring(pos + 1);
            }
        }

        public short[] Data
        {
            get { return data; }
            set { data = value; }
        }

        public string Riff
        {
            get { return Encoding.Default.GetString(riff); }
            set { riff = Encoding.Default.GetBytes(value); }
        }

        public uint RiffSize
        {
            get
            {
                return BitConverter.ToUInt32(riffSize, 0);
            }
            set
            {
                riffSize = BitConverter.GetBytes(value);
            }

        }

        public string WaveID
        {
            get { return Encoding.Default.GetString(waveID); }
            set { waveID = Encoding.Default.GetBytes(value); }
        }

        public string FmtID
        {
            get { return Encoding.Default.GetString(fmtID); }
            set { fmtID = Encoding.Default.GetBytes(value); }
        }

        public int NotDefinition
        {
            get
            {
                return BitConverter.ToInt32(notDefinition, 0);
            }

            set { notDefinition = BitConverter.GetBytes(value); }
        }

        public short WaveType
        {
            get
            {
                return BitConverter.ToInt16(waveType, 0);
            }
            set { waveType = BitConverter.GetBytes(value); }
        }


        public ushort Channel
        {
            get
            {
                return BitConverter.ToUInt16(channel, 0);
            }
            set { channel = BitConverter.GetBytes(value); }
        }

        public uint Sample
        {
            get
            {
                return BitConverter.ToUInt32(sample, 0);
            }
            set { sample = BitConverter.GetBytes(value); }
        }

        public uint Send
        {
            get { return BitConverter.ToUInt32(send, 0); }
            set { send = BitConverter.GetBytes(value); }
        }

        public ushort BlockAjust
        {
            get
            {
                return BitConverter.ToUInt16(blockAjust, 0);
            }
            set { blockAjust = BitConverter.GetBytes(value); }
        }

        public ushort BitNum
        {
            get
            {
                return BitConverter.ToUInt16(bitNum, 0);
            }
            set { bitNum = BitConverter.GetBytes(value); }
        }

        public ushort Unknown
        {
            get
            {
                if (unknown == null)
                {
                    return 1;
                }
                else
                    return BitConverter.ToUInt16(unknown, 0);
            }

            set { unknown = BitConverter.GetBytes(value); }
        }

        public string DataID
        {
            get { return Encoding.Default.GetString(dataID); }
            set { dataID = Encoding.Default.GetBytes(value); }
        }

        public uint DataLength
        {
            get
            {
                return BitConverter.ToUInt32(dataLength, 0);
            }
            set { dataLength = BitConverter.GetBytes(value); }
        }

        public WaveOpeater() { }
        FileStream fs;
        String m_filepath;
        BinaryReader bread;
        public void InitWave(string filepath)
        {
           m_filepath = filepath;
            try
            {
                riff = new byte[4];
                riffSize = new byte[4];
                waveID = new byte[4];
                fmtID = new byte[4];
                notDefinition = new byte[4];
                waveType = new byte[2];
                channel = new byte[2];
                sample = new byte[4];
                send = new byte[4];
                blockAjust = new byte[2];
                bitNum = new byte[2];
                unknown = new byte[2];
                dataID = new byte[4];  //52 
                dataLength = new byte[4];  //56个字节             

               if (File.Exists(filepath))
               {
                    fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    bread = new BinaryReader(fs);
                    riff = bread.ReadBytes(4);
                    riffSize = bread.ReadBytes(4);
                    waveID = bread.ReadBytes(4);
                    fmtID = bread.ReadBytes(4);
                    notDefinition = bread.ReadBytes(4);
                    waveType = bread.ReadBytes(2);
                    channel = bread.ReadBytes(2);
                    sample = bread.ReadBytes(4);
                    send = bread.ReadBytes(4);
                    blockAjust = bread.ReadBytes(2);
                    bitNum = bread.ReadBytes(2);
                    if (notDefinition.Length>0&&  BitConverter.ToUInt32(notDefinition, 0) == 18)
                    {
                        unknown = bread.ReadBytes(2);
                    }
                    dataID = bread.ReadBytes(4);
                }


            }
            catch (System.Exception ex)
            {
                Console.Write(ex.Message);
            }
        }

        int DataCount = 3200 ;
        int DataCountByte = 6400;
        int preIndex = 0;
        int Curent = 0;
        public byte[] GetCurrentData()
        {
            Curent = GetDataAmount();
            //  Curent = amount;
            if (preIndex == Curent)
            {
                System.Threading.Thread.Sleep(10);
                return null;
            }
            // Debug.Write("当前读取到的音频数据帧号" + Curent);
            preIndex = Curent;
            if (Curent > 1)
            {

                long offset = 0;
                offset = 44 + (Curent - 1) * DataCountByte;//44字节的头  ,加上数据块的便偏移
                fs.Seek(offset, SeekOrigin.Begin);
                byte[] data2 = new byte[DataCountByte];
                bread.Read(data2, 0, DataCountByte);
                return data2;
            }
            else
            {
                return null;
            }
        }

        public byte[] GetAudioSegment()
        {
            Curent = GetDataAmount();
            //  Curent = amount;
            if (preIndex == Curent)
            {
                System.Threading.Thread.Sleep(10);
                return null;
            }
            if ((Curent - preIndex)>20|| preIndex> Curent)
            {
                preIndex = Curent;
                return null;
            }
            if ( Curent> preIndex)
            {

                long offset = 0;
                offset = 44 + (preIndex) * DataCountByte;//44字节的头  ,加上数据块的便偏移
                fs.Seek(offset, SeekOrigin.Begin);
                int  readLength = (Curent - preIndex) * DataCountByte;
                byte[] data2 = new byte[readLength];
                bread.Read(data2, 0, readLength);
                preIndex = Curent;
                return data2;
            }
            else
            {
                return null;
            }

        }

        private short[] ByteArrayToShortArray(Byte[] shortarr)
        {
            short[] arrs = new short[shortarr.Length/2];

            for (int i = 0; i < shortarr.Length/2; i++)
            {
                arrs[i]=System.BitConverter.ToInt16(shortarr, i*2);                
            }
            return arrs;
        }
        private int  GetDataAmount()
        {
            longFileName = m_filepath;
            System.IO.FileInfo f = new FileInfo(m_filepath);
            long fileLength = f.Length;
            long _dataLength = fileLength - 44;
            dataLength = BitConverter.GetBytes(_dataLength);

            int number =(int) DataLength / DataCountByte;
            return number;
        }

        public void Close()
        {
            if (fs!=null)
            {
                bread.Close();
                fs.Close();                
            }
        }




        private short[] GetData(uint begin, uint end)
        {
            if ((end - begin) >= Data.Length)
                return Data;
            else
            {
                uint temp = end - begin + 1;
                short[] dataTemp = new short[temp];
                uint j = begin;
                for (int i = 0; i < temp; i++)
                {
                    dataTemp[i] = Data[j];//读入2字节有符号整数
                    j++;
                }
                return dataTemp;
            }
        }

        /// <summary>
        /// 生成wav文件到系统
        /// </summary>
        /// <param name="fileName">要保存的文件名</param>
        /// <returns></returns>
        public bool bulidWave(string fileName)
        {
            try
            {
                FileInfo fi = new FileInfo(fileName);
                if (fi.Exists)
                    fi.Delete();
                FileStream fs = new FileStream(fileName, FileMode.CreateNew);
                BinaryWriter bwriter = new BinaryWriter(fs);
                bwriter.Seek(0, SeekOrigin.Begin);
                bwriter.Write(Encoding.Default.GetBytes(this.Riff));     //不可以直接写入string类型的字符串,字符串会有串结束符,比原来的bytes多一个字节
                bwriter.Write(this.RiffSize);
                bwriter.Write(Encoding.Default.GetBytes(this.WaveID));
                bwriter.Write(Encoding.Default.GetBytes(this.FmtID));
                bwriter.Write(this.NotDefinition);
                bwriter.Write(this.WaveType);
                bwriter.Write(this.Channel);
                bwriter.Write(this.Sample);
                bwriter.Write(this.Send);
                bwriter.Write(this.BlockAjust);
                bwriter.Write(this.BitNum);
                if (this.Unknown != 0)
                    bwriter.Write(this.Unknown);
                bwriter.Write(Encoding.Default.GetBytes(this.DataID));
                bwriter.Write(this.DataLength);

                for (int i = 0; i < this.Data.Length; i++)
                {
                    bwriter.Write(this.Data[i]);
                }


                bwriter.Flush();
                fs.Close();
                bwriter.Close();
                fi = null;
                return true;
            }
            catch (System.Exception ex)
            {
                Console.Write(ex.Message);
                return false;
            }
        }


        public bool CheckStatus()
        {
            return true;
        }
    }

播放pcm格式 的代码
需要三个dll 动态连接库 audio.dll kennel32.dll WINMM.DLL,这三个文件请注意其要与程序配置X64,X86相匹配,否者会出现试图加载格式不正确的程序 ,我已测试过,可以运行。

  public class AudioOutOperator
    {
        private static List<int> IDS;
        private static int m_CurentID;
        private int m_ID;
        private static object m_IDLocker;
        private object m_Locker;
        private uint m_Port;
        public AudioOutOperator()
        {
            m_IDLocker = new object();
            IDS = new List<int>();
            m_CurentID = -1;
        }
        public AudioOutOperator(uint _Port)
        {
            this.m_Locker = new object();
            this.m_Port = 0;
            this.m_ID = 0;
            this.m_Port = _Port;
            this.m_ID = CreateID();
        }
        public static int CreateID()
        {
            lock (m_IDLocker)
            {
                m_CurentID++;
                if (m_CurentID >= 0x3e8)
                {
                    m_CurentID = 0;
                }
                while (IDS.Contains(m_CurentID))
                {
                    m_CurentID++;
                    if (m_CurentID >= 0x3e8)
                    {
                        m_CurentID = 0;
                    }
                }
                IDS.Add(m_CurentID);
                return m_CurentID;
            }
        }
        public static AudioOutOperator CreateInstance(uint _Port)
        {
            return new AudioOutOperator(_Port);
        }
        public void PlayAudio(AudioOutData _Audio)
        {
            //             object CS$2$0000;
            //             Monitor.Enter(CS$2$0000 = this.m_Locker);
            try
            {
                AudioFormat _AudioFormat = AudioFormat.CreateInstance(_Audio);
                IntPtr _PtrFormat = StructToPtr(typeof(AudioFormat), _AudioFormat);
                IntPtr _PtrData = ArrayToPtr(_Audio.Data);
                SendAudioData(this.m_ID, this.m_Port, _PtrFormat, _PtrData, _Audio.Data.Length);
                Marshal.FreeHGlobal(_PtrFormat);
                Marshal.FreeHGlobal(_PtrData);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
            finally
            {
                //                Monitor.Exit(CS$2$0000);
            }
        }
        [DllImport("Audio.dll")]
        private static extern int SendAudioData(int _ID, uint _Port, IntPtr _FORMAT, IntPtr _Data, int Len);
        public void StopAudio()
        {
            try
            {
                IDS.Remove(this.m_ID);
                StopPlay(this.m_ID);
            }
            catch
            {
            }
        }
        [DllImport("Audio.dll")]
        private static extern int StopPlay(int _ID);
        private static IntPtr ArrayToPtr(byte[] _Data)
        {
            if (_Data == null)
            {
                return new IntPtr();
            }
            IntPtr _adress = Marshal.AllocHGlobal(_Data.Length);
            Marshal.Copy(_Data, 0, _adress, _Data.Length);
            return _adress;
        }
        public static IntPtr StructToPtr(Type _Type, object _Obj)
        {
            IntPtr _Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(_Type));
            Marshal.StructureToPtr(_Obj, _Ptr, true);
            return _Ptr;
        }
    }
    public struct AudioOutData
    {
        public ushort wFormatTag;           // format type
        public ushort nChannels;            // number of channels (i.e. mono, stereo...)
        public uint nSamplesPerSec;         // sample rate
        public uint nAvgBytesPerSec;        // for buffer estimation
        public ushort nBlockAlign;          // block size of data
        public ushort wBitsPerSample;       // Number of bits per sample of mono data
        public ushort cbSize;               // The count in bytes of the size of extra information (after cbSize)
        public byte[] Data;
    }
    public struct AudioFormat
    {
        [MarshalAs(UnmanagedType.U4)]
        public uint nSampleRate;
        [MarshalAs(UnmanagedType.U2)]
        public ushort nBitsPerSample;
        [MarshalAs(UnmanagedType.U2)]
        public ushort nNoOfChannels;
        [MarshalAs(UnmanagedType.U4)]
        public uint nRateInBytesPerSec;
        [MarshalAs(UnmanagedType.U1)]
        public byte cFrameLen;
        public static AudioFormat CreateInstance(AudioOutData _Audio)
        {
            return new AudioFormat { nRateInBytesPerSec = _Audio.nAvgBytesPerSec, nNoOfChannels = _Audio.nChannels, nSampleRate = _Audio.nSamplesPerSec, nBitsPerSample = _Audio.wBitsPerSample, cFrameLen = (byte)_Audio.nBlockAlign };
        }
        public static AudioOutData CreateAudioData(AudioFormat _AudioFormat)
        {
            return new AudioOutData { nAvgBytesPerSec = _AudioFormat.nRateInBytesPerSec, nChannels = _AudioFormat.nNoOfChannels, nSamplesPerSec = _AudioFormat.nSampleRate, wBitsPerSample = _AudioFormat.nBitsPerSample, nBlockAlign = _AudioFormat.cFrameLen };
        }
    }

调用代码的参数设置如下,

                      AudioOutOperator audioData2 = new AudioOutOperator();
                     AudioOutData test = new AudioOutData();                 
                    test.nSamplesPerSec = 32000;
                    test.nChannels = 1;
                    test.Data = buffer;//buffer为数组,音频数据
                    test.nAvgBytesPerSec = test.nSamplesPerSec / 16;                 
                    test.nBlockAlign = 6400;
                    test.wBitsPerSample = 16;
                    audioData2.PlayAudio(test);

项目工程在我的下载里面 http://download.csdn.net/download/wangchao712217/10145696

1、Java实现wav音频文件转换为pcm音频文件(AudioUtils.java) 2、Java实现播放pcm音频文件(PCMPlay.java) WAVwav是一种无损的音频文件格式WAV符合 PIFF(Resource Interchange File Format)规范。所有的WAV都有一个文件头,这个文件头音频流的编码参数WAV音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV音频流进行编码。 PCM:PCM(Pulse Code Modulation----脉码调制录音)。所谓PCM录音就是将声音等模拟信号变成符号化的脉冲列,再予以记录。PCM信号是由[1]、[0]等符号构成的数字信号,而未经过任何编码和压缩处理。与模拟信号比,它不易受传送系统的杂波及失真的影响。动态范围宽,可得到音质相当好的影响效果。 简单来说:wav是一种无损的音频文件格式pcm是没有压缩的编码方式。 WAVPCM关系 WAV可以使用多种音频编码来压缩其音频流,不过我们常见的都是音频流被PCM编码处理的WAV,但这不表示WAV只能使用PCM编码,MP3编码同样也可以运用在WAV中,和AVI一样,只要安装好了相应的Decode,就可以欣赏这些WAV了。在Windows平台下,基于PCM编码的WAV是被支持得最好的音频格式,所有音频软件都能完美支持,由于本身可以达到较高的音质的要求,因此,WAV也是音乐编辑创作的首选格式,适合保存音乐素材。因此,基于PCM编码的WAV被作为了一种中介的格式,常常使用在其他编码的相互转换之中,例如MP3转换成WMA。 简单来说:pcm是无损wav文件中音频数据的一种编码方式,但wav还可以用其它方式编码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值