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); }