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);
        }
Example #3
0
        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));
 }
Example #5
0
 internal static extern ExtendedAudioFileStatus ExtAudioFileWrite(NativeExtendedAudioFileHandle handle, uint frames, ref AudioBufferList data);
Example #6
0
 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));
 }