public static void MainLoop <U>( PlayFileWithEffectsGeneratorParams <T, W> generatorParams, Synthesizer.DataOutCallbackMethod <OutputGeneric <T, U, W> > dataCallback, OutputGeneric <T, U, W> dataCallbackState, Synthesizer.StopTask stopper) { try { generatorParams.result = Synthesizer.SynthStateRec.InitializeSynthesizer( out generatorParams.synthState, generatorParams.mainWindow.Document, new List <TrackObjectRec>(), null, 0 /*FrameToStartAt*/, generatorParams.reader.SamplingRate, 1 /*Oversampling*/, generatorParams.mainWindow.Document.EnvelopeUpdateRate, (LargeBCDType)generatorParams.mainWindow.Document.DefaultBeatsPerMinute, 1 /*OverallVolumeScalingReciprocal*/, (LargeBCDType)0d /*ScanningGap*/, out generatorParams.errorInfo, TextWriter.Synchronized(generatorParams.interactionLog), generatorParams.mainWindow.Document.Deterministic, generatorParams.mainWindow.Document.Seed, new Synthesizer.AutomationSettings()); if (generatorParams.result != Synthesizer.SynthErrorCodes.eSynthDone) { return; } // HACK! generatorParams.result = Synthesizer.NewTrackEffectGenerator( generatorParams.effectSpec, generatorParams.synthState.SynthParams0, out generatorParams.synthState.ScoreEffectProcessor); if (generatorParams.result != Synthesizer.SynthErrorCodes.eSynthDone) { return; } while (!stopper.Stopped) { // TODO: shouldn't ask for nAllocatedPointsOneChannel, that's slightly inaccurate. Should // use the clock logic in SynthGenerateOneCycle -- see e.g. nActualFrames int c; if (generatorParams.reader.NumChannels == NumChannelsType.eSampleMono) { c = generatorParams.reader.ReadPoints( generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceLOffset, generatorParams.synthState.SynthParams0.nAllocatedPointsOneChannel); Synthesizer.FloatVectorCopy( generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceLOffset, generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceROffset, c); } else { c = generatorParams.reader.ReadPoints( generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.SectionWorkspaceLOffset, generatorParams.synthState.SynthParams0.nAllocatedPointsOneChannel * 2); c /= 2; Synthesizer.FloatVectorMakeUninterleaved( generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.SectionWorkspaceLOffset, generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceLOffset, generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceROffset, c); } if (c == 0) { break; } // HACK! // Should create specialized version of Synthesizer.SynthGenerateOneCycle that does this Synthesizer.UpdateStateTrackEffectGenerator( generatorParams.synthState.ScoreEffectProcessor, generatorParams.synthState.SynthParams0); Synthesizer.ApplyTrackEffectGenerator( generatorParams.synthState.ScoreEffectProcessor, generatorParams.synthState.SynthParams0.workspace, c, generatorParams.synthState.SynthParams0.ScoreWorkspaceLOffset, generatorParams.synthState.SynthParams0.ScoreWorkspaceROffset, generatorParams.synthState.SynthParams0); Synthesizer.FloatVectorMakeInterleaved( generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceLOffset, generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.ScoreWorkspaceROffset, c, generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.SectionWorkspaceLOffset); dataCallback( dataCallbackState, generatorParams.synthState.SynthParams0.workspace, generatorParams.synthState.SynthParams0.SectionWorkspaceLOffset, c); } } catch (Exception exception) { generatorParams.exception = exception; stopper.Stop(); } }