1<?xml version="1.0"?>
2<!DOCTYPE xsl[
3<!ENTITY version "0.4.2">
4<!ENTITY buildid "XSLT">
5<!ENTITY audiochannels "1">
6<!ENTITY defaultsf2 ""> <!-- /usr/share/sounds/sf2/FluidR3_GM.sf2 -->
7<!ENTITY preset ""> <!-- "Yamaha Grand Piano" -->
8<!ENTITY instrument ""> <!-- "Yamaha Grand Piano" -->
9]>
10
11<!-- Copyright (C) 2005-2018 Jo\u00EBl Kr\u00E4hemann -->
12<!-- Copying and distribution of this file, with or without modification, -->
13<!-- are permitted in any medium without royalty provided the copyright -->
14<!-- notice and this notice are preserved.  This file is offered as-is, -->
15<!-- without any warranty. -->
16
17
18<xsl:stylesheet version="1.0"
19		xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
20
21  <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
22  <xsl:strip-space elements="*"/>
23
24  <!-- ticks to tact -->
25  <xsl:template name="ticks-to-tact">
26    <xsl:param name="current-tick"/>
27
28    <xsl:variable name="division" select="//midi-header/@division"/>
29    <xsl:variable name="tempo" select="//midi-tracks/midi-track[1]/midi-message[@event='tempo-number']/@tempo"/>
30    <xsl:variable name="secs">60.0</xsl:variable>
31    <xsl:variable name="microsecs">1000000.0</xsl:variable>
32
33    <xsl:variable name="bpm">
34      <xsl:call-template name="midi-read-bpm"/>
35    </xsl:variable>
36
37    <xsl:if test="$division &gt; 0">
38
39      <xsl:value-of select="16.0 * $bpm div $secs * $current-tick * $tempo div $division div $microsecs"/>
40    </xsl:if>
41
42    <xsl:if test="not($division &gt; 0)">
43      <xsl:variable name="smtpe-format">floor($division div 256)</xsl:variable>
44      <xsl:variable name="smtpe-resoulution">floor($division div 256) * 256</xsl:variable>
45
46      <xsl:value-of select="16.0 * $bpm div $secs * $current-tick div $smtpe-format div $smtpe-resolution div $microsecs"/>
47    </xsl:if>
48  </xsl:template>
49
50
51  <!-- midi read bpm -->
52  <xsl:template name="midi-read-bpm">
53    <xsl:variable name="ticks" select="//midi-header/@division"/>
54    <xsl:variable name="division" select="//midi-header/@division"/>
55    <xsl:variable name="tempo" select="//midi-tracks/midi-track[1]/midi-message[@event='tempo-number']/@tempo"/>
56    <xsl:variable name="secs">60.0</xsl:variable>
57    <xsl:variable name="microsecs">1000000.0</xsl:variable>
58
59    <xsl:if test="$division &gt; 0">
60
61      <xsl:value-of select="$secs div $ticks div $tempo * $division * $microsecs"/>
62
63    </xsl:if>
64
65    <xsl:if test="not($division &gt; 0)">
66      <xsl:variable name="smtpe-format">floor($division div 256)</xsl:variable>
67      <xsl:variable name="smtpe-resoulution">floor($division div 256) * 256</xsl:variable>
68
69      <xsl:value-of select="$secs div $ticks * $smtpe-format * $smtpe-resolution * $microsecs"/>
70
71    </xsl:if>
72  </xsl:template>
73
74  <!-- note node -->
75  <xsl:template match="midi-message">
76    <xsl:param name="parent-sequence"/>
77    <xsl:param name="parent-instrument"/>
78
79    <xsl:if test="current()/@event='note-on'">
80
81      <xsl:variable name="sequence" select="../midi-message[boolean(@sequence-name)]/@sequence-name"/>
82      <xsl:variable name="instrument" select="../midi-message[boolean(@instrument-name)]/@instrument-name"/>
83      <xsl:variable name="current-tick"><xsl:value-of select="./@delta-time"/></xsl:variable>
84
85      <xsl:if test="$parent-sequence=$sequence and $parent-instrument=$instrument">
86	<ags-note>
87
88	  <xsl:attribute name="id">note-<xsl:value-of select="position()"/></xsl:attribute>
89	  <xsl:attribute name="flags">0</xsl:attribute>
90
91	  <xsl:variable name="y" select="./@note"/>
92	  <xsl:attribute name="y"><xsl:value-of select="$y"/></xsl:attribute>
93
94	  <xsl:variable name="x0">
95	    <xsl:call-template name="ticks-to-tact">
96	      <xsl:with-param name="current-tick" select="$current-tick"/>
97	    </xsl:call-template>
98	  </xsl:variable>
99	  <xsl:attribute name="x0"><xsl:value-of select="round($x0)"/></xsl:attribute>
100
101	  <xsl:if test="following-sibling::node()[@event='note-off' and @note='$y']">
102	    <xsl:variable name="next-tick"><xsl:value-of select="following-sibling::node()[@event='note-off' and @note='$y']/@delta-time"/></xsl:variable>
103
104	    <xsl:variable name="x1">
105	      <xsl:call-template name="ticks-to-tact">
106		<xsl:with-param name="current-tick" select="$next-tick"/>
107	      </xsl:call-template>
108	    </xsl:variable>
109
110	    <xsl:attribute name="x1">
111	      <xsl:value-of select="floor($x1)"/>
112	    </xsl:attribute>
113	  </xsl:if>
114
115	  <xsl:if test="not(following-sibling::ags-note[@event='note-off' and @note='$y'])">
116	    <xsl:variable name="add-one" select="1"/>
117	    <xsl:attribute name="x1"><xsl:value-of select="round($x0) + $add-one"/></xsl:attribute>
118	  </xsl:if>
119
120	</ags-note>
121      </xsl:if>
122
123    </xsl:if>
124
125  </xsl:template>
126
127  <!-- notation node -->
128  <xsl:template name="add-notation">
129    <xsl:param name="sequence"/>
130    <xsl:param name="instrument"/>
131    <xsl:param name="num" select="1"/>
132    <xsl:param name="count"/>
133
134    <ags-notation>
135      <xsl:attribute name="id">notation-<xsl:value-of select="position()"/></xsl:attribute>
136      <xsl:attribute name="flags">0</xsl:attribute>
137      <xsl:attribute name="audio-channel"><xsl:value-of select="$num - 1"/></xsl:attribute>
138      <xsl:attribute name="base-note">C</xsl:attribute>
139
140      <ags-note-list>
141	<xsl:attribute name="id">note-list-<xsl:value-of select="position()"/></xsl:attribute>
142
143	<xsl:apply-templates select="/midi/midi-tracks/midi-track/midi-message">
144	  <xsl:with-param name="parent-sequence" select="$sequence"/>
145	  <xsl:with-param name="parent-instrument" select="$instrument"/>
146	</xsl:apply-templates>
147
148      </ags-note-list>
149    </ags-notation>
150
151    <xsl:if test="$num &lt; $count">
152      <xsl:call-template name="add-notation">
153	<xsl:with-param name="num" select="$num + 1"/>
154	<xsl:with-param name="count" select="$count"/>
155      </xsl:call-template>
156    </xsl:if>
157
158  </xsl:template>
159
160  <!-- audio node -->
161  <xsl:template name="add-audio">
162    <xsl:param name="sequence"/>
163    <xsl:param name="instrument"/>
164
165    <ags-audio>
166      <xsl:attribute name="id"><xsl:value-of select="$sequence"/>_<xsl:value-of select="$instrument"/></xsl:attribute>
167      <xsl:attribute name="flags">13f</xsl:attribute>
168      <xsl:attribute name="sequence-length">0</xsl:attribute>
169      <xsl:attribute name="audio-channels">&audiochannels;</xsl:attribute>
170      <xsl:attribute name="output-pads">1</xsl:attribute>
171      <xsl:attribute name="input-pads">128</xsl:attribute>
172      <xsl:attribute name="devout">xpath=//ags-devout</xsl:attribute>
173
174      <ags-notation-list>
175	<xsl:attribute name="id">notation-list-<xsl:value-of select="position()"/></xsl:attribute>
176
177	<xsl:call-template name="add-notation">
178	  <xsl:with-param name="count" select="&audiochannels;"/>
179	  <xsl:with-param name="sequence" select="$sequence"/>
180	  <xsl:with-param name="instrument" select="$instrument"/>
181	</xsl:call-template>
182
183      </ags-notation-list>
184    </ags-audio>
185
186  </xsl:template>
187
188  <!-- machine node -->
189  <xsl:template name="add-machine">
190    <xsl:param name="sequence"/>
191    <xsl:param name="instrument"/>
192
193    <ags-machine>
194      <xsl:attribute name="type">AgsFFPlayer</xsl:attribute>
195      <xsl:attribute name="id">machine-<xsl:value-of select="position()"/></xsl:attribute>
196      <xsl:attribute name="flags">628</xsl:attribute>
197      <xsl:attribute name="version">&version;</xsl:attribute>
198      <xsl:attribute name="build-id">&buildid;</xsl:attribute>
199      <xsl:attribute name="file-input-flags">0</xsl:attribute>
200      <xsl:attribute name="name"><xsl:value-of select="$sequence"/> - <xsl:value-of select="$instrument"/></xsl:attribute>
201      <xsl:attribute name="audio">xpath=//ags-audio[@id='<xsl:value-of select="$sequence"/>_<xsl:value-of select="$instrument"/>']</xsl:attribute>
202
203      <ags-ffplayer>
204	<xsl:attribute name="id">ffplayer-<xsl:value-of select="position()"/></xsl:attribute>
205	<xsl:attribute name="filename">&defaultsf2;</xsl:attribute>
206	<xsl:attribute name="preset">&preset;</xsl:attribute>
207	<xsl:attribute name="instrument">&instrument;</xsl:attribute>
208      </ags-ffplayer>
209    </ags-machine>
210
211  </xsl:template>
212
213  <!-- midi track -->
214  <xsl:template match="/midi/midi-tracks/midi-track">
215    <xsl:param name="parent"/>
216
217    <xsl:if test="not(midi-message[@event='time-signature'])">
218      <xsl:variable name="sequence" select="midi-message[boolean(@sequence-name)]/@sequence-name"/>
219      <xsl:variable name="instrument" select="midi-message[boolean(@instrument-name)]/@instrument-name"/>
220
221      <xsl:variable name="previous" select="preceding-sibling::node()"/>
222
223      <xsl:if test="not($previous/midi-message/@sequence-name=$sequence and $previous/midi-message/@instrument-name=$instrument)">
224	<xsl:if test="$parent='ags-audio-list'">
225	  <xsl:call-template name="add-audio">
226	    <xsl:with-param name="sequence" select="$sequence"/>
227	    <xsl:with-param name="instrument" select="$instrument"/>
228	  </xsl:call-template>
229	</xsl:if>
230
231	<xsl:if test="$parent='ags-machine-list'">
232	  <xsl:call-template name="add-machine">
233	    <xsl:with-param name="sequence" select="$sequence"/>
234	    <xsl:with-param name="instrument" select="$instrument"/>
235	  </xsl:call-template>
236	</xsl:if>
237      </xsl:if>
238    </xsl:if>
239  </xsl:template>
240
241  <xsl:template match="midi-header">
242    <xsl:variable name="bpm">
243      <xsl:call-template name="midi-read-bpm"/>
244    </xsl:variable>
245  </xsl:template>
246
247  <!-- root node -->
248  <xsl:template match="/">
249    <ags>
250      <ags-main version="&version;" build-id="&buildid;" flags="0">
251	<xsl:attribute name="id">ags-main-<xsl:value-of select="position()"/></xsl:attribute>
252
253	<ags-devout-list>
254	  <xsl:attribute name="id">devout-list-<xsl:value-of select="position()"/></xsl:attribute>
255
256	  <ags-devout>
257	    <xsl:attribute name="id">ags-devout-<xsl:value-of select="position()"/></xsl:attribute>
258	    <xsl:attribute name="flags">100</xsl:attribute>
259	    <xsl:attribute name="bpm">
260	      <xsl:call-template name="midi-read-bpm"/>
261	    </xsl:attribute>
262
263	    <ags-audio-list>
264	      <xsl:attribute name="id">ags-audio-list-<xsl:value-of select="position()"/></xsl:attribute>
265
266	      <xsl:apply-templates select="/midi/midi-tracks/midi-track">
267		<xsl:with-param name="parent">ags-audio-list</xsl:with-param>
268	      </xsl:apply-templates>
269
270	    </ags-audio-list>
271	  </ags-devout>
272	</ags-devout-list>
273	<ags-window>
274	  <xsl:attribute name="id">window-<xsl:value-of select="position()"/></xsl:attribute>
275	  <xsl:attribute name="flags">0</xsl:attribute>
276	  <xsl:attribute name="devout">xpath=//ags-devout</xsl:attribute>
277
278	  <ags-machine-list>
279	    <xsl:attribute name="id">machine-list-<xsl:value-of select="position()"/></xsl:attribute>
280
281	    <xsl:apply-templates select="/midi/midi-tracks/midi-track">
282	      <xsl:with-param name="parent">ags-machine-list</xsl:with-param>
283	    </xsl:apply-templates>
284
285	  </ags-machine-list>
286
287	  <ags-navigation/>
288	</ags-window>
289      </ags-main>
290    </ags>
291
292  </xsl:template>
293
294</xsl:stylesheet>
295