Esempio n. 1
0
        private void LoadOggFile(IOggFileSource source)
        {
            m_Source       = source;
            m_CSVorbisFile = source.VorbisFile;
            m_TagLibFile   = source.TagLibFile;

            // 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", source.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", source.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();
        }
Esempio n. 2
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.");
            }
        }
Esempio n. 3
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);
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        /// <summary>
        /// Caches the given number of bytes by reading them in and discarding
        /// them.  This is useful so that when the sound if first played,
        /// there's not a delay.
        /// </summary>
        /// <param name="bytes">Then number of PCM bytes to read.</param>
        protected void Cache(int bytes)
        {
            VorbisFileInstance instance = rawClip.makeInstance();

            int totalBytes = 0;

            byte[] buffer = new byte[4096];

            while (totalBytes < bytes)
            {
                int bytesRead = instance.read(buffer, buffer.Length, 0, 2, 1, null);

                if (bytesRead <= 0)
                {
                    break;
                }

                totalBytes += bytesRead;
            }
        }
Esempio n. 6
0
        //FIXED BY ALEXEY MIKHAYLOV!!!!

        /// <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 bool ResetFile()
        {
            try
            {
                // Grab a fresh instance of the file
                if (m_CSVorbisFile == null)
                {
                    return(false);
                }
                m_CSVorbisFileInstance = m_CSVorbisFile.makeInstance();

                m_TagLibFile = null;
                m_TagLibFile = m_Source.TagLibFile;

                return(true);
            }
            catch (Exception ex)
            {
                //throw new Exception("Unable to reload OggFile [" + m_Source.FileName + "]", ex);
                return(false);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Plays the audio clip on the first free channel.
        /// </summary>
        /// <param name="clip">The audio clip to play.</param>
        public int 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(channel.Source);
                    }
                }
                catch (Exception e)
                {
#if DEBUG
                    //Debug.Print(e.StackTrace);
#endif
                }
            }

            return(-1);
        }