Click here to Skip to main content
15,881,568 members
Articles / Programming Languages / C#

Sending and playing microphone audio over network

Rate me:
Please Sign up or sign in to vote.
4.92/5 (65 votes)
3 Aug 20072 min read 521K   42.9K   336  
Sending and playing microphone audio over network
using System;
using System.IO;

namespace LumiSoft.Data.lsDB
{
	/// <summary>
	/// Data page.
	/// </summary>
	internal class DataPage
	{
		private DbFile     m_pOwnerDB             = null;
		private long       m_StartPointer         = 0;
		private bool       m_Used                 = false;
		private long       m_OwnerID              = 0;
		private long       m_OwnerDataPagePointer = 0;
		private long       m_NextDataPagePointer  = 0;
		private int        m_DataAreaSize         = 1000;
		private int        m_StoredDataLength     = 0;

		private byte[]     m_Data                 = null;

		/// <summary>
		/// Default constructor.
		/// </summary>
		/// <param name="dataPageDataAreaSize">Specifies how much data data page can store.</param>
		/// <param name="ownerDB">Owner DB file..</param>
		/// <param name="startOffset">Data page start offset pointer.</param>
		public DataPage(int dataPageDataAreaSize,DbFile ownerDB,long startOffset)
		{
			/* DataPage structure
			   2 bytes                 - CRLF
			   1 byte                  - used (f - unused,u - used)
			   8 byte	               - owner object id
			   8 bytes                 - owner data page pointer
			   8 bytes                 - continuing data page pointer
			   4 bytes                 - stored data length in data area
			   2 bytes                 - CRLF
			   1000 bytes              - data area
			*/
			
			m_DataAreaSize = dataPageDataAreaSize;
			m_pOwnerDB = ownerDB;
			m_StartPointer = startOffset;
		
			byte[] dataPageInfo = new byte[33];
			ownerDB.SetFilePosition(startOffset);
			ownerDB.ReadFromFile(dataPageInfo,0,dataPageInfo.Length);
			m_Data = new byte[dataPageDataAreaSize];
			ownerDB.ReadFromFile(m_Data,0,dataPageDataAreaSize);

			// CRLF
			if(dataPageInfo[0] != (byte)'\r'){
				throw new Exception("Not right data page startOffset, or invalid data page <CR> is expected but is '" + (int)dataPageInfo[0] + "' !");
			}
			if(dataPageInfo[1] != (byte)'\n'){
				throw new Exception("Not right data page startOffset, or invalid data page <LF> is expected but is '" + (int)dataPageInfo[1] + "' !");
			}

			// used
			if(dataPageInfo[2] == (byte)'u'){
				m_Used = true;
			}
			else{
				m_Used = false;
			}

			// owner object id
			m_OwnerID = ldb_Utils.ByteToLong(dataPageInfo,3);

			// owner data page pointer
			m_OwnerDataPagePointer = ldb_Utils.ByteToLong(dataPageInfo,11);

			// continuing data page pointer
			m_NextDataPagePointer = ldb_Utils.ByteToLong(dataPageInfo,19);

			// stored data length in data area
			m_StoredDataLength = ldb_Utils.ByteToInt(dataPageInfo,27);

			// CRLF
			if(dataPageInfo[31] != (byte)'\r'){
				throw new Exception("Not right data page startOffset, or invalid data page <CR> is expected but is '" + (int)dataPageInfo[31] + "' !");
			}
			if(dataPageInfo[32] != (byte)'\n'){
				throw new Exception("Not right data page startOffset, or invalid data page <LF> is expected but is '" + (int)dataPageInfo[32] + "' !");
			}
		}

		

		#region static method CreateDataPage

		/// <summary>
		/// Creates new data page structure.
		/// </summary>
		/// <param name="dataPageDataAreaSize">Specifies how much data can data page store.</param>
		/// <param name="used">Specifies if data page is used or free space. If this value is false, all toher parameters aren't stored.</param>
		/// <param name="ownerID">Owner data object ID.</param>
		/// <param name="ownerDataPagePointer">This data page owner data page pointer. This value can be 0, if no owner.</param>
		/// <param name="nextDataPagePointer">Data page pointer, what continues this data page. This value can be 0 if, data page won't spread to multiple data pages.</param>
		/// <param name="data">Data what data page stores. Maximum length is dataPageDataAreaSize.</param>
		/// <returns></returns>
		public static byte[] CreateDataPage(int dataPageDataAreaSize,bool used,long ownerID,long ownerDataPagePointer,long nextDataPagePointer,byte[] data)
		{
			/* DataPage structure
			   2 bytes                    - CRLF
			   1 byte                     - used (f - unused,u - used)
			   8 byte	                  - owner object id
			   8 bytes                    - owner data page pointer
			   8 bytes                    - continuing data page pointer
			   4 bytes                    - stored data length in data area
			   2 bytes                    - CRLF
			   dataPageDataAreaSize bytes - data area
			*/

			if(data.Length > dataPageDataAreaSize){
				throw new Exception("Data page can store only " + dataPageDataAreaSize + " bytes, data conatins '" + data.Length + "' bytes !");
			}

			byte[] dataPage = new byte[dataPageDataAreaSize + 33];
			// CRLF
			dataPage[0] = (byte)'\r';
			dataPage[1] = (byte)'\n';
			if(used){
				// used
				dataPage[2] = (byte)'u';
				// owner object id
				Array.Copy(ldb_Utils.LongToByte(ownerID),0,dataPage,3,8);
				// owner data page pointer
				Array.Copy(ldb_Utils.LongToByte(ownerDataPagePointer),0,dataPage,11,8);
				// continuing data page pointer
				Array.Copy(ldb_Utils.LongToByte(nextDataPagePointer),0,dataPage,19,8);
				// stored data length in data area
				Array.Copy(ldb_Utils.IntToByte(data.Length),0,dataPage,27,4);
				// CRLF
				dataPage[31] = (byte)'\r';
				dataPage[32] = (byte)'\n';
				// data area
				Array.Copy(data,0,dataPage,33,data.Length);
			}
			else{
				// used
				dataPage[2] = (byte)'f';
				// CRLF
				dataPage[31] = (byte)'\r';
				dataPage[32] = (byte)'\n';
			}

			return dataPage;
		}

		#endregion


		#region method ReadData

		/// <summary>
		/// Reads specified amount data to buffer.
		/// </summary>
		/// <param name="buffer">Buffer where to store data.</param>
		/// <param name="startIndexInBuffer">Start index in buffer where data storing begins. Start index is included.</param>
		/// <param name="length">Number of bytes to read.</param>
		/// <param name="startOffset">Zero based offset of data area.</param>
		/// <returns></returns>
		public void ReadData(byte[] buffer,int startIndexInBuffer,int length,int startOffset)
		{
			if(startOffset < 0){
				throw new Exception("startOffset can't negative value !");
			}
			if((length + startOffset) > this.DataAreaSize){
				throw new Exception("startOffset and length are out of range data page data area !");
			}
			if((length + startOffset) > m_StoredDataLength){
				throw new Exception("There isn't so much data stored in data page as requested ! Stored data length = " + m_StoredDataLength + "; start offset = " + startOffset + "; length wanted = " + length);
			}

			Array.Copy(m_Data,startOffset,buffer,startIndexInBuffer,length);
		}

		/// <summary>
		/// Reads data page data. Offset byte is included.
		/// </summary>
		/// <param name="startOffset">Zero based offset of data area.</param>
		/// <param name="length">Specifies how much data to read.</param>
		/// <returns></returns>
		public byte[] ReadData(int startOffset,int length)
		{
			if(startOffset < 0){
				throw new Exception("startOffset can't negative value !");
			}
			if((length + startOffset) > this.DataAreaSize){
				throw new Exception("startOffset and length are out of range data page data area !");
			}
			if((length + startOffset) > m_StoredDataLength){
				throw new Exception("There isn't so much data stored in data page as requested ! Stored data length = " + m_StoredDataLength + "; start offset = " + startOffset + "; length wanted = " + length);
			}

			byte[] data = new byte[length];
			Array.Copy(m_Data,startOffset,data,0,length);

			return data; 
		}

		#endregion

		#region method WriteData

		/// <summary>
		/// Writed data to data page.
		/// </summary>
		/// <param name="data">Data to write.</param>
		public void WriteData(byte[] data)
		{
			if(data.Length > this.DataAreaSize){
				throw new Exception("Data page can't store more than " + this.DataAreaSize + " bytes, use mutliple data pages !");
			}
		
			// Set stored data length
			m_pOwnerDB.SetFilePosition(m_StartPointer + 27);
			m_pOwnerDB.WriteToFile(ldb_Utils.IntToByte(data.Length),0,4);
				
            // Store data
			m_pOwnerDB.SetFilePosition(m_StartPointer + 33);
			m_pOwnerDB.WriteToFile(data,0,data.Length);

			m_StoredDataLength = data.Length;
		}

		#endregion


		#region Properties Implementation

		/// <summary>
		/// Gets data page size on disk in bytes.
		/// </summary>
		public int DataPageSize
		{
			get{ return 33 + this.DataAreaSize; }
		}

		/// <summary>
		/// Gets this data page address (offset in database file).
		/// </summary>
		public long Pointer
		{
			get{ return m_StartPointer; }
		}

		/// <summary>
		/// Gets or sets if data page used or free space.
		/// </summary>
		public bool Used
		{
			get{ return m_Used; }

			set{
				m_pOwnerDB.SetFilePosition(m_StartPointer + 2);
				m_pOwnerDB.WriteToFile(new byte[]{Convert.ToByte(value)},0,1);
			}
		}

		/// <summary>
		/// Gets owner object id what owns this data page.
		/// </summary>
		public long OwnerID
		{
			get{ return m_OwnerID; }
		}

		/// <summary>
		/// Gets or sets owner data page pointer.
		/// Returns 0 if this is first data page of multiple data pages or only data page.
		/// </summary>
		public long OwnerDataPagePointer
		{
			get{ return m_OwnerDataPagePointer; }

			set{
				// owner data page pointer
				m_pOwnerDB.SetFilePosition(m_StartPointer + 11);
				m_pOwnerDB.WriteToFile(ldb_Utils.LongToByte(value),0,8);

				m_OwnerDataPagePointer = value;
			}
		}

		/// <summary>
		/// Gets or sets pointer to data page what continues this data page.
		/// Returns 0 if data page has enough room for data and there isn't continuing data page.
		/// </summary>
		public long NextDataPagePointer
		{
			get{ return m_NextDataPagePointer; }

			set{
				// continuing data page pointer
				m_pOwnerDB.SetFilePosition(m_StartPointer + 19);
				m_pOwnerDB.WriteToFile(ldb_Utils.LongToByte(value),0,8);

				m_NextDataPagePointer = value;
			}
		}
/*
		/// <summary>
		/// Gets or sets data that data page holds. Maximum size is this.DataAreaSize. Returns null if no data stored.
		/// </summary>
		public byte[] Data
		{
			get{ 
				byte[] data = new byte[m_StoredDataLength];
				m_pDbFileStream.Position = m_StartPointer + 33;
				m_pDbFileStream.Read(data,0,data.Length);

				return data; 
			}

			set{
				if(value.Length > this.DataAreaSize){
					throw new Exception("Data page can't store more than " + this.DataAreaSize + " bytes, use mutliple data pages !");
				}
		
				// Set stored data length
				m_pDbFileStream.Position = m_StartPointer + 27;
				byte[] dataLength = ldb_Utils.IntToByte(value.Length);
				m_pDbFileStream.Write(dataLength,0,dataLength.Length);
				
                // Store data
				m_pDbFileStream.Position = m_StartPointer + 33;
				m_pDbFileStream.Write(value,0,value.Length);

				m_StoredDataLength = value.Length;
			}
		}
*/
		/// <summary>
		/// Gets how many data data page can store.
		/// </summary>
		public int DataAreaSize
		{
			get{ return m_DataAreaSize; }
		}

		/// <summary>
		/// Gets stored data length.
		/// </summary>
		public int StoredDataLength
		{
			get{ return m_StoredDataLength; }
		}

		/// <summary>
		/// Gets how much free data space is availabe in data page.
		/// </summary>
		public long SpaceAvailable
		{
			get{ return this.DataAreaSize - m_StoredDataLength; }
		}

		#endregion

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Estonia Estonia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions