public SampleCollection DecodeSamples() { Contract.Ensures(_buffer != null); Contract.Ensures(Contract.Result <SampleCollection>() != null); uint sampleCount = 4096; if (_buffer == null) { _buffer = new int[sampleCount * _inputDescription.ChannelsPerFrame]; } GCHandle handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned); try { var bufferList = new AudioBufferList { NumberBuffers = 1, Buffers = new AudioBuffer[1] }; bufferList.Buffers[0].NumberChannels = _inputDescription.ChannelsPerFrame; bufferList.Buffers[0].DataByteSize = (uint)(_buffer.Length); bufferList.Buffers[0].Data = handle.AddrOfPinnedObject(); AudioConverterStatus status = _converter.FillBuffer(ref sampleCount, ref bufferList, null); if (status != AudioConverterStatus.Ok) { throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.LosslessSampleDecoderFillBufferError, status)); } SampleCollection result = SampleCollectionFactory.Instance.Create((int)_inputDescription.ChannelsPerFrame, (int)sampleCount); // De-interlace the output buffer into the new sample collection, converting to floating point values: var index = 0; for (var sample = 0; sample < result.SampleCount; sample++) { for (var channel = 0; channel < result.Channels; channel++) { result[channel][sample] = _buffer[index++] / _divisor; } } return(result); } finally { handle.Free(); } }
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); }
public void Submit(SampleCollection samples) { Contract.Ensures(_buffer != null); if (_buffer == null) { _buffer = new int[samples.SampleCount * samples.Channels]; } if (!samples.IsLast) { var index = 0; for (var sample = 0; sample < samples.SampleCount; sample++) { for (var channel = 0; channel < samples.Channels; channel++) { _buffer[index++] = (int)Math.Round(samples[channel][sample] * _multiplier); } } GCHandle handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned); try { var bufferList = new AudioBufferList { NumberBuffers = 1, Buffers = new AudioBuffer[1] }; bufferList.Buffers[0].NumberChannels = (uint)samples.Channels; bufferList.Buffers[0].DataByteSize = (uint)(index * Marshal.SizeOf <int>()); bufferList.Buffers[0].Data = handle.AddrOfPinnedObject(); ExtendedAudioFileStatus status = _audioFile.Write(bufferList, (uint)samples.SampleCount); if (status != ExtendedAudioFileStatus.Ok) { throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.SampleEncoderWriteError, status)); } } finally { handle.Free(); } } else { _audioFile.Dispose(); // Call an external MP4 encoder for writing iTunes-compatible atoms: _stream.Position = 0; ExportFactory <IMetadataEncoder> metadataEncoderFactory = ExtensionProvider.GetFactories <IMetadataEncoder>("Extension", EncoderInfo.FileExtension) .SingleOrDefault(); if (metadataEncoderFactory == null) { throw new ExtensionInitializationException(string.Format(CultureInfo.CurrentCulture, Resources.SampleEncoderMetadataEncoderError, EncoderInfo.FileExtension)); } using (ExportLifetimeContext <IMetadataEncoder> metadataEncoderLifetime = metadataEncoderFactory.CreateExport()) metadataEncoderLifetime.Value.WriteMetadata(_stream, _metadata, _settings); } }
internal AudioConverterStatus FillBuffer(ref uint packetSize, ref AudioBufferList outputBuffer, AudioStreamPacketDescription[] packetDescriptions) { return(SafeNativeMethods.AudioConverterFillComplexBuffer(_handle, _inputCallback, IntPtr.Zero, ref packetSize, ref outputBuffer, packetDescriptions)); }
internal static extern ExtendedAudioFileStatus ExtAudioFileWrite(NativeExtendedAudioFileHandle handle, uint frames, ref AudioBufferList data);
internal static extern AudioConverterStatus AudioConverterFillComplexBuffer(NativeAudioConverterHandle handle, AudioConverterComplexInputCallback inputCallback, IntPtr userData, ref uint packetSize, ref AudioBufferList outputData, [In, Out] AudioStreamPacketDescription[] packetDescriptions);
internal ExtendedAudioFileStatus Write(AudioBufferList data, uint frames) { return(SafeNativeMethods.ExtAudioFileWrite(_handle, frames, ref data)); }