/// <summary>
        /// Exports <c>this</c> to a given destination <see cref="Presentation"/>
        /// </summary>
        /// <param name="destPres">The given destination presentation</param>
        /// <returns>The exported wav audio media data</returns>
        protected override MediaData ExportProtected(Presentation destPres)
        {
            WavAudioMediaData expWAMD = destPres.MediaDataFactory.Create <WavAudioMediaData>();

            expWAMD.PCMFormat = PCMFormat.Copy();

            // it is better to export at the level of asset stream and leave the clip composition behind
            // exporting clips also exports the shared DataProvider multiple times, which increases the size exponentially
            Stream stream = this.OpenPcmInputStream();

            try
            {
                expWAMD.AppendPcmData(stream, null);
            }
            finally
            {
                stream.Close();
            }

            //foreach (WavClip clip in mWavClips)
            //{
            //expWAMD.mWavClips.Add(clip.Export(destPres));
            //}
            return(expWAMD);
        }
        public WavAudioMediaData Copy(Time timeBegin, Time timeEnd)
        {
            if (timeBegin == null || timeEnd == null)
            {
                throw new exception.MethodParameterIsNullException("Clip begin or clip end can not be null");
            }


            if (
                timeBegin.IsLessThan(Time.Zero) ||
                timeEnd.IsLessThan(Time.Zero) ||
                (timeEnd.IsGreaterThan(Time.Zero) && timeBegin.IsGreaterThan(timeEnd)) ||
                timeEnd.IsGreaterThan(AudioDuration))
            {
                throw new exception.MethodParameterIsOutOfBoundsException(
                          String.Format("The given clip times are not valid, must be between 00:00:00.000 and {0} ([{1} --> {2})",
                                        AudioDuration, timeBegin, timeEnd));
            }

            WavAudioMediaData copy = Copy();

            if (timeEnd.IsGreaterThan(Time.Zero) && timeEnd.IsLessThan(AudioDuration))
            {
                copy.RemovePcmData(timeEnd, AudioDuration);
            }

            if (timeBegin.IsGreaterThan(Time.Zero))
            {
                copy.RemovePcmData(Time.Zero, timeBegin);
            }

            return(copy);
        }
 /// <summary>
 /// Merges <c>this</c> with a given other <see cref="AudioMediaData"/>,
 /// appending the audio data of the other <see cref="AudioMediaData"/> to <c>this</c>,
 /// leaving the other <see cref="AudioMediaData"/> without audio data
 /// </summary>
 /// <param name="other">The given other AudioMediaData</param>
 /// <exception cref="exception.MethodParameterIsNullException">
 /// Thrown when <paramref name="other"/> is <c>null</c>
 /// </exception>
 /// <exception cref="exception.InvalidDataFormatException">
 /// Thrown when the PCM format of <c>this</c> is not compatible with that of <paramref name="other"/>
 /// </exception>
 public override void MergeWith(AudioMediaData other)
 {
     if (other == this)
     {
         throw new exception.OperationNotValidException("Can not merge a AudioMediaData with itself");
     }
     if (other is WavAudioMediaData)
     {
         if (!PCMFormat.Data.IsCompatibleWith(other.PCMFormat.Data))
         {
             throw new exception.InvalidDataFormatException(
                       "Can not merge this with a WavAudioMediaData with incompatible audio data");
         }
         Time thisInsertPoint       = AudioDuration;
         WavAudioMediaData otherWav = (WavAudioMediaData)other;
         mWavClips.AddRange(otherWav.mWavClips);
         Time dur = otherWav.AudioDuration;
         NotifyAudioDataInserted(this, thisInsertPoint, dur);
         otherWav.RemovePcmData(Time.Zero);
     }
     else
     {
         base.MergeWith(other);
     }
 }
        /// <summary>
        /// Part of technical solution to make copy method return correct type.
        /// In implementing classes this method should return a copy of the class instances
        /// </summary>
        /// <returns>The copy</returns>
        protected override MediaData CopyProtected()
        {
            WavAudioMediaData copy = Presentation.MediaDataFactory.Create <WavAudioMediaData>();

            copy.PCMFormat = PCMFormat.Copy();
            foreach (WavClip clip in mWavClips)
            {
                copy.mWavClips.Add(clip.Copy());
            }
            return(copy);
        }
        public void InsertPcmData(WavAudioMediaData mediaData, Time insertPoint, Time duration)
        {
            Time movingInsertPoint          = insertPoint.Copy();
            Time remainingAvailableDuration = duration.Copy();

            foreach (WavClip wavClip in mediaData.mWavClips)
            {
                Time wavClipDur = wavClip.Duration;

                if (wavClipDur.IsLessThan(remainingAvailableDuration) ||
                    wavClipDur.IsEqualTo(remainingAvailableDuration))
                {
                    InsertPcmData(wavClip.Copy(), movingInsertPoint, wavClipDur);
                    movingInsertPoint.Add(wavClipDur);
                    remainingAvailableDuration.Substract(wavClipDur);

                    if (remainingAvailableDuration.IsLessThan(Time.Zero) ||
                        remainingAvailableDuration.IsEqualTo(Time.Zero))
                    {
                        break;
                    }
                }
                else
                {
                    WavClip smallerClip = wavClip.Copy();
                    smallerClip.ClipEnd = smallerClip.ClipBegin.Copy();
                    smallerClip.ClipEnd.Add(remainingAvailableDuration);

                    InsertPcmData(smallerClip, movingInsertPoint, remainingAvailableDuration);

                    //Stream stream = wavClip.OpenPcmInputStream(Time.Zero,
                    //    new Time(wavClip.ClipBegin.AsTimeSpan + remainingAvailableDuration.AsTimeSpan));
                    //try
                    //{
                    //    InsertPcmData(stream, movingInsertPoint, remainingAvailableDuration);
                    //}
                    //finally
                    //{
                    //    stream.Close();
                    //}
                    break;
                }
            }
        }
        public override bool ValueEquals(WithPresentation other)
        {
            if (!base.ValueEquals(other))
            {
                return(false);
            }

            WavAudioMediaData otherz = other as WavAudioMediaData;

            if (otherz == null)
            {
                return(false);
            }

            //Here we do not compare the WavClip/FileDataProvider equality. Instead, we let the super class compare the resulting streams of PCM data.
            //See AudioMediaData.ValueEquals();

            return(true);
        }
        /// <summary>
        /// Splits the audio media data at a given split point in time,
        /// <c>this</c> retaining the audio before the split point,
        /// creating a new <see cref="WavAudioMediaData"/> containing the audio after the split point
        /// </summary>
        /// <param name="splitPoint">The given split point</param>
        /// <returns>A audio media data containing the audio after the split point</returns>
        /// <exception cref="exception.MethodParameterIsNullException">
        /// Thrown when the given split point is <c>null</c>
        /// </exception>
        /// <exception cref="exception.MethodParameterIsOutOfBoundsException">
        /// Thrown when the given split point is negative or is beyond the duration of <c>this</c>
        /// </exception>
        public override AudioMediaData Split(Time splitPoint)
        {
            if (splitPoint == null)
            {
                throw new exception.MethodParameterIsNullException(
                          "The split point can not be null");
            }
            if (splitPoint.IsNegative)
            {
                throw new exception.MethodParameterIsOutOfBoundsException(
                          "The split point can not be negative");
            }
            if (splitPoint.IsGreaterThan(AudioDuration))
            {
                throw new exception.MethodParameterIsOutOfBoundsException(
                          String.Format(
                              "Split point {0} is beyond the WavAudioMediaData end - audio length is {1}",
                              splitPoint, AudioDuration));
            }
            WavAudioMediaData oWAMD =
                Presentation.MediaDataFactory.Create <WavAudioMediaData>();

            if (oWAMD == null)
            {
                throw new exception.FactoryCannotCreateTypeException(String.Format(
                                                                         "Thrown if the MediaDataFactory can not create a WacAudioMediaData matching Xuk QName {1}:{0}",
                                                                         GetXukName(), GetXukNamespace()));
            }
            oWAMD.PCMFormat = PCMFormat.Copy();

            Time originalDuration = AudioDuration;
            Time newClipDuration  = AudioDuration.GetDifference(splitPoint);

            Time           curClip_Begin = Time.Zero;
            List <WavClip> clips         = new List <WavClip>(mWavClips);

            mWavClips.Clear();
            oWAMD.mWavClips.Clear();
            for (int i = 0; i < clips.Count; i++)
            {
                WavClip curClip = clips[i];
                Time    savedCurClipDuration = curClip.Duration;

                Time curClip_End = new Time(curClip_Begin.AsTimeSpanTicks + curClip.Duration.AsTimeSpanTicks, true);
                if (splitPoint.IsLessThanOrEqualTo(curClip_Begin))
                {
                    oWAMD.mWavClips.Add(curClip);
                }
                else if (splitPoint.IsLessThan(curClip_End))
                {
                    WavClip secondPartClip = new WavClip(
                        curClip.DataProvider,
                        curClip.ClipBegin,
                        curClip.IsClipEndTiedToEOM ? null : curClip.ClipEnd);

                    curClip.ClipEnd = new Time(curClip.ClipBegin.AsTimeSpanTicks + (splitPoint.AsTimeSpanTicks - curClip_Begin.AsTimeSpanTicks), true);

                    secondPartClip.ClipBegin = curClip.ClipEnd.Copy();
                    mWavClips.Add(curClip);
                    oWAMD.mWavClips.Add(secondPartClip);
                }
                else
                {
                    mWavClips.Add(curClip);
                }
                curClip_Begin.Add(savedCurClipDuration);
            }
            NotifyAudioDataRemoved(this, splitPoint, newClipDuration);
            oWAMD.NotifyAudioDataInserted(oWAMD, Time.Zero, newClipDuration);

#if DEBUG
            DebugFix.Assert(AudioLibPCMFormat.TimesAreEqualWithMillisecondsTolerance(
                                newClipDuration.AsLocalUnits,
                                oWAMD.AudioDuration.AsLocalUnits));

            DebugFix.Assert(newClipDuration.IsEqualTo(oWAMD.AudioDuration));



            DebugFix.Assert(AudioLibPCMFormat.TimesAreEqualWithMillisecondsTolerance(
                                this.AudioDuration.AsLocalUnits + oWAMD.AudioDuration.AsLocalUnits,
                                originalDuration.AsLocalUnits));

            Time copy = this.AudioDuration.Copy();
            copy.Add(oWAMD.AudioDuration);
            DebugFix.Assert(originalDuration.IsEqualTo(copy));
#endif //DEBUG

            return(oWAMD);
        }