/// <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); }
/// <summary>Constructor - Supports opening a FLAC file</summary> public FLACFileReader(string 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); }
/// <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; lock (m_repositionLock) { m_NAudioSampleBuffer = playbackSampleBuffer; m_playbackBufferOffset = offset; // 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); }