public void Initialize(Stream stream)
        {
            Contract.Ensures(_converter != null);
            Contract.Ensures(_magicCookie != IntPtr.Zero);
            Contract.Ensures(_divisor > 0);

            try
            {
                var audioFile = new NativeAudioFile(AudioFileType.M4A, stream);

                _inputDescription = audioFile.GetProperty <AudioStreamBasicDescription>(AudioFilePropertyId.DataFormat);
                if (_inputDescription.AudioFormat != AudioFormat.AppleLossless)
                {
                    throw new UnsupportedAudioException(Resources.LosslessSampleDecoderFormatError);
                }

                var outputDescription = InitializeOutputDescription(_inputDescription);

                _divisor = (float)Math.Pow(2, outputDescription.BitsPerChannel - 1);

                _converter = new NativeAudioConverter(ref _inputDescription, ref outputDescription, audioFile);

                _magicCookie = InitializeMagicCookie(audioFile, _converter);
            }
            catch (TypeInitializationException e)
            {
                if (e.InnerException != null && e.InnerException.GetType() == typeof(ExtensionInitializationException))
                {
                    throw e.InnerException;
                }
                throw;
            }
        }
        static IntPtr InitializeMagicCookie(NativeAudioFile audioFile, NativeAudioConverter converter)
        {
            Contract.Requires(audioFile != null);
            Contract.Requires(converter != null);

            uint dataSize;
            uint isWritable;

            AudioFileStatus getStatus = audioFile.GetPropertyInfo(AudioFilePropertyId.MagicCookieData, out dataSize,
                                                                  out isWritable);

            if (getStatus != AudioFileStatus.Ok)
            {
                throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                    Resources.LosslessSampleDecoderGetCookieInfoError, getStatus));
            }

            if (dataSize == 0)
            {
                return(IntPtr.Zero);
            }

            IntPtr cookie = audioFile.GetProperty(AudioFilePropertyId.MagicCookieData, dataSize);

            AudioConverterStatus setStatus = converter.SetProperty(AudioConverterPropertyId.DecompressionMagicCookie,
                                                                   dataSize, cookie);

            if (setStatus != AudioConverterStatus.Ok)
            {
                throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                    Resources.LosslessSampleDecoderSetCookieError, setStatus));
            }

            return(cookie);
        }
        AudioConverterStatus InputCallback(IntPtr handle, ref uint numberPackets, ref AudioBufferList data, IntPtr packetDescriptions, IntPtr userData)
        {
            Contract.Requires(data.Buffers.Length > 0);

            if (_buffer == null)
            {
                _buffer       = new byte[numberPackets * _audioFile.GetProperty <uint>(AudioFilePropertyId.PacketSizeUpperBound)];
                _bufferHandle = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
            }

            if (_descriptionsHandle.IsAllocated)
            {
                _descriptionsHandle.Free();
            }

            uint            numBytes;
            var             inputDescriptions = new AudioStreamPacketDescription[numberPackets];
            AudioFileStatus status            = _audioFile.ReadPackets(out numBytes, inputDescriptions, _packetIndex,
                                                                       ref numberPackets, _bufferHandle.AddrOfPinnedObject());

            if (status != AudioFileStatus.Ok)
            {
                throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.NativeAudioConverterReadError,
                                                    status));
            }

            _packetIndex += numberPackets;

            data.Buffers[0].DataByteSize = numBytes;
            data.Buffers[0].Data         = _bufferHandle.AddrOfPinnedObject();

            // If this conversion requires packet descriptions, provide them:
            if (packetDescriptions != IntPtr.Zero)
            {
                _descriptionsHandle = GCHandle.Alloc(inputDescriptions, GCHandleType.Pinned);
                Marshal.WriteIntPtr(packetDescriptions, _descriptionsHandle.AddrOfPinnedObject());
            }

            return(AudioConverterStatus.Ok);
        }