Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/slmml/Track.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 80 - (hide annotations) (download)
Fri May 1 13:41:09 2009 UTC (14 years, 11 months ago) by hikarin
File size: 21600 byte(s)
[ocmml/slmml] * changed short to double at GetSamples()
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     for (int i = start; i < end; )
68     {
69     bool loop = false;
70     double delta = 0;
71     int eventCount = m_events.Count;
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     #endregion
381    
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     m_events.Add(e);
402     }
403    
404     private void SetDelta(Events.Event e)
405     {
406     e.Delta = m_delta;
407     m_delta = 0;
408     }
409    
410     private void SetDeltaAndAddEvent(Events.Event e)
411     {
412     SetDelta(e);
413     m_events.Add(e);
414     }
415    
416     private double CalculateSPT(double bpm)
417     {
418     return Sample.RATE / (bpm * 96.0 / 60.0);
419     }
420 hikarin 67 #if DEBUG
421     internal List<Dictionary<string, string>> Dump()
422     {
423     List<Dictionary<string, string>> r = new List<Dictionary<string, string>>();
424     foreach (Events.Event e in m_events)
425     {
426     Dictionary<string, string> data = new Dictionary<string, string>();
427 hikarin 68 data["status"] = e.GetType().Name;
428 hikarin 67 if (e is Events.NoteOn)
429     {
430     Events.NoteOn noteOn = (Events.NoteOn)e;
431 hikarin 68 data["index"] = noteOn.Index.ToString();
432 hikarin 67 data["velocity"] = noteOn.Velocity.ToString();
433     }
434     else if (e is Events.Note)
435 hikarin 68 data["index"] = ((Events.Note)(e)).Index.ToString();
436 hikarin 67 else if (e is Events.Tempo)
437 hikarin 68 data["bpm"] = ((Events.Tempo)e).Value.ToString();
438 hikarin 67 else if (e is Events.Form)
439     {
440     Events.Form form = (Events.Form)e;
441     data["form"] = ((int)form.Main).ToString();
442     data["subform"] = ((int)form.Sub).ToString();
443     }
444     else if (e is Events.VCO)
445     {
446     Events.VCO vco = (Events.VCO)e;
447     data["attack"] = vco.Attack.ToString();
448     data["decay"] = vco.Decay.ToString();
449     r.Add(data);
450     data = new Dictionary<string, string>();
451 hikarin 68 data["status"] = "VCO";
452 hikarin 67 data["sustain"] = vco.Sustain.ToString();
453     data["release"] = vco.Release.ToString();
454     }
455     else if (e is Events.VCF)
456     {
457     Events.VCF vcf = (Events.VCF)e;
458     data["attack"] = vcf.Attack.ToString();
459     data["decay"] = vcf.Decay.ToString();
460     r.Add(data);
461     data = new Dictionary<string, string>();
462 hikarin 68 data["status"] = "VCF";
463 hikarin 67 data["sustain"] = vcf.Sustain.ToString();
464     data["release"] = vcf.Release.ToString();
465     }
466     else if (e is Events.NoiseFrequency)
467     data["frequency"] = ((Events.NoiseFrequency)e).Value.ToString();
468     else if (e is Events.PWM)
469     data["pwm"] = ((Events.PWM)e).Value.ToString();
470     else if (e is Events.Pan)
471     data["pan"] = ((Events.Pan)e).Value.ToString();
472     else if (e is Events.Vowel)
473 hikarin 69 data["formant"] = ((int)((Events.Vowel)e).Value).ToString();
474 hikarin 67 else if (e is Events.Detune)
475     data["detune"] = ((Events.Detune)e).Value.ToString();
476     else if (e is Events.LFO)
477     {
478     Events.LFO lfo = (Events.LFO)e;
479 hikarin 69 int rv = lfo.Reverse ? -1 : 1;
480     data["form"] = ((int)lfo.Main * rv).ToString();
481 hikarin 67 data["subform"] = ((int)lfo.Sub).ToString();
482 hikarin 68 r.Add(data);
483 hikarin 69 double width = lfo.Width * m_spt;
484 hikarin 68 data = new Dictionary<string, string>();
485 hikarin 69 data["status"] = "LFO";
486 hikarin 68 data["depth"] = lfo.Depth.ToString();
487 hikarin 69 //data["width"] = (44100.0 / width).ToString();
488 hikarin 68 r.Add(data);
489     data = new Dictionary<string, string>();
490 hikarin 69 data["status"] = "LFO";
491     data["delay"] = ((lfo.Delay * m_spt)).ToString();
492     //data["time"] = ((lfo.Time * lfo.Width)).ToString();
493 hikarin 67 }
494     else if (e is Events.LPF)
495     {
496     Events.LPF lpf = (Events.LPF)e;
497     data["switch"] = ((int)lpf.Switch).ToString();
498     data["amount"] = lpf.Amount.ToString();
499 hikarin 68 r.Add(data);
500     data = new Dictionary<string, string>();
501     data["status"] = "LPF";
502 hikarin 67 data["frequency"] = lpf.Frequency.ToString();
503     data["resonance"] = lpf.Resonance.ToString();
504     }
505     else if (e is Events.VolumeMode)
506     data["volumeMode"] = ((Events.VolumeMode)e).Value.ToString();
507     else if (e is Events.Input)
508     {
509     Events.Input input = (Events.Input)e;
510     data["sens"] = input.Sens.ToString();
511     data["pipe"] = input.Pipe.ToString();
512     }
513     else if (e is Events.Output)
514     {
515     Events.Output output = (Events.Output)e;
516 hikarin 69 data["mode"] = ((int)output.Mode).ToString();
517 hikarin 67 data["pipe"] = output.Pipe.ToString();
518     }
519     r.Add(data);
520     }
521     return r;
522     }
523     #endif
524 hikarin 37 #endregion
525    
526     #region ������������������������������
527     public bool End
528     {
529     get;
530     private set;
531     }
532    
533     public uint GlobalTick
534     {
535     get;
536     private set;
537     }
538    
539 hikarin 49 public Duration Duration
540 hikarin 37 {
541     get;
542     private set;
543     }
544    
545     public double BPM
546     {
547     get
548     {
549     return m_bpm;
550     }
551     set
552     {
553     m_bpm = value;
554     m_spt = CalculateSPT(value);
555     }
556     }
557    
558     public int EventCount
559     {
560     get
561     {
562     return m_events.Count;
563     }
564     }
565     #endregion
566    
567     #region ���������������������������
568     public static readonly int DEFAULT_BPM = 120;
569     private Channel m_channel;
570     private List<Events.Event> m_events;
571     private int m_index;
572     private int m_delta;
573     private double m_bpm;
574     private double m_spt;
575     private double m_needle;
576     private double m_gate;
577     private double m_gate2;
578     #endregion
579     }
580     }

Properties

Name Value
svn:keywords Id

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