Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/slmml/Sequencer.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (hide annotations) (download)
Tue Mar 31 14:07:27 2009 UTC (15 years ago) by hikarin
File size: 7798 byte(s)
[ocmml/slmml] * fixed a problem that causes high latency
1 hikarin 37 using System;
2     using System.Collections.Generic;
3     using System.IO;
4     using System.Threading;
5     using System.Windows.Media;
6    
7     namespace SlMML
8     {
9     enum SequencerStep
10     {
11     None,
12     Pre,
13     Track,
14     Post
15     }
16    
17     public sealed class Sequencer : MediaStreamSource
18     {
19     #region 定数の定義
20     public static readonly int BUFFER_SIZE = 8192;
21     public static readonly int BUFFER_ARRAY_SIZE = 2;
22 hikarin 47 private static readonly int BLOCK_ALIGNMENT = 2 * sizeof(short);
23     private static readonly int BUFFER_BLOCK_SIZE = BUFFER_SIZE * BLOCK_ALIGNMENT;
24 hikarin 37 private static readonly string WAVE_HEADER = "0100020044ac000010b10200040010000000";
25     #endregion
26    
27     #region コンストラクタおよびデストラクタの定義
28     public Sequencer(int multiple)
29     {
30     m_bufferSize = BUFFER_SIZE * multiple;
31     m_buffer = new short[m_bufferSize << 1];
32     m_tracks = new List<Track>();
33     m_multiple = multiple;
34     m_mediaSampleAttributes = new Dictionary<MediaSampleAttributeKeys, string>();
35     MasterVolume = 100;
36     Channel.Initialize(BUFFER_SIZE * multiple);
37     }
38     #endregion
39    
40     #region MediaStreamSourceの派生メソッドの定義
41     protected override void OpenMediaAsync()
42     {
43     m_last = false;
44 hikarin 47 m_timestampBlock = 10000000 / (Sample.RATE * BLOCK_ALIGNMENT * m_multiple);
45 hikarin 37 Dictionary<MediaStreamAttributeKeys, string> mediaStreamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();
46     mediaStreamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = WAVE_HEADER;
47     description = new MediaStreamDescription(MediaStreamType.Audio, mediaStreamAttributes);
48     Dictionary<MediaSourceAttributesKeys, string> mediaSourceAttributes = new Dictionary<MediaSourceAttributesKeys, string>();
49     mediaSourceAttributes[MediaSourceAttributesKeys.CanSeek] = false.ToString();
50     mediaSourceAttributes[MediaSourceAttributesKeys.Duration] = (m_tracks[Track.TEMPO_TRACK].Duration * 10).ToString();
51     List<MediaStreamDescription> availableMediaStreams = new List<MediaStreamDescription>();
52     availableMediaStreams.Add(new MediaStreamDescription(MediaStreamType.Audio, mediaStreamAttributes));
53     ReportOpenMediaCompleted(mediaSourceAttributes, availableMediaStreams);
54     ReportGetSampleProgress(0);
55     GetSamples();
56     }
57    
58     protected override void CloseMedia()
59     {
60     Console.Write("end");
61     }
62    
63     protected override void GetDiagnosticAsync(MediaStreamSourceDiagnosticKind diagnosticKind)
64     {
65     ReportGetDiagnosticCompleted(diagnosticKind, 0);
66     }
67    
68     protected override void GetSampleAsync(MediaStreamType mediaStreamType)
69     {
70     MediaStreamSample sample;
71     if (m_last)
72     {
73     sample = new MediaStreamSample(description, null, 0, 0, 0, m_mediaSampleAttributes);
74     ReportGetSampleCompleted(sample);
75     }
76     else
77 hikarin 47 {
78     if ((m_tracks[Track.TEMPO_TRACK]).End)
79 hikarin 37 m_last = true;
80 hikarin 47 using (MemoryStream stream = new MemoryStream())
81     using (BinaryWriter writer = new BinaryWriter(stream))
82     {
83     int index = m_count * BUFFER_SIZE;
84     double volume = Math.Min(MasterVolume, 100) / 100;
85     for (int i = index; i < index + BUFFER_SIZE; i++)
86     {
87     int bufferIndex = i << 1;
88     writer.Write((short)(m_buffer[bufferIndex] * volume));
89     writer.Write((short)(m_buffer[bufferIndex + 1] * volume));
90     }
91     m_count++;
92     m_timestampIndex += m_timestampBlock;
93     sample = new MediaStreamSample(description, stream, 0, BUFFER_BLOCK_SIZE, m_timestampIndex, m_mediaSampleAttributes);
94     ReportGetSampleCompleted(sample);
95     }
96     }
97     if (m_count == m_multiple)
98     {
99 hikarin 37 GetSamples();
100 hikarin 47 m_count = 0;
101 hikarin 37 }
102     }
103    
104     protected override void SeekAsync(long seekToTime)
105     {
106     ReportSeekCompleted(seekToTime);
107     }
108    
109     protected override void SwitchMediaStreamAsync(MediaStreamDescription mediaStreamDescription)
110     {
111     ReportSwitchMediaStreamCompleted(mediaStreamDescription);
112     }
113     #endregion
114    
115     #region 公開メソッドの定義
116     public void ClearTracks()
117     {
118     m_tracks.Clear();
119     }
120    
121     public void AddTrack(Track track)
122     {
123     m_tracks.Add(track);
124     }
125    
126     public void CreatePipes(int number)
127     {
128     Channel.CreatePipes(number);
129     }
130     #endregion
131    
132     #region 非公開メソッドの定義
133     private void GetSamples()
134     {
135     bool loop = true;
136     int blen = Math.Min((BUFFER_SIZE << 2), m_bufferSize);
137     int offset = 0;
138     int trackIndex = 0;
139     int trackCount = m_tracks.Count;
140     SequencerStep step = SequencerStep.Pre;
141     while (loop)
142     {
143     switch (step)
144     {
145     case SequencerStep.Pre:
146     for (int i = (m_bufferSize << 1) - 1; i >= 0; i--)
147     m_buffer[i] = (0.0).ToShort();
148     if (trackCount > 0)
149     {
150     Track track = m_tracks[Track.TEMPO_TRACK];
151     track.GetSamples(ref m_buffer, 0, m_bufferSize, false);
152     }
153     step = SequencerStep.Track;
154     trackIndex = Track.FIRST_TRACK;
155     offset = 0;
156     break;
157     case SequencerStep.Track:
158     if (trackIndex >= trackCount)
159     step = SequencerStep.Post;
160     else
161     {
162     Track track = m_tracks[trackIndex];
163     track.GetSamples(ref m_buffer, offset, offset + blen, true);
164     offset += blen;
165     if (offset >= m_bufferSize)
166     {
167     offset = 0;
168     trackIndex++;
169     //m_buffered = (m_trackIndex + 1.0) / (trackCount + 1.0);
170     }
171     }
172     break;
173     case SequencerStep.Post:
174     loop = false;
175     break;
176     }
177     }
178     }
179     #endregion
180    
181     #region 公開プロパティの定義
182     public uint MasterVolume
183     {
184     get;
185     set;
186     }
187     #endregion
188    
189     #region メンバー変数の定義
190     private Dictionary<MediaSampleAttributeKeys, string> m_mediaSampleAttributes;
191     private MediaStreamDescription description;
192     private List<Track> m_tracks;
193     private short[] m_buffer;
194 hikarin 47 private long m_timestampIndex;
195     private long m_timestampBlock;
196 hikarin 37 private int m_bufferSize;
197     private int m_multiple;
198 hikarin 47 private int m_count;
199 hikarin 37 private bool m_last;
200     #endregion
201     }
202     }

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