示例#1
0
        /// <summary>
        /// Reset the OggFile (reload from disk).
        /// Useful if tags have changed externally, or to reset the internal position pointer to replay the file from the beginning
        /// SeekToTime(0) is the preferred method of moving the internal pointer to the beginning however however
        /// </summary>		
        public void ResetFile()
        {
            try
            {
                // Grab a fresh instance of the file
                m_CSVorbisFileInstance = m_CSVorbisFile.makeInstance();

                m_TagLibFile = null;
                m_TagLibFile = TagLib.File.Create(m_Filename);
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to reload OggFile [" + m_Filename + "]", ex);
            }
        }
示例#2
0
        private TagLib.File m_TagLibFile; // TagLibSharp file object

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="Filename">
        /// A <see cref="System.String"/> containing the path to the Ogg Vorbis file this instance represents
        /// </param>
        public OggFile(string Filename)
        {
            // Check that the file exists
            if (!(System.IO.File.Exists(Filename))) { throw new OggFileReadException("File not found", Filename); }
            // Load the relevant objects
            m_Filename = Filename;
            try
            {
                m_CSVorbisFile = new VorbisFile(m_Filename);
            }
            catch (Exception ex)
            {
                throw new OggFileReadException("Unable to open file for data reading\n" + ex.Message, Filename);
            }
            try
            {
                m_TagLibFile = TagLib.File.Create(m_Filename);
            }
            catch (TagLib.UnsupportedFormatException ex)
            {
                throw new OggFileReadException("Unsupported format (not an ogg?)\n" + ex.Message, Filename);
            }
            catch (TagLib.CorruptFileException ex)
            {
                throw new OggFileCorruptException(ex.Message, Filename, "Tags");
            }

            // Populate some other info shizzle and do a little bit of sanity checking
            m_Streams = m_CSVorbisFile.streams();
            if (m_Streams<=0) { throw new OggFileReadException("File doesn't contain any logical bitstreams", Filename); }
            // Assuming <0 is for whole file and >=0 is for specific logical bitstreams
            m_Bitrate = m_CSVorbisFile.bitrate(-1);
            m_LengthTime = (int)m_CSVorbisFile.time_total(-1);
            // Figure out the ALFormat of the stream
            m_Info = m_CSVorbisFile.getInfo();	// Get the info of the first stream, assuming all streams are the same? Dunno if this is safe tbh
            if (m_Info[0] == null) { throw new OggFileReadException("Unable to determine Format{FileInfo.Channels} for first bitstream", Filename); }
            if (m_TagLibFile.Properties.AudioBitrate==16) {
                m_Format = (m_Info[0].channels)==1 ? ALFormat.Mono16 : ALFormat.Stereo16; // This looks like a fudge, but I've seen it a couple of times (what about the other formats I wonder?)
            }
            else
            {
                m_Format = (m_Info[0].channels)==1 ? ALFormat.Mono8 : ALFormat.Stereo8;
            }

            // A grab our first instance of the file so we're ready to play
            m_CSVorbisFileInstance = m_CSVorbisFile.makeInstance();
        }
        /// <summary>
        /// Retrive the source info from a vorbis file
        /// </summary>
        /// <param name="source">the source file to retrieve data from</param>
        /// <returns></returns>
        public Info RetrieveSourceInfo(VorbisFileInstance source)
        {
            Info[] formatInfo = source.vorbisFile.getInfo();
            if (formatInfo.Length < 1 || formatInfo[0] == null)
                throw new ArgumentException("NO CLIP INFORMATION");

            Info sourceInfo = formatInfo[0];
            return sourceInfo;
        }
 public void StopFile(VorbisFileInstance audioFile)
 {
     foreach(AudioSource source in AudioSources)
     {
         try
         {
                 source.PauseSource(audioFile);
                 source.Dispose();
                 return;
         }
         catch (Exception e)
         {
             Console.WriteLine("Cannot remove source");
         }
     }
 }
		public int bisect_forward_serialno(long begin, long searched, long end, int currentno, int m, VorbisFileInstance instance)
		{
			long endsearched=end;
			long next=end;
			Page page=new Page();
			int ret;

			while(searched<endsearched)
			{
				long bisect;
				if(endsearched-searched<CHUNKSIZE)
				{
					bisect=searched;
				}
				else
				{
					bisect=(searched+endsearched)/2;
				}

                seek_helper(bisect, instance);
                ret = get_next_page(page, -1, instance);
				if(ret==OV_EREAD) return OV_EREAD;
				if(ret<0 || page.serialno()!=currentno)
				{
					endsearched=bisect;
					if(ret>=0)next=ret;
				}
				else
				{
					searched=ret+page.header_len+page.body_len;
				}
			}
            seek_helper(next, instance);
            ret = get_next_page(page, -1, instance);
			if(ret==OV_EREAD) return OV_EREAD;

			if(searched>=end || ret==-1)
			{
				links=m+1;
				offsets=new long[m+2];
				offsets[m+1]=searched;
			}
			else
			{
				ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1, instance);
				if(ret==OV_EREAD)return OV_EREAD;
			}
			offsets[m]=begin;
			return 0;  
		}
		// last step of the OggVorbis_File initialization; get all the
		// vorbis_info structs and PCM positions.  Only called by the seekable
		// initialization (local stream storage is hacked slightly; pay
		// attention to how that's done)
		public void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset,
            VorbisFileInstance instance)
		{
			Page og=new Page();
			int ret;
  
			vi=new Info[links];
			vc=new Comment[links];
			dataoffsets=new long[links];
			pcmlengths=new long[links];
			serialnos=new int[links];
  
			for(int i=0;i<links;i++)
			{
				if(first_i!=null && first_c!=null && i==0)
				{
					// we already grabbed the initial header earlier.  This just
					// saves the waste of grabbing it again
					// !!!!!!!!!!!!!
					vi[i]=first_i;
					//memcpy(vf->vi+i,first_i,sizeof(vorbis_info));
					vc[i]=first_c;
					//memcpy(vf->vc+i,first_c,sizeof(vorbis_comment));
					dataoffsets[i]=dataoffset;
				}
				else
				{
					// seek to the location of the initial header
                    seek_helper(offsets[i], instance); //!!!
                    if (fetch_headers(vi[i], vc[i], null, null, instance) == -1)
					{
						Console.Error.WriteLine("Error opening logical bitstream #"+(i+1)+"\n");
						dataoffsets[i]=-1;
					}
					else
					{
						dataoffsets[i]=offset;
						instance.os.clear();
					}
				}

				// get the serial number and PCM length of this link. To do this,
				// get the last page of the stream
				long end=offsets[i+1]; //!!!
                seek_helper(end, instance);

				while(true)
				{
					ret=get_prev_page(og, instance);
					if(ret==-1)
					{
						// this should not be possible
						Console.Error.WriteLine("Could not find last page of logical "+
							"bitstream #"+(i)+"\n");
						vi[i].clear();
						vc[i].clear();
						break;
					}
					if(og.granulepos()!=-1)
					{
						serialnos[i]=og.serialno();
						pcmlengths[i]=og.granulepos();
						break;
					}
				}
			}
		}
示例#7
0
        /// <summary>
        /// Begins playing the given clip.
        /// </summary>
        /// <param name="file">The clip to play.</param>
        public void Play(VorbisFileInstance clip)
        {
            DequeuUsedBuffers();

            CurrentFormat = DetermineFormat(clip);
            CurrentRate = DetermineRate(clip);

            CurrentClip = clip;
            eof = false;

            // Buffer initial audio
            int usedBuffers = 0;
            for (int i = 0; i < BufferCount; i++)
            {
                int bytesRead = clip.read(SegmentBuffer, SegmentBuffer.Length,
                    _BIGENDIANREADMODE, _WORDREADMODE, _SGNEDREADMODE, null);

                if (bytesRead > 0)
                {
                    // Buffer the segment
                    AL.BufferData(Buffers[i], CurrentFormat, SegmentBuffer, bytesRead,
                        CurrentRate);

                    usedBuffers++;
                }
                else if (bytesRead == 0)
                {
                    // Clip is too small to fill the initial buffer, so stop
                    // buffering.
                    break;
                }
                else
                {
                    // TODO: There was an error reading the file
                    throw new System.IO.IOException("Error reading or processing OGG file");
                }
            }

            // Start playing the clip
            AL.SourceQueueBuffers(Source, usedBuffers, Buffers);
            AL.SourcePlay(Source);
        }
		public int get_next_page(Page page, long boundary, VorbisFileInstance instance)
		{
			if(boundary>0) boundary+=offset;
			while(true)
			{
				int more;
				if(boundary>0 && offset>=boundary)return OV_FALSE;
                more = instance.oy.pageseek(page);
				if(more<0){offset-=more;}
				else
				{
					if(more==0)
					{
						if(boundary==0)return OV_FALSE;
						//	  if(get_data()<=0)return -1;
						int ret=get_data(instance);
						if(ret==0) return OV_EOF;
						if(ret<0) return OV_EREAD; 
					}
					else
					{
						int ret=(int)offset; //!!!
						offset+=more;
						return ret;
					}
				}
			}
		}
示例#9
0
        /// <summary>
        /// Determines the format of the given audio clip.
        /// </summary>
        /// <param name="clip">The clip to determine the format of.</param>
        /// <returns>The audio format.</returns>
        public static ALFormat DetermineFormat(VorbisFileInstance clip)
        {
            // TODO: Should probably do more than just check the format of the first stream.
            Info[] clipInfo = clip.vorbisFile.getInfo();

            if (clipInfo.Length < 1 || clipInfo[0] == null)
                throw new ArgumentException("Audio clip does not have track information");

            Info info = clipInfo[0];

            // The number of channels is determined by the clip.  The bit depth
            // however is the choice of the player.  If desired, 8-bit audio
            // could be supported here.
            if (info.channels == 1)
            {
                return ALFormat.Mono16;
            }
            else if (info.channels == 2)
            {
                return ALFormat.Stereo16;
            }
            else
            {
                throw new NotImplementedException("Only mono and stereo are implemented.  Audio has too many channels.");
            }
        }
示例#10
0
        /// <summary>
        /// Determines the rate of the given audio clip.
        /// </summary>
        /// <param name="clip">The clip to determine the rate of.</param>
        /// <returns>The audio rate.</returns>
        public int DetermineRate(VorbisFileInstance clip)
        {
            // TODO: Should probably do more than just check the format of the first stream.
            Info[] clipInfo = clip.vorbisFile.getInfo();

            if (clipInfo.Length < 1 || clipInfo[0] == null)
                throw new ArgumentException("Audio clip does not have track information");

            Info info = clipInfo[0];

            return info.rate;
        }
        // DETERMINES THE ALFORMAT FOR A GIVEN SOURCE
        public ALFormat DetermineSourceFormat(VorbisFileInstance source)
        {
            Info sourceInfo = RetrieveSourceInfo(source);

            if (sourceInfo.channels == 1)
            {
                return ALFormat.Mono16;
            }
            else if (sourceInfo.channels == 2)
            {
                return ALFormat.Stereo16;
            }
            else
            {
                throw new NotImplementedException("Only mono and stereo are implemented.  Audio has too many channels.");
            }
        }
 // PAUSE
 public void PauseSource(VorbisFileInstance source)
 {
     // TO DO
     AL.SourcePause(Source);
 }
        // PLAY
        public void PlaySource(VorbisFileInstance source)
        {
            // Remove any empty buffers
            RemoveEmptyBuffers();

            // Set up all the source parameters
            AudioFormat = DetermineSourceFormat(source);
            AudioRate = DetermineSourceRate(source);

            // Initialize the source to play
            SourceFile = source;
            FileHasEnded = false;


            // Start buffer
            int processedBuffers = 0;
            for (int i = 0; i < BufferCount; i++)
            {
                int bytesRead = source.read(SegmentBuffer, SegmentBuffer.Length, _BIGENDIANREADMODE, _WORDREADMODE, _SGNEDREADMODE, null);
                if (bytesRead > 0)
                {
                    AL.BufferData(Buffers[i], AudioFormat, SegmentBuffer, bytesRead, AudioRate);
                    processedBuffers++;
                }
                else if (bytesRead == 0)
                {
                    break;
                }
                else
                {
                    throw new System.IO.IOException("Unable to open OGG File");
                }
            }

            // Play buffered clip
            AL.SourceQueueBuffers(Source, processedBuffers, Buffers);

            AL.SourcePlay(Source);
        }
		public int get_data(VorbisFileInstance instance)
		{
			int index=instance.oy.buffer(CHUNKSIZE);
            byte[] buffer = instance.oy.data;
			//  int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource);
			int bytes=0;
			try
			{
				bytes=datasource.Read(buffer, index, CHUNKSIZE);
			}
			catch(Exception e)
			{
				Console.Error.WriteLine(e.Message);
				return OV_EREAD;
			}
            instance.oy.wrote(bytes);
			if(bytes==-1)
			{
				bytes=0;
			}
			return bytes;
		}
示例#15
0
 /// <summary>
 /// Plays the audio clip on the first free channel.
 /// </summary>
 /// <param name="clip">The audio clip to play.</param>
 public void PlayClip(VorbisFileInstance clip)
 {
     // TODO: If all channels are busy, the clip will be ignored.  There must be a more elegant way.
     foreach (AudioChannel channel in Channels)
     {
         try
         {
             if (channel.IsFree)
             {
                 channel.Play(clip);
                 return;
             }
         }
         catch (Exception e)
         {
     #if DEBUG
             Debug.Print(e.StackTrace);
     #endif
         }
     }
 }
		public void seek_helper(long offst, VorbisFileInstance instance)
		{
			//callbacks.seek_func(datasource, offst, SEEK_SET);
			fseek(datasource, offst, SEEK_SET);
			this.offset=offst;
			instance.oy.reset();
		}
        // Play Call
        public void PlayFile(VorbisFileInstance audioFile)
        {
            foreach (AudioSource source in AudioSources)
            {
                try
                {
                    if (source.IsFree)
                    {
                        source.PlaySource(audioFile);
                        return;
                    }

                }
                catch (Exception e)
                {
					//Console.WriteLine("AudioManager threw exception!");
                    //Console.WriteLine(e.StackTrace);
                }
            }
        }
        private int get_prev_page(Page page, VorbisFileInstance instance)
		{
			long begin=offset; //!!!
			int ret;
			int offst=-1;
			while(offst==-1)
			{
				begin-=CHUNKSIZE;
				if(begin<0)
					begin=0;
				seek_helper(begin, instance);
				while(offset<begin+CHUNKSIZE)
				{
					ret=get_next_page(page, begin+CHUNKSIZE-offset, instance);
					if(ret==OV_EREAD){ return OV_EREAD; }
					if(ret<0){ break; }
					else{ offst=ret; }
				}
			}
            seek_helper(offst, instance); //!!!
			ret=get_next_page(page, CHUNKSIZE, instance);
			if(ret<0)
			{
				//System.err.println("Missed page fencepost at end of logical bitstream Exiting");
				//System.exit(1);
				return OV_EFAULT;
			}
			return offst;
		}
        public void PlayFile(VorbisFileInstance audioFile, out AudioSource currentSource)
        {
            currentSource = null;
            foreach (AudioSource source in AudioSources)
            {
                try
                {
                    if (source.IsFree)
                    {
                        Thread.Sleep(500);
                        source.PlaySource(audioFile);
                        currentSource = source;
                        return;
                    }

                }
                catch (Exception e)
                {
                    //Console.WriteLine("AudioManager threw exception!");
                    //Console.WriteLine(e.StackTrace);
                    //currentSource = null;
                }
            }
        }
		// uses the local ogg_stream storage in vf; this is important for
		// non-streaming input sources
        public int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr, VorbisFileInstance instance)
		{
			//System.err.println("fetch_headers");
			Page og=new Page();
			Packet op=new Packet();
			int ret;

			if(og_ptr==null)
			{
                ret = get_next_page(og, CHUNKSIZE, instance);
				if(ret==OV_EREAD)return OV_EREAD;
				if(ret<0) return OV_ENOTVORBIS;
				og_ptr=og;
			}
  
			if(serialno!=null)serialno[0]=og_ptr.serialno();

			instance.os.init(og_ptr.serialno());
  
			// extract the initial header from the first page and verify that the
			// Ogg bitstream is in fact Vorbis data
  
			vi.init();
			vc.init();
  
			int i=0;
			while(i<3)
			{
                instance.os.pagein(og_ptr);
				while(i<3)
				{
                    int result = instance.os.packetout(op);
					if(result==0)break;
					if(result==-1)
					{
						Console.Error.WriteLine("Corrupt header in logical bitstream.");
						//goto bail_header;
						vi.clear();
						vc.clear();
                        instance.os.clear();
						return -1;
					}
					if(vi.synthesis_headerin(vc, op)!=0)
					{
						Console.Error.WriteLine("Illegal header in logical bitstream.");
						//goto bail_header;
						vi.clear();
						vc.clear();
                        instance.os.clear();
						return -1;
					}
					i++;
				}
				if(i<3)
					if(get_next_page(og_ptr, 1, instance)<0)
					{
						Console.Error.WriteLine("Missing header in logical bitstream.");
						//goto bail_header;
						vi.clear();
						vc.clear();
                        instance.os.clear();
						return -1;
					}
			}
			return 0; 
		}
 public void PauseFile(VorbisFileInstance audioFile)
 {
     foreach (AudioSource source in AudioSources)
     {
         try
         {
             source.PauseSource(audioFile);
             return;
         }
         catch (Exception e)
         {
             Console.WriteLine("issue with {0}", e);
         }
     }
 }
 public VorbisFileInstance makeInstance()
 {
     VorbisFileInstance instance = new VorbisFileInstance(this);
     return instance;
 }
        // DETERMINE THE RATE OF A GIVEN SOURCE
        public int DetermineSourceRate(VorbisFileInstance source)
        {
            Info sourceInfo = RetrieveSourceInfo(source);

            return sourceInfo.rate;
        }