Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/slmml/Track.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 93 - (hide annotations) (download)
Wed May 6 11:30:16 2009 UTC (14 years, 11 months ago) by hikarin
File size: 22274 byte(s)
[ocmml/slmml] * optimized at Track class
1 hikarin 58 /*
2     Copyright (c) 2009, hkrn All rights reserved.
3    
4     Redistribution and use in source and binary forms, with or without
5     modification, are permitted provided that the following conditions are met:
6    
7     Redistributions of source code must retain the above copyright notice, this
8     list of conditions and the following disclaimer. Redistributions in binary
9     form must reproduce the above copyright notice, this list of conditions and
10     the following disclaimer in the documentation and/or other materials
11     provided with the distribution. Neither the name of the hkrn nor
12     the names of its contributors may be used to endorse or promote products
13     derived from this software without specific prior written permission.
14    
15     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
19     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25     DAMAGE.
26     */
27    
28     //
29     // $Id$
30     //
31    
32     using System;
33 hikarin 37 using System.Collections.Generic;
34 hikarin 49 using System.Windows;
35 hikarin 37
36     namespace SlMML
37     {
38     public class Track
39     {
40     #region ���������������
41     public const int TEMPO_TRACK = 0;
42     public const int FIRST_TRACK = 1;
43     #endregion
44    
45     #region ���������������������������������������������������������
46     public Track()
47     {
48     End = false;
49     m_channel = new Channel();
50     m_events = new List<Events.Event>(32);
51     m_index = 0;
52     m_delta = 0;
53     GlobalTick = 0;
54     m_needle = 0.0;
55 hikarin 49 Duration = new Duration(TimeSpan.FromMilliseconds(0));
56 hikarin 37 BPM = DEFAULT_BPM;
57     RecordGate(15.0 / 16.0);
58     RecordGate(0);
59     }
60     #endregion
61    
62     #region ���������������������������
63 hikarin 80 public void GetSamples(ref double[] samples, int start, int end, bool update)
64 hikarin 37 {
65     if (End)
66     return;
67 hikarin 93 int eventCount = m_events.Count, i = start;
68     while (i < end)
69 hikarin 37 {
70     bool loop = false;
71     double delta = 0;
72     do
73     {
74     loop = false;
75     if (m_index < eventCount)
76     {
77     Events.Event e = m_events[m_index];
78     delta = e.Delta * m_spt;
79     if (m_needle >= delta)
80     {
81     loop = true;
82     if (e is Events.NoteOn)
83     m_channel.EnableNote((Events.NoteOn)e);
84     else if (e is Events.NoteOff)
85     m_channel.DisableNote();
86     else if (e is Events.Note)
87     m_channel.NoteIndex = ((Events.Note)(e)).Index;
88     else if (e is Events.Tempo)
89     BPM = ((Events.Tempo)e).Value;
90     else if (e is Events.Form)
91     m_channel.Form = (Events.Form)e;
92     else if (e is Events.VCO)
93     m_channel.ADSRForVCO = (Events.VCO)e;
94     else if (e is Events.VCF)
95     m_channel.ADSRForVCF = (Events.VCF)e;
96     else if (e is Events.NoiseFrequency)
97     m_channel.NoiseFrequency = ((Events.NoiseFrequency)e).Value;
98     else if (e is Events.PWM)
99     m_channel.PWM = ((Events.PWM)e).Value;
100     else if (e is Events.Pan)
101     m_channel.Pan = ((Events.Pan)e).Value;
102     else if (e is Events.Vowel)
103     m_channel.FormantVowel = ((Events.Vowel)e).Value;
104     else if (e is Events.Detune)
105     m_channel.Detune = ((Events.Detune)e).Value;
106     else if (e is Events.LFO)
107     {
108     Events.LFO lfo = (Events.LFO)e;
109     double width = lfo.Width * m_spt;
110     lfo.Delay = (int)(lfo.Delay * m_spt);
111     lfo.Time = (int)(lfo.Time * width);
112     m_channel.SetLFO(lfo, Sample.RATE / width);
113     }
114     else if (e is Events.LPF)
115     m_channel.LPF = (Events.LPF)e;
116     else if (e is Events.VolumeMode)
117     m_channel.VolumeMode = ((Events.VolumeMode)e).Value;
118     else if (e is Events.Input)
119     m_channel.Input = (Events.Input)e;
120     else if (e is Events.Output)
121     m_channel.Output = (Events.Output)e;
122 hikarin 79 else if (e is Events.Expression)
123     m_channel.Expression = ((Events.Expression)e).Value;
124 hikarin 37 else if (e is Events.Close)
125     m_channel.Close();
126     else if (e is Events.Eot)
127     End = true;
128     m_needle -= delta;
129     m_index++;
130     }
131     }
132     }
133     while (loop);
134     int di = 0;
135     if (m_index < eventCount)
136     {
137     Events.Event e = m_events[m_index];
138     delta = e.Delta * m_spt;
139     di = (int)Math.Ceiling(delta - m_needle);
140     if (i + di >= end)
141     di = end - i;
142     m_needle += di;
143     if (update)
144     m_channel.GetSamples(ref samples, i, di, end);
145     i += di;
146     }
147     else
148     break;
149     }
150     }
151    
152     public void Seek()
153     {
154     GlobalTick = 0;
155     }
156    
157     public void Seek(int delta)
158     {
159     m_delta += delta;
160     GlobalTick += (uint)delta;
161     }
162    
163     public void RecordNote(int index, int length, int velocity, bool keyOn, bool keyOff)
164     {
165     Events.Event e;
166     if (keyOn)
167     e = new Events.NoteOn() { Index = index, Velocity = velocity };
168     else
169     e = new Events.Note() { Index = index };
170     SetDeltaAndAddEvent(e);
171     if (keyOff)
172     {
173     int gate = Math.Max((int)(length * m_gate - m_gate2), 0);
174     Seek(gate);
175     e = new Events.NoteOff() { Index = index, Velocity = velocity };
176     SetDeltaAndAddEvent(e);
177     Seek(length - gate);
178     }
179     else
180     Seek(length);
181     }
182    
183     public void RecordRest(int length)
184     {
185     Seek(length);
186     }
187    
188     public void RecordRest(uint msec)
189     {
190     int length = (int)(msec * Sample.RATE / (m_spt * 1000));
191     Seek(length);
192     }
193    
194     public void RecordVolume(int volume)
195     {
196     Events.Volume e = new Events.Volume() { Value = volume };
197     SetDeltaAndAddEvent(e);
198     }
199    
200     public void RecordTempo(int tempo, uint globalTick)
201     {
202     Events.Tempo e = new Events.Tempo() { Value = tempo };
203     SetDelta(e);
204     RecordGlobalTick(globalTick, e);
205     }
206    
207     public void RecordEOT()
208     {
209     Events.Eot e = new Events.Eot() { Delta = m_delta };
210     SetDeltaAndAddEvent(e);
211     }
212    
213     public void RecordGate(double gate)
214     {
215     m_gate = gate;
216     }
217    
218     public void RecordGate(int gate)
219     {
220     m_gate2 = Math.Max(gate, 0);
221     }
222    
223     public void RecordForm(OscillatorForm form, OscillatorForm subform)
224     {
225     Events.Form e = new Events.Form() { Main = form, Sub = subform };
226     SetDeltaAndAddEvent(e);
227     }
228    
229     public void RecordNoiseFrequency(int frequency)
230     {
231     Events.NoiseFrequency e = new Events.NoiseFrequency() { Value = frequency };
232     SetDeltaAndAddEvent(e);
233     }
234    
235     public void RecordPWM(int pwm)
236     {
237     Events.PWM e = new Events.PWM() { Value = pwm };
238     SetDeltaAndAddEvent(e);
239     }
240    
241     public void RecordPan(int pan)
242     {
243     Events.Pan e = new Events.Pan() { Value = pan };
244     SetDeltaAndAddEvent(e);
245     }
246    
247     public void RecordFormantVowel(FormantVowel vowel)
248     {
249     Events.Vowel e = new Events.Vowel() { Value = vowel };
250     SetDeltaAndAddEvent(e);
251     }
252    
253     public void RecordDetune(int detune)
254     {
255     Events.Detune e = new Events.Detune() { Value = detune };
256     SetDeltaAndAddEvent(e);
257     }
258    
259     public void RecordLFO(OscillatorForm form, OscillatorForm subform, int depth, int width, int delay, int time, bool reverse)
260     {
261     Events.LFO e = new Events.LFO()
262     {
263     Main = form,
264     Sub = subform,
265     Depth = depth,
266     Width = width,
267     Delay = delay,
268     Time = time,
269     Reverse = reverse
270     };
271     SetDeltaAndAddEvent(e);
272     }
273    
274     public void RecordLPF(FilterType sw, int amount, int frequency, int resonance)
275     {
276     Events.LPF e = new Events.LPF()
277     {
278     Switch = sw,
279     Amount = amount,
280     Frequency = frequency,
281     Resonance = resonance
282     };
283     SetDeltaAndAddEvent(e);
284     }
285    
286     public void RecordVolumeMode(int mode)
287     {
288     Events.VolumeMode e = new Events.VolumeMode() { Value = mode };
289     SetDeltaAndAddEvent(e);
290     }
291    
292     public void RecordInput(int inSens, int pipe)
293     {
294     Events.Input e = new Events.Input() { Sens = inSens, Pipe = pipe };
295     SetDeltaAndAddEvent(e);
296     }
297    
298     public void RecordOutput(ChannelOutputMode mode, int pipe)
299     {
300     Events.Output e = new Events.Output() { Mode = mode, Pipe = pipe };
301     SetDeltaAndAddEvent(e);
302     }
303    
304 hikarin 79 public void RecordExpression(int expression)
305     {
306     Events.Expression e = new Events.Expression() { Value = expression };
307     SetDeltaAndAddEvent(e);
308     }
309    
310 hikarin 37 public void RecordClose()
311     {
312     Events.Close e = new Events.Close();
313     SetDeltaAndAddEvent(e);
314     }
315    
316     public void RecordEnvelopeADSR(int attack, int decay, int sustain, int release, bool isVCO)
317     {
318     Events.Event e;
319     if (isVCO)
320     e = new Events.VCO()
321     {
322     Delta = m_delta,
323     Attack = attack,
324     Decay = decay,
325     Sustain = sustain,
326     Release = release
327     };
328     else
329     e = new Events.VCF()
330     {
331     Delta = m_delta,
332     Attack = attack,
333     Decay = decay,
334     Sustain = sustain,
335     Release = release
336     };
337     SetDeltaAndAddEvent(e);
338     }
339    
340     public void ConductTracks(IList<Track> tracks)
341     {
342     int ni = m_events.Count;
343     int nj = tracks.Count;
344     uint globalSample = 0, globalTick = 0;
345     double spt = CalculateSPT(DEFAULT_BPM);
346     for (int i = 0; i < ni; i++)
347     {
348     Events.Event e = m_events[i];
349     uint delta = (uint)e.Delta;
350     globalTick += delta;
351     globalSample += (uint)(delta * spt);
352     Events.Tempo tempo = e as Events.Tempo;
353     if (tempo != null)
354     {
355     int tempoValue = tempo.Value;
356     for (int j = FIRST_TRACK; j < nj; j++)
357     {
358     Track track = tracks[j];
359     track.RecordTempo(tempoValue, globalTick);
360     spt = CalculateSPT(tempoValue);
361     }
362     }
363     }
364     uint maxGlobalTick = 0;
365     for (int j = FIRST_TRACK; j < nj; j++)
366     {
367     Track track = tracks[j];
368     uint trackGlobalTick = track.GlobalTick;
369     if (maxGlobalTick < trackGlobalTick)
370     maxGlobalTick = trackGlobalTick;
371     }
372     Events.Close close = new Events.Close();
373     RecordGlobalTick(maxGlobalTick, close);
374     globalSample += (uint)((maxGlobalTick - globalTick) * spt);
375     RecordRest((uint)3000);
376     RecordEOT();
377     globalSample += 3 * 44100;
378 hikarin 49 Duration = new Duration(TimeSpan.FromMilliseconds(globalSample * (1000.0 / Sample.RATE)));
379 hikarin 37 }
380 hikarin 86 #endregion
381 hikarin 37
382     #region ������������������������������
383     private void RecordGlobalTick(uint globalTick, Events.Event e)
384     {
385     int eventCount = m_events.Count;
386     uint preGlobalTick = 0;
387     for (int i = 0; i < eventCount; i++)
388     {
389     Events.Event ev = m_events[i];
390     uint nextTick = (uint)(preGlobalTick + ev.Delta);
391     if (nextTick >= globalTick)
392     {
393     ev.Delta = (int)(nextTick - globalTick);
394     e.Delta = (int)(globalTick - preGlobalTick);
395     m_events.Insert(i, e);
396     return;
397     }
398     preGlobalTick = nextTick;
399     }
400     e.Delta = (int)(globalTick - preGlobalTick);
401 hikarin 86 AddEvent(e);
402 hikarin 37 }
403    
404 hikarin 86 private void SetDeltaAndAddEvent(Events.Event e)
405     {
406     SetDelta(e);
407     AddEvent(e);
408     }
409    
410 hikarin 37 private void SetDelta(Events.Event e)
411     {
412     e.Delta = m_delta;
413     m_delta = 0;
414     }
415    
416 hikarin 86 private void AddEvent(Events.Event e)
417 hikarin 37 {
418     m_events.Add(e);
419     }
420    
421     private double CalculateSPT(double bpm)
422     {
423     return Sample.RATE / (bpm * 96.0 / 60.0);
424     }
425 hikarin 67 #if DEBUG
426     internal List<Dictionary<string, string>> Dump()
427     {
428     List<Dictionary<string, string>> r = new List<Dictionary<string, string>>();
429     foreach (Events.Event e in m_events)
430     {
431     Dictionary<string, string> data = new Dictionary<string, string>();
432 hikarin 68 data["status"] = e.GetType().Name;
433 hikarin 67 if (e is Events.NoteOn)
434     {
435     Events.NoteOn noteOn = (Events.NoteOn)e;
436 hikarin 68 data["index"] = noteOn.Index.ToString();
437 hikarin 67 data["velocity"] = noteOn.Velocity.ToString();
438     }
439     else if (e is Events.Note)
440 hikarin 68 data["index"] = ((Events.Note)(e)).Index.ToString();
441 hikarin 67 else if (e is Events.Tempo)
442 hikarin 68 data["bpm"] = ((Events.Tempo)e).Value.ToString();
443 hikarin 67 else if (e is Events.Form)
444     {
445     Events.Form form = (Events.Form)e;
446     data["form"] = ((int)form.Main).ToString();
447     data["subform"] = ((int)form.Sub).ToString();
448     }
449     else if (e is Events.VCO)
450     {
451     Events.VCO vco = (Events.VCO)e;
452     data["attack"] = vco.Attack.ToString();
453     data["decay"] = vco.Decay.ToString();
454     r.Add(data);
455     data = new Dictionary<string, string>();
456 hikarin 68 data["status"] = "VCO";
457 hikarin 67 data["sustain"] = vco.Sustain.ToString();
458     data["release"] = vco.Release.ToString();
459     }
460     else if (e is Events.VCF)
461     {
462     Events.VCF vcf = (Events.VCF)e;
463     data["attack"] = vcf.Attack.ToString();
464     data["decay"] = vcf.Decay.ToString();
465     r.Add(data);
466     data = new Dictionary<string, string>();
467 hikarin 68 data["status"] = "VCF";
468 hikarin 67 data["sustain"] = vcf.Sustain.ToString();
469     data["release"] = vcf.Release.ToString();
470     }
471     else if (e is Events.NoiseFrequency)
472     data["frequency"] = ((Events.NoiseFrequency)e).Value.ToString();
473     else if (e is Events.PWM)
474     data["pwm"] = ((Events.PWM)e).Value.ToString();
475     else if (e is Events.Pan)
476     data["pan"] = ((Events.Pan)e).Value.ToString();
477     else if (e is Events.Vowel)
478 hikarin 69 data["formant"] = ((int)((Events.Vowel)e).Value).ToString();
479 hikarin 67 else if (e is Events.Detune)
480     data["detune"] = ((Events.Detune)e).Value.ToString();
481     else if (e is Events.LFO)
482     {
483     Events.LFO lfo = (Events.LFO)e;
484 hikarin 69 int rv = lfo.Reverse ? -1 : 1;
485     data["form"] = ((int)lfo.Main * rv).ToString();
486 hikarin 67 data["subform"] = ((int)lfo.Sub).ToString();
487 hikarin 68 r.Add(data);
488 hikarin 69 double width = lfo.Width * m_spt;
489 hikarin 68 data = new Dictionary<string, string>();
490 hikarin 69 data["status"] = "LFO";
491 hikarin 68 data["depth"] = lfo.Depth.ToString();
492 hikarin 69 //data["width"] = (44100.0 / width).ToString();
493 hikarin 68 r.Add(data);
494     data = new Dictionary<string, string>();
495 hikarin 69 data["status"] = "LFO";
496     data["delay"] = ((lfo.Delay * m_spt)).ToString();
497     //data["time"] = ((lfo.Time * lfo.Width)).ToString();
498 hikarin 67 }
499     else if (e is Events.LPF)
500     {
501     Events.LPF lpf = (Events.LPF)e;
502     data["switch"] = ((int)lpf.Switch).ToString();
503     data["amount"] = lpf.Amount.ToString();
504 hikarin 68 r.Add(data);
505     data = new Dictionary<string, string>();
506     data["status"] = "LPF";
507 hikarin 67 data["frequency"] = lpf.Frequency.ToString();
508     data["resonance"] = lpf.Resonance.ToString();
509     }
510     else if (e is Events.VolumeMode)
511     data["volumeMode"] = ((Events.VolumeMode)e).Value.ToString();
512     else if (e is Events.Input)
513     {
514     Events.Input input = (Events.Input)e;
515     data["sens"] = input.Sens.ToString();
516     data["pipe"] = input.Pipe.ToString();
517     }
518     else if (e is Events.Output)
519     {
520     Events.Output output = (Events.Output)e;
521 hikarin 69 data["mode"] = ((int)output.Mode).ToString();
522 hikarin 67 data["pipe"] = output.Pipe.ToString();
523     }
524 hikarin 86 else if (e is Events.Expression)
525     data["expression"] = ((Events.Expression)e).Value.ToString();
526 hikarin 67 r.Add(data);
527     }
528     return r;
529     }
530     #endif
531 hikarin 37 #endregion
532    
533     #region ������������������������������
534     public bool End
535     {
536     get;
537     private set;
538     }
539    
540     public uint GlobalTick
541     {
542     get;
543     private set;
544     }
545    
546 hikarin 49 public Duration Duration
547 hikarin 37 {
548     get;
549     private set;
550     }
551    
552     public double BPM
553     {
554     get
555     {
556     return m_bpm;
557     }
558     set
559     {
560     m_bpm = value;
561     m_spt = CalculateSPT(value);
562     }
563     }
564    
565     public int EventCount
566     {
567     get
568     {
569     return m_events.Count;
570     }
571     }
572 hikarin 93
573     public Dictionary<int,int> DeltasToSeek
574     {
575     get
576     {
577     Dictionary<int, int> r = new Dictionary<int, int>();
578     int delta = 0, i = 0;
579     foreach (Events.Event e in m_events)
580     {
581     r[delta] = i;
582     delta += e.Delta;
583     i++;
584     }
585     return r;
586     }
587     }
588 hikarin 37 #endregion
589    
590     #region ���������������������������
591     public static readonly int DEFAULT_BPM = 120;
592     private Channel m_channel;
593     private List<Events.Event> m_events;
594     private int m_index;
595     private int m_delta;
596     private double m_bpm;
597     private double m_spt;
598     private double m_needle;
599     private double m_gate;
600     private double m_gate2;
601     #endregion
602     }
603     }

Properties

Name Value
svn:keywords Id

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26