protected override unsafe short[] EndFrame() { // Update metronome if there is a beat. var metronome = metronomeSound; if (beat && beatIndex >= 0 && metronome != null) { metronomePlayPosition = 0; } SamplePair pair = new SamplePair(); pair.samples = base.EndFrame(); pair.metronomePosition = metronomePlayPosition; pair.metronomePitch = beatIndex == 0 ? MetronomeFirstBeatPitch : 1.0f; pair.metronomeVolume = beatIndex == 0 ? MetronomeFirstBeatVolume : 1.0f; if (metronomePlayPosition >= 0) { metronomePlayPosition += (int)(pair.samples.Length * pair.metronomePitch); if (metronome == null || metronomePlayPosition >= metronome.Length) { metronomePlayPosition = -1; } } sampleQueue.Enqueue(pair); // Wait until we have queued the maximum number of buffered frames to start // the audio thread, otherwise, we risk starving on the first frame. if (!audioStream.IsStarted && sampleQueue.Count == numBufferedFrames) { // Semaphore should be zero by now. Debug.Assert(bufferSemaphore.WaitOne(0) == false); audioStream.Start(); } return(null); }
internal static IEnumerable <string> GenerateVcfStrings([CanBeNull] IWittyerResult queryResult, [CanBeNull] IWittyerResult truthResult, [CanBeNull] string cmdLine) { if (truthResult == null && queryResult == null) { throw new InvalidOperationException( $"called {nameof(GenerateVcfStrings)} when both {nameof(truthResult)} & {nameof(queryResult)} was null!"); } if (truthResult?.IsTruth == false || queryResult?.IsTruth == true) { throw new InvalidDataException( $"Passed in the wrong {nameof(IWittyerResult)} for {nameof(truthResult)} or {nameof(queryResult)}!"); } IEnumerable <(IVcfVariant variant, bool?isTruth)> elements = ImmutableList <(IVcfVariant, bool?)> .Empty; if (truthResult != null) { var isTruthValue = queryResult == null ? null : (bool?)true; elements = elements.Concat(ProcessVariants(truthResult, isTruthValue).Select(v => (v, isTruthValue))); } if (queryResult != null) { var isTruthValue = truthResult == null ? null : (bool?)false; elements = elements.Concat(ProcessVariants(queryResult, isTruthValue).Select(v => (v, isTruthValue))); } var count = 0U; var comparer = CreateComparer(queryResult?.Contigs, truthResult?.Contigs); foreach (var line in GetMergedWittyerVcfHeaderLocal()) { yield return(line); } foreach (var line in elements.OrderBy(x => x.variant, comparer) .Select(x => ToString(x.variant, x.isTruth))) { count++; yield return(line); } if (truthResult is IMutableWittyerResult truth && queryResult is IMutableWittyerResult query && count != truth.NumEntries + query.NumEntries) { throw new InvalidDataException( "Final VCF entry count was not the same as expected. Please contact witty.er developer!"); } IEnumerable <string> GetMergedWittyerVcfHeaderLocal() { if (truthResult == null) { return(ToSingleSampleHeader(queryResult)); } if (queryResult == null) { return(ToSingleSampleHeader(truthResult)); } return(truthResult.VcfHeader.MergedWith(queryResult.VcfHeader, SamplePair.Create(truthResult.SampleName, queryResult.SampleName), cmdLine)); IEnumerable <string> ToSingleSampleHeader(IWittyerResult result) { var builder = result.VcfHeader.ToBuilder(); var wittyerLines = VcfHeaderUtils.GenerateWittyerLines( result.VcfHeader.ColumnMetaInfoLines.InfoLines.Values, result.VcfHeader.ColumnMetaInfoLines.SampleFormatLines.Values, cmdLine); foreach (var line in wittyerLines) { builder.AddLine(line); } return(builder.Build().ToStrings().Select(line => line.StartsWith(Header.MetaPrefix) ? line : Header.Prefix + Header.ColumnNames.MinimumRequiredPlusSampleFormat .FollowedWith(result.SampleName) .StringJoin(ColumnDelimiter))); } } }