Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/slmml/Track.cs

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:keywords Id

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