private void verifyTree(TreeNode node, bool ancestorHasAudio, string ancestorExtAudioFile) { if (TreeNodeMustBeSkipped(node)) { return; } if (TreeNodeTriggersNewAudioFile(node) && ancestorExtAudioFile == null) { ancestorExtAudioFile = ""; } Media manSeqMedia = node.GetManagedAudioMediaOrSequenceMedia(); if (ancestorHasAudio) { DebugFix.Assert(manSeqMedia == null); } if (node.HasChannelsProperty) { ChannelsProperty chProp = node.GetChannelsProperty(); Media media = chProp.GetMedia(DestinationChannel); if (ancestorHasAudio) { DebugFix.Assert(media == null); } if (media != null) { DebugFix.Assert(media is ExternalAudioMedia); DebugFix.Assert(manSeqMedia != null); if (!ancestorHasAudio) { ExternalAudioMedia extMedia = (ExternalAudioMedia)media; ancestorHasAudio = true; if (ancestorExtAudioFile != null) { if (ancestorExtAudioFile == "") { ancestorExtAudioFile = extMedia.Uri.LocalPath; } else { DebugFix.Assert(ancestorExtAudioFile == extMedia.Uri.LocalPath); } } else { ancestorExtAudioFile = extMedia.Uri.LocalPath; } string ext = Path.GetExtension(ancestorExtAudioFile); if (!DataProviderFactory.AUDIO_WAV_EXTENSION.Equals(ext, StringComparison.OrdinalIgnoreCase)) { Debug.Fail("Verification can only be done if external media points to wav file!"); } //reportProgress(-1, @"DEBUG: " + ancestorExtAudioFile); Stream extMediaStream = new FileStream(ancestorExtAudioFile, FileMode.Open, FileAccess.Read, FileShare.None); Stream manMediaStream = null; ManagedAudioMedia manMedia = node.GetManagedAudioMedia(); #if ENABLE_SEQ_MEDIA SequenceMedia seqMedia = node.GetManagedAudioSequenceMedia(); #endif //ENABLE_SEQ_MEDIA if (manMedia != null) { #if ENABLE_SEQ_MEDIA DebugFix.Assert(seqMedia == null); #endif //ENABLE_SEQ_MEDIA DebugFix.Assert(manMedia.HasActualAudioMediaData); manMediaStream = manMedia.AudioMediaData.OpenPcmInputStream(); } else { Debug.Fail("SequenceMedia is normally removed at import time...have you tried re-importing the DAISY book ?"); #if ENABLE_SEQ_MEDIA DebugFix.Assert(seqMedia != null); DebugFix.Assert(!seqMedia.AllowMultipleTypes); DebugFix.Assert(seqMedia.ChildMedias.Count > 0); DebugFix.Assert(seqMedia.ChildMedias.Get(0) is ManagedAudioMedia); manMediaStream = seqMedia.OpenPcmInputStreamOfManagedAudioMedia(); #endif //ENABLE_SEQ_MEDIA } try { uint extMediaPcmLength; AudioLibPCMFormat pcmInfo = AudioLibPCMFormat.RiffHeaderParse(extMediaStream, out extMediaPcmLength); DebugFix.Assert(extMediaPcmLength == extMediaStream.Length - extMediaStream.Position); if (manMedia != null) { DebugFix.Assert(pcmInfo.IsCompatibleWith(manMedia.AudioMediaData.PCMFormat.Data)); } #if ENABLE_SEQ_MEDIA if (seqMedia != null) { DebugFix.Assert( pcmInfo.IsCompatibleWith( ((ManagedAudioMedia)seqMedia.ChildMedias.Get(0)).AudioMediaData.PCMFormat.Data)); } #endif //ENABLE_SEQ_MEDIA extMediaStream.Position += pcmInfo.ConvertTimeToBytes(extMedia.ClipBegin.AsLocalUnits); long manMediaStreamPosBefore = manMediaStream.Position; long extMediaStreamPosBefore = extMediaStream.Position; //DebugFix.Assert(AudioLibPCMFormat.CompareStreamData(manMediaStream, extMediaStream, (int)manMediaStream.Length)); //DebugFix.Assert(manMediaStream.Position == manMediaStreamPosBefore + manMediaStream.Length); //DebugFix.Assert(extMediaStream.Position == extMediaStreamPosBefore + manMediaStream.Length); } finally { extMediaStream.Close(); manMediaStream.Close(); } } } else { DebugFix.Assert(manSeqMedia == null); } } else { DebugFix.Assert(manSeqMedia == null); } foreach (TreeNode child in node.Children.ContentsAs_Enumerable) { verifyTree(child, ancestorHasAudio, ancestorExtAudioFile); } }
/// <summary> /// Gets an input <see cref="Stream"/> providing read access to the raw PCM audio data /// between given sub-clip begin and end times /// </summary> /// <param name="subClipBegin">The beginning of the sub-clip</param> /// <param name="subClipEnd">The end of the sub-clip</param> /// <returns>The raw PCM audio data <see cref="Stream"/></returns> /// <remarks> /// <para>Sub-clip times must be in the interval <c>[0;this.getAudioDuration()]</c>.</para> /// <para> /// The sub-clip is /// relative to clip begin of the WavClip, that if <c>this.getClipBegin()</c> /// returns <c>00:00:10</c>, <c>this.getClipEnd()</c> returns <c>00:00:50</c>, /// <c>x</c> and <c>y</c> is <c>00:00:05</c> and <c>00:00:30</c> respectively, /// then <c>this.GetAudioData(x, y)</c> will get the audio in the underlying wave audio between /// <c>00:00:15</c> and <c>00:00:40</c> /// </para> /// </remarks> public Stream OpenPcmInputStream(Time subClipBegin, Time subClipEnd) { if (subClipBegin == null) { throw new exception.MethodParameterIsNullException("subClipBegin must not be null"); } if (subClipEnd == null) { throw new exception.MethodParameterIsNullException("subClipEnd must not be null"); } if ( subClipBegin.IsLessThan(Time.Zero) || subClipEnd.IsLessThan(subClipBegin) || subClipEnd.IsGreaterThan(Duration) ) { string msg = String.Format( "subClipBegin/subClipEnd [{0};{1}] not within ([0;{2}])", subClipBegin, subClipEnd, Duration); throw new exception.MethodParameterIsOutOfBoundsException(msg); } Stream raw = DataProvider.OpenInputStream(); uint dataLength; AudioLibPCMFormat format = AudioLibPCMFormat.RiffHeaderParse(raw, out dataLength); Time rawEndTime = new Time(format.ConvertBytesToTime(dataLength)); #if DEBUG DebugFix.Assert(rawEndTime.IsEqualTo(MediaDuration)); #endif //Time rawEndTime = Time.Zero.Add(MediaDuration); // We don't call this to avoid unnecessary I/O (Strem.Open() twice) if ( ClipBegin.IsLessThan(Time.Zero) || ClipBegin.IsGreaterThan(ClipEnd) || ClipEnd.IsGreaterThan(rawEndTime) ) { string msg = String.Format( "WavClip [{0};{1}] is empty or not within the underlying wave data stream ([0;{2}])", ClipBegin, ClipEnd, rawEndTime); throw new exception.InvalidDataFormatException(msg); } /* * Time clipDuration = Duration; * if (subClipBegin.IsEqualTo(Time.Zero) && subClipEnd.IsEqualTo(Time.Zero.Add(clipDuration))) * { * // Stream.Position is at the end of the RIFF header, we need to bring it back to the begining * return new SubStream( * raw, * raw.Position, raw.Length - raw.Position); * } */ //Time rawClipBegin = new Time(ClipBegin.AsTimeSpan + subClipBegin.AsTimeSpan); //Time rawClipEnd = new Time(ClipBegin.AsTimeSpan + subClipEnd.AsTimeSpan); long ClipBegin_AsLocalUnits = ClipBegin.AsLocalUnits; long posRiffHeader = raw.Position; //44 long beginPos = posRiffHeader + format.ConvertTimeToBytes(ClipBegin_AsLocalUnits + subClipBegin.AsLocalUnits); long endPos = posRiffHeader + format.ConvertTimeToBytes(ClipBegin_AsLocalUnits + subClipEnd.AsLocalUnits); long rawLen = raw.Length; #if DEBUG long rawLenCheck = posRiffHeader + dataLength; DebugFix.Assert(rawLen == rawLenCheck); #endif if (endPos > rawLen) { //#if DEBUG // Debugger.Break(); //#endif endPos = rawLen; } long len = endPos - beginPos; return(new SubStream( raw, beginPos, len, DataProvider is FileDataProvider ? ((FileDataProvider)DataProvider).DataFileFullPath : null)); }
private static void CheckPublishedFiles(TreeNode node, Channel sourceCh, Channel destCh, Uri curWavUri_, MemoryStream curAudioData, PCMFormatInfo curPCMFormat) { Uri curWavUri = (curWavUri_ == null ? null : new Uri(curWavUri_.ToString())); if (node.HasProperties(typeof(ChannelsProperty))) { ChannelsProperty chProp = node.GetProperty <ChannelsProperty>(); ManagedAudioMedia mam = chProp.GetMedia(sourceCh) as ManagedAudioMedia; ExternalAudioMedia eam = chProp.GetMedia(destCh) as ExternalAudioMedia; Assert.AreEqual(mam == null, eam == null, "There may be external audio media if and only if there is managed audio media"); if (mam != null && eam != null) { Assert.IsTrue(mam.Duration.IsEqualTo(eam.Duration), "Duration of managed and external audio media differs"); if (eam.Uri != null) { FileStream wavFS_ = new FileStream(eam.Uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.None); Stream manAudioStream = mam.AudioMediaData.OpenPcmInputStream(); try { uint dataLength; AudioLibPCMFormat pcmInfo = AudioLibPCMFormat.RiffHeaderParse(wavFS_, out dataLength); Assert.IsTrue(pcmInfo.IsCompatibleWith(mam.AudioMediaData.PCMFormat.Data), "External audio has incompatible pcm format"); wavFS_.Position += pcmInfo.ConvertTimeToBytes(eam.ClipBegin.TimeAsMillisecondFloat); Assert.IsTrue( AudioLibPCMFormat.CompareStreamData(manAudioStream, wavFS_, (int)manAudioStream.Length), "External audio contains wrong data"); } finally { wavFS_.Close(); manAudioStream.Close(); } } if (curWavUri != null) { FileStream wavFS = new FileStream(curWavUri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.None); try { uint dataLength; AudioLibPCMFormat pcmInfo = AudioLibPCMFormat.RiffHeaderParse(wavFS, out dataLength); Assert.IsTrue(pcmInfo.IsCompatibleWith(curPCMFormat.Data), "External audio has incompatible pcm format"); curAudioData.Position = 0; Assert.AreEqual(curAudioData.Length, (long)dataLength, "External audio has unexpected length"); Assert.IsTrue( AudioLibPCMFormat.CompareStreamData(curAudioData, wavFS, (int)curAudioData.Length), "External audio contains wrong data"); } finally { wavFS.Close(); } } if (curWavUri == null) { curWavUri = new Uri(eam.Uri.ToString()); curAudioData = new MemoryStream(); curPCMFormat = mam.AudioMediaData.PCMFormat; } else if (curWavUri.ToString() != eam.Uri.ToString()) { curWavUri = new Uri(eam.Uri.ToString()); curAudioData = new MemoryStream(); curPCMFormat = mam.AudioMediaData.PCMFormat; } Assert.IsTrue(curPCMFormat.ValueEquals(mam.AudioMediaData.PCMFormat), "Managed audio has incompatible pcm format"); Stream manAudio = mam.AudioMediaData.OpenPcmInputStream(); try { media.data.StreamUtils.CopyData(manAudio, curAudioData); } finally { manAudio.Close(); } } } foreach (TreeNode child in node.Children.ContentsAs_YieldEnumerable) { CheckPublishedFiles(child, sourceCh, destCh, curWavUri, curAudioData, curPCMFormat); } }