示例#1
0
        /// <summary>
        /// FLAC Write Call Back - libFlac notifies back on a frame that was read from the source file and written as a frame
        /// </summary>
        /// <param name="context"></param>
        /// <param name="frame"></param>
        /// <param name="buffer"></param>
        /// <param name="clientData"></param>
        private void FLAC_WriteCallback(IntPtr context, IntPtr frame, IntPtr buffer, IntPtr clientData)
        {
            // Read the FLAC Frame into a memory samples buffer (m_flacSamples)
            LibFLACSharp.FlacFrame flacFrame = (LibFLACSharp.FlacFrame)Marshal.PtrToStructure(frame, typeof(LibFLACSharp.FlacFrame));

            if (m_flacSamples == null)
            {
                // First time - Create Flac sample buffer
                m_samplesPerChannel = flacFrame.Header.BlockSize;
                m_flacSamples       = new int[m_samplesPerChannel * m_flacStreamInfo.Channels];
                m_flacSampleIndex   = 0;
            }

            // Iterate on all channels, copy the unmanaged channel bits (samples) to the a managed samples array
            for (int inputChannel = 0; inputChannel < m_flacStreamInfo.Channels; inputChannel++)
            {
                // Get pointer to channel bits, for the current channel
                IntPtr pChannelBits = Marshal.ReadIntPtr(buffer, inputChannel * IntPtr.Size);

                // Copy the unmanaged bits to managed memory
                Marshal.Copy(pChannelBits, m_flacSamples, inputChannel * m_samplesPerChannel, m_samplesPerChannel);
            }

            lock (m_repositionLock)
            {
                // Keep the current sample number for reporting purposes (See: Position property of FlacFileReader)
                m_lastSampleNumber = flacFrame.Header.FrameOrSampleNumber;

                if (m_repositionRequested)
                {
                    m_repositionRequested = false;
                    FLACCheck(LibFLACSharp.FLAC__stream_decoder_seek_absolute(m_decoderContext, m_flacReposition), "Could not seek absolute: " + m_flacReposition);
                }
            }
        }
示例#2
0
        /// <summary>
        /// Disposes this WaveStream
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (m_decoderContext != IntPtr.Zero)
                {
                    FLACCheck(
                        LibFLACSharp.FLAC__stream_decoder_finish(m_decoderContext),
                        "finalize stream decoder");

                    FLACCheck(
                        LibFLACSharp.FLAC__stream_decoder_delete(m_decoderContext),
                        "dispose of stream decoder instance");

                    m_decoderContext = IntPtr.Zero;
                }

                if (m_stream != null)
                {
                    m_stream.Close();
                    m_stream.Dispose();
                    m_stream = null;
                }

                if (m_reader != null)
                {
                    m_reader.Close();
                    m_reader = null;
                }
            }
            base.Dispose(disposing);
        }
示例#3
0
        /// <summary>Constructor - Supports opening a FLAC file</summary>
        public FLACFileReader(string flacFileName)
        {
            Console.WriteLine("FLACFileReader: " + flacFileName);
            // Open the flac file for reading through a binary reader
            m_stream = File.OpenRead(flacFileName);
            m_reader = new BinaryReader(m_stream);
            // Create the FLAC decoder
            m_decoderContext = LibFLACSharp.FLAC__stream_decoder_new();

            if (m_decoderContext == IntPtr.Zero)
            {
                throw new ApplicationException("FLAC: Could not initialize stream decoder!");
            }

            // Create call back delegates
            m_writeCallback    = new LibFLACSharp.Decoder_WriteCallback(FLAC_WriteCallback);
            m_metadataCallback = new LibFLACSharp.Decoder_MetadataCallback(FLAC_MetadataCallback);
            m_errorCallback    = new LibFLACSharp.Decoder_ErrorCallback(FLAC_ErrorCallback);

            // Initialize the FLAC decoder
            if (LibFLACSharp.FLAC__stream_decoder_init_file(m_decoderContext,
                                                            flacFileName, m_writeCallback, m_metadataCallback, m_errorCallback,
                                                            IntPtr.Zero) != 0)
            {
                throw new ApplicationException("FLAC: Could not open stream for reading!");
            }

            // Process the meta-data (but not the audio frames) so we can prepare the NAudio wave format
            FLACCheck(
                LibFLACSharp.FLAC__stream_decoder_process_until_end_of_metadata(m_decoderContext),
                "Could not process until end of metadata");

            // Initialize NAudio wave format
            m_waveFormat = new WaveFormat(m_flacStreamInfo.SampleRate, m_flacStreamInfo.BitsPerSample, m_flacStreamInfo.Channels);

            Console.WriteLine("Total FLAC Samples: {0}", LibFLACSharp.FLAC__stream_decoder_get_total_samples(m_decoderContext));
        }
示例#4
0
        /// <summary>
        /// Reads decompressed PCM data from our FLAC file into the NAudio playback sample buffer
        /// </summary>
        /// <remarks>
        /// 1. The original code did not stop on end of stream. tomislavtustonic applied a fix using FLAC__stream_decoder_get_state. <seealso cref="https://code.google.com/p/practicesharp/issues/detail?id=14"/>
        /// </remarks>
        public override int Read(byte[] playbackSampleBuffer, int offset, int numBytes)
        {
            int flacBytesCopied = 0;

            m_NAudioSampleBuffer   = playbackSampleBuffer;
            m_playbackBufferOffset = offset;

            lock (m_repositionLock)
            {
                // If there are still samples in the flac buffer, use them first before reading the next FLAC frame
                if (m_flacSampleIndex > 0)
                {
                    flacBytesCopied = CopyFlacBufferToNAudioBuffer();
                }
            }
            var decoderState = LibFLACSharp.FLAC__stream_decoder_get_state(m_decoderContext);

            // Keep reading flac packets until enough bytes have been copied
            while (flacBytesCopied < numBytes)
            {
                // Read the next PCM bytes from the FLAC File into the sample buffer
                FLACCheck(
                    LibFLACSharp.FLAC__stream_decoder_process_single(m_decoderContext),
                    "process single");
                decoderState = LibFLACSharp.FLAC__stream_decoder_get_state(m_decoderContext);
                if (decoderState == LibFLACSharp.StreamDecoderState.EndOfStream)
                {
                    break;
                }
                else
                {
                    flacBytesCopied += CopyFlacBufferToNAudioBuffer();
                }
            }

            return(flacBytesCopied);
        }
 /// <summary>
 /// FLAC Error Call Back - libFlac notifies about a decoding error
 /// </summary>
 /// <param name="context"></param>
 /// <param name="status"></param>
 /// <param name="userData"></param>
 private void FLAC_ErrorCallback(IntPtr context, LibFLACSharp.DecodeError status, IntPtr userData)
 {
     throw new ApplicationException(string.Format("FLAC: Could not decode frame: {0}!", status));
 }