Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/slmml/Track.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 67 - (hide annotations) (download)
Sun Apr 26 13:48:12 2009 UTC (14 years, 11 months ago) by hikarin
File size: 21207 byte(s)
[ocmml/slmml] * added Dump method for SlMML's test
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     public void GetSamples(ref short[] samples, int start, int end, bool update)
64     {
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     else if (e is Events.Close)
123     m_channel.Close();
124     else if (e is Events.Eot)
125     End = true;
126     m_needle -= delta;
127     m_index++;
128     }
129     }
130     }
131     while (loop);
132     int di = 0;
133     if (m_index < eventCount)
134     {
135     Events.Event e = m_events[m_index];
136     delta = e.Delta * m_spt;
137     di = (int)Math.Ceiling(delta - m_needle);
138     if (i + di >= end)
139     di = end - i;
140     m_needle += di;
141     if (update)
142     m_channel.GetSamples(ref samples, i, di, end);
143     i += di;
144     }
145     else
146     break;
147     }
148     }
149    
150     public void Seek()
151     {
152     GlobalTick = 0;
153     }
154    
155     public void Seek(int delta)
156     {
157     m_delta += delta;
158     GlobalTick += (uint)delta;
159     }
160    
161     public void RecordNote(int index, int length, int velocity, bool keyOn, bool keyOff)
162     {
163     Events.Event e;
164     if (keyOn)
165     e = new Events.NoteOn() { Index = index, Velocity = velocity };
166     else
167     e = new Events.Note() { Index = index };
168     SetDeltaAndAddEvent(e);
169     if (keyOff)
170     {
171     int gate = Math.Max((int)(length * m_gate - m_gate2), 0);
172     Seek(gate);
173     e = new Events.NoteOff() { Index = index, Velocity = velocity };
174     SetDeltaAndAddEvent(e);
175     Seek(length - gate);
176     }
177     else
178     Seek(length);
179     }
180    
181     public void RecordRest(int length)
182     {
183     Seek(length);
184     }
185    
186     public void RecordRest(uint msec)
187     {
188     int length = (int)(msec * Sample.RATE / (m_spt * 1000));
189     Seek(length);
190     }
191    
192     public void RecordVolume(int volume)
193     {
194     Events.Volume e = new Events.Volume() { Value = volume };
195     SetDeltaAndAddEvent(e);
196     }
197    
198     public void RecordTempo(int tempo, uint globalTick)
199     {
200     Events.Tempo e = new Events.Tempo() { Value = tempo };
201     SetDelta(e);
202     RecordGlobalTick(globalTick, e);
203     }
204    
205     public void RecordEOT()
206     {
207     Events.Eot e = new Events.Eot() { Delta = m_delta };
208     SetDeltaAndAddEvent(e);
209     }
210    
211     public void RecordGate(double gate)
212     {
213     m_gate = gate;
214     }
215    
216     public void RecordGate(int gate)
217     {
218     m_gate2 = Math.Max(gate, 0);
219     }
220    
221     public void RecordForm(OscillatorForm form, OscillatorForm subform)
222     {
223     Events.Form e = new Events.Form() { Main = form, Sub = subform };
224     SetDeltaAndAddEvent(e);
225     }
226    
227     public void RecordNoiseFrequency(int frequency)
228     {
229     Events.NoiseFrequency e = new Events.NoiseFrequency() { Value = frequency };
230     SetDeltaAndAddEvent(e);
231     }
232    
233     public void RecordPWM(int pwm)
234     {
235     Events.PWM e = new Events.PWM() { Value = pwm };
236     SetDeltaAndAddEvent(e);
237     }
238    
239     public void RecordPan(int pan)
240     {
241     Events.Pan e = new Events.Pan() { Value = pan };
242     SetDeltaAndAddEvent(e);
243     }
244    
245     public void RecordFormantVowel(FormantVowel vowel)
246     {
247     Events.Vowel e = new Events.Vowel() { Value = vowel };
248     SetDeltaAndAddEvent(e);
249     }
250    
251     public void RecordDetune(int detune)
252     {
253     Events.Detune e = new Events.Detune() { Value = detune };
254     SetDeltaAndAddEvent(e);
255     }
256    
257     public void RecordLFO(OscillatorForm form, OscillatorForm subform, int depth, int width, int delay, int time, bool reverse)
258     {
259     Events.LFO e = new Events.LFO()
260     {
261     Main = form,
262     Sub = subform,
263     Depth = depth,
264     Width = width,
265     Delay = delay,
266     Time = time,
267     Reverse = reverse
268     };
269     SetDeltaAndAddEvent(e);
270     }
271    
272     public void RecordLPF(FilterType sw, int amount, int frequency, int resonance)
273     {
274     Events.LPF e = new Events.LPF()
275     {
276     Switch = sw,
277     Amount = amount,
278     Frequency = frequency,
279     Resonance = resonance
280     };
281     SetDeltaAndAddEvent(e);
282     }
283    
284     public void RecordVolumeMode(int mode)
285     {
286     Events.VolumeMode e = new Events.VolumeMode() { Value = mode };
287     SetDeltaAndAddEvent(e);
288     }
289    
290     public void RecordInput(int inSens, int pipe)
291     {
292     Events.Input e = new Events.Input() { Sens = inSens, Pipe = pipe };
293     SetDeltaAndAddEvent(e);
294     }
295    
296     public void RecordOutput(ChannelOutputMode mode, int pipe)
297     {
298     Events.Output e = new Events.Output() { Mode = mode, Pipe = pipe };
299     SetDeltaAndAddEvent(e);
300     }
301    
302     public void RecordClose()
303     {
304     Events.Close e = new Events.Close();
305     SetDeltaAndAddEvent(e);
306     }
307    
308     public void RecordEnvelopeADSR(int attack, int decay, int sustain, int release, bool isVCO)
309     {
310     Events.Event e;
311     if (isVCO)
312     e = new Events.VCO()
313     {
314     Delta = m_delta,
315     Attack = attack,
316     Decay = decay,
317     Sustain = sustain,
318     Release = release
319     };
320     else
321     e = new Events.VCF()
322     {
323     Delta = m_delta,
324     Attack = attack,
325     Decay = decay,
326     Sustain = sustain,
327     Release = release
328     };
329     SetDeltaAndAddEvent(e);
330     }
331    
332     public void ConductTracks(IList<Track> tracks)
333     {
334     int ni = m_events.Count;
335     int nj = tracks.Count;
336     uint globalSample = 0, globalTick = 0;
337     double spt = CalculateSPT(DEFAULT_BPM);
338     for (int i = 0; i < ni; i++)
339     {
340     Events.Event e = m_events[i];
341     uint delta = (uint)e.Delta;
342     globalTick += delta;
343     globalSample += (uint)(delta * spt);
344     Events.Tempo tempo = e as Events.Tempo;
345     if (tempo != null)
346     {
347     int tempoValue = tempo.Value;
348     for (int j = FIRST_TRACK; j < nj; j++)
349     {
350     Track track = tracks[j];
351     track.RecordTempo(tempoValue, globalTick);
352     spt = CalculateSPT(tempoValue);
353     }
354     }
355     }
356     uint maxGlobalTick = 0;
357     for (int j = FIRST_TRACK; j < nj; j++)
358     {
359     Track track = tracks[j];
360     uint trackGlobalTick = track.GlobalTick;
361     if (maxGlobalTick < trackGlobalTick)
362     maxGlobalTick = trackGlobalTick;
363     }
364     Events.Close close = new Events.Close();
365     RecordGlobalTick(maxGlobalTick, close);
366     globalSample += (uint)((maxGlobalTick - globalTick) * spt);
367     RecordRest((uint)3000);
368     RecordEOT();
369     globalSample += 3 * 44100;
370 hikarin 49 Duration = new Duration(TimeSpan.FromMilliseconds(globalSample * (1000.0 / Sample.RATE)));
371 hikarin 37 }
372     #endregion
373    
374     #region ������������������������������
375     private void RecordGlobalTick(uint globalTick, Events.Event e)
376     {
377     int eventCount = m_events.Count;
378     uint preGlobalTick = 0;
379     for (int i = 0; i < eventCount; i++)
380     {
381     Events.Event ev = m_events[i];
382     uint nextTick = (uint)(preGlobalTick + ev.Delta);
383     if (nextTick >= globalTick)
384     {
385     ev.Delta = (int)(nextTick - globalTick);
386     e.Delta = (int)(globalTick - preGlobalTick);
387     m_events.Insert(i, e);
388     return;
389     }
390     preGlobalTick = nextTick;
391     }
392     e.Delta = (int)(globalTick - preGlobalTick);
393     m_events.Add(e);
394     }
395    
396     private void SetDelta(Events.Event e)
397     {
398     e.Delta = m_delta;
399     m_delta = 0;
400     }
401    
402     private void SetDeltaAndAddEvent(Events.Event e)
403     {
404     SetDelta(e);
405     m_events.Add(e);
406     }
407    
408     private double CalculateSPT(double bpm)
409     {
410     return Sample.RATE / (bpm * 96.0 / 60.0);
411     }
412 hikarin 67 #if DEBUG
413     internal List<Dictionary<string, string>> Dump()
414     {
415     List<Dictionary<string, string>> r = new List<Dictionary<string, string>>();
416     foreach (Events.Event e in m_events)
417     {
418     Dictionary<string, string> data = new Dictionary<string, string>();
419     data["status"] = e.GetType().Name.ToUpper();
420     if (e is Events.NoteOn)
421     {
422     Events.NoteOn noteOn = (Events.NoteOn)e;
423     data["status"] = "NOTE_ON";
424     data["note"] = noteOn.Index.ToString();
425     data["velocity"] = noteOn.Velocity.ToString();
426     }
427     else if (e is Events.NoteOff)
428     data["status"] = "NOTE_OFF";
429     else if (e is Events.Note)
430     data["note"] = ((Events.Note)(e)).Index.ToString();
431     else if (e is Events.Tempo)
432     data["tempo"] = ((Events.Tempo)e).Value.ToString();
433     else if (e is Events.Form)
434     {
435     Events.Form form = (Events.Form)e;
436     data["form"] = ((int)form.Main).ToString();
437     data["subform"] = ((int)form.Sub).ToString();
438     }
439     else if (e is Events.VCO)
440     {
441     Events.VCO vco = (Events.VCO)e;
442     data["status"] = "ENVELOPE";
443     data["attack"] = vco.Attack.ToString();
444     data["decay"] = vco.Decay.ToString();
445     r.Add(data);
446     data = new Dictionary<string, string>();
447     data["status"] = "ENVELOPE";
448     data["sustain"] = vco.Sustain.ToString();
449     data["release"] = vco.Release.ToString();
450     }
451     else if (e is Events.VCF)
452     {
453     Events.VCF vcf = (Events.VCF)e;
454     data["status"] = "ENVELOPE2";
455     data["attack"] = vcf.Attack.ToString();
456     data["decay"] = vcf.Decay.ToString();
457     r.Add(data);
458     data = new Dictionary<string, string>();
459     data["status"] = "ENVELOPE2";
460     data["sustain"] = vcf.Sustain.ToString();
461     data["release"] = vcf.Release.ToString();
462     }
463     else if (e is Events.NoiseFrequency)
464     {
465     data["status"] = "NOISE_FREQUENCY";
466     data["frequency"] = ((Events.NoiseFrequency)e).Value.ToString();
467     }
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     data["formant"] = ((Events.Vowel)e).Value.ToString();
474     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     double width = lfo.Width * m_spt;
480     data["form"] = ((int)lfo.Main).ToString();
481     data["subform"] = ((int)lfo.Sub).ToString();
482     data["width"] = lfo.Width.ToString();
483     data["delay"] = ((int)(lfo.Delay * m_spt)).ToString();
484     data["time"] = ((int)(lfo.Time * width)).ToString();
485     data["depth"] = lfo.Depth.ToString();
486     }
487     else if (e is Events.LPF)
488     {
489     Events.LPF lpf = (Events.LPF)e;
490     data["switch"] = ((int)lpf.Switch).ToString();
491     data["amount"] = lpf.Amount.ToString();
492     data["frequency"] = lpf.Frequency.ToString();
493     data["resonance"] = lpf.Resonance.ToString();
494     }
495     else if (e is Events.VolumeMode)
496     {
497     data["status"] = "VOLUME_MODE";
498     data["volumeMode"] = ((Events.VolumeMode)e).Value.ToString();
499     }
500     else if (e is Events.Input)
501     {
502     Events.Input input = (Events.Input)e;
503     data["sens"] = input.Sens.ToString();
504     data["pipe"] = input.Pipe.ToString();
505     }
506     else if (e is Events.Output)
507     {
508     Events.Output output = (Events.Output)e;
509     data["mode"] = output.Mode.ToString();
510     data["pipe"] = output.Pipe.ToString();
511     }
512     r.Add(data);
513     }
514     return r;
515     }
516     #endif
517 hikarin 37 #endregion
518    
519     #region ������������������������������
520     public bool End
521     {
522     get;
523     private set;
524     }
525    
526     public uint GlobalTick
527     {
528     get;
529     private set;
530     }
531    
532 hikarin 49 public Duration Duration
533 hikarin 37 {
534     get;
535     private set;
536     }
537    
538     public double BPM
539     {
540     get
541     {
542     return m_bpm;
543     }
544     set
545     {
546     m_bpm = value;
547     m_spt = CalculateSPT(value);
548     }
549     }
550    
551     public int EventCount
552     {
553     get
554     {
555     return m_events.Count;
556     }
557     }
558     #endregion
559    
560     #region ���������������������������
561     public static readonly int DEFAULT_BPM = 120;
562     private Channel m_channel;
563     private List<Events.Event> m_events;
564     private int m_index;
565     private int m_delta;
566     private double m_bpm;
567     private double m_spt;
568     private double m_needle;
569     private double m_gate;
570     private double m_gate2;
571     #endregion
572     }
573     }

Properties

Name Value
svn:keywords Id

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