Beispiel #1
0
        public DiscreteSignal GetSignal()
        {
            stopwatch.Restart();

            // unique NoteSegments
            Dictionary <(int Track, byte Channel, int DurationSamples, byte Note, byte Velocity), NoteSegment> noteSegmentsToRender = new Dictionary <(int Track, byte Channel, int DurationSamples, byte Note, byte Velocity), NoteSegment>();

            // find unique note segments
            foreach (var segment in Interpretation.NoteSegments)
            {
                // If the dictionary does not contain the segment's identifierr, add the segment
                if (!noteSegmentsToRender.ContainsKey(segment.ReuseIdentifier))
                {
                    noteSegmentsToRender[segment.ReuseIdentifier] = segment; // cache the first of a repeated signal
                }
            }

            OnProgressChanged(new GenerationProgressChangedEventArgs(1, 5, "Duplicate note consolidation", stopwatch.Elapsed));
            stopwatch.Restart();

            int notesRendered = 0;
            int totalToRender = noteSegmentsToRender.Count;

            // unique DiscreteSignals
            ConcurrentDictionary <(int Track, byte Channel, int DurationSamples, byte Note, byte Velocity), DiscreteSignal> signalCache = new ConcurrentDictionary <(int Track, byte Channel, int DurationSamples, byte Note, byte Velocity), DiscreteSignal>();

            // generate unique signals in parallel
            Parallel.ForEach(noteSegmentsToRender, segment =>
            {
                signalCache[segment.Value.ReuseIdentifier] = Render(segment.Value);

                Interlocked.Increment(ref notesRendered);
                OnProgressChanged(new NoteRenderedEventArguments(notesRendered, totalToRender, "Note rendered in parallel"));
            });

            OnProgressChanged(new GenerationProgressChangedEventArgs(2, 5, "Unique note rendering", stopwatch.Elapsed));
            stopwatch.Restart();

            float[] samples = new float[Interpretation.TotalDurationSamples];

            // assemble the final wav
            foreach (NoteSegment segment in Interpretation.NoteSegments)
            {
                DiscreteSignal segmentSignal = signalCache[segment.ReuseIdentifier];

                long startSample = segment.StartSample;

                for (long i = 0; i < segmentSignal.Samples.Length; i++)
                {
                    samples[startSample + i] = samples[startSample + i] + segmentSignal.Samples[i]; // add the samples together
                }
            }

            OnProgressChanged(new GenerationProgressChangedEventArgs(3, 5, "Wave assembly", stopwatch.Elapsed));
            stopwatch.Restart();

            DiscreteSignal signal = new DiscreteSignal(44100, samples);

            signal.ScaleAmplitude(0.9f); // adjust the samples to fit between [-1, 1] (using a value of 1 sometimes seems to cause clipping)

            OnProgressChanged(new GenerationProgressChangedEventArgs(4, 5, "Wave normalization", stopwatch.Elapsed));
            stopwatch.Stop();

            return(signal);
        }