OSDN Git Service

jQueryのアップデートに伴う変更。
[nacltest/xmplayer.git] / _mod.cc
1 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2 ▼     簡易 MOD / XM プレイヤー(2001 / 03 / 08 版)
3                                                                                                         by ファミベのよっしん
4 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
5 #include "_mod.h"
6 #undef          WARNING_LEVEL
7 #define         WARNING_LEVEL           ( 2 )
8
9 #define         TYPE_NOTAVAILABLE       ( 0 )
10 #define         TYPE_MOD                        ( 1 )
11 #define         TYPE_S3M                        ( 2 )
12 #define         TYPE_XM                         ( 3 )
13 #define         TYPE_IT                         ( 4 )
14
15 #undef          SFT
16 #define         SFT                                     ( 12 )                  /* 固定小数ビット数 */
17 #undef          ONE
18 #define         ONE                                     (1 << 12)               /* 固定小数表記の 1 */
19 #undef          DECIMAL
20 #define         DECIMAL                         ((1 << 12) - 1) /* 固定小数の、少数部分抽出用 */
21
22 #define         ENV_ON                          ( 1 )
23 #define         ENV_SUSTAIN                     ( 2 )
24 #define         ENV_LOOP                        ( 4 )
25
26 #define         SMP_LOOP                        ( 1 )
27 #define         SMP_PINGPONGLOOP        ( 2 )
28 #define         SMP_16BIT                       ( 16 )
29
30 #define         VM_ON                           ( 1 )
31 #define         VM_LOOP                         ( 2 )
32 #define         VM_16BIT                        ( 4 )
33
34 #define         LINEAR_FREQUENCY        ( 1 )
35
36 extern void LogMsg(void* instance,const char* format,...);
37
38 /* Vibrato Tremolo Panbrello Auto-Vibrato 共通波形データ */
39 static const S32 _aaWaveTable[7][64] =
40 {
41         /* 0 : サイン波 */
42         {
43                     0,  12,  25,  37,  49,  60,  71,  81,  90,  98, 106, 112, 117, 122, 125, 126
44                 , 127, 126, 125, 122, 117, 112, 106,  98,  90,  81,  71,  60,  49,  37,  25,  12
45                 ,   0, -12, -25, -37, -49, -60, -71, -81, -90, -98,-106,-112,-117,-122,-125,-126
46                 ,-127,-126,-125,-122,-117,-112,-106, -98, -90, -81, -71, -60, -49, -37, -25, -12
47         }
48         ,
49         /* 1 : サイン波(反転)*/
50         {
51                     0, -12, -25, -37, -49, -60, -71, -81, -90, -98,-106,-112,-117,-122,-125,-126
52                 ,-127,-126,-125,-122,-117,-112,-106, -98, -90, -81, -71, -60, -49, -37, -25, -12
53                 ,   0,  12,  25,  37,  49,  60,  71,  81,  90,  98, 106, 112, 117, 122, 125, 126
54                 , 127, 126, 125, 122, 117, 112, 106,  98,  90,  81,  71,  60,  49,  37,  25,  12
55         }
56         ,
57         /* 2 : ノコギリ波 */
58         {
59                     0,  -4,  -8, -12, -16, -20, -24, -28, -32, -36, -40, -44, -48, -52, -56, -60
60                 , -64, -68, -72, -76, -80, -84, -88, -92, -96,-100,-104,-108,-112,-116,-120,-124
61                 , 127, 123, 119, 115, 111, 107, 103,  99,  95,  91,  87,  83,  79,  75,  71,  67
62                 ,  63,  59,  55,  51,  47,  43,  39,  35,  31,  27,  23,  19,  15,  11,   7,   3
63         }
64         ,
65         /* 3 : ノコギリ波(反転)*/
66         {
67                     0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  44,  48,  52,  56,  60
68                 ,  64,  68,  72,  76,  80,  84,  88,  92,  96, 100, 104, 108, 112, 116, 120, 124
69                 ,-127,-123,-119,-115,-111,-107,-103, -99, -95, -91, -87, -83, -79, -75, -71, -67
70                 , -63, -59, -55, -51, -47, -43, -39, -35, -31, -27, -23, -19, -15, -11,  -7,  -3
71         }
72         ,
73         /* 4 : 矩形波 */
74         {
75                   127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127
76                 , 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127
77                 ,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127
78                 ,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127
79         }
80         ,
81         /* 5 : 矩形波(反転)*/
82         {
83                  -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127
84                 ,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127
85                 , 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127
86                 , 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127
87         }
88         ,
89         /* 6 : ランダム波 */
90         {
91                    98,-127, -43,  88, 102,  41, -65, -94, 125,  20, -71, -86, -70, -32, -16, -96
92                 ,  17,  72, 107,  -5, 116, -69, -62, -40,  10, -61,  65, 109, -18, -38, -13, -76
93                 , -23,  88,  21, -94,   8, 106,  21,-112,   6, 109,  20, -88, -30,   9,-127, 118
94                 ,  42, -34,  89,  -4, -51, -72,  21, -29, 112, 123,  84,-101, -92,  98, -54, -95
95         }
96 };
97
98 /* Vibrato Tremolo Panbrello Auto-Vibrato 各種波形の割り当て */
99 static const S32 _aVibratoWaveType[4]           = { 0 , 2 , 4 , 6 };
100 static const S32 _aTremoloWaveType[4]           = { 0 , 2 , 4 , 6 };
101 static const S32 _aPanbrelloWaveType[4]         = { 0 , 2 , 4 , 6 };
102 static const S32 _aAutoVibratoWaveType[5]       = { 1 , 5 , 3 , 2 , 6 };
103
104
105
106 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
107 ▼     XM_PATTERN 構造体の破棄
108
109         戻値・TRUE  = 成功
110                 ・FALSE = 失敗
111 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
112 static S32 XM_PATTERN__Destruct(
113         XM_PATTERN *p           /* this ポインター */
114 ){
115         if(     p == NULL ) return( FALSE );
116
117         if(     p->pPatternData != NULL ){
118                 FreeMemory( p->pPatternData );
119                 p->pPatternData = NULL ;
120         }
121         FreeMemory( p );
122         return( TRUE );
123 }
124
125
126
127 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
128 ▼     XM_PATTERN 構造体の確保と初期化
129
130         戻値:       確保した構造体へのポインター
131                         NULL なら失敗
132 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
133 static XM_PATTERN *XM_PATTERN__Create(
134 ){
135         S32     i ;
136         S32     size = sizeof( XM_PATTERN );
137         XM_PATTERN      *p = reinterpret_cast<XM_PATTERN        *>(AllocMemory( size ));
138
139         if( p == NULL ) return( NULL );
140
141         /* 面倒なので0でクリア */
142         for( i=0 ; i<size ; i++ ) ((U8*)p)[i] = 0 ;
143
144         /* メンバーの初期値 */
145         p->pPatternData = NULL ;
146
147         return( p );
148 }
149
150
151
152 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
153 ▼     XM_INSTRUMENT 構造体の破棄
154
155         戻値・TRUE  = 成功
156                 ・FALSE = 失敗
157 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
158 static S32 XM_INSTRUMENT__Destruct(
159         XM_INSTRUMENT *p                /* this ポインター */
160 ){
161         if(     p == NULL ) return( FALSE );
162
163         FreeMemory( p );
164         return( TRUE );
165 }
166
167
168
169 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
170 ▼     XM_INSTRUMENT 構造体の確保と初期化
171
172         戻値:       確保した構造体へのポインター
173                         NULL なら失敗
174 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
175 static XM_INSTRUMENT *XM_INSTRUMENT__Create(
176 ){
177         S32     i ;
178         S32     size = sizeof( XM_INSTRUMENT );
179         XM_INSTRUMENT   *p = reinterpret_cast<XM_INSTRUMENT     *>(AllocMemory( size ));
180
181         if( p == NULL ) return( NULL );
182
183         /* 面倒なので0でクリア */
184         for( i=0 ; i<size ; i++ ) ((U8*)p)[i] = 0 ;
185
186         /* メンバーの初期値 */
187         for( i=0 ; i<96 ; i++ ) p->apAllNoteXM_SAMPLE[ i ] = NULL ;
188
189         return( p );
190 }
191
192
193
194 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
195 ▼     XM_SAMPLE 構造体の破棄
196
197         戻値・TRUE  = 成功
198                 ・FALSE = 失敗
199 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
200 static S32 XM_SAMPLE__Destruct(
201         XM_SAMPLE *p            /* this ポインター */
202 ){
203         if(     p == NULL ) return( FALSE );
204
205         if(     p->pSampleData != NULL ){
206                 FreeMemory( p->pSampleData );
207                 p->pSampleData = NULL ;
208         }
209         FreeMemory( p );
210         return( TRUE );
211 }
212
213
214
215 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
216 ▼     XM_SAMPLE 構造体の確保と初期化
217
218         戻値:       確保した構造体へのポインター
219                         NULL なら失敗
220 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
221 static XM_SAMPLE *XM_SAMPLE__Create(
222 ){
223         S32     i ;
224         S32     size = sizeof( XM_SAMPLE );
225         XM_SAMPLE       *p = reinterpret_cast<XM_SAMPLE *>(AllocMemory( size ));
226
227         if( p == NULL ) return( NULL );
228
229         /* 面倒なので0でクリア */
230         for( i=0 ; i<size ; i++ ) ((U8*)p)[i] = 0 ;
231
232         /* メンバーの初期値 */
233         p->pSampleData = NULL ;
234
235         return( p );
236 }
237
238
239
240 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
241 ▼     XM 形式とみなして読み込み
242
243         戻値・TRUE  = 成功
244                 ・FALSE = 失敗
245 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
246 static S32 MOD__LoadSongAsXM(
247          MOD    *pMOD
248         ,void   *pMusDat_
249         ,S32     lMusDat
250 ){
251         U8      *pMusDat = (U8*)pMusDat_ ;
252         S32     ofs = 0 ;
253
254         if(     pMOD == NULL ) return( FALSE );
255
256         /* XM_ID */
257         {
258                 /* 無効なデータを事前に排除 */
259                 if(     lMusDat - ofs < 60 ){
260                         #if (WARNING_LEVEL >= 2)
261                                 LogMsg(pMOD->Instance,
262                                         "MOD__LoadSongAsXM : \n"
263                                         "       データサイズが不足しています。XM_ID を読み込めません。\n"
264                                         "       読み込みをキャンセルします。\n"
265                                 );
266                         #endif
267                         MOD__ReleaseSong( pMOD );
268                         return( FALSE );
269                 }
270
271                 /* データ読み込み */
272                 memcpy( &pMOD->XmId.aszID_Text[0]               ,  &pMusDat[ ofs +  0 ] , 17 );
273                 memcpy( &pMOD->XmId.aszModuleName[0]    ,  &pMusDat[ ofs + 17 ] , 20 );
274                 pMOD->XmId.aszModuleName[20] = 0 ;      /* 文字列終点 */
275                 pMOD->XmId.ID_Byte                      = (S32)*((U8*) &pMusDat[ ofs + 37 ]);
276                 memcpy( &pMOD->XmId.aszTrackerName[0]   ,  &pMusDat[ ofs + 38 ] , 20 );
277                 pMOD->XmId.aszTrackerName[20] = 0 ;     /* 文字列終点 */
278                 pMOD->XmId.VersionNumber        = (S32)*((U16*)&pMusDat[ ofs + 58 ]);
279                 ofs += 60 ;
280
281                 /* 識別文字列の確認 */
282                 if(     memcmp( "Extended Module:" , &(pMOD->XmId.aszID_Text[0]) , 16 ) != 0
283                 ||      pMOD->XmId.ID_Byte != 0x1a
284                 ){
285                         #if (WARNING_LEVEL >= 2)
286                                 LogMsg(pMOD->Instance,
287                                         "MOD__LoadSongAsXM : \n"
288                                         "       XM 形式識別文字列が存在しません。\n"
289                                         "       読み込みをキャンセルします。\n"
290                                 );
291                         #endif
292                         MOD__ReleaseSong( pMOD );
293                         return( FALSE );
294                 }
295
296                 /* データ形式のバージョンを確認 */
297                 if(     pMOD->XmId.VersionNumber < 0x103 ){
298                         #if (WARNING_LEVEL >= 2)
299                                 LogMsg(pMOD->Instance,
300                                         "MOD__LoadSongAsXM : \n"
301                                         "       フォーマットのバージョンが古すぎます。\n"
302                                         "       読み込みをキャンセルします。\n"
303                                 );
304                         #endif
305                         MOD__ReleaseSong( pMOD );
306                         return( FALSE );
307                 }
308
309                 #if (WARNING_LEVEL >= 2)
310                         LogMsg(pMOD->Instance,
311                                 "MOD__LoadSongAsXM : ModName = %s \n"
312                                 ,pMOD->XmId.aszModuleName
313                         );
314
315                         LogMsg(pMOD->Instance,
316                                 "MOD__LoadSongAsXM : TrackerName = %s \n"
317                                 ,pMOD->XmId.aszTrackerName
318                         );
319                 #endif
320         }
321
322
323         /* XM_HEADER */
324         {
325                 /* 無効なデータを事前に排除 */
326                 if(     lMusDat - ofs < 276 ){
327                         #if (WARNING_LEVEL >= 2)
328                                 LogMsg(pMOD->Instance,
329                                         "MOD__LoadSongAsXM : \n"
330                                         "       データサイズが不足しています。XM_HEADER を読み込めません。\n"
331                                         "       読み込みをキャンセルします。\n"
332                                 );
333                         #endif
334                         MOD__ReleaseSong( pMOD );
335                         return( FALSE );
336                 }
337
338                 /* データ読み込み */
339                 pMOD->XmHeader.HeaderSize                       = (S32)*((S32*)&pMusDat[ ofs +  0 ]);
340                 pMOD->XmHeader.SongLength                       = (S32)*((U16*)&pMusDat[ ofs +  4 ]);
341                 pMOD->XmHeader.RestartPosition          = (S32)*((U16*)&pMusDat[ ofs +  6 ]);
342                 pMOD->XmHeader.NumberOfChannels         = (S32)*((U16*)&pMusDat[ ofs +  8 ]);
343                 pMOD->XmHeader.NumberOfPatterns         = (S32)*((U16*)&pMusDat[ ofs + 10 ]);
344                 pMOD->XmHeader.NumberOfInstruments      = (S32)*((U16*)&pMusDat[ ofs + 12 ]);
345                 pMOD->XmHeader.Flags                            = (S32)*((U16*)&pMusDat[ ofs + 14 ]);
346                 pMOD->XmHeader.DefaultTempo                     = (S32)*((U16*)&pMusDat[ ofs + 16 ]);
347                 pMOD->XmHeader.DefaultBPM                       = (S32)*((U16*)&pMusDat[ ofs + 18 ]);
348                 memcpy( &(pMOD->XmHeader.aPatternOrderTable[0]) ,  &pMusDat[ ofs + 20 ] , 256 );
349                 ofs += pMOD->XmHeader.HeaderSize ;
350
351                 #if (WARNING_LEVEL >= 3)
352                         LogMsg(pMOD->Instance,
353                                 "MOD__LoadSongAsXM : \n"
354                                 "       pMOD->XmHeader.HeaderSize          %d \n"
355                                 "       pMOD->XmHeader.SongLength          %d \n"
356                                 "       pMOD->XmHeader.RestartPosition     %d \n"
357                                 "       pMOD->XmHeader.NumberOfChannels    %d \n"
358                                 "       pMOD->XmHeader.NumberOfPatterns    %d \n"
359                                 "       pMOD->XmHeader.NumberOfInstruments %d \n"
360                                 "       pMOD->XmHeader.Flags               %d \n"
361                                 "       pMOD->XmHeader.DefaultTempo        %d \n"
362                                 "       pMOD->XmHeader.DefaultBPM          %d \n"
363                                 ,pMOD->XmHeader.HeaderSize
364                                 ,pMOD->XmHeader.SongLength
365                                 ,pMOD->XmHeader.RestartPosition
366                                 ,pMOD->XmHeader.NumberOfChannels
367                                 ,pMOD->XmHeader.NumberOfPatterns
368                                 ,pMOD->XmHeader.NumberOfInstruments
369                                 ,pMOD->XmHeader.Flags
370                                 ,pMOD->XmHeader.DefaultTempo
371                                 ,pMOD->XmHeader.DefaultBPM
372                         );
373                 #endif
374
375                 /* 無効なデータを事前に排除 */
376                 if(     pMOD->XmHeader.SongLength > 256
377                 ||      pMOD->XmHeader.SongLength == 0
378                 ||      pMOD->XmHeader.NumberOfChannels > MAX_CHANNELS
379                 ||      pMOD->XmHeader.NumberOfChannels == 0
380                 ||      pMOD->XmHeader.NumberOfPatterns > MAX_PATTERNS
381                 ||      pMOD->XmHeader.NumberOfPatterns == 0
382                 ||      pMOD->XmHeader.NumberOfInstruments > MAX_INSTRUMENTS
383                 ||      pMOD->XmHeader.NumberOfInstruments == 0
384                 ){
385                         #if (WARNING_LEVEL >= 2)
386                                 LogMsg(pMOD->Instance,
387                                         "MOD__LoadSongAsXM : \n"
388                                         "       XM_HEADER に無効な値が含まれています。\n"
389                                         "       読み込みをキャンセルします。\n"
390                                 );
391                         #endif
392                         MOD__ReleaseSong( pMOD );
393                         return( FALSE );
394                 }
395         }
396
397
398         /* XM_PATTERN の読み込み */
399         {
400                 S32     idxPattern ;
401                 S32     i ;
402
403                 for( idxPattern = 0 ; idxPattern < pMOD->XmHeader.NumberOfPatterns ; idxPattern++ ){
404                         S32     Size ;
405                         XM_PATTERN      *pXM_PATTERN = XM_PATTERN__Create( );
406
407                         /* メモリ不足? */
408                         if(     pXM_PATTERN == NULL ){
409                                 #if (WARNING_LEVEL >= 1)
410                                         LogMsg(pMOD->Instance,
411                                                 "MOD__LoadSongAsXM : \n"
412                                                 "       XM_PATTERN 構造体の確保に失敗しました。\n"
413                                                 "       読み込みをキャンセルします。\n"
414                                         );
415                                 #endif
416                                 MOD__ReleaseSong( pMOD );
417                                 return( FALSE );
418                         }
419
420                         pMOD->apXM_PATTERN[ idxPattern ] = pXM_PATTERN ;
421
422                         /* 無効なデータを事前に排除 */
423                         if(     lMusDat - ofs < 9 ){
424                                 #if (WARNING_LEVEL >= 2)
425                                         LogMsg(pMOD->Instance,
426                                                 "MOD__LoadSongAsXM : \n"
427                                                 "       データサイズが不足しています。XM_PATTERN を読み込めません。\n"
428                                                 "       読み込みをキャンセルします。\n"
429                                         );
430                                 #endif
431                                 MOD__ReleaseSong( pMOD );
432                                 return( FALSE );
433                         }
434
435                         /* データ読み込み */
436                         pXM_PATTERN->PatternHeaderLength        = (S32)*((S32*)&pMusDat[ ofs +  0 ]);
437                         pXM_PATTERN->PackingType                        = (S32)*((U8*) &pMusDat[ ofs +  4 ]);
438                         pXM_PATTERN->NumberOfRowsInPattern      = (S32)*((U16*)&pMusDat[ ofs +  5 ]);
439                         pXM_PATTERN->PackedPatterndataSize      = (S32)*((U16*)&pMusDat[ ofs +  7 ]);
440                         ofs  +=9 ;
441
442                         #if (WARNING_LEVEL >= 3)
443                                 LogMsg(pMOD->Instance,
444                                         "MOD__LoadSongAsXM : \n"
445                                         "       pXM_PATTERN->PatternHeaderLength   %d \n"
446                                         "       pXM_PATTERN->PackingType           %d \n"
447                                         "       pXM_PATTERN->NumberOfRowsInPattern %d \n"
448                                         "       pXM_PATTERN->PackedPatterndataSize %d \n"
449                                         ,pXM_PATTERN->PatternHeaderLength
450                                         ,pXM_PATTERN->PackingType
451                                         ,pXM_PATTERN->NumberOfRowsInPattern
452                                         ,pXM_PATTERN->PackedPatterndataSize
453                                 );
454                         #endif
455
456                         /* 無効なデータを事前に排除 */
457                         if(     pXM_PATTERN->NumberOfRowsInPattern == 0 ){
458                                 #if (WARNING_LEVEL >= 2)
459                                         LogMsg(pMOD->Instance,
460                                                 "MOD__LoadSongAsXM : \n"
461                                                 "       XM_PATTERN に無効な値が含まれています。\n"
462                                                 "       読み込みをキャンセルします。\n"
463                                         );
464                                 #endif
465                                 MOD__ReleaseSong( pMOD );
466                                 return( FALSE );
467                         }
468
469                         /* パターン展開先のメモリを確保 */
470                         Size = 5 * pXM_PATTERN->NumberOfRowsInPattern * pMOD->XmHeader.NumberOfChannels ;
471                         pXM_PATTERN->pPatternData = reinterpret_cast<U8*>(AllocMemory( Size ));
472
473                         /* メモリ不足? */
474                         if(     pXM_PATTERN->pPatternData == NULL ){
475                                 #if (WARNING_LEVEL >= 1)
476                                         LogMsg(pMOD->Instance,
477                                                 "MOD__LoadSongAsXM : \n"
478                                                 "       パターン展開先メモリの確保に失敗しました。\n"
479                                                 "       読み込みをキャンセルします。\n"
480                                         );
481                                 #endif
482                                 MOD__ReleaseSong( pMOD );
483                                 return( FALSE );
484                         }
485
486                         /* 0 クリア */
487                         for( i=0 ; i<Size ; i++ ) pXM_PATTERN->pPatternData[ i ] = 0 ;
488
489                         /* 無効なデータを事前に排除 */
490                         if(     lMusDat - ofs < pXM_PATTERN->PackedPatterndataSize ){
491                                 #if (WARNING_LEVEL >= 2)
492                                         LogMsg(pMOD->Instance,
493                                                 "MOD__LoadSongAsXM : \n"
494                                                 "       データサイズが不足しています。圧縮パターンデータを読み込めません。\n"
495                                                 "       読み込みをキャンセルします。\n"
496                                         );
497                                 #endif
498                                 MOD__ReleaseSong( pMOD );
499                                 return( FALSE );
500                         }
501
502                         if(     pXM_PATTERN->PackedPatterndataSize ){
503                                 S32     PackLeft        = pXM_PATTERN->PackedPatterndataSize ;
504                                 U8      *pUnPacked      = pXM_PATTERN->pPatternData ;
505                                 U8      *pPacked        = &pMusDat[ ofs ];
506
507                                 while( PackLeft ){
508                                         U8      Flag = *pPacked++ ;
509                                         PackLeft-- ;
510
511                                         /* 圧縮されているか? */
512                                         if(     Flag & 0x80 ){
513                                                 /* Note */
514                                                 if(     Flag & 0x01 ){
515                                                         *pUnPacked++ = *pPacked++ ;
516                                                         PackLeft-- ;
517                                                 } else {
518                                                         pUnPacked++ ;
519                                                 }
520                                                 /* Instrument */
521                                                 if(     Flag & 0x02 ){
522                                                         *pUnPacked++ = *pPacked++ ;
523                                                         PackLeft-- ;
524                                                 } else {
525                                                         pUnPacked++ ;
526                                                 }
527                                                 /* Volume column */
528                                                 if(     Flag & 0x04 ){
529                                                         *pUnPacked++ = *pPacked++ ;
530                                                         PackLeft-- ;
531                                                 } else {
532                                                         pUnPacked++ ;
533                                                 }
534                                                 /* Effect */
535                                                 if(     Flag & 0x08 ){
536                                                         *pUnPacked++ = *pPacked++ ;
537                                                         PackLeft-- ;
538                                                 } else {
539                                                         pUnPacked++ ;
540                                                 }
541                                                 /* Effect parameter */
542                                                 if(     Flag & 0x10 ){
543                                                         *pUnPacked++ = *pPacked++ ;
544                                                         PackLeft-- ;
545                                                 } else {
546                                                         pUnPacked++ ;
547                                                 }
548                                         } else {
549                                                 *pUnPacked++ = Flag ;                   /* Note */
550                                                 *pUnPacked++ = *pPacked++ ;             /* Instrument */
551                                                 *pUnPacked++ = *pPacked++ ;             /* Volume column */
552                                                 *pUnPacked++ = *pPacked++ ;             /* Effect */
553                                                 *pUnPacked++ = *pPacked++ ;             /* Effect parameter */
554                                                 PackLeft -= 4 ;
555                                         }
556                                 }
557
558                                 ofs += pXM_PATTERN->PackedPatterndataSize ;
559                         }
560                 }
561         }
562
563         /* XM_INSTRUMENT の読み込み */
564         {
565                 S32     idxInst ;
566
567                 for( idxInst = 0 ; idxInst < pMOD->XmHeader.NumberOfInstruments ; idxInst++ ){
568                         XM_INSTRUMENT   *pXM_INSTRUMENT = XM_INSTRUMENT__Create( );
569
570                         /* メモリ不足? */
571                         if(     pXM_INSTRUMENT == NULL ){
572                                 #if (WARNING_LEVEL >= 1)
573                                         LogMsg(pMOD->Instance,
574                                                 "MOD__LoadSongAsXM : \n"
575                                                 "       XM_INSTRUMENT 構造体の確保に失敗しました。\n"
576                                                 "       読み込みをキャンセルします。\n"
577                                         );
578                                 #endif
579                                 MOD__ReleaseSong( pMOD );
580                                 return( FALSE );
581                         }
582
583                         pMOD->apXM_INSTRUMENT[ idxInst ] = pXM_INSTRUMENT ;
584
585                         /* 無効なデータを事前に排除 */
586                         if(     lMusDat - ofs < 29 ){
587                                 #if (WARNING_LEVEL >= 2)
588                                         LogMsg(pMOD->Instance,
589                                                 "MOD__LoadSongAsXM : \n"
590                                                 "       データサイズが不足しています。XM_INSTRUMENT(+28 まで)を読み込めません。\n"
591                                                 "       読み込みをキャンセルします。\n"
592                                         );
593                                 #endif
594                                 MOD__ReleaseSong( pMOD );
595                                 return( FALSE );
596                         }
597
598                         /* データ読み込み */
599                         pXM_INSTRUMENT->InstrumentSize                          = (S32)*((S32*)&pMusDat[ ofs +  0 ]);
600                         memcpy( &pXM_INSTRUMENT->aszInstrumentName[0]                   ,  &pMusDat[ ofs +  4 ] , 22 );
601                         pXM_INSTRUMENT->aszInstrumentName[22] = 0 ;             /* 文字列終点 */
602                         pXM_INSTRUMENT->InstrumentType                          = (S32)*((U8*) &pMusDat[ ofs + 26 ]);
603                         pXM_INSTRUMENT->NumberOfSamplesInInstrument     = (S32)*((U16*)&pMusDat[ ofs + 27 ]);
604
605                         #if (WARNING_LEVEL >= 3)
606                                 LogMsg(pMOD->Instance,
607                                         "MOD__LoadSongAsXM : \n"
608                                         "       pXM_INSTRUMENT->InstrumentSize              %d \n"
609                                         "       pXM_INSTRUMENT->aszInstrumentName           %s \n"
610                                         "       pXM_INSTRUMENT->InstrumentType              %d \n"
611                                         "       pXM_INSTRUMENT->NumberOfSamplesInInstrument %d \n"
612                                         ,pXM_INSTRUMENT->InstrumentSize
613                                         ,pXM_INSTRUMENT->aszInstrumentName
614                                         ,pXM_INSTRUMENT->InstrumentType
615                                         ,pXM_INSTRUMENT->NumberOfSamplesInInstrument
616                                 );
617                         #endif
618
619                         /* 無効なデータを事前に排除 */
620                         if(     pXM_INSTRUMENT->NumberOfSamplesInInstrument > MAX_SAMPLES_IN_INSTRUMENT ){
621                                 #if (WARNING_LEVEL >= 2)
622                                         LogMsg(pMOD->Instance,
623                                                 "MOD__LoadSongAsXM : \n"
624                                                 "       以下の値が不正です。\n"
625                                                 "       pXM_INSTRUMENT->NumberOfSamplesInInstrument = %d \n"
626                                                 "       読み込みをキャンセルします。\n"
627                                         );
628                                 #endif
629                                 MOD__ReleaseSong( pMOD );
630                                 return( FALSE );
631                         }
632
633                         if(     pXM_INSTRUMENT->NumberOfSamplesInInstrument == 0 ){
634                                 ofs += pXM_INSTRUMENT->InstrumentSize ;
635
636                         } else {
637                                 /* 無効なデータを事前に排除 */
638                                 if(     lMusDat - ofs < 243 ){
639                                         #if (WARNING_LEVEL >= 2)
640                                                 LogMsg(pMOD->Instance,
641                                                         "MOD__LoadSongAsXM : \n"
642                                                         "       データサイズが不足しています。XM_INSTRUMENT(+29 以降)を読み込めません。\n"
643                                                         "       読み込みをキャンセルします。\n"
644                                                 );
645                                         #endif
646                                         MOD__ReleaseSong( pMOD );
647                                         return( FALSE );
648                                 }
649
650                                 /* データ読み込み */
651                                 pXM_INSTRUMENT->SampleHeaderSize                        = (S32)*((S32*)&pMusDat[ ofs +  29 ]);
652                                 memcpy( &pXM_INSTRUMENT->aSampleNumberForAllNotes[0]    ,  &pMusDat[ ofs +  33 ] , 96 );
653                                 memcpy( &pXM_INSTRUMENT->aPointsForVolumeEnvelope[0]    ,  &pMusDat[ ofs + 129 ] , 48 );
654                                 memcpy( &pXM_INSTRUMENT->aPointsForPanningEnvelope[0]   ,  &pMusDat[ ofs + 177 ] , 48 );
655                                 pXM_INSTRUMENT->NumberOfVolumePoints            = (S32)*((U8*) &pMusDat[ ofs + 225 ]);
656                                 pXM_INSTRUMENT->NumberOfPanningPoints           = (S32)*((U8*) &pMusDat[ ofs + 226 ]);
657                                 pXM_INSTRUMENT->VolumeSustainPoint                      = (S32)*((U8*) &pMusDat[ ofs + 227 ]);
658                                 pXM_INSTRUMENT->VolumeLoopStartPoint            = (S32)*((U8*) &pMusDat[ ofs + 228 ]);
659                                 pXM_INSTRUMENT->VolumeLoopEndPoint                      = (S32)*((U8*) &pMusDat[ ofs + 229 ]);
660                                 pXM_INSTRUMENT->PanningSustainPoint                     = (S32)*((U8*) &pMusDat[ ofs + 230 ]);
661                                 pXM_INSTRUMENT->PanningLoopStartPoint           = (S32)*((U8*) &pMusDat[ ofs + 231 ]);
662                                 pXM_INSTRUMENT->PanningLoopEndPoint                     = (S32)*((U8*) &pMusDat[ ofs + 232 ]);
663                                 pXM_INSTRUMENT->VolumeType                                      = (S32)*((U8*) &pMusDat[ ofs + 233 ]);
664                                 pXM_INSTRUMENT->PanningType                                     = (S32)*((U8*) &pMusDat[ ofs + 234 ]);
665                                 pXM_INSTRUMENT->AutoVibratoType                         = (S32)*((U8*) &pMusDat[ ofs + 235 ]);
666                                 pXM_INSTRUMENT->AutoVibratoSweep                        = (S32)*((U8*) &pMusDat[ ofs + 236 ]);
667                                 pXM_INSTRUMENT->AutoVibratoDepth                        = (S32)*((U8*) &pMusDat[ ofs + 237 ]);
668                                 pXM_INSTRUMENT->AutoVibratoRate                         = (S32)*((U8*) &pMusDat[ ofs + 238 ]);
669                                 pXM_INSTRUMENT->VolumeFadeout                           = (S32)*((U16*)&pMusDat[ ofs + 239 ]);
670                                 pXM_INSTRUMENT->Reserved                                        = (S32)*((U16*)&pMusDat[ ofs + 241 ]);
671                                 ofs += pXM_INSTRUMENT->InstrumentSize ;
672
673                                 #if (WARNING_LEVEL >= 3)
674                                         LogMsg(pMOD->Instance,
675                                                 "MOD__LoadSongAsXM : \n"
676                                                 "       pXM_INSTRUMENT->SampleHeaderSize      %d \n"
677                                                 "       pXM_INSTRUMENT->NumberOfVolumePoints  %d \n"
678                                                 "       pXM_INSTRUMENT->NumberOfPanningPoints %d \n"
679                                                 "       pXM_INSTRUMENT->VolumeSustainPoint    %d \n"
680                                                 "       pXM_INSTRUMENT->VolumeLoopStartPoint  %d \n"
681                                                 "       pXM_INSTRUMENT->VolumeLoopEndPoint    %d \n"
682                                                 "       pXM_INSTRUMENT->PanningSustainPoint   %d \n"
683                                                 "       pXM_INSTRUMENT->PanningLoopStartPoint %d \n"
684                                                 "       pXM_INSTRUMENT->PanningLoopEndPoint   %d \n"
685                                                 "       pXM_INSTRUMENT->VolumeType            %d \n"
686                                                 "       pXM_INSTRUMENT->PanningType           %d \n"
687                                                 "       pXM_INSTRUMENT->VibratoType           %d \n"
688                                                 "       pXM_INSTRUMENT->VibratoSweep          %d \n"
689                                                 "       pXM_INSTRUMENT->VibratoDepth          %d \n"
690                                                 "       pXM_INSTRUMENT->VibratoRate           %d \n"
691                                                 "       pXM_INSTRUMENT->VolumeFadeout         %d \n"
692                                                 "       pXM_INSTRUMENT->Reserved              %d \n"
693                                                 ,pXM_INSTRUMENT->SampleHeaderSize
694                                                 ,pXM_INSTRUMENT->NumberOfVolumePoints
695                                                 ,pXM_INSTRUMENT->NumberOfPanningPoints
696                                                 ,pXM_INSTRUMENT->VolumeSustainPoint
697                                                 ,pXM_INSTRUMENT->VolumeLoopStartPoint
698                                                 ,pXM_INSTRUMENT->VolumeLoopEndPoint
699                                                 ,pXM_INSTRUMENT->PanningSustainPoint
700                                                 ,pXM_INSTRUMENT->PanningLoopStartPoint
701                                                 ,pXM_INSTRUMENT->PanningLoopEndPoint
702                                                 ,pXM_INSTRUMENT->VolumeType
703                                                 ,pXM_INSTRUMENT->PanningType
704                                                 ,pXM_INSTRUMENT->AutoVibratoType
705                                                 ,pXM_INSTRUMENT->AutoVibratoSweep
706                                                 ,pXM_INSTRUMENT->AutoVibratoDepth
707                                                 ,pXM_INSTRUMENT->AutoVibratoRate
708                                                 ,pXM_INSTRUMENT->VolumeFadeout
709                                                 ,pXM_INSTRUMENT->Reserved
710                                         );
711
712                                         #if 1
713                                                 /* 各キーに割り当てられたサンプリング番号を表示 */
714                                                 {
715                                                         S32     i , j ;
716                                                         LogMsg( pMOD->Instance,"        pXM_INSTRUMENT->aSampleNumberForAllNotes[] = { \n" );
717                                                         for( i=0 ; i<96 ; i+=12 ){
718                                                                 LogMsg(pMOD->Instance, "                " );
719                                                                 for( j=i ; j<i+12 ; j++ ){
720                                                                         LogMsg(pMOD->Instance,
721                                                                                 "%03d "
722                                                                                 ,pXM_INSTRUMENT->aSampleNumberForAllNotes[j]
723                                                                         );
724                                                                 }
725                                                                 LogMsg(pMOD->Instance, "\n" );
726                                                         }
727                                                         LogMsg( pMOD->Instance,"        } \n" );
728                                                 }
729                                         #endif
730                                 #endif
731
732
733                                 /* 無効なデータを事前に修正 */
734                                 if(     pXM_INSTRUMENT->NumberOfVolumePoints    > 12 ) pXM_INSTRUMENT->NumberOfVolumePoints             = 12 ;
735                                 if(     pXM_INSTRUMENT->NumberOfPanningPoints   > 12 ) pXM_INSTRUMENT->NumberOfPanningPoints    = 12 ;
736                                 if(     pXM_INSTRUMENT->VolumeSustainPoint              > 11 ) pXM_INSTRUMENT->VolumeSustainPoint               = 11 ;
737                                 if(     pXM_INSTRUMENT->VolumeLoopStartPoint    > 11 ) pXM_INSTRUMENT->VolumeLoopStartPoint             = 11 ;
738                                 if(     pXM_INSTRUMENT->VolumeLoopEndPoint              > 11 ) pXM_INSTRUMENT->VolumeLoopEndPoint               = 11 ;
739                                 if(     pXM_INSTRUMENT->PanningSustainPoint             > 11 ) pXM_INSTRUMENT->PanningSustainPoint              = 11 ;
740                                 if(     pXM_INSTRUMENT->PanningLoopStartPoint   > 11 ) pXM_INSTRUMENT->PanningLoopStartPoint    = 11 ;
741                                 if(     pXM_INSTRUMENT->PanningLoopEndPoint             > 11 ) pXM_INSTRUMENT->PanningLoopEndPoint              = 11 ;
742
743                                 /* エンベロープ変化を先に展開してテーブル化 */
744                                 {
745                                         S32     idxPoint ;
746
747                                         if(     pXM_INSTRUMENT->VolumeType & ENV_ON ){
748                                                 for( idxPoint = 0 ; idxPoint <= 11 ; idxPoint++ ){
749                                                         /* 逸脱して長いエンベロープデータを補正 */
750                                                         if(     pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].x > 324 ){
751                                                                 pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].x = 324 ;
752                                                         }
753                                                         /* オーバーフローを回避 */
754                                                         if(     pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].y > 255 ){
755                                                                 pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].y = 255 ;
756                                                         }
757                                                 }
758
759                                                 for( idxPoint = 0 ; idxPoint < pXM_INSTRUMENT->NumberOfVolumePoints - 1 ; idxPoint++ ){
760                                                         S32     x , y , dx , dy ;
761
762                                                         x       = pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].x ;
763                                                         y       = pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].y ;
764                                                         dx      = pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint + 1 ].x - x ;
765                                                         dy      = pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint + 1 ].y - y ;
766
767                                                         /* 隣の区間まで線形補完 */
768                                                         if(     dx ){
769                                                                 for( x = 0 ; x < dx ; x++ ){
770                                                                         pXM_INSTRUMENT->VolumeEnvelopeTable[
771                                                                                 x + pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].x
772                                                                         ] =     (U8)(y + dy * x / dx) ;
773                                                                 }
774                                                         }
775
776                                                         /* 終点に達したら、最終値をテーブル末端まで維持 */
777                                                         if( idxPoint == pXM_INSTRUMENT->NumberOfVolumePoints - 2 ){
778                                                                 for( x = pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint + 1 ].x ; x < 325 ; x++ ){
779                                                                         U16     Val = pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint + 1 ].y ;
780                                                                         pXM_INSTRUMENT->VolumeEnvelopeTable[ x ] = (U8)Val ;
781                                                                 }
782                                                         }
783                                                 }
784
785                                                 /* 制御点ナンバーから、テーブルオフセットに変換 */
786                                                 pXM_INSTRUMENT->VolumeSustainPoint
787                                                 =       pXM_INSTRUMENT->aPointsForVolumeEnvelope[ pXM_INSTRUMENT->VolumeSustainPoint ].x ;
788                                                 pXM_INSTRUMENT->VolumeLoopStartPoint
789                                                 =       pXM_INSTRUMENT->aPointsForVolumeEnvelope[ pXM_INSTRUMENT->VolumeLoopStartPoint ].x ;
790                                                 pXM_INSTRUMENT->VolumeLoopEndPoint
791                                                 =       pXM_INSTRUMENT->aPointsForVolumeEnvelope[ pXM_INSTRUMENT->VolumeLoopEndPoint ].x ;
792
793                                                 /* ループ区間の長さが 0 の時は、ループを無効化 */
794                                                 if(     pXM_INSTRUMENT->VolumeLoopStartPoint == pXM_INSTRUMENT->VolumeLoopEndPoint ){
795                                                         pXM_INSTRUMENT->VolumeType &= ~ENV_LOOP ;
796                                                 }
797                                         }
798
799                                         if(     pXM_INSTRUMENT->PanningType & ENV_ON ){
800                                                 for( idxPoint = 0 ; idxPoint <= 11 ; idxPoint++ ){
801                                                         /* 逸脱して長いエンベロープデータを補正 */
802                                                         if(     pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint ].x > 324 ){
803                                                                 pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint ].x = 324 ;
804                                                         }
805                                                         /* オーバーフローを回避 */
806                                                         if(     pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].y > 255 ){
807                                                                 pXM_INSTRUMENT->aPointsForVolumeEnvelope[ idxPoint ].y = 255 ;
808                                                         }
809                                                 }
810
811                                                 for( idxPoint = 0 ; idxPoint < pXM_INSTRUMENT->NumberOfPanningPoints - 1 ; idxPoint++ ){
812                                                         S32 x , y , dx , dy ;
813
814                                                         x       = pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint ].x ;
815                                                         y       = pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint ].y ;
816                                                         dx      = pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint + 1 ].x - x ;
817                                                         dy      = pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint + 1 ].y - y ;
818
819                                                         /* 隣の区間まで線形補完 */
820                                                         if( dx ){
821                                                                 for( x = 0 ; x < dx ; x++ ){
822                                                                         pXM_INSTRUMENT->PanningEnvelopeTable[
823                                                                                 x + pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint ].x
824                                                                         ] =     (U8)(y + dy * x / dx) ;
825                                                                 }
826                                                         }
827
828                                                         /* 終点に達したら、最終値をテーブル末端まで維持 */
829                                                         if(     idxPoint == pXM_INSTRUMENT->NumberOfPanningPoints - 2 ){
830                                                                 for( x = pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint + 1 ].x ; x < 325 ; x++ ){
831                                                                         U16     Val = pXM_INSTRUMENT->aPointsForPanningEnvelope[ idxPoint + 1 ].y ;
832                                                                         pXM_INSTRUMENT->PanningEnvelopeTable[ x ] = (U8)Val ;
833                                                                 }
834                                                         }
835                                                 }
836
837                                                 /* 制御点ナンバーから、テーブルオフセットに変換 */
838                                                 pXM_INSTRUMENT->PanningSustainPoint
839                                                 =       pXM_INSTRUMENT->aPointsForPanningEnvelope[ pXM_INSTRUMENT->PanningSustainPoint ].x ;
840                                                 pXM_INSTRUMENT->PanningLoopStartPoint
841                                                 =       pXM_INSTRUMENT->aPointsForPanningEnvelope[ pXM_INSTRUMENT->PanningLoopStartPoint ].x ;
842                                                 pXM_INSTRUMENT->PanningLoopEndPoint
843                                                 =       pXM_INSTRUMENT->aPointsForPanningEnvelope[ pXM_INSTRUMENT->PanningLoopEndPoint ].x ;
844
845                                                 /* ループ区間の長さが 0 の時は、ループを無効化 */
846                                                 if(     pXM_INSTRUMENT->PanningLoopStartPoint == pXM_INSTRUMENT->PanningLoopEndPoint ){
847                                                         pXM_INSTRUMENT->PanningType &= ~ENV_LOOP ;
848                                                 }
849                                         }
850                                 }
851
852                                 /*
853                                         XM_SAMPLE の読み込み
854                                         XM の妙なフォーマットの都合上、処理ステップを2つに分けなければならない。
855                                 */
856                                 {
857                                         S32     idxLocalSample ;
858
859                                         /* 処理ステップ1 */
860                                         for( idxLocalSample = 0
861                                         ;        idxLocalSample < pXM_INSTRUMENT->NumberOfSamplesInInstrument
862                                         ;        idxLocalSample++
863                                         ){
864                                                 S32     reserve ;
865                                                 S32     idxSample = idxInst * MAX_SAMPLES_IN_INSTRUMENT + idxLocalSample ;
866                                                 XM_SAMPLE       *pXM_SAMPLE = XM_SAMPLE__Create( );
867                                                 pMOD->apXM_SAMPLE[ idxSample ] = pXM_SAMPLE ;
868
869                                                 /* メモリ不足? */
870                                                 if(     pXM_SAMPLE == NULL ){
871                                                         #if (WARNING_LEVEL >= 1)
872                                                                 LogMsg(pMOD->Instance,
873                                                                         "MOD__LoadSongAsXM : \n"
874                                                                         "       XM_SAMPLE 構造体の確保に失敗しました。\n"
875                                                                         "       読み込みをキャンセルします。\n"
876                                                                 );
877                                                         #endif
878                                                         MOD__ReleaseSong( pMOD );
879                                                         return( FALSE );
880                                                 }
881
882                                                 /* データ読み込み */
883                                                 pXM_SAMPLE->SampleLength                = (S32)*((S32*)&pMusDat[ ofs +  0 ]);
884                                                 pXM_SAMPLE->SampleLoopStart             = (S32)*((S32*)&pMusDat[ ofs +  4 ]);
885                                                 pXM_SAMPLE->SampleLoopLength    = (S32)*((S32*)&pMusDat[ ofs +  8 ]);
886                                                 pXM_SAMPLE->Volume                              = (S32)*((U8*) &pMusDat[ ofs + 12 ]);
887                                                 pXM_SAMPLE->FineTune                    = (S32)*((S8*) &pMusDat[ ofs + 13 ]);
888                                                 pXM_SAMPLE->Type                                = (S32)*((U8*) &pMusDat[ ofs + 14 ]);
889                                                 pXM_SAMPLE->Panning                             = (S32)*((U8*) &pMusDat[ ofs + 15 ]);
890                                                 pXM_SAMPLE->RelativeNoteNumber  = (S32)*((S8*) &pMusDat[ ofs + 16 ]);
891                                                 pXM_SAMPLE->Reserved                    = (S32)*((U8*) &pMusDat[ ofs + 17 ]);
892                                                 memcpy( &pXM_SAMPLE->aszSampleName[0]           ,  &pMusDat[ ofs + 18 ] , 22 );
893                                                 pXM_SAMPLE->aszSampleName[22] = 0 ;             /* 文字列終点 */
894                                                 ofs += pXM_INSTRUMENT->SampleHeaderSize ;
895
896                                                 #if (WARNING_LEVEL >= 3)
897                                                         LogMsg(pMOD->Instance,
898                                                                 "MOD__LoadSongAsXM : \n"
899                                                                 "       pXM_SAMPLE->SampleLength       %d \n"
900                                                                 "       pXM_SAMPLE->SampleLoopStart    %d \n"
901                                                                 "       pXM_SAMPLE->SampleLoopLength   %d \n"
902                                                                 "       pXM_SAMPLE->Volume             %d \n"
903                                                                 "       pXM_SAMPLE->FineTune           %d \n"
904                                                                 "       pXM_SAMPLE->Type               %d \n"
905                                                                 "       pXM_SAMPLE->Panning            %d \n"
906                                                                 "       pXM_SAMPLE->RelativeNoteNumber %d \n"
907                                                                 "       pXM_SAMPLE->Reserved           %d \n"
908                                                                 "       pXM_SAMPLE->aszSampleName      %s \n"
909                                                                 ,pXM_SAMPLE->SampleLength
910                                                                 ,pXM_SAMPLE->SampleLoopStart
911                                                                 ,pXM_SAMPLE->SampleLoopLength
912                                                                 ,pXM_SAMPLE->Volume
913                                                                 ,pXM_SAMPLE->FineTune
914                                                                 ,pXM_SAMPLE->Type
915                                                                 ,pXM_SAMPLE->Panning
916                                                                 ,pXM_SAMPLE->RelativeNoteNumber
917                                                                 ,pXM_SAMPLE->Reserved
918                                                                 ,pXM_SAMPLE->aszSampleName
919                                                         );
920                                                 #endif
921
922                                                 /* ループ区間の長さが 0 または、長さが 0 なら、ループを無効化 */
923                                                 if(     pXM_SAMPLE->SampleLoopLength == 0
924                                                 ||      pXM_SAMPLE->SampleLength == 0
925                                                 ){
926                                                         pXM_SAMPLE->Type &= ~(SMP_LOOP | SMP_PINGPONGLOOP);
927                                                         pXM_SAMPLE->SampleLoopStart  = 0 ;
928                                                         pXM_SAMPLE->SampleLoopLength = 0 ;
929                                                 }
930
931                                                 if(     pXM_SAMPLE->Type & (SMP_LOOP | SMP_PINGPONGLOOP) ){
932                                                         /* 無効なデータを事前に排除 */
933                                                         if(     pXM_SAMPLE->SampleLength < pXM_SAMPLE->SampleLoopStart + pXM_SAMPLE->SampleLoopLength ){
934                                                                 #if (WARNING_LEVEL >= 2)
935                                                                         LogMsg(pMOD->Instance,
936                                                                                 "MOD__LoadSongAsXM : \n"
937                                                                                 "       サンプリングデータサイズと、ループ区間の長さの整合性が取れていません。\n"
938                                                                                 "       読み込みをキャンセルします。\n"
939                                                                         );
940                                                                 #endif
941                                                                 MOD__ReleaseSong( pMOD );
942                                                                 return( FALSE );
943                                                         }
944                                                 }
945
946                                                 /* ループ展開後のサンプリングデータの全長 */
947                                                 reserve = pXM_SAMPLE->SampleLength ;
948                                                 if(     pXM_SAMPLE->Type & SMP_PINGPONGLOOP ) reserve += pXM_SAMPLE->SampleLoopLength ;
949
950                                                 /* 必要なら、サンプリングデータ領域のメモリ確保 */
951                                                 if(     reserve ){
952                                                         /*
953                                                                 プチノイズ対策のため、余分に確保。
954                                                                 reserve は要素数でなくバイト長である点に注意。
955                                                         */
956                                                         void    *pSampleData = AllocMemory( reserve + 512 );
957                                                         pXM_SAMPLE->pSampleData = pSampleData ;
958
959                                                         /* メモリ不足? */
960                                                         if(     pSampleData == NULL ){
961                                                                 #if (WARNING_LEVEL >= 1)
962                                                                         LogMsg(pMOD->Instance,
963                                                                                 "MOD__LoadSongAsXM : \n"
964                                                                                 "       サンプリングデータ読み込み先メモリの確保に失敗しました。\n"
965                                                                                 "       読み込みをキャンセルします。\n"
966                                                                         );
967                                                                 #endif
968                                                                 MOD__ReleaseSong( pMOD );
969                                                                 return( FALSE );
970                                                         }
971                                                 } else {
972                                                         pXM_SAMPLE->pSampleData = NULL ;
973                                                 }
974                                         }
975
976                                         /* 処理ステップ2 */
977                                         for( idxLocalSample = 0
978                                         ;        idxLocalSample < pXM_INSTRUMENT->NumberOfSamplesInInstrument
979                                         ;        idxLocalSample++
980                                         ){
981                                                 S32     idxSample = idxInst * MAX_SAMPLES_IN_INSTRUMENT + idxLocalSample ;
982                                                 XM_SAMPLE       *pXM_SAMPLE = pMOD->apXM_SAMPLE[ idxSample ];
983
984                                                 /* メモリ確保されていたなら処理 */
985                                                 if(     pXM_SAMPLE->pSampleData != NULL ){
986                                                         /* 無効なデータを事前に排除 */
987                                                         if(     lMusDat - ofs < pXM_SAMPLE->SampleLength ){
988                                                                 #if (WARNING_LEVEL >= 2)
989                                                                         LogMsg(pMOD->Instance,
990                                                                                 "MOD__LoadSongAsXM : \n"
991                                                                                 "       データサイズが不足しています。サンプリングデータを読み込めません。\n"
992                                                                                 "       読み込みをキャンセルします。\n"
993                                                                         );
994                                                                 #endif
995                                                                 MOD__ReleaseSong( pMOD );
996                                                                 return( FALSE );
997                                                         }
998
999                                                         /* 波形データの読み込み */
1000                                                         memcpy( pXM_SAMPLE->pSampleData , &pMusDat[ ofs ] , pXM_SAMPLE->SampleLength );
1001                                                         ofs += pXM_SAMPLE->SampleLength ;
1002
1003                                                         pXM_SAMPLE->VoiceMode = VM_ON ;
1004                                                         if(     pXM_SAMPLE->Type & (SMP_LOOP | SMP_PINGPONGLOOP) ){
1005                                                                 pXM_SAMPLE->VoiceMode |= VM_LOOP ;
1006                                                         }
1007
1008                                                         /*
1009                                                                 Δ値 -> 実際値 の変換。
1010                                                                 オーバーフローが生じても、補正しないのが正しい。
1011                                                         */
1012                                                         if(     pXM_SAMPLE->Type & SMP_16BIT ){
1013                                                                 S32     Cnt             = pXM_SAMPLE->SampleLength >> 1 ;       /* 1要素2バイト */
1014                                                                 S32     OldVal  = 0 ;
1015                                                                 S32     NewVal  = 0 ;
1016                                                                 S16     *pScan  = (S16 *)pXM_SAMPLE->pSampleData ;
1017
1018                                                                 pXM_SAMPLE->VoiceMode |= VM_16BIT ;
1019                                                                 while( Cnt-- > 0 ){
1020                                                                         NewVal = *pScan + OldVal ;
1021                                                                         *pScan++ = (S16)NewVal ;
1022                                                                         OldVal = NewVal ;
1023                                                                 }
1024                                                         } else {
1025                                                                 S32     Cnt             = pXM_SAMPLE->SampleLength ;            /* 1要素1バイト */
1026                                                                 S32     OldVal  = 0 ;
1027                                                                 S32     NewVal  = 0 ;
1028                                                                 S8      *pScan  = (S8 *)pXM_SAMPLE->pSampleData ;
1029
1030                                                                 while( Cnt-- > 0 ){
1031                                                                         NewVal = *pScan + OldVal ;
1032                                                                         *pScan++ = (S8)NewVal ;
1033                                                                         OldVal = NewVal ;
1034                                                                 }
1035                                                         }
1036
1037                                                         /* ピンポンループを展開 */
1038                                                         if(     pXM_SAMPLE->Type & SMP_PINGPONGLOOP ){
1039                                                                 pXM_SAMPLE->VoiceMode |= VM_LOOP ;
1040                                                                 if(     pXM_SAMPLE->Type & SMP_16BIT ){
1041                                                                         S32     Cnt = pXM_SAMPLE->SampleLoopLength >> 1 ;
1042                                                                         S8      *pSampleData = reinterpret_cast<S8*>(pXM_SAMPLE->pSampleData);
1043                                                                         S16     *pSrc   =  reinterpret_cast<S16 *>(pSampleData
1044                                                                                                                 + pXM_SAMPLE->SampleLoopStart
1045                                                                                                                 + pXM_SAMPLE->SampleLoopLength
1046                                                                                                                 - 2 );
1047                                                                         S16     *pDst   =  reinterpret_cast<S16 *>(pSampleData
1048                                                                                                                 + pXM_SAMPLE->SampleLoopStart
1049                                                                                                                 + pXM_SAMPLE->SampleLoopLength
1050                                                                                                                 );
1051
1052                                                                         while( Cnt-- > 0 ) *pDst++ = *pSrc-- ;
1053                                                                 } else {
1054                                                                         S32     Cnt = pXM_SAMPLE->SampleLoopLength ;
1055                                                                         S8      *pSampleData = reinterpret_cast<S8*>(pXM_SAMPLE->pSampleData );
1056                                                                         S8      *pSrc   = reinterpret_cast<S8 *>( pSampleData
1057                                                                                                                 + pXM_SAMPLE->SampleLoopStart
1058                                                                                                                 + pXM_SAMPLE->SampleLoopLength
1059                                                                                                                 - 2 );
1060                                                                         S8      *pDst   = reinterpret_cast<S8 *>( pSampleData
1061                                                                                                                 + pXM_SAMPLE->SampleLoopStart
1062                                                                                                                 + pXM_SAMPLE->SampleLoopLength
1063                                                                                                                 );
1064
1065                                                                         while( Cnt-- > 0 ) *pDst++ = *pSrc-- ;
1066                                                                 }
1067                                                                 /* 展開したので、ループ区間の長さは2倍になる */
1068                                                                 pXM_SAMPLE->SampleLoopLength <<= 1 ;
1069                                                         }
1070
1071                                                         /* 16 BIT サンプルは、長さの単位を変換 */
1072                                                         if(     pXM_SAMPLE->Type & SMP_16BIT ){
1073                                                                 pXM_SAMPLE->SampleLength         >>= 1 ;
1074                                                                 pXM_SAMPLE->SampleLoopStart      >>= 1 ;
1075                                                                 pXM_SAMPLE->SampleLoopLength >>= 1 ;
1076                                                         }
1077
1078                                                         if(     pXM_SAMPLE->VoiceMode & VM_LOOP ){
1079                                                                 /* SampleLength の再算出 */
1080                                                                 pXM_SAMPLE->SampleLength = pXM_SAMPLE->SampleLoopStart + pXM_SAMPLE->SampleLoopLength ;
1081
1082                                                                 /* 線形補完の連続性のため、末端に1要素コピー */
1083                                                                 if(     pXM_SAMPLE->Type & SMP_16BIT ){
1084                                                                         S16     *pSampleData = reinterpret_cast<S16*>(pXM_SAMPLE->pSampleData) ;
1085                                                                         pSampleData[ pXM_SAMPLE->SampleLength ] = pSampleData[ pXM_SAMPLE->SampleLoopStart ];
1086                                                                 } else {
1087                                                                         S8      *pSampleData = reinterpret_cast<S8*>(pXM_SAMPLE->pSampleData) ;
1088                                                                         pSampleData[ pXM_SAMPLE->SampleLength ] = pSampleData[ pXM_SAMPLE->SampleLoopStart ];
1089                                                                 }
1090
1091                                                         } else {
1092                                                                 /* キーオフ時プチノイズ対策(波形の最終要素を徐々に減衰させる)*/
1093                                                                 if(     pXM_SAMPLE->Type & SMP_16BIT ){
1094                                                                         S16     *pSampleData =reinterpret_cast<S16*>(pXM_SAMPLE->pSampleData );
1095                                                                         S32     LastVal_ = pSampleData[ pXM_SAMPLE->SampleLength - 1 ] << SFT ;
1096                                                                         S32     i ;
1097                                                                         for( i=0 ; i<256 ; i++ ){
1098                                                                                 pSampleData[ pXM_SAMPLE->SampleLength + i ] = (S16)(LastVal_ >> SFT) ;
1099                                                                                 LastVal_ -= LastVal_ >> 6 ;
1100                                                                         }
1101                                                                 } else {
1102                                                                         S8      *pSampleData = reinterpret_cast<S8*>(pXM_SAMPLE->pSampleData) ;
1103                                                                         S32     LastVal_ = pSampleData[ pXM_SAMPLE->SampleLength - 1 ] << SFT ;
1104                                                                         S32     i ;
1105                                                                         for( i=0 ; i<256 ; i++ ){
1106                                                                                 pSampleData[ pXM_SAMPLE->SampleLength + i ] = (S8)(LastVal_ >> SFT) ;
1107                                                                                 LastVal_ -= LastVal_ >> 6 ;
1108                                                                         }
1109                                                                 }
1110                                                                 pXM_SAMPLE->SampleLength += 255 ;       /* 1 要素の余裕を持たせる */
1111                                                         }
1112                                                 }
1113                                         }
1114                                 }
1115
1116                                 /* 全 Note 対応のサンプリングデータへのポインターをここで先に求めておく */
1117                                 {
1118                                         S32     idxNote ;
1119                                         for( idxNote = 0 ; idxNote <= 95 ; idxNote++ ){
1120                                                 S32     idxSample = pXM_INSTRUMENT->aSampleNumberForAllNotes[ idxNote ];
1121
1122                                                 if(     0 <= idxSample
1123                                                 &&      idxSample < MAX_SAMPLES_IN_INSTRUMENT
1124                                                 ){
1125                                                         pXM_INSTRUMENT->apAllNoteXM_SAMPLE[ idxNote ]
1126                                                         =       pMOD->apXM_SAMPLE[ idxInst * MAX_SAMPLES_IN_INSTRUMENT + idxSample ];
1127                                                 } else {
1128                                                         pXM_INSTRUMENT->apAllNoteXM_SAMPLE[ idxNote ] = NULL ;
1129                                                 }
1130                                         }
1131                                 }
1132                         }
1133                 }
1134         }
1135
1136         return( TRUE );
1137 }
1138
1139
1140
1141 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1142 ▼     MOD 形式とみなして読み込み
1143
1144         戻値・TRUE  = 成功
1145                 ・FALSE = 失敗
1146 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1147 static S32 MOD__LoadSongAsMOD(
1148          MOD    *pMOD
1149         ,void   *pMusDat_
1150         ,S32     lMusDat
1151 ){
1152         U8      *pMusDat = reinterpret_cast<U8*>(pMusDat_) ;
1153         S32     i ;
1154         S32     ofs = 0 ;
1155
1156         if(     pMOD == NULL ) return( FALSE );
1157
1158         /* 無効なデータを事前に排除 */
1159         if(     lMusDat < 1080+4 ){
1160                 #if (WARNING_LEVEL >= 2)
1161                         LogMsg(pMOD->Instance,
1162                                 "MOD__LoadSongAsMOD : \n"
1163                                 "       データサイズが不足しています。\n"
1164                                 "       読み込みをキャンセルします。\n"
1165                         );
1166                 #endif
1167                 MOD__ReleaseSong( pMOD );
1168                 return( FALSE );
1169         }
1170
1171         /* データ読み込み */
1172         memcpy( &pMOD->XmId.aszModuleName[0] , &pMusDat[ ofs + 0 ] , 20 );
1173         pMOD->XmId.aszModuleName[19] = 0 ;      /* 文字列終点 */
1174         ofs += 20 ;
1175
1176         #if (WARNING_LEVEL >= 2)
1177                 LogMsg(pMOD->Instance,
1178                         "MOD__LoadSongAsMOD : ModName = %s \n"
1179                         ,pMOD->XmId.aszModuleName
1180                 );
1181         #endif
1182
1183         /*
1184                 フォーマット識別から、サンプリングデータ総数と、総チャンネル数を知る。
1185                 識別子が無い場合は、この位置がパターンデータの出発点となり、
1186                 サンプリングデータは 15 種類となるが、そのような古いデータには対応しない。
1187         */
1188         {
1189                 struct {
1190                         const char      *pszExt ;
1191                         S32             idxChannel ;
1192                         S32             idxInst ;
1193                 } ExtInfo[] = {
1194                          { "M.K." , 4 , 31 }            /* protracker 4 channel */
1195                         ,{ "M!K!" , 4 , 31 }            /* protracker 4 channel(パターンの Row 数が可変らしい?)*/
1196                         ,{ "M&K!" , 4 , 31 }
1197                         ,{ "FLT4" , 4 , 31 }            /* startracker 4 channel */
1198                         ,{ "FLT8" , 4 , 31 }            /* 怪しいが、4ch 扱いとするらしい。*/
1199                         ,{ "N.T." , 4 , 15 }            /* 古い 0xFxx コマンドによるテンポ設定を有効にしなければならない */
1200                         ,{ "CD81" , 8 , 31 }            /* atari oktalyzer 8 channel */
1201                         ,{ "OKTA" , 8 , 31 }            /* atari oktalyzer 8 channel */
1202                         ,{ "TDZ1" , 1 , 31 }
1203                         ,{ "TDZ2" , 2 , 31 }
1204                         ,{ "TDZ3" , 3 , 31 }
1205                         ,{ "TDZ4" , 4 , 31 }
1206                         ,{ "TDZ5" , 5 , 31 }
1207                         ,{ "TDZ6" , 6 , 31 }
1208                         ,{ "TDZ7" , 7 , 31 }
1209                         ,{ "TDZ8" , 8 , 31 }
1210                         ,{ "TDZ9" , 9 , 31 }
1211                         ,{ "1CHN" , 1 , 31 }
1212                         ,{ "2CHN" , 2 , 31 }
1213                         ,{ "3CHN" , 3 , 31 }
1214                         ,{ "4CHN" , 4 , 31 }            /* fasttracker 4 channel */
1215                         ,{ "5CHN" , 5 , 31 }
1216                         ,{ "6CHN" , 6 , 31 }            /* fasttracker 6 channel */
1217                         ,{ "7CHN" , 7 , 31 }
1218                         ,{ "8CHN" , 8 , 31 }            /* fasttracker 8 channel */
1219                         ,{ "9CHN" , 9 , 31 }
1220                         ,{ "10CH" ,10 , 31 }
1221                         ,{ "11CH" ,11 , 31 }
1222                         ,{ "12CH" ,12 , 31 }
1223                         ,{ "13CH" ,13 , 31 }
1224                         ,{ "14CH" ,14 , 31 }
1225                         ,{ "15CH" ,15 , 31 }
1226                         ,{ "16CH" ,16 , 31 }
1227                         ,{ "17CH" ,17 , 31 }
1228                         ,{ "18CH" ,18 , 31 }
1229                         ,{ "19CH" ,19 , 31 }
1230                         ,{ "20CH" ,20 , 31 }
1231                         ,{ "21CH" ,21 , 31 }
1232                         ,{ "22CH" ,22 , 31 }
1233                         ,{ "23CH" ,23 , 31 }
1234                         ,{ "24CH" ,24 , 31 }
1235                         ,{ "25CH" ,25 , 31 }
1236                         ,{ "26CH" ,26 , 31 }
1237                         ,{ "27CH" ,27 , 31 }
1238                         ,{ "28CH" ,28 , 31 }
1239                         ,{ "29CH" ,29 , 31 }
1240                         ,{ "30CH" ,30 , 31 }
1241                         ,{ "31CH" ,31 , 31 }
1242                         ,{ "32CH" ,32 , 31 }
1243                         ,{ "16CN" ,16 , 31 }            /* taketracker 16 channel */
1244                         ,{ "32CN" ,32 , 31 }            /* taketracker 32 channel */
1245                         ,{ "    " , 4 , 15 }
1246                         ,{  NULL  , 0 ,  0 }
1247                 };
1248
1249                 #if (WARNING_LEVEL >= 2)
1250                 {
1251                         char    aExt[5];
1252                         aExt[0] = pMusDat[1080] ;
1253                         aExt[1] = pMusDat[1081] ;
1254                         aExt[2] = pMusDat[1082] ;
1255                         aExt[3] = pMusDat[1083] ;
1256                         aExt[4] = 0 ;
1257
1258                         LogMsg(pMOD->Instance,
1259                                 "MOD__LoadSongAsMOD : +1080 識別子 = [%s] \n"
1260                                 ,aExt
1261                         );
1262                 }
1263                 #endif
1264
1265                 i = 0 ;
1266                 while( -1 ){
1267                         /* 終点に達したら異常終了 */
1268                         if(     ExtInfo[ i ].pszExt == NULL ){
1269                                 #if (WARNING_LEVEL >= 2)
1270                                         LogMsg(pMOD->Instance,
1271                                                 "MOD__LoadSongAsMOD : "
1272                                                 "       不明な +1080 識別子です。読み込みをキャンセルします。\n"
1273                                         );
1274                                 #endif
1275                                 MOD__ReleaseSong( pMOD );
1276                                 return( FALSE );
1277                         }
1278
1279                         /* 識別子が一致したら、認識成功 */
1280                         if(     pMusDat[1080] == ExtInfo[ i ].pszExt[0]
1281                         &&      pMusDat[1081] == ExtInfo[ i ].pszExt[1]
1282                         &&      pMusDat[1082] == ExtInfo[ i ].pszExt[2]
1283                         &&      pMusDat[1083] == ExtInfo[ i ].pszExt[3]
1284                         ){
1285                                 pMOD->XmHeader.NumberOfChannels         = ExtInfo[ i ].idxChannel ;
1286                                 pMOD->XmHeader.NumberOfInstruments      = ExtInfo[ i ].idxInst ;
1287                                 #if (WARNING_LEVEL >= 3)
1288                                         LogMsg(pMOD->Instance,
1289                                                 "MOD__LoadSongAsMOD : \n"
1290                                                 "       +1080 識別子の認識に成功しました。\n"
1291                                                 "       チャンネル数 = %d , サンプリングデータ数 = %d \n"
1292                                                 ,pMOD->XmHeader.NumberOfChannels
1293                                                 ,pMOD->XmHeader.NumberOfInstruments
1294                                         );
1295                                 #endif
1296                                 break ;
1297                         }
1298
1299                         i++ ;
1300                 }
1301         }
1302
1303
1304         /* サンプリングデータの情報を取得 */
1305         {
1306                 S32     idxInst ;
1307
1308                 /* XM_SAMPLE */
1309                 for( idxInst = 0 ; idxInst < pMOD->XmHeader.NumberOfInstruments ; idxInst++ ){
1310                         S32     idxSample = idxInst * MAX_SAMPLES_IN_INSTRUMENT ;
1311                         XM_SAMPLE               *pXM_SAMPLE ; 
1312
1313                         /* XM_SAMPLE 構造体の確保 */
1314                         pMOD->apXM_SAMPLE[ idxSample ] = pXM_SAMPLE = XM_SAMPLE__Create( );
1315
1316                         /* メモリ不足? */
1317                         if(     pXM_SAMPLE == NULL ){
1318                                 #if (WARNING_LEVEL >= 1)
1319                                         LogMsg(pMOD->Instance,
1320                                                 "MOD__LoadSongAsMOD : \n"
1321                                                 "       XM_SAMPLE 構造体の確保に失敗しました。\n"
1322                                                 "       読み込みをキャンセルします。\n"
1323                                         );
1324                                 #endif
1325                                 MOD__ReleaseSong( pMOD );
1326                                 return( FALSE );
1327                         }
1328
1329                         /* XM_SAMPLE 構造体の初期化 */
1330                         {
1331                                 pXM_SAMPLE->Type                                = 0 ;
1332                                 pXM_SAMPLE->Panning                             = 0x80 ;
1333                                 pXM_SAMPLE->RelativeNoteNumber  = 0 ;
1334                                 pXM_SAMPLE->Reserved                    = 0 ;
1335
1336                                 /* サンプリングデータの名前を取得 */
1337                                 memcpy( &pXM_SAMPLE->aszSampleName[0] , &pMusDat[ ofs ] , 21 );
1338                                 pXM_SAMPLE->aszSampleName[21] = 0 ;             /* 文字列終点 */
1339                                 ofs += 22 ;
1340
1341                                 /*
1342                                         サンプリングデータの長さを取得。
1343                                         2倍してはじめて、バイト長となる。
1344                                 */
1345                                 pXM_SAMPLE->SampleLength = (U32)( ((U32)pMusDat[ ofs + 0 ] << 8)
1346                                                                                                 | ((U32)pMusDat[ ofs + 1 ] << 0) );
1347                                 pXM_SAMPLE->SampleLength *= 2 ;
1348                                 ofs += 2 ;
1349
1350                                 /*
1351                                         正規の音階に合わせるための修正値。
1352                                         上位 4 bit は 0 であること。
1353                                 */
1354                                 {
1355                                         S32     Val = pMusDat[ ofs ] & 15 ;
1356                                         if(     Val >= 8 ){
1357                                                 Val = Val - 16 ;
1358                                         }
1359                                         pXM_SAMPLE->FineTune = Val << 4 ;
1360                                 }
1361                                 ofs++ ;
1362
1363                                 /* サンプリングデータのデフォルト音量( 0 - 64 の値)*/
1364                                 pXM_SAMPLE->Volume = pMusDat[ ofs ];
1365                                 ofs++ ;
1366
1367                                 /*
1368                                         サンプリングデータのループ開始位置。
1369                                         2倍してはじめて、バイト長となる。
1370                                 */
1371                                 pXM_SAMPLE->SampleLoopStart     = (S32)( ((U32)pMusDat[ ofs + 0 ] << 8)
1372                                                                                                         |((U32)pMusDat[ ofs + 1 ] << 0) );
1373                                 pXM_SAMPLE->SampleLoopStart     *= 2 ;
1374                                 ofs += 2 ;
1375
1376                                 /*
1377                                         サンプリングデータのループ区間の長さ。
1378                                         2倍してはじめて、バイト長となる。
1379                                 */
1380                                 pXM_SAMPLE->SampleLoopLength = (S32)( ((U32)pMusDat[ ofs + 0 ] << 8)
1381                                                                                                         | ((U32)pMusDat[ ofs + 1 ] << 0) );
1382                                 pXM_SAMPLE->SampleLoopLength *= 2 ;
1383                                 ofs += 2 ;
1384
1385                                 /* サンプリングのループ再生有無の判定 */
1386                                 if(     pXM_SAMPLE->SampleLoopLength <= 2
1387                                 ||      pXM_SAMPLE->SampleLength == 0
1388                                 ){
1389                                         pXM_SAMPLE->Type &= ~(SMP_LOOP | SMP_PINGPONGLOOP);
1390                                         pXM_SAMPLE->SampleLoopStart  = 0 ;
1391                                         pXM_SAMPLE->SampleLoopLength = 0 ;
1392                                 } else {
1393                                         pXM_SAMPLE->Type |= SMP_LOOP ;
1394
1395                                         /* 無効なデータを事前に排除 */
1396                                         if(     pXM_SAMPLE->SampleLength < pXM_SAMPLE->SampleLoopStart + pXM_SAMPLE->SampleLoopLength ){
1397                                                 #if (WARNING_LEVEL >= 2)
1398                                                         LogMsg(pMOD->Instance,
1399                                                                 "MOD__LoadSongAsMOD : \n"
1400                                                                 "       サンプリングデータサイズと、ループ区間の長さの整合性が取れていません。\n"
1401                                                                 "       読み込みをキャンセルします。\n"
1402                                                         );
1403                                                 #endif
1404                                                 MOD__ReleaseSong( pMOD );
1405                                                 return( FALSE );
1406                                         }
1407                                 }
1408
1409                                 /* 読みこみ結果のモニタリング */
1410                                 #if (WARNING_LEVEL >= 3)
1411                                         LogMsg(pMOD->Instance,
1412                                                 "MOD__LoadSongAsMOD : \n"
1413                                                 "       pXM_SAMPLE->SampleLength       %d \n"
1414                                                 "       pXM_SAMPLE->SampleLoopStart    %d \n"
1415                                                 "       pXM_SAMPLE->SampleLoopLength   %d \n"
1416                                                 "       pXM_SAMPLE->Volume             %d \n"
1417                                                 "       pXM_SAMPLE->FineTune           %d \n"
1418                                                 "       pXM_SAMPLE->Type               %d \n"
1419                                                 "       pXM_SAMPLE->Panning            %d \n"
1420                                                 "       pXM_SAMPLE->RelativeNoteNumber %d \n"
1421                                                 "       pXM_SAMPLE->Reserved           %d \n"
1422                                                 "       pXM_SAMPLE->aszSampleName      %s \n"
1423                                                 ,pXM_SAMPLE->SampleLength
1424                                                 ,pXM_SAMPLE->SampleLoopStart
1425                                                 ,pXM_SAMPLE->SampleLoopLength
1426                                                 ,pXM_SAMPLE->Volume
1427                                                 ,pXM_SAMPLE->FineTune
1428                                                 ,pXM_SAMPLE->Type
1429                                                 ,pXM_SAMPLE->Panning
1430                                                 ,pXM_SAMPLE->RelativeNoteNumber
1431                                                 ,pXM_SAMPLE->Reserved
1432                                                 ,pXM_SAMPLE->aszSampleName
1433                                         );
1434                                 #endif
1435                         }
1436                 }
1437
1438                 /* XM_INSTRUMENT */
1439                 for( idxInst = 0 ; idxInst < pMOD->XmHeader.NumberOfInstruments ; idxInst++ ){
1440                         S32     idxSample = idxInst * MAX_SAMPLES_IN_INSTRUMENT ;
1441                         XM_INSTRUMENT   *pXM_INSTRUMENT ;
1442
1443                         /* XM_INSTRUMENT 構造体の確保 */
1444                         pMOD->apXM_INSTRUMENT[ idxInst ] = pXM_INSTRUMENT = XM_INSTRUMENT__Create( );
1445
1446                         /* メモリ不足? */
1447                         if(     pXM_INSTRUMENT == NULL ){
1448                                 #if (WARNING_LEVEL >= 1)
1449                                         LogMsg(pMOD->Instance,
1450                                                 "MOD__LoadSongAsMOD : \n"
1451                                                 "       XM_INSTRUMENT 構造体の確保に失敗しました。\n"
1452                                                 "       読み込みをキャンセルします。\n"
1453                                         );
1454                                 #endif
1455                                 MOD__ReleaseSong( pMOD );
1456                                 return( FALSE );
1457                         }
1458
1459                         /* XM_INSTRUMENT 構造体の初期化 */
1460                         {
1461                                 pXM_INSTRUMENT->InstrumentSize                          = 0 ;
1462                                 pXM_INSTRUMENT->aszInstrumentName[0]            = 0 ;
1463                                 pXM_INSTRUMENT->InstrumentType                          = 0 ;
1464                                 pXM_INSTRUMENT->NumberOfSamplesInInstrument     = 1 ;
1465                                 pXM_INSTRUMENT->SampleHeaderSize                        = 0 ;
1466                                 for( i=0 ; i<96 ; i++ ){
1467                                         pXM_INSTRUMENT->aSampleNumberForAllNotes[i] = (U8)idxInst ;
1468                                 }
1469                                 for( i=0 ; i<12 ; i++ ){
1470                                         pXM_INSTRUMENT->aPointsForVolumeEnvelope[i].x   = 0 ;
1471                                         pXM_INSTRUMENT->aPointsForVolumeEnvelope[i].y   = 0 ;
1472                                         pXM_INSTRUMENT->aPointsForPanningEnvelope[i].x  = 0 ;
1473                                         pXM_INSTRUMENT->aPointsForPanningEnvelope[i].y  = 0 ;
1474                                 }
1475                                 pXM_INSTRUMENT->NumberOfVolumePoints            = 0 ;
1476                                 pXM_INSTRUMENT->NumberOfPanningPoints           = 0 ;
1477                                 pXM_INSTRUMENT->VolumeSustainPoint                      = 0 ;
1478                                 pXM_INSTRUMENT->VolumeLoopStartPoint            = 0 ;
1479                                 pXM_INSTRUMENT->VolumeLoopEndPoint                      = 0 ;
1480                                 pXM_INSTRUMENT->PanningSustainPoint                     = 0 ;
1481                                 pXM_INSTRUMENT->PanningLoopStartPoint           = 0 ;
1482                                 pXM_INSTRUMENT->PanningLoopEndPoint                     = 0 ;
1483                                 pXM_INSTRUMENT->VolumeType                                      = 0 ;
1484                                 pXM_INSTRUMENT->PanningType                                     = 0 ;
1485                                 pXM_INSTRUMENT->AutoVibratoType                         = 0 ;
1486                                 pXM_INSTRUMENT->AutoVibratoSweep                        = 0 ;
1487                                 pXM_INSTRUMENT->AutoVibratoDepth                        = 0 ;
1488                                 pXM_INSTRUMENT->AutoVibratoRate                         = 0 ;
1489                                 pXM_INSTRUMENT->VolumeFadeout                           = 0 ;
1490                                 pXM_INSTRUMENT->Reserved                                        = 0 ;
1491
1492                                 for( i=0 ; i<96 ; i++ ){
1493                                         pXM_INSTRUMENT->apAllNoteXM_SAMPLE[ i ] = pMOD->apXM_SAMPLE[ idxSample ];
1494                                 }
1495                                 for( i=0 ; i<325 ; i++ ){
1496                                         pXM_INSTRUMENT->VolumeEnvelopeTable[ i ]        = 0 ;
1497                                         pXM_INSTRUMENT->PanningEnvelopeTable[ i ]       = 0 ;
1498                                 }
1499                         }
1500                 }
1501         }
1502
1503
1504         /* オーダーテーブルの全長(1 ~ 128)*/
1505         pMOD->XmHeader.SongLength = pMusDat[ ofs ];
1506         ofs++ ;
1507
1508         /*
1509                 NoiseTracker がオーダーテーブルのリピートポイントとしたバイト。
1510                 ProTracker モジュールでは無意味なので、スキップする。
1511         */
1512         ofs++ ;
1513
1514
1515         /* パターンオーダーテーブルと、パターンデータの取得 */
1516         {
1517                 S32     idxPattern ;
1518                 S32     idxRow ;
1519                 S32     idxCannel ;
1520
1521                 /* パターンオーダーテーブルの取得(MOD 形式では、128 byte 固定)*/
1522                 memcpy( &pMOD->XmHeader.aPatternOrderTable[0] , &pMusDat[ ofs ] , 128 );
1523                 ofs += 128 ;
1524
1525                 /* パターンオーダーテーブル中の最大の値が、総パターンデータ数である。*/
1526                 pMOD->XmHeader.NumberOfPatterns = 0 ;
1527                 for( i=0 ; i<=127 ; i++ ){
1528                         if(     pMOD->XmHeader.NumberOfPatterns < pMOD->XmHeader.aPatternOrderTable[i] + 1 ){
1529                                 pMOD->XmHeader.NumberOfPatterns = pMOD->XmHeader.aPatternOrderTable[i] + 1 ;
1530                         }
1531                 }
1532
1533                 #if (WARNING_LEVEL >= 3)
1534                         LogMsg(pMOD->Instance,
1535                                 "MOD__LoadSongAsMOD : \n"
1536                                 "       pMOD->XmHeader.NumberOfPatterns = %d \n"
1537                                 ,pMOD->XmHeader.NumberOfPatterns
1538                         );
1539                 #endif
1540
1541                 /* +1080 フォーマット識別子をスキップ */
1542                 ofs += 4 ;
1543
1544                 /* 無効なデータを事前に排除 */
1545                 if(     lMusDat - ofs <   pMOD->XmHeader.NumberOfChannels
1546                                                         * pMOD->XmHeader.NumberOfPatterns
1547                                                         * 64    /* MOD 形式では、パターンデータは 64 Row */
1548                                                         * 4
1549                 ){
1550                         #if (WARNING_LEVEL >= 3)
1551                                 LogMsg(pMOD->Instance,
1552                                         "MOD__LoadSongAsMOD : \n"
1553                                         "       データサイズが不足しています。パターンデータを読み込めません。\n"
1554                                         "       読み込みをキャンセルします。\n"
1555                                 );
1556                         #endif
1557                         MOD__ReleaseSong( pMOD );
1558                         return( FALSE );
1559                 }
1560
1561                 for( idxPattern = 0 ; idxPattern < pMOD->XmHeader.NumberOfPatterns ; idxPattern++ ){
1562                         XM_PATTERN      *pXM_PATTERN ;
1563
1564                         /* XM_PATTERN 構造体の確保 */
1565                         pMOD->apXM_PATTERN[ idxPattern ] = pXM_PATTERN = XM_PATTERN__Create( );
1566
1567                         /* メモリ不足? */
1568                         if(     pXM_PATTERN == NULL ){
1569                                 #if (WARNING_LEVEL >= 1)
1570                                         LogMsg(pMOD->Instance,
1571                                                 "MOD__LoadSongAsMOD : \n"
1572                                                 "       XM_PATTERN 構造体の確保に失敗しました。\n"
1573                                                 "       読み込みをキャンセルします。\n"
1574                                         );
1575                                 #endif
1576                                 MOD__ReleaseSong( pMOD );
1577                                 return( FALSE );
1578                         }
1579
1580                         /* XM_PATTERN 構造体の初期化 */
1581                         {
1582                                 pXM_PATTERN->PatternHeaderLength        = 0 ;
1583                                 pXM_PATTERN->PackingType                        = 0 ;
1584                                 pXM_PATTERN->NumberOfRowsInPattern      = 64 ;  /* MOD 形式では、パターンデータは 64 Row */
1585                                 pXM_PATTERN->PackedPatterndataSize      = 0 ;
1586
1587                                 pXM_PATTERN->pPatternData
1588                                 =       reinterpret_cast<U8*>(AllocMemory( pMOD->XmHeader.NumberOfChannels * pXM_PATTERN->NumberOfRowsInPattern * 5 ));
1589
1590                                 if(     pXM_PATTERN->pPatternData == NULL ){
1591                                         #if (WARNING_LEVEL >= 1)
1592                                                 LogMsg(pMOD->Instance,
1593                                                         "MOD__LoadSongAsMOD : 異常事態発生 \n"
1594                                                         "       パターンデータ領域の確保に失敗しました。\n"
1595                                                         "       読み込みをキャンセルします。\n"
1596                                                 );
1597                                         #endif
1598                                         MOD__ReleaseSong( pMOD );
1599                                         return( FALSE );
1600                                 }
1601                         }
1602
1603                         /*
1604                                 MOD 形式 -> XM 形式の変換を行いつつ読み込む。
1605                                 MOD 形式のパターンデータは、1チャンネル当たり、Row数 * 4 バイトで構成される。
1606                                 XM  形式のパターンデータは、1チャンネル当たり、Row数 * 5 バイトで構成される。
1607                         */
1608                         for( idxRow = 0 ; idxRow < pXM_PATTERN->NumberOfRowsInPattern ; idxRow++ ){
1609                                 for( idxCannel = 0 ; idxCannel < pMOD->XmHeader.NumberOfChannels ; idxCannel++ ){
1610                                         static const S32 _aPeriodTable[] =
1611                                         {
1612                                                 0x6B0,0x650,0x5F5,0x5A0,0x54F,0x503,0x4BB,0x477,0x436,0x3FA,0x3C1,0x38B,        /* Octave 0 */
1613                                                 0x358,0x328,0x2FB,0x2D0,0x2A7,0x281,0x25D,0x23B,0x21B,0x1FD,0x1E0,0x1C5,        /* Octave 1 */
1614                                                 0x1AC,0x194,0x17D,0x168,0x154,0x141,0x12F,0x11E,0x10E,0x0FE,0x0F0,0x0E3,        /* Octave 2 */
1615                                                 0x0D6,0x0CA,0x0BF,0x0B4,0x0AA,0x0A0,0x097,0x08F,0x087,0x07F,0x078,0x071,        /* Octave 3 */
1616                                                 0x06B,0x065,0x05F,0x05A,0x055,0x050,0x04C,0x047,0x043,0x040,0x03C,0x039,        /* Octave 4 */
1617                                                 0x035,0x032,0x030,0x02D,0x02A,0x028,0x026,0x024,0x022,0x020,0x01E,0x01C,        /* Octave 5 */
1618                                                 0x01B,0x019,0x018,0x016,0x015,0x014,0x013,0x012,0x011,0x010,0x00F,0x00E         /* Octave 6 */
1619                                         };
1620
1621                                         S32     idxInst         = ((pMusDat[ ofs + 2 ] >> 4) & 0x0F) | (pMusDat[ ofs + 0 ] & 0xF0) ;
1622                                         S32     Period          = pMusDat[ ofs + 1 ] | ((pMusDat[ ofs + 0 ] & 0x0F) << 8) ;
1623                                         S32     Command         = pMusDat[ ofs + 2 ] & 0x0F ;
1624                                         S32     Param           = pMusDat[ ofs + 3 ];
1625
1626                                         S32     idxKey          = 0 ;
1627                                         S32     VolumeColumn= 0 ;
1628                                         S32     i ;
1629
1630                                         /* Period -> Key 変換(テーブルから、最も近そうな値を検索)*/
1631                                         if(     Period ){
1632                                                 for( i = 0 ; i <= 7*12-2 ; i++ ){
1633                                                         if(     Period >= _aPeriodTable[i] + ((_aPeriodTable[i+1] - _aPeriodTable[i]) >> 1) ){
1634                                                                 idxKey = i+1 ;
1635                                                                 break ;
1636                                                         }
1637                                                 }
1638                                                 idxKey += 24 ;
1639                                         }
1640
1641                                         /*
1642                                                 MOD 形式では、音色指定を行う時、Volume column にデフォルト音量を
1643                                                 指定するのと同じ効果が得られる。
1644                                         */
1645                                         if(     idxInst ){
1646                                                 XM_SAMPLE *pXM_SAMPLE = pMOD->apXM_SAMPLE[ MAX_SAMPLES_IN_INSTRUMENT * (idxInst - 1) ];
1647                                                 if(     pXM_SAMPLE != NULL ){
1648                                                         VolumeColumn = pXM_SAMPLE->Volume + 0x10 ;
1649                                                 }
1650                                         }
1651
1652                                         /* 出力 */
1653                                         {
1654                                                 S32     zxc = (idxRow * pMOD->XmHeader.NumberOfChannels + idxCannel) * 5 ;
1655                                                 pXM_PATTERN->pPatternData[ zxc + 0 ] = (U8)idxKey ;
1656                                                 pXM_PATTERN->pPatternData[ zxc + 1 ] = (U8)idxInst ;
1657                                                 pXM_PATTERN->pPatternData[ zxc + 2 ] = (U8)VolumeColumn ;
1658                                                 pXM_PATTERN->pPatternData[ zxc + 3 ] = (U8)Command ;
1659                                                 pXM_PATTERN->pPatternData[ zxc + 4 ] = (U8)Param ;
1660                                         }
1661
1662                                         ofs += 4 ;
1663                                 }
1664                         }
1665                 }
1666
1667                 /* 有効なパターンデータ数分、有効なポインターを割り当て、それ以降は NULL とする。*/
1668                 for( idxPattern = pMOD->XmHeader.NumberOfPatterns ; idxPattern < MAX_PATTERNS ; idxPattern++ ){
1669                         pMOD->apXM_PATTERN[ idxPattern ] = NULL ;
1670                 }
1671         }
1672
1673
1674         /* サンプリングデータの読みこみ */
1675         {
1676                 S32     idxInst ;
1677
1678                 for( idxInst = 0 ; idxInst < pMOD->XmHeader.NumberOfInstruments ; idxInst++ ){
1679                         XM_SAMPLE *pXM_SAMPLE = pMOD->apXM_SAMPLE[ MAX_SAMPLES_IN_INSTRUMENT * idxInst ];
1680
1681                         if(     pXM_SAMPLE != NULL ){
1682                                 S32     len = pXM_SAMPLE->SampleLength ;
1683
1684                                 if(     len ){
1685                                         /* 無効なデータを事前に排除 */
1686                                         if(     lMusDat - ofs < len ){
1687                                                 #if (WARNING_LEVEL >= 2)
1688                                                         LogMsg(pMOD->Instance,
1689                                                                 "MOD__LoadSongAsMOD : \n"
1690                                                                 "       データサイズが不足しています。サンプリングデータを読み込めません。\n"
1691                                                                 "       読み込みをキャンセルします。\n"
1692                                                         );
1693                                                 #endif
1694                                                 MOD__ReleaseSong( pMOD );
1695                                                 return( FALSE );
1696                                         }
1697
1698                                         /* メモリ確保(プチノイズ対策のため、余分に確保)。*/
1699                                         pXM_SAMPLE->pSampleData = AllocMemory( len + 256 );
1700
1701                                         if(     pXM_SAMPLE->pSampleData == NULL ){
1702                                                 #if (WARNING_LEVEL >= 1)
1703                                                         LogMsg(pMOD->Instance,
1704                                                                 "MOD__LoadSongAsMOD : 異常事態発生 \n"
1705                                                                 "       サンプリングデータ領域の確保に失敗しました。\n"
1706                                                                 "       読み込みをキャンセルします。\n"
1707                                                         );
1708                                                 #endif
1709                                                 MOD__ReleaseSong( pMOD );
1710                                                 return( FALSE );
1711                                         }
1712
1713                                         #if (WARNING_LEVEL >= 3)
1714                                                 LogMsg(pMOD->Instance,
1715                                                         "MOD__LoadSongAsMOD : \n"
1716                                                         "       サンプリングデータ %d 読みこみ。len = %d \n"
1717                                                         ,idxInst
1718                                                         ,len
1719                                                 );
1720                                         #endif
1721
1722                                         memcpy( pXM_SAMPLE->pSampleData , &pMusDat[ ofs ] , len );
1723                                         ofs += len ;
1724
1725                                         pXM_SAMPLE->VoiceMode = VM_ON ;
1726
1727                                         if(     pXM_SAMPLE->Type & SMP_LOOP ){
1728                                                 pXM_SAMPLE->VoiceMode |= VM_LOOP ;
1729
1730                                                 /* SampleLength の再算出 */
1731                                                 pXM_SAMPLE->SampleLength = pXM_SAMPLE->SampleLoopStart + pXM_SAMPLE->SampleLoopLength ;
1732
1733                                                 /* 線形補完の連続性のため、末端に1要素コピー */
1734                                                 {
1735                                                         S8      *pSampleData = (S8*)pXM_SAMPLE->pSampleData ;
1736                                                         pSampleData[ pXM_SAMPLE->SampleLength ] = pSampleData[ pXM_SAMPLE->SampleLoopStart ];
1737                                                 }
1738
1739                                         } else {
1740                                                 /* キーオフ時プチノイズ対策(波形の最終要素を徐々に減衰させる)*/
1741                                                 S8      *pSampleData = (S8*)pXM_SAMPLE->pSampleData ;
1742                                                 S32     LastVal_ = pSampleData[ pXM_SAMPLE->SampleLength - 1 ] << SFT ;
1743                                                 S32     i ;
1744                                                 for( i=0 ; i<256 ; i++ ){
1745                                                         pSampleData[ pXM_SAMPLE->SampleLength + i ] = (S8)(LastVal_ >> SFT) ;
1746                                                         LastVal_ -= LastVal_ >> 6 ;
1747                                                 }
1748
1749                                                 pXM_SAMPLE->SampleLength += 255 ;       /* 1 要素の余裕を持たせる */
1750                                         }
1751                                 }
1752                         }
1753                 }
1754         }
1755
1756         /* その他 */
1757         pMOD->XmId.aszID_Text[0]                                = 0 ;                   /* 文字列終点 */
1758         pMOD->XmId.ID_Byte                                              = 0 ;                   /* ダミー */
1759         pMOD->XmId.aszTrackerName[0]                    = 0 ;                   /* 文字列終点 */
1760         pMOD->XmId.VersionNumber                                = 0 ;                   /* ダミー */
1761         pMOD->XmHeader.HeaderSize                               = 0 ;                   /* ダミー */
1762         pMOD->XmHeader.RestartPosition                  = 0 ;                   /* ダミー */
1763         pMOD->XmHeader.Flags                                    = 0 ;
1764         pMOD->XmHeader.DefaultTempo                             = 6 ;
1765         pMOD->XmHeader.DefaultBPM                               = 125 ;
1766
1767         return( TRUE );
1768 }
1769
1770
1771
1772 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1773 ▼     MOD データの読み込み
1774
1775         戻値・TRUE  = 成功
1776                 ・FALSE = 失敗
1777 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1778 S32 MOD__LoadSong(
1779          MOD    *pMOD           /* this ポインター */
1780         ,void   *pMusDat_       /* メモリ上にファイルを読み込み、そのポインターをここに指定 */
1781         ,S32     lMusDat        /* データサイズ */
1782 ){
1783         if(     pMOD == NULL ) return( FALSE );
1784
1785         /* 前回までの古いデータを破棄 */
1786         MOD__ReleaseSong( pMOD );
1787
1788         /* XM 形式? */
1789         if(     MOD__LoadSongAsXM( pMOD , pMusDat_ , lMusDat ) ){
1790                 pMOD->FormatType = TYPE_XM ;
1791                 MOD__InitPlay( pMOD );
1792
1793                 #if (WARNING_LEVEL >= 2)
1794                         LogMsg(pMOD->Instance,
1795                                 "MOD__LoadSong : XM 形式として読み込みました。\n"
1796                         );
1797                 #endif
1798
1799                 return( TRUE );
1800         }
1801
1802         /* MOD 形式? */
1803         if(     MOD__LoadSongAsMOD( pMOD , pMusDat_ , lMusDat ) ){
1804                 pMOD->FormatType = TYPE_MOD ;
1805                 MOD__InitPlay( pMOD );
1806
1807                 #if (WARNING_LEVEL >= 2)
1808                         LogMsg(pMOD->Instance,
1809                                 "MOD__LoadSong : MOD 形式として読み込みました。\n"
1810                         );
1811                 #endif
1812
1813                 return( TRUE );
1814         }
1815
1816         /* 無効な型とみなす */
1817         pMOD->FormatType = TYPE_NOTAVAILABLE ;
1818         return( FALSE );
1819 }
1820
1821
1822
1823 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1824 ▼     MOD データの破棄
1825
1826         戻値・TRUE  = 成功
1827                 ・FALSE = 失敗
1828 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1829 S32 MOD__ReleaseSong(
1830          MOD    *pMOD           /* this ポインター */
1831 ){
1832         S32     i ;
1833
1834         if(     pMOD == NULL ) return( FALSE );
1835
1836         for( i=0 ; i<MAX_PATTERNS ; i++ ){
1837                 if(     pMOD->apXM_PATTERN[i] != NULL ){
1838                         XM_PATTERN__Destruct( pMOD->apXM_PATTERN[i] );
1839                         pMOD->apXM_PATTERN[i] = NULL ;
1840                 }
1841         }
1842
1843         for( i=0 ; i<MAX_INSTRUMENTS ; i++ ){
1844                 if(     pMOD->apXM_INSTRUMENT[i] != NULL ){
1845                         XM_INSTRUMENT__Destruct( pMOD->apXM_INSTRUMENT[i] );
1846                         pMOD->apXM_INSTRUMENT[i] = NULL ;
1847                 }
1848         }
1849
1850         for( i=0 ; i<MAX_SAMPLES ; i++ ){
1851                 if(     pMOD->apXM_SAMPLE[i] != NULL ){
1852                         XM_SAMPLE__Destruct( pMOD->apXM_SAMPLE[i] );
1853                         pMOD->apXM_SAMPLE[i] = NULL ;
1854                 }
1855         }
1856
1857         pMOD->FormatType = TYPE_NOTAVAILABLE ;
1858
1859         return( TRUE );
1860 }
1861
1862
1863
1864 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1865 ▼     Key -> Period_ 変換
1866
1867         戻値 : Period_
1868 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1869 static S32      MOD__KeyToPeriod_(
1870          MOD    *pMOD
1871         ,S32    Key
1872         ,S32    FineTune
1873 ){
1874         S32     Period_ ;
1875
1876         if(     pMOD == NULL ) return( FALSE );
1877
1878         if(     Key < 0 )       Key = 0 ;
1879         if(     Key > 118 )     Key = 118 ;
1880
1881         if(     pMOD->XmHeader.Flags & LINEAR_FREQUENCY ){
1882         /* 線形周波数モード */
1883                 Period_ = ((10*12*16*4 - Key*16*4) << SFT) - (FineTune << (SFT - 1)) ;
1884                 return( Period_ );
1885
1886         } else {
1887         /* AmigaPeriod モード */
1888                 static const U32 aAmigaFreqTable[] =
1889                 {
1890                           907, 900, 894, 887, 881, 875, 868, 862, 856, 850, 844, 838, 832, 826, 820, 814
1891                         , 808, 802, 796, 791, 785, 779, 774, 768, 762, 757, 752, 746, 741, 736, 730, 725
1892                         , 720, 715, 709, 704, 699, 694, 689, 684, 678, 675, 670, 665, 660, 655, 651, 646
1893                         , 640, 636, 632, 628, 623, 619, 614, 610, 604, 601, 597, 592, 588, 584, 580, 575
1894                         , 570, 567, 563, 559, 555, 551, 547, 543, 538, 535, 532, 528, 524, 520, 516, 513
1895                         , 508, 505, 502, 498, 494, 491, 487, 484, 480, 477, 474, 470, 467, 463, 460, 457
1896                         , 453, 450, 447, 443, 440, 437, 434, 431, 428
1897                 };
1898                 S32     offset = (Key % 12) << 3 ;
1899                 S32     nShift = Key / 12 ;
1900                 S32     RoughFineTune ;
1901                 S32     FineFineTune ;
1902                 S32     Val ;
1903
1904                 if(     FineTune >= 0 ){
1905                         RoughFineTune   = FineTune / 16 ;
1906                         FineFineTune    = FineTune & 15 ;
1907                 } else {
1908                         RoughFineTune   = (FineTune - 15) / 16 ;
1909                         FineFineTune    = FineTune & 15 ;
1910                 }
1911
1912                 Val =   (       aAmigaFreqTable[ 8 + offset + RoughFineTune ] * (16 - FineFineTune)
1913                                 +       aAmigaFreqTable[ 9 + offset + RoughFineTune ] * FineFineTune
1914                                 ) * 2 ;
1915
1916                 nShift -= SFT ;
1917                 if(     nShift > 0 ) Val >>=  nShift ;
1918                 if(     nShift < 0 ) Val <<= -nShift ;
1919
1920                 return( Val );
1921         }
1922 }
1923
1924
1925
1926 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1927 ▼     Period_ -> Key 変換
1928
1929         戻値 : Key
1930 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1931 static S32      MOD__Period_ToKey(
1932          MOD    *pMOD
1933         ,S32    Period_
1934         ,S32    FineTune
1935 ){
1936         if(     pMOD == NULL ) return( FALSE );
1937
1938         if(     pMOD->XmHeader.Flags & LINEAR_FREQUENCY ){
1939         /* 線形周波数モード */
1940                 S32     Key =   (       (10*12*16*4 << SFT) - (FineTune << (SFT - 1)) - Period_
1941                                         +       (16*4 << SFT)/2         /* 四捨五入 */
1942                                         ) / (16*4 << SFT) ;
1943                 return( Key );
1944
1945         } else {
1946         /* AmigaPeriod モード */
1947                 S32     Key ;
1948                 S32     BestKey = -1 ;
1949                 S32     Min             = 0x7FFFFFFF ;
1950
1951                 for( Key = 0 ; Key <= 118 ; Key++ ){
1952                         S32     zxc = abs( Period_ - MOD__KeyToPeriod_( pMOD , Key , FineTune ) );
1953
1954                         if(     zxc <= Min ){
1955                                 Min             = zxc ;
1956                                 BestKey = Key ;
1957                         }
1958                 }
1959
1960                 return( BestKey );
1961         }
1962 }
1963
1964
1965
1966 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1967 ▼     音量の設定
1968
1969         戻値・TRUE  = 成功
1970                 ・FALSE = 失敗
1971 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1972 S32 MOD__Set_Volume(
1973          MOD    *pMOD           /* this ポインター */
1974         ,S32    Volume          /* 音量 0 ~ 256(それ以上にも設定可能)*/
1975 ){
1976         if(     pMOD == NULL ) return( FALSE );
1977
1978         if(     Volume <= 0 )   Volume = 0 ;    /* 無効な値を回避 */
1979         pMOD->GlobalVolumeScale_ = ONE * Volume >> 8 ;
1980
1981         return( TRUE );
1982 }
1983
1984
1985
1986 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1987 ▼     再生レートの設定
1988
1989         戻値・TRUE  = 成功
1990                 ・FALSE = 失敗
1991 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
1992 S32 MOD__Set_nWavePerSec(
1993          MOD    *pMOD                   /* this ポインター */
1994         ,S32    nWavePerSec             /* WAVE 出力デバイスの周波数(Hz) */
1995 ){
1996         if(     pMOD == NULL ) return( FALSE );
1997
1998         if(     nWavePerSec <= 0 )      nWavePerSec     = 44100 ;       /* 無効な値を回避 */
1999         pMOD->nWavePerSec = nWavePerSec ;
2000
2001         return( TRUE );
2002 }
2003
2004
2005
2006 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2007 ▼     ループ再生モード / 非ループ再生モード の指定
2008
2009         戻値・TRUE  = 成功
2010                 ・FALSE = 失敗
2011 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
2012 S32 MOD__Set_bLoopMode(
2013          MOD    *pMOD                   /* this ポインター */
2014         ,S32    bLoopMode               /* ループ再生モードか? TRUE / FALSE */
2015 ){
2016         if(     pMOD == NULL ) return( FALSE );
2017
2018         pMOD->bLoopMode = bLoopMode ;
2019
2020         return( TRUE );
2021 }
2022
2023
2024
2025 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2026 ▼     自動ゲインコントロールするかどうか の指定
2027
2028         戻値・TRUE  = 成功
2029                 ・FALSE = 失敗
2030 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
2031 S32 MOD__Set_bAutoGainControl(
2032          MOD    *pMOD                           /* this ポインター */
2033         ,S32    bAutoGainControl        /* 自動ゲインコントロールするか? TRUE / FALSE */
2034 ){
2035         if(     pMOD == NULL ) return( FALSE );
2036
2037         pMOD->bAutoGainControl = bAutoGainControl ;
2038
2039         return( TRUE );
2040 }
2041
2042
2043
2044 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2045 ▼     PatternLoop の復帰点を、パターンの先頭に設置
2046
2047         パターン切り替わり時に、必ず実行すること。
2048         コマンド E6x にて、復帰点を設置しない場合の対策である。
2049
2050         戻値・TRUE  = 成功
2051                 ・FALSE = 失敗
2052 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
2053 static S32 MOD__InitPatternLoop(
2054          MOD    *pMOD
2055 ){
2056         S32     i ;
2057
2058         if(     pMOD == NULL ) return( FALSE );
2059
2060         /* 各チャンネルの状態を初期化 */
2061         for( i=0 ; i<MAX_CHANNELS ; i++ ){
2062                 CHANSTAT *pCHANSTAT = &(pMOD->aCHANSTAT[ i ]);
2063                 pCHANSTAT->PatternLoopRow       = 0 ;
2064                 pCHANSTAT->PatternLoopCount     = 0 ;
2065         }
2066
2067         return( TRUE );
2068 }
2069
2070
2071
2072 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2073 ▼     再生を初期化(内部パラメーターを初期化し、先頭から再生し直す)
2074
2075         戻値・TRUE  = 成功
2076                 ・FALSE = 失敗
2077 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
2078 S32 MOD__InitPlay(
2079          MOD    *pMOD           /* this ポインター */
2080 ){
2081         S32     i ;
2082
2083         if(     pMOD == NULL ) return( FALSE );
2084
2085         if(     pMOD->FormatType == TYPE_NOTAVAILABLE ) return( FALSE );
2086
2087         pMOD->bDone                             = FALSE ;
2088
2089         pMOD->TickCount                 = 0 ;
2090         pMOD->nTickPerRow               = pMOD->XmHeader.DefaultTempo ;
2091         pMOD->BPM                               = pMOD->XmHeader.DefaultBPM ;
2092         pMOD->nWavePerTick              = (pMOD->nWavePerSec * 5) / (pMOD->BPM * 2);
2093         pMOD->nRestWave                 = 0 ;
2094
2095         pMOD->Row                               = 0 ;
2096         pMOD->BreakSequence             = -1 ;
2097         pMOD->BreakRow                  = -1 ;
2098         pMOD->PatternDelay              = 0 ;
2099         pMOD->FinePatternDelay  = 0 ;
2100
2101         pMOD->idxSequenceData   = 0 ;
2102
2103         pMOD->GlobalVolume_             = 0x40 << SFT ;
2104         pMOD->GlobalVolumeSlide = 0 ;
2105         pMOD->GainControlScale_ = ONE ;
2106
2107         pMOD->AntiNoiseVal_L    = 0 ;
2108         pMOD->AntiNoiseVal_R    = 0 ;
2109
2110
2111         /* 各チャンネルの状態を初期化 */
2112         for( i=0 ; i<MAX_CHANNELS ; i++ ){
2113                 CHANSTAT        *pCHANSTAT = &(pMOD->aCHANSTAT[ i ]);
2114
2115                 pCHANSTAT->idxNowPatternNote            = -1 ;
2116                 pCHANSTAT->idxNowRealNote                       = -1 ;
2117                 pCHANSTAT->NowVolumeColumn                      = 0 ;
2118                 pCHANSTAT->NowCommand                           = 0 ;
2119                 pCHANSTAT->NowParam                                     = 0 ;
2120                 pCHANSTAT->NowPeriod_                           = 0 ;
2121                 pCHANSTAT->idxNowInst                           = -1 ;
2122
2123                 pCHANSTAT->pPendingXM_INSTRUMENT        = NULL ;
2124                 pCHANSTAT->pPlayingXM_INSTRUMENT        = NULL ;
2125                 pCHANSTAT->pPlayingXM_SAMPLE            = NULL ;
2126
2127                 pCHANSTAT->idxLastRealNote                      = 0 ;
2128
2129                 pCHANSTAT->PendingPeriod_                       = 0 ;
2130                 pCHANSTAT->PlayingPeriod_                       = 0 ;
2131                 pCHANSTAT->FinalPeriod_                         = 0 ;
2132                 pCHANSTAT->PeriodLowLimit_                      = 0 ;
2133                 pCHANSTAT->PeriodHighLimit_                     = 0 ;
2134
2135                 pCHANSTAT->PlayingFineTune                      = 0 ;
2136
2137                 pCHANSTAT->PlayingVolume_                       = 0 ;
2138                 pCHANSTAT->FinalVolume_                         = 0 ;
2139                 pCHANSTAT->FinalVolume_L_                       = 0 ;
2140                 pCHANSTAT->FinalVolume_R_                       = 0 ;
2141                 pCHANSTAT->VolumeSlide                          = 0 ;
2142                 pCHANSTAT->FineVolumeSlide                      = 0 ;
2143                 pCHANSTAT->VolumeScale_                         = ONE ;
2144
2145                 if(     pMOD->FormatType == TYPE_MOD ){
2146                         static const S32 DefaultPanning[4] = { 0x00 , 0xFF , 0xFF , 0x00 };
2147                         pCHANSTAT->PlayingPanning_              = DefaultPanning[ i & 3 ] << SFT ;
2148                         pCHANSTAT->FinalPanning_                = DefaultPanning[ i & 3 ] << SFT ;
2149                 } else {
2150                         pCHANSTAT->PlayingPanning_              = 0x80 << SFT ;
2151                         pCHANSTAT->FinalPanning_                = 0x80 << SFT ;
2152                 }
2153                 pCHANSTAT->PanningSlide                         = 0 ;
2154
2155                 pCHANSTAT->idxVolumeEnvelopeTable       = 0 ;
2156                 pCHANSTAT->idxPanningEnvelopeTable      = 0 ;
2157
2158                 pCHANSTAT->VibratoType                          = 0 ;
2159                 pCHANSTAT->VibratoPosition_                     = 0 ;
2160                 pCHANSTAT->VibratoRate                          = 0 ;
2161                 pCHANSTAT->VibratoDepth                         = 0 ;
2162
2163                 pCHANSTAT->TremoloType                          = 0 ;
2164                 pCHANSTAT->TremoloPosition_                     = 0 ;
2165                 pCHANSTAT->TremoloRate                          = 0 ;
2166                 pCHANSTAT->TremoloDepth                         = 0 ;
2167
2168                 pCHANSTAT->PortamentoInc                        = 0 ;
2169                 pCHANSTAT->TonePortamentoInc            = 0 ;
2170                 pCHANSTAT->TonePortamentoDst_           = 0 ;
2171                 pCHANSTAT->FinePortamentoInc            = 0 ;
2172                 pCHANSTAT->ExtraFinePortamentoInc       = 0 ;
2173
2174                 pCHANSTAT->ArpeggioPeriod_[0]           = 0 ;
2175                 pCHANSTAT->ArpeggioPeriod_[1]           = 0 ;
2176                 pCHANSTAT->idxArpeggio                          = 0 ;
2177
2178                 pCHANSTAT->TremorCount                          = 0 ;
2179                 pCHANSTAT->TremorOnTime                         = 0 ;
2180                 pCHANSTAT->TremorOffTime                        = 0 ;
2181                 pCHANSTAT->bTremorMute                          = FALSE ;
2182
2183                 pCHANSTAT->MultiRetrigCount                     = 0 ;
2184                 pCHANSTAT->MultiRetrigInterval          = 1 ;
2185                 pCHANSTAT->MultiRetrigVolumeChange      = 1 ;
2186
2187                 pCHANSTAT->PanbrelloType                        = 0 ;
2188                 pCHANSTAT->PanbrelloPosition            = 0 ;
2189                 pCHANSTAT->PanbrelloRate                        = 0 ;
2190                 pCHANSTAT->PanbrelloDepth                       = 0 ;
2191
2192                 pCHANSTAT->bFadeOut                                     = FALSE ;
2193                 pCHANSTAT->FadeOutVolume_1_15_16        = 1 << 16 ;
2194
2195                 pCHANSTAT->AutoVibratoPosition          = 0 ;
2196                 pCHANSTAT->AutoVibratoDepth_            = 0 ;
2197
2198                 pCHANSTAT->bSurround                            = FALSE ;
2199
2200                 pCHANSTAT->SamplePosition_                      = 0 ;
2201                 pCHANSTAT->SampleRate_                          = 0 ;
2202                 pCHANSTAT->SampleOffset                         = 0 ;
2203                 pCHANSTAT->SampleHighOffset                     = 0 ;
2204                 pCHANSTAT->bGrissando                           = FALSE ;
2205                 pCHANSTAT->VolumeColumnContinueValue= 0 ;
2206
2207                 pCHANSTAT->pLastPlayingXM_SAMPLE        = NULL ;
2208                 pCHANSTAT->LastSamplePosition_          = 0 ;
2209                 pCHANSTAT->LastWaveVal_L                        = 0 ;
2210                 pCHANSTAT->LastWaveVal_R                        = 0 ;
2211                 pCHANSTAT->LastSampleVolume_L_          = 0 ;
2212                 pCHANSTAT->LastSampleVolume_R_          = 0 ;
2213         }
2214
2215         MOD__InitPatternLoop( pMOD );
2216
2217         return( TRUE );
2218 }
2219
2220
2221
2222 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2223 ▼     波形データの出力 16bit stereo
2224
2225         波形のミキシングを行っている。最適化するならここを重点的に。
2226
2227         戻値・TRUE  = 成功
2228                 ・FALSE = 失敗
2229 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
2230 static S32 MOD__OutPut_16BitStereo(
2231          MOD    *pMOD
2232         ,U32    *pWaveOutPut    /* 波形出力先(L R をひとまとめにして、U32 単位で出力する)*/
2233         ,S32     nWaveOutPut    /* 出力波形数 */
2234 ){
2235         #define N_MIX   ( 256 )
2236
2237         S32     aMixBuff[ N_MIX * 2 ];  /* ミキシング用テンポラリバッファ(L R 交互)*/
2238         S32     i ;
2239
2240         /* 引数が無効なら強制終了 */
2241         if(     pMOD == NULL
2242         ||      pWaveOutPut == NULL
2243         ) return( FALSE );
2244
2245         if(     pMOD->FormatType == TYPE_NOTAVAILABLE ) return( FALSE );
2246
2247         while( nWaveOutPut > 0 ){
2248                 S32     nWaveOutPutSub ;
2249
2250
2251                 /* 処理する波形数を決定 */
2252                 if(     nWaveOutPut >= N_MIX ){
2253                         nWaveOutPutSub = N_MIX ;
2254                 } else {
2255                         nWaveOutPutSub = nWaveOutPut ;
2256                 }
2257                 nWaveOutPut -= nWaveOutPutSub ;
2258
2259
2260                 /* プチノイズ対策 */
2261                 for( i=0 ; i<pMOD->XmHeader.NumberOfChannels ; i++ ){
2262                         CHANSTAT        *pCHANSTAT      = &(pMOD->aCHANSTAT[ i ]);
2263
2264                         /* 音量(0_ ~ 1_) */
2265                         S32     SampleVolume_L_ = (pCHANSTAT->FinalVolume_L_ >> 6) * pMOD->GainControlScale_ >> SFT ;
2266                         S32     SampleVolume_R_ = (pCHANSTAT->FinalVolume_R_ >> 6) * pMOD->GainControlScale_ >> SFT ;
2267
2268                         /*
2269                                 音色が差し替えられている場合
2270                                 波形ポジションが差し替えられている場合
2271                                 音量が変化している場合
2272                         */
2273                         if(     pCHANSTAT->LastSamplePosition_   != pCHANSTAT->SamplePosition_
2274                         ||      pCHANSTAT->pLastPlayingXM_SAMPLE != pCHANSTAT->pPlayingXM_SAMPLE
2275                         ||      pCHANSTAT->LastSampleVolume_L_   != SampleVolume_L_
2276                         ||      pCHANSTAT->LastSampleVolume_R_   != SampleVolume_R_
2277                         ){
2278                                 XM_SAMPLE       *pXM_SAMPLE     = pCHANSTAT->pPlayingXM_SAMPLE ;
2279                                 S32     NowVal_L        = 0 ;
2280                                 S32     NowVal_R        = 0 ;
2281
2282                                 if(     pXM_SAMPLE != NULL ){
2283                                         U32     SamplePosition_ = pCHANSTAT->SamplePosition_ ;
2284                                         U32     SampleLength_   = pXM_SAMPLE->SampleLength << SFT ;
2285                                         if(     SamplePosition_ < SampleLength_ ){
2286                                                 S32     Val      = 0 ;
2287                                                 S32     Val0 = 0 ;
2288                                                 S32     Val1 = 0 ;
2289
2290                                                 if(     (pXM_SAMPLE->VoiceMode & VM_16BIT) == 0 ){
2291                                                         S8      *pSampleData = reinterpret_cast<S8*>(pXM_SAMPLE->pSampleData) ;
2292                                                         if(     pSampleData != NULL ){
2293                                                                 Val0    = (S32)pSampleData[  SamplePosition_ >> SFT ] << 8 ;
2294                                                                 Val1    = (S32)pSampleData[ (SamplePosition_ >> SFT) + 1 ] << 8 ;
2295                                                         }
2296                                                 } else {
2297                                                         S16     *pSampleData =  reinterpret_cast<S16*>(pXM_SAMPLE->pSampleData);
2298                                                         if(     pSampleData != NULL ){
2299                                                                 Val0    = (S32)pSampleData[  SamplePosition_ >> SFT ];
2300                                                                 Val1    = (S32)pSampleData[ (SamplePosition_ >> SFT) + 1 ];
2301                                                         }
2302                                                 }
2303
2304                                                 Val                     = Val0 + (((Val1 - Val0) * ((S32)SamplePosition_ & DECIMAL)) >> SFT) ;
2305                                                 NowVal_L        = Val * SampleVolume_L_ >> SFT ;
2306                                                 NowVal_R        = Val * SampleVolume_R_ >> SFT ;
2307                                         }
2308                                 }
2309
2310                                 pMOD->AntiNoiseVal_L += pCHANSTAT->LastWaveVal_L - NowVal_L ;
2311                                 pMOD->AntiNoiseVal_R += pCHANSTAT->LastWaveVal_R - NowVal_R ;
2312                         }
2313                 }
2314
2315
2316                 /* プチノイズ対策しつつ、バッファをクリア */
2317                 {
2318                         S32     AntiNoiseVal_L = pMOD->AntiNoiseVal_L ;
2319                         S32     AntiNoiseVal_R = pMOD->AntiNoiseVal_R ;
2320
2321                         for( i=0 ; i<nWaveOutPutSub*2 ; i+=2 ){
2322                                 aMixBuff[i  ] = AntiNoiseVal_L ;
2323                                 aMixBuff[i+1] = AntiNoiseVal_R ;
2324                                 AntiNoiseVal_L -= AntiNoiseVal_L >> 6 ;
2325                                 AntiNoiseVal_R -= AntiNoiseVal_R >> 6 ;
2326                         }
2327
2328                         pMOD->AntiNoiseVal_L = AntiNoiseVal_L ;
2329                         pMOD->AntiNoiseVal_R = AntiNoiseVal_R ;
2330                 }
2331
2332
2333                 /* 総チャンネル数分繰り返し */
2334                 for( i=0 ; i<pMOD->XmHeader.NumberOfChannels ; i++ ){
2335                         CHANSTAT        *pCHANSTAT      = &(pMOD->aCHANSTAT[ i ]);
2336                         XM_SAMPLE       *pXM_SAMPLE     = pCHANSTAT->pPlayingXM_SAMPLE ;
2337
2338                         /* 音量(0_ ~ 1_) */
2339                         S32     SampleVolume_L_         = (pCHANSTAT->FinalVolume_L_ >> 6) * pMOD->GainControlScale_ >> SFT ;
2340                         S32     SampleVolume_R_         = (pCHANSTAT->FinalVolume_R_ >> 6) * pMOD->GainControlScale_ >> SFT ;
2341
2342                         S32     Val_L   = 0 ;
2343                         S32     Val_R   = 0 ;
2344
2345                         S32     CaseVal = 0 ;
2346
2347                         /* 音量が 0 の時のための場合分け(計算誤差を考慮して判定を甘くしてある)*/
2348                         if(     SampleVolume_L_ < -ONE/128  ||  ONE/128 < SampleVolume_L_ ) CaseVal |= 1 ;
2349                         if(     SampleVolume_R_ < -ONE/128  ||  ONE/128 < SampleVolume_R_ ) CaseVal |= 2 ;
2350
2351                         if(     pXM_SAMPLE != NULL ){
2352                                 S32     *pMixBuff                       = &(aMixBuff[ 0 ]) ;
2353                                 S32     *pMixEnd                        = &(aMixBuff[ nWaveOutPutSub * 2 ]) ;
2354                                 U32     SampleRate_                     = pCHANSTAT->SampleRate_ ;
2355                                 U32     SamplePosition_         = pCHANSTAT->SamplePosition_ ;
2356                                 U32     SampleLength_           = pXM_SAMPLE->SampleLength << SFT ;
2357                                 U32     SampleLoopLength_       = pXM_SAMPLE->SampleLoopLength << SFT ;
2358
2359                                 /* 線形補完しつつ波形生成 */
2360                                 if(     pXM_SAMPLE->pSampleData != NULL
2361                                 &&      pXM_SAMPLE->VoiceMode & VM_ON
2362                                 &&      SampleRate_
2363                                 ){
2364                                         S32     bLoop = ((pXM_SAMPLE->VoiceMode & VM_LOOP) != 0) ;
2365
2366                                         /*-------- マクロの定義(ここから)--------*/
2367
2368                                         #undef  MACRO
2369                                         #define MACRO( _CaseVal_ , _nShift_ )                                                                                           \
2370                                         while( pMixBuff < pMixEnd ){                                                                                                            \
2371                                                 if(     SamplePosition_ >= SampleLength_ ){                                                                                     \
2372                                                         if(     bLoop == FALSE ) break ;                                                                                                \
2373                                                         do {                                                                                                                                            \
2374                                                                 SamplePosition_ -= SampleLoopLength_ ;                                                                  \
2375                                                         } while( SamplePosition_ >= SampleLength_ );                                                            \
2376                                                 }                                                                                                                                                               \
2377                                                                                                                                                                                                                 \
2378                                                 if(     _CaseVal_ & 3 ){                                                                                                                        \
2379                                                         S32     Val0 , Val1 , Val ;                                                                                                             \
2380                                                         Val0 = (S32)pSampleData[  SamplePosition_ >> SFT ];                                                     \
2381                                                         if(     _nShift_ ) Val0 <<= _nShift_ ;                                                                                  \
2382                                                         Val1 = (S32)pSampleData[ (SamplePosition_ >> SFT) + 1 ];                                        \
2383                                                         if(     _nShift_ ) Val1 <<= _nShift_ ;                                                                                  \
2384                                                         Val = Val0 + (((Val1 - Val0) * ((S32)SamplePosition_ & DECIMAL)) >> SFT) ;      \
2385                                                         if( _CaseVal_ & 1 ) Val_L = Val * SampleVolume_L_ >> SFT ;                                      \
2386                                                         if( _CaseVal_ & 2 ) Val_R = Val * SampleVolume_R_ >> SFT ;                                      \
2387                                                         if( _CaseVal_ & 1 ) pMixBuff[0] += Val_L ;                                                                      \
2388                                                         if( _CaseVal_ & 2 ) pMixBuff[1] += Val_R ;                                                                      \
2389                                                 }                                                                                                                                                               \
2390                                                 pMixBuff += 2 ;                                                                                                                                 \
2391                                                 SamplePosition_ += SampleRate_ ;                                                                                                \
2392                                         }                                                                                                                                                                       \
2393
2394                                         /*-------- マクロの定義(ここまで)--------*/
2395
2396                                         if(     (pXM_SAMPLE->VoiceMode & VM_16BIT) == 0 ){
2397                                         /* 8 bit sample */
2398                                                 S8      *pSampleData = (S8*)pXM_SAMPLE->pSampleData ;
2399                                                 switch( CaseVal ){
2400                                                         /* L R とも処理しない */
2401                                                         case 0 :{
2402                                                                 MACRO( 0 , 8 );
2403                                                         } break ;
2404
2405                                                         /* L のみ処理 */
2406                                                         case 1 :{
2407                                                                 MACRO( 1 , 8 );
2408                                                         } break ;
2409
2410                                                         /* R のみ処理 */
2411                                                         case 2 :{
2412                                                                 MACRO( 2 , 8 );
2413                                                         } break ;
2414
2415                                                         /* L R とも処理 */
2416                                                         case 3 :{
2417                                                                 MACRO( 3 , 8 );
2418                                                         } break ;
2419                                                 }
2420                                         } else {
2421                                         /* 16 bit sample */
2422                                                 S16     *pSampleData = (S16*)pXM_SAMPLE->pSampleData ;
2423                                                 switch( CaseVal ){
2424                                                         /* L R とも処理しない */
2425                                                         case 0 :{
2426                                                                 MACRO( 0 , 0 );
2427                                                         } break ;
2428
2429                                                         /* L のみ処理 */
2430                                                         case 1 :{
2431                                                                 MACRO( 1 , 0 );
2432                                                         } break ;
2433
2434                                                         /* R のみ処理 */
2435                                                         case 2 :{
2436                                                                 MACRO( 2 , 0 );
2437                                                         } break ;
2438
2439                                                         /* L R とも処理 */
2440                                                         case 3 :{
2441                                                                 MACRO( 3 , 0 );
2442                                                         } break ;
2443                                                 }
2444                                         }
2445
2446                                         pCHANSTAT->SamplePosition_ = SamplePosition_ ;
2447                                 }
2448                         }
2449
2450                         /* プチノイズ対策用 */
2451                         pCHANSTAT->pLastPlayingXM_SAMPLE        = pCHANSTAT->pPlayingXM_SAMPLE ;
2452                         pCHANSTAT->LastSamplePosition_          = pCHANSTAT->SamplePosition_ ;
2453                         pCHANSTAT->LastWaveVal_L                        = Val_L ;
2454                         pCHANSTAT->LastWaveVal_R                        = Val_R ;
2455                         pCHANSTAT->LastSampleVolume_L_          = SampleVolume_L_ ;
2456                         pCHANSTAT->LastSampleVolume_R_          = SampleVolume_R_ ;
2457                 }
2458
2459
2460                 /* 飽和処理しつつ、波形出力 */
2461                 {
2462                         S32     *pMixBuff = &(aMixBuff[0]) ;
2463                         S32     nOver = 0 ;
2464
2465                         while( nWaveOutPutSub > 0 ){
2466                                 S32     ValL = pMixBuff[0] ;
2467                                 S32     ValR = pMixBuff[1] ;
2468                                 pMixBuff += 2 ;
2469
2470                                 if(     ValL < -0x7FFF ){ ValL = -0x7FFF ; nOver++ ; }
2471                                 if(     ValL >  0x7FFF ){ ValL =  0x7FFF ; nOver++ ; }
2472                                 if(     ValR < -0x7FFF ){ ValR = -0x7FFF ; nOver++ ; }
2473                                 if(     ValR >  0x7FFF ){ ValR =  0x7FFF ; nOver++ ; }
2474
2475                                 *pWaveOutPut = (U32)((ValL & 0xFFFF) | (ValR << 16)) ;
2476
2477                                 pWaveOutPut++ ;
2478                                 nWaveOutPutSub-- ;
2479                         }
2480
2481                         /* ゲインコントロール */
2482                         if(     pMOD->bAutoGainControl ){
2483                                 if(     nOver > 8 ){
2484                                         pMOD->GainControlScale_ -= pMOD->GainControlScale_ >> 8 ;
2485                                 } else {
2486                                         pMOD->GainControlScale_ += pMOD->GainControlScale_ >> 8 ;
2487                                         pMOD->GainControlScale_++ ;
2488                                         if(     pMOD->GainControlScale_ > ONE ){
2489                                                 pMOD->GainControlScale_ = ONE ;
2490                                         }
2491                                 }
2492                         } else {
2493                                 pMOD->GainControlScale_ = ONE ;
2494                         }
2495                 }
2496         }
2497
2498
2499         return( TRUE );
2500 }
2501
2502
2503
2504 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2505 ▼     MOD データの再生
2506
2507         指定数の 16bit stereo 波形を生成する。
2508
2509         戻値・TRUE  = 成功
2510                 ・FALSE = 失敗
2511 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
2512 S32 MOD__PlaySong(
2513          MOD    *pMOD                   /* this ポインター */
2514         ,U32    *pWaveOutPut    /* 波形出力先(L R をひとまとめにして、U32 単位で出力する)*/
2515         ,S32     nWaveOutPut    /* 出力波形数 */
2516 ){
2517         if(     pMOD == NULL ) return( FALSE );
2518         if(     pMOD->FormatType == TYPE_NOTAVAILABLE ) return( FALSE );
2519
2520         /* ノルマ達成までループする */
2521         while( TRUE ){
2522
2523                 /* 波形の出力 */
2524                 if(     pMOD->nRestWave > 0 ){
2525                         if(     pMOD->nRestWave >= nWaveOutPut ){
2526                         /* 残存波形の出力のみで今回のノルマは達成される。*/
2527                                 MOD__OutPut_16BitStereo(
2528                                          pMOD
2529                                         ,pWaveOutPut
2530                                         ,nWaveOutPut
2531                                 );
2532
2533                                 pMOD->nRestWave -= nWaveOutPut ;
2534
2535                                 pWaveOutPut += nWaveOutPut ;
2536                                 nWaveOutPut -= nWaveOutPut ;
2537
2538                                 return( TRUE );
2539
2540                         } else {
2541                         /* 残存波形が足りないぞ! 出せる分だけ出す。*/
2542                                 MOD__OutPut_16BitStereo(
2543                                          pMOD
2544                                         ,pWaveOutPut
2545                                         ,pMOD->nRestWave
2546                                 );
2547
2548                                 pWaveOutPut += pMOD->nRestWave ;
2549                                 nWaveOutPut -= pMOD->nRestWave ;
2550
2551                                 pMOD->nRestWave = 0 ;
2552                         }
2553                 }
2554
2555
2556
2557                 /* 以下、1 tick 分の波形生成 */
2558
2559
2560
2561                 /* 再生を終了していたら */
2562                 if(     pMOD->bDone == TRUE ){
2563
2564                         if(     pMOD->bLoopMode == FALSE ){
2565                                 /* ミュート状態にする */
2566                                 MOD__InitPlay( pMOD );
2567
2568                                 /* 無音状態を維持 */
2569                                 pMOD->nRestWave += pMOD->nWavePerTick ;
2570                                 continue ;
2571
2572                         } else {
2573                                 /* ループ点から再生 */
2574                                 pMOD->idxSequenceData = pMOD->XmHeader.RestartPosition ;
2575                                 if(     pMOD->idxSequenceData >= pMOD->XmHeader.SongLength ){   /* 範囲オーバー? */
2576                                         pMOD->idxSequenceData = 0 ;
2577                                 }
2578
2579                                 /*
2580                                         ループ再生が有効なデータでは、ここで特に初期化手続きは取らない。
2581                                         しかし、ループ再生が有効かどうかを判断する手段が無い。
2582                                         やむを得ず、先頭から再生の場合は、ループ再生が無効と判断する。
2583                                         ModPlug でも同じ手法を用いているらしい。
2584                                 */
2585                                 if(     pMOD->idxSequenceData == 0 ){
2586                                         MOD__InitPlay( pMOD );
2587                                 }
2588
2589                                 pMOD->bDone = FALSE ;
2590                         }
2591                 }
2592
2593
2594                 while( TRUE ){  /* ラベルジャンプ回避用 */
2595                         S32     i ;
2596                         S32     ModifyVal_      = ONE * (pMOD->nTickPerRow - 1) / pMOD->nTickPerRow ;
2597                         S32     idxPattern      = pMOD->XmHeader.aPatternOrderTable[ pMOD->idxSequenceData ];
2598                         XM_PATTERN *pXM_PATTERN = pMOD->apXM_PATTERN[ idxPattern ];
2599                         U8      *pPatternData ;
2600
2601                         if(     pXM_PATTERN == NULL ){
2602                                 #if (WARNING_LEVEL >= 2)
2603                                         LogMsg(pMOD->Instance,
2604                                                 "MOD__PlaySong : 警告 \n"
2605                                                 "       pMOD->apXM_PATTERN[ %d ] == NULL です。\n"
2606                                                 ,idxPattern
2607                                         );
2608                                 #endif
2609                                 break ;
2610                         }
2611
2612                         pPatternData = pXM_PATTERN->pPatternData ;
2613                         if(     pPatternData == NULL ){
2614                                 #if (WARNING_LEVEL >= 2)
2615                                         LogMsg(pMOD->Instance,
2616                                                 "MOD__PlaySong : 警告 \n"
2617                                                 "       pMOD->apXM_PATTERN[ %d ]->pPatternData == NULL です。\n"
2618                                                 ,idxPattern
2619                                         );
2620                                 #endif
2621                                 break ;
2622                         }
2623
2624                         #if (WARNING_LEVEL >= 2)
2625                                 if(     pMOD->TickCount == 0
2626                                 &&      pMOD->Row == 0
2627                                 ){
2628                                         LogMsg(pMOD->Instance,
2629                                                 "Pos[%02d] Pat[%02d] ----------------------------------- \n"
2630                                                 ,pMOD->idxSequenceData
2631                                                 ,idxPattern
2632                                         );
2633                                 }
2634                         #endif
2635
2636                         #if (WARNING_LEVEL >= 3)
2637                                 if(     pMOD->TickCount == 0 ){
2638                                         LogMsg(pMOD->Instance,
2639                                                 "Pos[%02d] Pat[%02d] ROW[%02d] "
2640                                                 ,pMOD->idxSequenceData
2641                                                 ,idxPattern
2642                                                 ,pMOD->Row
2643                                         );
2644                                 }
2645                         #endif
2646
2647
2648                         /* チャンネル数分繰り返し */
2649                         for( i=0 ; i < pMOD->XmHeader.NumberOfChannels ; i++ ){
2650                                 CHANSTAT *pCHANSTAT = &(pMOD->aCHANSTAT[i]) ;
2651                                 U8      *pNote                  = &pPatternData[ (pMOD->XmHeader.NumberOfChannels * pMOD->Row + i) * 5 ];
2652                                 S32     idxNowPatternNote ;
2653                                 S32     idxNowRealNote ;
2654                                 S32     idxNowInst ;
2655                                 S32     NowVolumeColumn ;
2656                                 S32     NowCommand ;
2657                                 S32     NowParam ;
2658                                 S32     NowPeriod_ ;
2659                                 S32     bArpeggio               = FALSE ;               /* Arpeggio は有効か?(TRUE / FALSE)*/
2660                                 S32     bVibrato                = FALSE ;               /* Vibrato は有効か?(TRUE / FALSE)*/
2661                                 S32     bTremolo                = FALSE ;               /* Tremolo は有効か?(TRUE / FALSE)*/
2662                                 S32     bPanbrello              = FALSE ;               /* Panbrello は有効か?(TRUE / FALSE)*/
2663                                 S32     bNoteDelay              = FALSE ;               /* NoteDelay の最中か?(TRUE / FALSE)*/
2664                                 S32     bFirstTrigger   = FALSE ;               /* 初回トリガー? */
2665
2666                                 /* モニタリング */
2667                                 #if (WARNING_LEVEL >= 3)
2668                                         if(     pMOD->TickCount == 0 ){
2669                                                 if(     pNote[0] ){
2670                                                         LogMsg( pMOD->Instance,":k%02X " , pNote[0] );
2671                                                 } else {
2672                                                         LogMsg( pMOD->Instance,":--- " );
2673                                                 }
2674
2675                                                 if(     pNote[1] ){
2676                                                         LogMsg( pMOD->Instance,"@%02X " , pNote[1] );
2677                                                 } else {
2678                                                         LogMsg( pMOD->Instance,"--- " );
2679                                                 }
2680
2681                                                 if(     pNote[2] ){
2682                                                         LogMsg(pMOD->Instance, "v%02X " , pNote[2] );
2683                                                 } else {
2684                                                         LogMsg(pMOD->Instance, "--- " );
2685                                                 }
2686
2687                                                 if(     pNote[3] ){
2688                                                         LogMsg( pMOD->Instance,"e[%02X%02X]" , pNote[3] , pNote[4] );
2689                                                 } else {
2690                                                         LogMsg(pMOD->Instance, "-------" );
2691                                                 }
2692                                         }
2693                                 #endif
2694
2695                                 /* 現在行のステータス 解釈 & 内部変数の更新 */
2696                                 {
2697                                         S32     idxPatternNote  = ((S32)pNote[0]) - 1 ;         /* 0..95 (0 = C-0, 95 = B-7) */
2698                                         S32     idxInst                 = ((S32)pNote[1]) - 1 ;         /* Instrument (0-128) */
2699                                         S32     VolumeColumn    = ((S32)pNote[2]) ;                     /* Volume column byte */
2700                                         S32     Command                 = ((S32)pNote[3]) << 4 ;        /* Effect type */
2701                                         S32     Param                   = ((S32)pNote[4]) ;                     /* Effect parameter */
2702                                         S32     idxRealNote             = -1 ;
2703                                         S32     Period_                 = 0 ;
2704
2705                                         /* 拡張コマンド時、Param 上位 4 bit はコマンド番号になる */
2706                                         if(     Command == 0x0E0
2707                                         ||      Command == 0x210
2708                                         ){
2709                                                 Command |= Param >> 4 ;
2710                                                 Param &= 0xF ;
2711                                         }
2712
2713                                         /*
2714                                                 NoteDelay の解釈 & 初回トリガー。
2715                                                 コマンド 0xED は、Param ==0 でも continue としない(MOD XM 共通)。
2716                                                 Delay 中は、エフェクトも停止する。
2717                                                 内部パラメーターの更新は、Delay が解除されたタイミングで行う。
2718                                                 よって、Delay 時間が TickPerRow を超える時、内部パラメーターの
2719                                                 更新さえも行われない。
2720                                                 以上、ModPlug の仕様。
2721                                         */
2722                                         if(     Command == 0xED ){
2723                                                 if(     pMOD->TickCount < Param ){
2724                                                         bNoteDelay = TRUE ;
2725                                                 }
2726                                                 if(     pMOD->TickCount == Param ) bFirstTrigger = TRUE ;
2727                                         } else {
2728                                                 if(     pMOD->TickCount == 0 ) bFirstTrigger = TRUE ;
2729                                         }
2730
2731                                         /* 初回トリガー? */
2732                                         if(     bFirstTrigger ){
2733                                                 S32     bPlay = FALSE ;         /* 発声? */
2734
2735                                                 /* 無効な値を排除 */
2736                                                 if(     idxInst >= pMOD->XmHeader.NumberOfInstruments ) idxInst = -1 ;
2737                                                 if(     idxPatternNote > 96 ) idxPatternNote = -1 ;
2738
2739                                                 /*
2740                                                         音階 音色 NoteOff の解釈の部分は、トラッカー毎の処理フローに
2741                                                         依存する固体差の温床となっている。この固体差を再現するには、
2742                                                         トラッカーの処理フローを予想して真似る必要があるが、
2743                                                         ばかばかしいので、以下、すべてのケースを場合分けして対処する。
2744                                                 */
2745
2746                                                 /* CASE 1 : NoteOff  &  音色有効 */
2747                                                 if(     idxPatternNote == 96
2748                                                 &&      idxInst != -1
2749                                                 ){
2750                                                         pCHANSTAT->pPendingXM_INSTRUMENT = pMOD->apXM_INSTRUMENT[ idxInst ];
2751
2752                                                 /* CASE 2 : 音階有効 */
2753                                                 } else
2754                                                 if(     idxPatternNote != -1
2755                                                 &&      idxPatternNote != 96    /* NoteOff ではない */
2756                                                 ){
2757                                                         /*
2758                                                                 発声の条件が、ややこしい。
2759                                                                 Tone-Portamento 時はトリガーは無い。
2760                                                                 Tone-Portamento 時でも、新規音色の指定がある時はトリガー。
2761                                                         */
2762
2763                                                         if(     !(      Command == 0x30                                 /* Tone-Portamento */
2764                                                                 ||      Command == 0x50                                 /* Tone-Portamento + Volume Slide */
2765                                                                 ||      (VolumeColumn & 0xF0) == 0xF0   /* Tone-Portamento */
2766                                                                 )
2767                                                         ){
2768                                                                 bPlay = TRUE ;
2769                                                         }
2770
2771                                                         if(     idxInst != -1 ){
2772                                                                 pCHANSTAT->bFadeOut                                     = FALSE ;
2773                                                                 pCHANSTAT->pPendingXM_INSTRUMENT        = pMOD->apXM_INSTRUMENT[ idxInst ];
2774                                                                 pCHANSTAT->idxVolumeEnvelopeTable       = 0 ;
2775                                                                 pCHANSTAT->idxPanningEnvelopeTable      = 0 ;
2776                                                                 pCHANSTAT->AutoVibratoPosition          = 0 ;
2777                                                                 pCHANSTAT->AutoVibratoDepth_            = 0 ;
2778                                                                 pCHANSTAT->MultiRetrigCount                     = 0 ;
2779                                                                 if(     pCHANSTAT->pPlayingXM_INSTRUMENT != pCHANSTAT->pPendingXM_INSTRUMENT ) bPlay = TRUE ;
2780                                                         }
2781                                                         pCHANSTAT->pPlayingXM_INSTRUMENT = pCHANSTAT->pPendingXM_INSTRUMENT ;
2782
2783                                                         if(     pCHANSTAT->pPlayingXM_INSTRUMENT != NULL ){
2784                                                                 pCHANSTAT->pPlayingXM_SAMPLE
2785                                                                 =       pCHANSTAT->pPlayingXM_INSTRUMENT->apAllNoteXM_SAMPLE[ idxPatternNote ];
2786                                                         }
2787
2788                                                         if(     pCHANSTAT->pPlayingXM_SAMPLE != NULL ){
2789                                                                 if(     idxInst != -1 ){
2790                                                                         pCHANSTAT->PlayingVolume_       = pCHANSTAT->pPlayingXM_SAMPLE->Volume << SFT ;
2791                                                                         if(     pMOD->FormatType == TYPE_XM ){
2792                                                                                 pCHANSTAT->PlayingPanning_      = pCHANSTAT->pPlayingXM_SAMPLE->Panning << SFT ;
2793                                                                         }
2794                                                                 }
2795                                                                 pCHANSTAT->PlayingFineTune = pCHANSTAT->pPlayingXM_SAMPLE->FineTune ;
2796                                                                 idxRealNote = idxPatternNote + pCHANSTAT->pPlayingXM_SAMPLE->RelativeNoteNumber ;
2797                                                                 Period_
2798                                                                 =       pCHANSTAT->PendingPeriod_
2799                                                                 =       MOD__KeyToPeriod_( pMOD , idxRealNote , pCHANSTAT->PlayingFineTune );
2800
2801                                                                 /* Tone-Portamento 目標値は、どのようなコマンドの最中でも更新される */
2802                                                                 pCHANSTAT->TonePortamentoDst_ = Period_ ;
2803
2804                                                                 /* 発声フラグ有効なら */
2805                                                                 if(     bPlay ){
2806                                                                         pCHANSTAT->idxLastRealNote      = idxRealNote ;
2807                                                                         pCHANSTAT->SamplePosition_      = 0 ;
2808                                                                         pCHANSTAT->PlayingPeriod_       = Period_ ;
2809                                                                         pCHANSTAT->PeriodLowLimit_      = MOD__KeyToPeriod_( pMOD , 12*10 - 1 , 0 );
2810                                                                         pCHANSTAT->PeriodHighLimit_     = MOD__KeyToPeriod_( pMOD ,         0 , 0 );
2811                                                                         if(     (pCHANSTAT->VibratoType & 4) == 0 ) pCHANSTAT->VibratoPosition_ = 0 ;
2812                                                                         if(     (pCHANSTAT->TremoloType & 4) == 0 ) pCHANSTAT->TremoloPosition_ = 0 ;
2813                                                                 }
2814
2815                                                         } else {
2816                                                                 pCHANSTAT->PlayingVolume_  = 0 ;
2817                                                         }
2818
2819                                                 /* CASE 3 : 音階無効  &  NoteOff でもない  &  音色有効 */
2820                                                 } else
2821                                                 if(     idxPatternNote == -1    /* 音階無効 */
2822                                                 &&      idxPatternNote != 96    /* NoteOff ではない */
2823                                                 &&      idxInst != -1                   /* 音色有効 */
2824                                                 ){
2825                                                         pCHANSTAT->bFadeOut                                     = FALSE ;
2826                                                         pCHANSTAT->pPendingXM_INSTRUMENT        = pMOD->apXM_INSTRUMENT[ idxInst ];
2827
2828                                                         if(     pCHANSTAT->pPlayingXM_SAMPLE != NULL ){
2829                                                                 pCHANSTAT->PlayingVolume_       = pCHANSTAT->pPlayingXM_SAMPLE->Volume << SFT ;
2830                                                                 if( pMOD->FormatType == TYPE_XM ){
2831                                                                         pCHANSTAT->PlayingPanning_      = pCHANSTAT->pPlayingXM_SAMPLE->Panning << SFT ;
2832                                                                 }
2833                                                         }
2834
2835                                                         pCHANSTAT->idxVolumeEnvelopeTable       = 0 ;
2836                                                         pCHANSTAT->idxPanningEnvelopeTable      = 0 ;
2837                                                         pCHANSTAT->AutoVibratoPosition          = 0 ;
2838                                                         pCHANSTAT->AutoVibratoDepth_            = 0 ;
2839                                                         pCHANSTAT->MultiRetrigCount                     = 0 ;
2840                                                 }
2841
2842                                                 /* NoteOff */
2843                                                 if(     idxPatternNote == 96 ) pCHANSTAT->bFadeOut = TRUE ;
2844
2845                                                 /* 内部変数の更新 */
2846                                                 pCHANSTAT->idxNowPatternNote    = idxPatternNote ;
2847                                                 pCHANSTAT->idxNowRealNote               = idxRealNote ;
2848                                                 pCHANSTAT->idxNowInst                   = idxInst ;
2849                                                 pCHANSTAT->NowVolumeColumn              = VolumeColumn ;
2850                                                 pCHANSTAT->NowCommand                   = Command ;
2851                                                 pCHANSTAT->NowParam                             = Param ;
2852                                                 pCHANSTAT->NowPeriod_                   = Period_ ;
2853
2854                                                 #if (WARNING_LEVEL >= 3)
2855                                                         /* 発声があったなら、! を表示 */
2856                                                         if(     bPlay ){
2857                                                         //      LogMsg( "![%04X][%s]" , Period_ >> SFT , pCHANSTAT->pPlayingXM_SAMPLE->aszSampleName );
2858                                                                 LogMsg(pMOD->Instance, "!" );
2859                                                         } else {
2860                                                                 LogMsg(pMOD->Instance, " " );
2861                                                         }
2862                                                 #endif
2863                                         }
2864                                 }
2865
2866                                 idxNowPatternNote       = pCHANSTAT->idxNowPatternNote ;
2867                                 idxNowRealNote          = pCHANSTAT->idxNowRealNote ;
2868                                 idxNowInst                      = pCHANSTAT->idxNowInst ;
2869                                 NowVolumeColumn         = pCHANSTAT->NowVolumeColumn ;
2870                                 NowCommand                      = pCHANSTAT->NowCommand ;
2871                                 NowParam                        = pCHANSTAT->NowParam ;
2872                                 NowPeriod_                      = pCHANSTAT->NowPeriod_ ;
2873
2874
2875                                 /* VolumeColumn コマンドを処理する */
2876                                 if(     bNoteDelay == FALSE ){
2877                                         /*
2878                                                 ModPlugTracker 上で動作確認した範囲からでしかわからないが、
2879                                                 VolumeColumn のパラメーター省略による continue はかなり特殊。
2880                                                 後づけ機能ゆえか、ひどい仕様。
2881                                                 コマンド 6x 7x 8x 9x ax bx dx ex で、共通の continue 値を持っている。
2882                                                 しかも、この値はメジャーコマンドに上書きされるのであった。
2883                                         */
2884                                         if(     (NowVolumeColumn & 0xF0) == 0x60
2885                                         ||      (NowVolumeColumn & 0xF0) == 0x70
2886                                         ||      (NowVolumeColumn & 0xF0) == 0x80
2887                                         ||      (NowVolumeColumn & 0xF0) == 0x90
2888                                         ||      (NowVolumeColumn & 0xF0) == 0xA0
2889                                         ||      (NowVolumeColumn & 0xF0) == 0xB0
2890                                         ||      (NowVolumeColumn & 0xF0) == 0xD0
2891                                         ||      (NowVolumeColumn & 0xF0) == 0xE0
2892                                         ){
2893                                                 if(     (NowVolumeColumn & 0xF) == 0 ){
2894                                                         NowVolumeColumn = (NowVolumeColumn & 0xF0) | pCHANSTAT->VolumeColumnContinueValue ;
2895                                                 } else {
2896                                                         pCHANSTAT->VolumeColumnContinueValue = NowVolumeColumn & 0xF ;
2897                                                 }
2898                                         }
2899
2900                                         switch( NowVolumeColumn & 0xF0 ){
2901                                                 case 0x00 :{
2902                                                 } break ;
2903
2904                                                 /* Set volume */
2905                                                 case 0x10 :
2906                                                 case 0x20 :
2907                                                 case 0x30 :
2908                                                 case 0x40 :
2909                                                 case 0x50 :{
2910                                                         if(     bFirstTrigger ){
2911                                                                 /*
2912                                                                         なんで 0x10 引くのか?
2913                                                                                 voleffect = 0x1* -> notevol = 0
2914                                                                                 voleffect = 0x2* -> notevol = 0x10
2915                                                                                 voleffect = 0x3* -> notevol = 0x20
2916                                                                                 voleffect = 0x4* -> notevol = 0x30
2917                                                                                 voleffect = 0x5* -> notevol = 0x40
2918                                                                         ということらしい。
2919                                                                 */
2920                                                                 pCHANSTAT->PlayingVolume_ = (NowVolumeColumn - 0x10) << SFT ;
2921                                                         }
2922                                                 } break ;
2923
2924                                                 /* $60-$6f : Volume slide down */
2925                                                 /* $70-$7f : Volume slide up */
2926                                                 /*
2927                                                         コマンド Axy 5xy 6xy との併用で作用は加算される。
2928                                                 */
2929                                                 case 0x60 :
2930                                                 case 0x70 :{
2931                                                         if(     bFirstTrigger ){
2932                                                                 if(     (NowVolumeColumn & 0xF0) == 0x60 ){
2933                                                                         pCHANSTAT->VolumeSlide = -(NowVolumeColumn & 0x0F) ;
2934                                                                 }
2935                                                                 if(     (NowVolumeColumn & 0xF0) == 0x70 ){
2936                                                                         pCHANSTAT->VolumeSlide =  (NowVolumeColumn & 0x0F) ;
2937                                                                 }
2938                                                         }
2939                                                         pCHANSTAT->PlayingVolume_ += pCHANSTAT->VolumeSlide * ModifyVal_ ;
2940                                                 } break ;
2941
2942                                                 /* $80-$8f : Fine volume slide down */
2943                                                 /* $90-$9f : Fine volume slide up */
2944                                                 /*
2945                                                         コマンド EAx EBx との併用で作用は加算される。
2946                                                 */
2947                                                 case 0x80 :
2948                                                 case 0x90 :{
2949                                                         if(     bFirstTrigger ){
2950                                                                 if(     (NowVolumeColumn & 0xF0) == 0x80 ){
2951                                                                         pCHANSTAT->FineVolumeSlide = -(NowVolumeColumn & 0x0F) ;
2952                                                                 }
2953                                                                 if(     (NowVolumeColumn & 0xF0) == 0x90 ){
2954                                                                         pCHANSTAT->FineVolumeSlide =  (NowVolumeColumn & 0x0F) ;
2955                                                                 }
2956                                                                 pCHANSTAT->PlayingVolume_ += pCHANSTAT->FineVolumeSlide << SFT ;
2957                                                         }
2958                                                 } break ;
2959
2960                                                 /* $a0-$af : Set vibrato speed */
2961                                                 /* $b0-$bf : Vibrato depth */
2962                                                 /*
2963                                                         オリジナルの FT2 では、$Ax では、スピードだけを設定したようだ。
2964                                                         しかし、ModPlug では、$Ax $Bx ともに、ビブラートが発効する。
2965                                                         効果は、コマンド 4xy と同じ。
2966                                                         コマンド 4xy との併用で、作用の増強はない。
2967                                                         内部変数は 4xy と共通。
2968                                                 */
2969                                                 case 0xA0 :
2970                                                 case 0xB0 :{
2971                                                         if(     bFirstTrigger ){
2972                                                                 if(     (NowVolumeColumn & 0xF0) == 0xA0 ){
2973                                                                         pCHANSTAT->VibratoRate  = NowVolumeColumn & 0xF ;
2974                                                                 }
2975                                                                 if(     (NowVolumeColumn & 0xF0) == 0xB0 ){
2976                                                                         pCHANSTAT->VibratoDepth = NowVolumeColumn & 0xF ;
2977                                                                 }
2978                                                         }
2979                                                         bVibrato = TRUE ;
2980                                                 } break ;
2981
2982                                                 /* $c0-$cf : Set panning */
2983                                                 case 0xC0 :{
2984                                                         if(     bFirstTrigger ){
2985                                                                 pCHANSTAT->PlayingPanning_ = (NowVolumeColumn & 0xF) * ((0xFF << SFT) / 0xF) ;
2986                                                         }
2987                                                 } break ;
2988
2989                                                 /* $d0-$df : Panning slide left */
2990                                                 /* $e0-$ef : Panning slide right */
2991                                                 /*
2992                                                         コマンド Pxy との併用で作用は加算される。
2993                                                         パラメーター変数も、内部で共通となっている。
2994                                                 */
2995                                                 case 0xD0 :
2996                                                 case 0xE0 :{
2997                                                         if(     bFirstTrigger ){
2998                                                                 if(     (NowVolumeColumn & 0xF0) == 0xD0 ){
2999                                                                         pCHANSTAT->PanningSlide = -((S32)NowVolumeColumn & 0x0F) * 4 ;  /* 左へ */
3000                                                                 }
3001                                                                 if(     (NowVolumeColumn & 0xF0) == 0xE0 ){
3002                                                                         pCHANSTAT->PanningSlide =  ((S32)NowVolumeColumn & 0x0F) * 4 ;  /* 右へ */
3003                                                                 }
3004                                                         }
3005                                                         pCHANSTAT->PlayingPanning_ += pCHANSTAT->PanningSlide * ModifyVal_ ;
3006                                                 } break ;
3007
3008                                                 /* $f0-$ff : Tone porta */
3009                                                 /*
3010                                                         メジャーエフェクトの記述をペーストした。
3011                                                         パラメーターは、3xx コマンドの 16 倍の効果を持つ。
3012                                                         メジャーエフェクトの 3xx と併用する時、効果が加算される。
3013                                                 */
3014                                                 case 0xF0 :{
3015                                                         if(     bFirstTrigger ){
3016                                                                 if(     NowVolumeColumn & 0xF ){
3017                                                                         pCHANSTAT->TonePortamentoInc = (NowVolumeColumn & 0xF) * 64 ;
3018                                                                 }
3019                                                         }
3020
3021                                                         if(     pCHANSTAT->TonePortamentoDst_ > pCHANSTAT->PlayingPeriod_ ){
3022                                                                 if(     (pCHANSTAT->PlayingPeriod_ += pCHANSTAT->TonePortamentoInc * ModifyVal_)
3023                                                                 >       pCHANSTAT->TonePortamentoDst_
3024                                                                 ){
3025                                                                         pCHANSTAT->PlayingPeriod_ = pCHANSTAT->TonePortamentoDst_ ;
3026                                                                 }
3027                                                         } else
3028                                                         if(     pCHANSTAT->TonePortamentoDst_ < pCHANSTAT->PlayingPeriod_ ){
3029                                                                 if(     (pCHANSTAT->PlayingPeriod_ -= pCHANSTAT->TonePortamentoInc * ModifyVal_)
3030                                                                 <       pCHANSTAT->TonePortamentoDst_
3031                                                                 ){
3032                                                                         pCHANSTAT->PlayingPeriod_ = pCHANSTAT->TonePortamentoDst_ ;
3033                                                                 }
3034                                                         }
3035                                                 } break ;
3036                                         }
3037
3038                                         /*
3039                                                 ここで一度、パラメーターの飽和処理が必要。
3040                                                 メジャーコマンドの処理後にも、やはり飽和処理をするので
3041                                                 2度手間だが、ModPlug の仕様である。
3042                                         */
3043                                         if(     pCHANSTAT->PlayingVolume_  <            0  ) pCHANSTAT->PlayingVolume_  = 0 ;
3044                                         if(     pCHANSTAT->PlayingVolume_  > (0x40 << SFT) ) pCHANSTAT->PlayingVolume_  = 0x40 << SFT ;
3045                                         if(     pCHANSTAT->PlayingPanning_ <            0  ) pCHANSTAT->PlayingPanning_ = 0 ;
3046                                         if(     pCHANSTAT->PlayingPanning_ > (0xFF << SFT) ) pCHANSTAT->PlayingPanning_ = 0xFF << SFT ;
3047                                 }
3048
3049
3050                                 /* メジャーコマンドを処理する */
3051                                 if(     bNoteDelay == FALSE ){
3052
3053                                         /* Arpeggio */
3054                                         if(     NowCommand == 0x00 ){
3055                                                 /* エフェクト無し(= 0x000)を Arpeggio と混同しない */
3056                                                 if(     NowParam ){
3057                                                         if(     bFirstTrigger ){
3058                                                                 S32     FineTune                = pCHANSTAT->PlayingFineTune ;
3059                                                                 S32     idxLastRealNote = pCHANSTAT->idxLastRealNote ;
3060
3061                                                                 pCHANSTAT->ArpeggioPeriod_[0]
3062                                                                 =       MOD__KeyToPeriod_( pMOD , idxLastRealNote +  (NowParam & 0x0F)       , FineTune );
3063                                                                 pCHANSTAT->ArpeggioPeriod_[1]
3064                                                                 =       MOD__KeyToPeriod_( pMOD , idxLastRealNote + ((NowParam & 0xF0) >> 4) , FineTune );
3065                                                                 pCHANSTAT->idxArpeggio = 0 ;
3066                                                         }
3067                                                         bArpeggio = TRUE ;
3068                                                 }
3069                                         }
3070
3071                                         /* Portamento Up */
3072                                         if(     NowCommand == 0x10 ){
3073                                                 if(     bFirstTrigger ){
3074                                                         if(     pMOD->FormatType == TYPE_MOD    /* MOD 形式では NowParam == 0 でも continue としない */
3075                                                         ||      (       pMOD->FormatType == TYPE_XM     /* XM 形式では NowParam == 0 は continue */
3076                                                                 &&      NowParam
3077                                                                 )
3078                                                         ){
3079                                                                 pCHANSTAT->PortamentoInc = NowParam * 4 ;
3080                                                         }
3081                                                 }
3082
3083                                                 pCHANSTAT->PlayingPeriod_ -= pCHANSTAT->PortamentoInc * ModifyVal_ ;
3084                                         }
3085
3086                                         /* Portamento Down */
3087                                         if(     NowCommand == 0x20 ){
3088                                                 if(     bFirstTrigger ){
3089                                                         if(     pMOD->FormatType == TYPE_MOD    /* MOD 形式では NowParam == 0 でも continue としない */
3090                                                         ||      (       pMOD->FormatType == TYPE_XM     /* XM 形式では NowParam == 0 は continue */
3091                                                                 &&      NowParam
3092                                                                 )
3093                                                         ){
3094                                                                 pCHANSTAT->PortamentoInc = NowParam * 4 ;
3095                                                         }
3096                                                 }
3097
3098                                                 pCHANSTAT->PlayingPeriod_ += pCHANSTAT->PortamentoInc * ModifyVal_ ;
3099                                         }
3100
3101                                         /* Tone-Portamento */
3102                                         /* Tone-Portamento + Volume Slide( NowParam は Volume Slide に適用)*/
3103                                         if(     NowCommand == 0x30
3104                                         ||      NowCommand == 0x50
3105                                         ){
3106                                                 if(     bFirstTrigger ){
3107                                                         if(     NowCommand != 0x50 ){           /* 0x50 の時、NowParam は Volume Slide に適用 */
3108                                                                 /* MOD/XM 形式共に、NowParam == 0 は continue */
3109                                                                 if(     NowParam ){
3110                                                                         pCHANSTAT->TonePortamentoInc = NowParam * 4 ;
3111                                                                 }
3112                                                         }
3113                                                 }
3114
3115                                                 if(     pCHANSTAT->TonePortamentoDst_ > pCHANSTAT->PlayingPeriod_ ){
3116                                                         if(     (pCHANSTAT->PlayingPeriod_ += pCHANSTAT->TonePortamentoInc * ModifyVal_)
3117                                                         >       pCHANSTAT->TonePortamentoDst_
3118                                                         ){
3119                                                                 pCHANSTAT->PlayingPeriod_ = pCHANSTAT->TonePortamentoDst_ ;
3120                                                         }
3121                                                 } else
3122                                                 if(     pCHANSTAT->TonePortamentoDst_ < pCHANSTAT->PlayingPeriod_ ){
3123                                                         if(     (pCHANSTAT->PlayingPeriod_ -= pCHANSTAT->TonePortamentoInc * ModifyVal_)
3124                                                         <       pCHANSTAT->TonePortamentoDst_
3125                                                         ){
3126                                                                 pCHANSTAT->PlayingPeriod_ = pCHANSTAT->TonePortamentoDst_ ;
3127                                                         }
3128                                                 }
3129                                         }
3130
3131                                         /* Vibrato */
3132                                         /* Vibrato + Volume Slide( NowParam は Volume Slide に適用)*/
3133                                         if(     NowCommand == 0x40
3134                                         ||      NowCommand == 0x60
3135                                         ){
3136                                                 if(     bFirstTrigger ){
3137                                                         if(     NowCommand != 0x60 ){           /* 0x60 の時、NowParam は Volume Slide に適用 */
3138                                                                 /* MOD/XM 形式ともに、Depth Rate 個別に 0 なら continue とする */
3139                                                                 if(     NowParam & 0x0F ){
3140                                                                         pCHANSTAT->VibratoDepth = NowParam & 0x0F ;
3141                                                                 }
3142                                                                 if(     NowParam & 0xF0 ){
3143                                                                         pCHANSTAT->VibratoRate = (NowParam & 0xF0) >> 4 ;
3144                                                                 }
3145                                                         }
3146                                                 }
3147                                                 bVibrato = TRUE ;
3148                                         }
3149
3150                                         /* Tone-Portamento + Volume Slide( NowParam は Volume Slide に適用)*/
3151                                         /* Vibrato + Volume Slide( NowParam は Volume Slide に適用)*/
3152                                         /* Volume Slide */
3153                                         if(     NowCommand == 0x50
3154                                         ||      NowCommand == 0x60
3155                                         ||      NowCommand == 0xA0
3156                                         ){
3157                                                 if(     bFirstTrigger ){
3158                                                         if(     pMOD->FormatType == TYPE_MOD    /* MOD 形式では NowParam == 0 でも continue としない */
3159                                                         ||      (       pMOD->FormatType == TYPE_XM     /* XM 形式では NowParam == 0 は continue */
3160                                                                 &&      NowParam
3161                                                                 )
3162                                                         ){
3163                                                                 /* NowParam 上位 4 bit を優先的に参照する。*/
3164                                                                 if(     NowParam & 0xF0 ){
3165                                                                         pCHANSTAT->VolumeSlide = ((NowParam & 0xF0) >> 4) ;
3166                                                                 } else {
3167                                                                         pCHANSTAT->VolumeSlide = -((S32)NowParam & 0x0F) ;
3168                                                                 }
3169                                                         }
3170                                                 }
3171                                                 pCHANSTAT->PlayingVolume_ += pCHANSTAT->VolumeSlide * ModifyVal_ ;
3172                                         }
3173
3174                                         /* Tremolo */
3175                                         if(     NowCommand == 0x70 ){
3176                                                 if(     bFirstTrigger ){
3177                                                         /* MOD/XM 形式ともに、Depth Rate 個別に、0 なら continue */
3178                                                         if(     NowParam & 0x0F ){
3179                                                                 pCHANSTAT->TremoloDepth = NowParam & 0x0F ;
3180                                                         }
3181                                                         if(     NowParam & 0xF0 ){
3182                                                                 pCHANSTAT->TremoloRate = (NowParam & 0xF0) >> 4 ;
3183                                                         }
3184                                                 }
3185                                                 bTremolo = TRUE ;
3186                                         }
3187
3188                                         /* Set Panning */
3189                                         if(     NowCommand == 0x80 ){
3190                                                 if(     bFirstTrigger ){
3191                                                         pCHANSTAT->bSurround = FALSE ;
3192
3193                                                         /*
3194                                                                 XM/IT 形式では、値は、00 (左) から FF (右)です。
3195                                                                 MOD/S3M 形式では、値は、00 (左) から 80 (右)です。
3196                                                                 MOD/S3M 形式において、値 A4 が指定されると、サラウンドモード(中央)になります。
3197                                                         */
3198                                                         if(     pMOD->FormatType == TYPE_MOD
3199                                                         ||      pMOD->FormatType == TYPE_S3M
3200                                                         ){
3201                                                                 S32     zxc = NowParam ;
3202                                                                 if( zxc == 0xA4 ){              /* コマンド 8A4 */
3203                                                                         pCHANSTAT->PlayingPanning_      = (0xFF << SFT) / 2 ;
3204                                                                         pCHANSTAT->bSurround            = TRUE ;
3205                                                                 } else {
3206                                                                         if( zxc <= 0x80 ){
3207                                                                                 pCHANSTAT->PlayingPanning_ = zxc * ((0xFF << SFT) / 0x80) ;
3208                                                                         }
3209                                                                 }
3210                                                         } else
3211                                                         if(     pMOD->FormatType == TYPE_XM
3212                                                         ||      pMOD->FormatType == TYPE_IT
3213                                                         ){
3214                                                                 pCHANSTAT->PlayingPanning_ = NowParam << SFT ;
3215                                                         }
3216                                                 }
3217                                         }
3218
3219                                         /* Set Sample Offset */
3220                                         if(     NowCommand == 0x90 ){
3221                                                 if(     bFirstTrigger
3222                                                 &&      NowPeriod_
3223                                                 ){
3224                                                         XM_SAMPLE       *pXM_SAMPLE = pCHANSTAT->pPlayingXM_SAMPLE ;
3225                                                         U32     SamplePosition = 0 ;
3226
3227                                                         /* MOD/XM 形式ともに、Param == 0 なら continue */
3228                                                         if(     NowParam ){
3229                                                                 pCHANSTAT->SampleOffset = NowParam ;
3230                                                         }
3231                                                         SamplePosition = pCHANSTAT->SampleOffset * 0x100 + pCHANSTAT->SampleHighOffset * 0x10000 ;
3232
3233                                                         if(     pXM_SAMPLE ){
3234                                                                 /*      !!
3235                                                                         MOD 形式の場合、サンプリング終点を超えるなら先頭に戻す。
3236                                                                         ループが有効なら、それを考慮した位置に再生点を置く。
3237                                                                         とやっているような気がするが不明。
3238                                                                 */
3239                                                                 if(     SamplePosition >= (U32)pXM_SAMPLE->SampleLength ){
3240                                                                         #if (WARNING_LEVEL >= 1)
3241                                                                                 LogMsg(pMOD->Instance,
3242                                                                                         "\n"
3243                                                                                         "MOD__PlaySong : 警告 \n"
3244                                                                                         "       CH = %d : コマンド 9%02X にて、範囲オーバー検出。POS=[%X / %X] \n"
3245                                                                                         ,i
3246                                                                                         ,NowParam
3247                                                                                         ,SamplePosition
3248                                                                                         ,pXM_SAMPLE->SampleLength
3249                                                                                 );
3250                                                                         #endif
3251                                                                         if(     pXM_SAMPLE->VoiceMode & VM_LOOP ){
3252                                                                                 SamplePosition -= pXM_SAMPLE->SampleLoopStart ;
3253                                                                                 SamplePosition %= pXM_SAMPLE->SampleLoopLength ;
3254                                                                                 SamplePosition += pXM_SAMPLE->SampleLoopStart ;
3255                                                                         }
3256                                                                 }
3257                                                         }
3258
3259                                                         pCHANSTAT->SamplePosition_ = SamplePosition << SFT ;
3260                                                 }
3261                                         }
3262
3263                                         /* Position Jump(この行自体は演奏される)*/
3264                                         if(     NowCommand == 0xB0 ){
3265                                                 if(     bFirstTrigger ){
3266                                                         if(     pMOD->bLoopMode == TRUE                                 /* ループ再生時は無条件に許可 */
3267                                                         ||      NowParam >= pMOD->idxSequenceData               /* 前方のジャンプは無条件に許可 */
3268                                                         ){
3269                                                                 pMOD->BreakSequence = NowParam ;
3270                                                         }
3271                                                 }
3272                                         }
3273
3274                                         /* Set Volume */
3275                                         if(     NowCommand == 0xC0 ){
3276                                                 if(     bFirstTrigger ){
3277                                                         pCHANSTAT->PlayingVolume_ = NowParam << SFT ;
3278                                                 }
3279                                         }
3280
3281                                         /* Pattern Break(この行自体は演奏される)*/
3282                                         if(     NowCommand == 0xD0 ){
3283                                                 if(     bFirstTrigger ){
3284                                                         pMOD->BreakRow          = ((NowParam & 0xF0) >> 4) * 10 + (NowParam & 0x0F) ;
3285                                                         pMOD->BreakSequence     = pMOD->idxSequenceData + 1 ;
3286                                                 }
3287                                         }
3288
3289                                         /* Extended MOD Commands */
3290                                         if(     (NowCommand & 0xFF0) == 0x0E0 ){
3291                                                 switch( NowCommand ){
3292                                                         /* E0x : Set Filter */
3293                                                         case 0xE0 :{
3294                                                                 switch( NowParam ){
3295                                                                         //      !! 未対応
3296                                                                         #if (WARNING_LEVEL >= 1)
3297                                                                                 LogMsg(pMOD->Instance,
3298                                                                                         "MOD__PlaySong : 警告 \n"
3299                                                                                         "       未対応のコマンド %03X です。\n"
3300                                                                                         ,NowCommand
3301                                                                                 );
3302                                                                         #endif
3303                                                                         /*
3304                                                                                 Amiga がハードウェアレベルで実装していた機能をコントロール
3305                                                                                 するコマンドだったらしい。妥協決定。
3306                                                                         */
3307                                                                 }
3308                                                         } break ;
3309
3310                                                         /* E1x : Fine Portamento Up */
3311                                                         /* E2x : Fine Portamento Down */
3312                                                         case 0xE1 :
3313                                                         case 0xE2 :{
3314                                                                 if(     bFirstTrigger ){
3315                                                                         if(     pMOD->FormatType == TYPE_MOD    /* MOD 形式では NowParam == 0 でも continue としない */
3316                                                                         ||      (       pMOD->FormatType == TYPE_XM     /* XM 形式では NowParam == 0 は continue */
3317                                                                                 &&      NowParam
3318                                                                                 )
3319                                                                         ){
3320                                                                                 pCHANSTAT->FinePortamentoInc = NowParam * 4 ;
3321                                                                         }
3322                                                                         if(     NowCommand == 0xE1 ){
3323                                                                                 pCHANSTAT->PlayingPeriod_ -= pCHANSTAT->FinePortamentoInc << SFT ;
3324                                                                         }
3325                                                                         if(     NowCommand == 0xE2 ){
3326                                                                                 pCHANSTAT->PlayingPeriod_ += pCHANSTAT->FinePortamentoInc << SFT ;
3327                                                                         }
3328                                                                 }
3329                                                         } break ;
3330
3331                                                         /* E3x : Grissando Control */
3332                                                         case 0xE3 :{
3333                                                                 if(     bFirstTrigger ){
3334                                                                         if(     NowParam ){
3335                                                                                 pCHANSTAT->bGrissando = TRUE ;
3336                                                                         } else {
3337                                                                                 pCHANSTAT->bGrissando = FALSE ;
3338                                                                         }
3339                                                                 }
3340                                                         } break ;
3341
3342                                                         /* E4x : Vibrato waveform */
3343                                                         case 0xE4 :{
3344                                                                 if(     bFirstTrigger ){
3345                                                                         pCHANSTAT->VibratoType = NowParam ;
3346                                                                 }
3347                                                         } break ;
3348
3349                                                         /* E5x : Set FineTune(MOD 形式のみサポート)*/
3350                                                         case 0xE5 :{
3351                                                                 if(     bFirstTrigger
3352                                                                 &&      pMOD->FormatType == TYPE_MOD
3353                                                                 ){
3354                                                                         S32     Val = NowParam ;
3355                                                                         if(     Val >= 8 ) Val = Val - 16 ;
3356
3357                                                                         /* Period を再算出する */
3358                                                                         pCHANSTAT->PlayingFineTune = Val << 4 ;
3359                                                                         pCHANSTAT->PendingPeriod_
3360                                                                         =       pCHANSTAT->PlayingPeriod_
3361                                                                         =       MOD__KeyToPeriod_( pMOD , pCHANSTAT->idxLastRealNote , pCHANSTAT->PlayingFineTune );
3362                                                                 }
3363                                                         } break ;
3364
3365                                                         /* E6x : Pattern loop */
3366                                                         case 0xE6 :{
3367                                                                 if(     bFirstTrigger ){
3368                                                                         /*
3369                                                                                 復帰点を設定
3370                                                                                 重複設定が行われた場合、最新のものが有効
3371                                                                         */
3372                                                                         if(     NowParam == 0 ){
3373                                                                                 /* 同一個所に復帰点を再設定する場合はキャンセル */
3374                                                                                 if(     pCHANSTAT->PatternLoopRow != pMOD->Row ){
3375                                                                                         pCHANSTAT->PatternLoopRow       = pMOD->Row ;
3376                                                                                         pCHANSTAT->PatternLoopCount     = 0 ;
3377                                                                                 }
3378                                                                         }
3379
3380                                                                         /* 必要な回数分岐する */
3381                                                                         if(     NowParam ){
3382                                                                                 if(     NowParam > pCHANSTAT->PatternLoopCount ){
3383                                                                                         pCHANSTAT->PatternLoopCount++ ;
3384                                                                                         pMOD->BreakRow = pCHANSTAT->PatternLoopRow ;
3385                                                                                 }
3386                                                                         }
3387                                                                 }
3388                                                         } break ;
3389
3390                                                         /* E7x : Tremolo waveform */
3391                                                         case 0xE7 :{
3392                                                                 if(     bFirstTrigger ){
3393                                                                         pCHANSTAT->TremoloType = NowParam ;
3394                                                                 }
3395                                                         } break ;
3396
3397                                                         /* E8x : Set Pannning */
3398                                                         case 0xE8 :{
3399                                                                 if(     bFirstTrigger ){
3400                                                                         pCHANSTAT->PlayingPanning_ = NowParam * ((0xFF << SFT) / 0x0F) ;
3401                                                                 }
3402                                                         } break ;
3403
3404                                                         /* E9x : Retrigger note */
3405                                                         /*
3406                                                                 この旧コマンドは、非常にややこしい仕様を持っている。
3407                                                                 tick 0 のトリガーは、通常の Note 欄の内容で処理。
3408                                                                 それ以降のトリガーはここで処理しなければならない。
3409                                                                 両者の効果は異なっている。
3410                                                                 スパゲティー化必至。しかもこれで正しいという保証も無い。
3411                                                         */
3412                                                         case 0xE9 :{
3413                                                                 S32     zxc = NowParam ;
3414                                                                 if( zxc <= 0 ) zxc = 1 ;
3415                                                                 if(     bFirstTrigger == FALSE
3416                                                                 &&      (pMOD->TickCount % zxc) == 0
3417                                                                 ){
3418                                                                         /*
3419                                                                                 NowInst が有効
3420                                                                                 ->      PendingInst   = NowInst
3421                                                                                         PlayingInst   = NowInst
3422                                                                                         PlayingPeriod = PendingPeriod
3423                                                                                         PlayingInst.Sample リスタート
3424                                                                                         Env 形状 = PlayingInst
3425                                                                                         Env リスタート
3426                                                                                         Auto-Vibrato は PlayingInst でリスタート
3427                                                                                 else
3428                                                                                 ->      PendingInst   = PlayingInst             (逆流。ひどいっす。)
3429                                                                                         PlayingPeriod = PendingPeriod
3430                                                                                         PlayingInst.Sample リスタート
3431                                                                                         Env 形状 = PlayingInst
3432                                                                                         Env リスタート
3433                                                                                         Auto-Vibrato は PlayingInst でリスタート
3434
3435                                                                                 そもそも、PendingInst でなく NowInst を参照している点が不自然。
3436                                                                                 古いデータの互換性のためなのか、ModPlug のバグなのか、それさえ不明。
3437                                                                         */
3438                                                                         if(     idxNowInst != -1 ){
3439                                                                                 pCHANSTAT->pPlayingXM_INSTRUMENT        = pCHANSTAT->pPendingXM_INSTRUMENT
3440                                                                                                                                                         = pMOD->apXM_INSTRUMENT[ idxNowInst ];
3441                                                                                 pCHANSTAT->PlayingPeriod_                       = pCHANSTAT->PendingPeriod_ ;
3442                                                                                 if(     pCHANSTAT->pPlayingXM_INSTRUMENT != NULL ){
3443                                                                                         pCHANSTAT->pPlayingXM_SAMPLE
3444                                                                                         =       pCHANSTAT->
3445                                                                                                 pPlayingXM_INSTRUMENT->
3446                                                                                                 apAllNoteXM_SAMPLE[ pCHANSTAT->idxLastRealNote ];
3447                                                                                 }
3448                                                                         } else {
3449                                                                                 pCHANSTAT->pPendingXM_INSTRUMENT        = pCHANSTAT->pPlayingXM_INSTRUMENT ;
3450                                                                                 pCHANSTAT->PlayingPeriod_                       = pCHANSTAT->PendingPeriod_ ;
3451                                                                         }
3452                                                                         pCHANSTAT->SamplePosition_                      = 0 ;
3453                                                                         pCHANSTAT->idxVolumeEnvelopeTable       = 0 ;
3454                                                                         pCHANSTAT->idxPanningEnvelopeTable      = 0 ;
3455                                                                         pCHANSTAT->AutoVibratoPosition          = 0 ;
3456                                                                         pCHANSTAT->AutoVibratoDepth_            = 0 ;
3457                                                                 }
3458                                                         } break ;
3459
3460                                                         /* EAx : Fine volslide up  */
3461                                                         /* EBx : Fine volslide down */
3462                                                         case 0xEA :
3463                                                         case 0xEB :{
3464                                                                 if(     bFirstTrigger ){
3465                                                                         if(     pMOD->FormatType == TYPE_MOD    /* MOD 形式では NowParam == 0 でも continue としない */
3466                                                                         ||      (       pMOD->FormatType == TYPE_XM     /* XM 形式では NowParam == 0 は continue */
3467                                                                                 &&      NowParam
3468                                                                                 )
3469                                                                         ){
3470                                                                                 pCHANSTAT->FineVolumeSlide = NowParam ;
3471                                                                         }
3472                                                                         if(     NowCommand == 0xEA ){
3473                                                                                 pCHANSTAT->PlayingVolume_ += pCHANSTAT->FineVolumeSlide << SFT ;
3474                                                                         }
3475                                                                         if(     NowCommand == 0xEB ){
3476                                                                                 pCHANSTAT->PlayingVolume_ -= pCHANSTAT->FineVolumeSlide << SFT ;
3477                                                                         }
3478                                                                 }
3479                                                         } break ;
3480
3481                                                         /* Note cut */
3482                                                         case 0xEC :{
3483                                                                 if(     pMOD->TickCount == NowParam ){
3484                                                                         pCHANSTAT->PlayingVolume_ = 0 ;
3485                                                                 }
3486                                                         } break ;
3487
3488                                                         /* Note delay */
3489                                                         case 0xED :{
3490                                                                 /* 冒頭にて処理済み */
3491                                                         } break ;
3492
3493                                                         /* Pattern delay */
3494                                                         case 0xEE :{
3495                                                                 if(     bFirstTrigger ){
3496                                                                         pMOD->PatternDelay = NowParam ;
3497                                                                 }
3498                                                         } break ;
3499
3500                                                         /* Set active macro(XM形式のみサポート)*/
3501                                                         case 0xEF :{
3502                                                                 //      !! 未対応
3503                                                                 #if (WARNING_LEVEL >= 1)
3504                                                                         LogMsg(pMOD->Instance,
3505                                                                                 "MOD__PlaySong : 警告 \n"
3506                                                                                 "       未対応のコマンド %03X です。\n"
3507                                                                                 ,NowCommand
3508                                                                         );
3509                                                                 #endif
3510                                                                 /*
3511                                                                         このコマンドが、どのような機能なのかは不明。
3512                                                                         MOD 形式の場合は、一部のトラッカーにて、サンプリング再生の方向を
3513                                                                         選択できたようだが、ModPlug にはそのような機能は存在しない。
3514                                                                         XM 形式の場合は、MIDI MACRO 関係の機能を持っているが、
3515                                                                         詳細不明。というか、使っているデータを見たことがない。
3516                                                                 */
3517                                                         } break ;
3518                                                 }
3519                                         }
3520
3521                                         /* Set Speed/Tempo (コマンド Fxx) */
3522                                         if(     NowCommand == 0xF0 ){
3523                                                 if(     bFirstTrigger ){
3524                                                         if(     NowParam ){
3525                                                                 if((    NowParam <= 0x20  &&  pMOD->FormatType == TYPE_MOD)
3526                                                                 ||      (NowParam <  0x20  &&  pMOD->FormatType == TYPE_XM)
3527                                                                 ){
3528                                                                         pMOD->nTickPerRow = NowParam ;
3529                                                                         if(     pMOD->nTickPerRow <= 0 ) pMOD->nTickPerRow = 1 ;
3530                                                                 } else {
3531                                                                         pMOD->BPM = NowParam ;
3532                                                                 }
3533                                                         } else {
3534                                                                 /* 省略時は、前回までの値を継続して使用 */
3535                                                         }
3536                                                 }
3537                                         }
3538
3539                                         /* Global volume(コマンド Gxx)*/
3540                                         if(     NowCommand == 0x100 ){
3541                                                 if(     bFirstTrigger ){
3542                                                         pMOD->GlobalVolume_ = NowParam << SFT ;
3543                                                 }
3544                                         }
3545
3546                                         /* Global volume slide(コマンド Hxy)*/
3547                                         if(     NowCommand == 0x110 ){
3548                                                 if(     bFirstTrigger ){
3549                                                         if( NowParam ){
3550                                                                 /* NowParam 上位 4 bit を優先的に参照する。*/
3551                                                                 if(     NowParam & 0xF0 ){
3552                                                                         pMOD->GlobalVolumeSlide = ((NowParam & 0xF0) >> 4) ;
3553                                                                 } else {
3554                                                                         pMOD->GlobalVolumeSlide = -((S32)NowParam & 0x0F) ;
3555                                                                 }
3556                                                         }
3557                                                 }
3558                                                 pMOD->GlobalVolume_ += pMOD->GlobalVolumeSlide * ModifyVal_ ;
3559                                         }
3560
3561                                         /* Keyoff(コマンド Kxx)*/
3562                                         /*
3563                                                 パラメーター xx に意味はない、らしい。
3564                                         */
3565                                         if(     NowCommand == 0x140 ){
3566                                                 if(     bFirstTrigger ){
3567                                                         pCHANSTAT->bFadeOut = TRUE ;
3568                                                 }
3569                                         }
3570
3571                                         /* Set envpos(コマンド Lxx)*/
3572                                         if(     NowCommand == 0x150 ){
3573                                                 if(     bFirstTrigger ){
3574                                                         pCHANSTAT->idxVolumeEnvelopeTable       = NowParam ;
3575                                                         pCHANSTAT->idxPanningEnvelopeTable      = NowParam ;
3576                                                 }
3577                                         }
3578
3579                                         /* Panning slide(コマンド Pxy)*/
3580                                         if(     NowCommand == 0x190 ){
3581                                                 if(     bFirstTrigger ){
3582                                                         if(     NowParam ){
3583                                                                 /* 例外的に、NowParam 下位 4 bit を優先的に参照する。*/
3584                                                                 if(     NowParam & 0x0F ){
3585                                                                         pCHANSTAT->PanningSlide = -((S32)NowParam & 0x0F) * 4 ;         /* 左へスライド */
3586                                                                 } else {
3587                                                                         pCHANSTAT->PanningSlide = ((NowParam & 0xF0) >> 4) * 4 ;        /* 右へスライド */
3588                                                                 }
3589                                                         }
3590                                                 }
3591                                                 pCHANSTAT->PlayingPanning_ += pCHANSTAT->PanningSlide * ModifyVal_ ;
3592                                         }
3593
3594                                         /* Multi retrig(コマンド Rxy)*/
3595                                         /*
3596                                                 tick 0 から発効し、ModifyVal_ の補正は不要。
3597                                                 古い世代の XM では、tick 0 では発効せず、ModifyVal_ の補正が必要らしい(未対応)。
3598                                         */
3599                                         if(     NowCommand == 0x1B0 ){
3600                                                 /*                                        +0  +1  +2  +3  +4  +5  +6  +7  +8  +9  +A  +B  +C  +D  +E  +F */
3601                                                 static const S8 aMultiRetrigMulTable[] = { 0,  0,  0,  0,  0,  0, 10,  8,  0,  0,  0,  0,  0,  0, 24, 32 };
3602                                                 static const S8 aMultiRetrigAddTable[] = { 0, -1, -2, -4, -8,-16,  0,  0,  0, +1, +2, +4, +8,+16,  0,  0 };
3603
3604                                                 if(     bFirstTrigger ){
3605                                                         /* x y 個別に、0 なら continue */
3606                                                         if(     NowParam & 0x0F ){
3607                                                                 pCHANSTAT->MultiRetrigInterval = NowParam & 0x0F ;
3608                                                         }
3609                                                         if(     NowParam & 0xF0 ){
3610                                                                 pCHANSTAT->MultiRetrigVolumeChange = (NowParam & 0xF0) >> 4 ;
3611                                                         }
3612                                                 }
3613
3614                                                 if(     pCHANSTAT->MultiRetrigCount >= pCHANSTAT->MultiRetrigInterval
3615                                                 &&      pCHANSTAT->MultiRetrigInterval
3616                                                 ){
3617                                                         pCHANSTAT->SamplePosition_      = 0 ;   /* 再生位置の初期化のみ */
3618                                                         pCHANSTAT->MultiRetrigCount     = 0 ;
3619
3620                                                         if(     aMultiRetrigMulTable[ pCHANSTAT->MultiRetrigVolumeChange ] == 0 ){
3621                                                                 pCHANSTAT->PlayingVolume_ += aMultiRetrigAddTable[ pCHANSTAT->MultiRetrigVolumeChange ] << SFT ;
3622                                                                 if(     pCHANSTAT->PlayingVolume_ < (   0 << SFT) ) pCHANSTAT->PlayingVolume_ = (   0 << SFT) ;
3623                                                                 if(     pCHANSTAT->PlayingVolume_ > (0x40 << SFT) ) pCHANSTAT->PlayingVolume_ = (0x40 << SFT) ;
3624                                                         } else {
3625                                                                 pCHANSTAT->PlayingVolume_
3626                                                                 =       pCHANSTAT->PlayingVolume_ * aMultiRetrigMulTable[ pCHANSTAT->MultiRetrigVolumeChange ] >> 4 ;
3627                                                                 if(     pCHANSTAT->PlayingVolume_ > (0x40 << SFT) ) pCHANSTAT->PlayingVolume_ = (0x40 << SFT) ;
3628                                                         }
3629                                                 }
3630                                                 pCHANSTAT->MultiRetrigCount++ ;
3631                                         }
3632
3633                                         /* Tremor(コマンド Txy)*/
3634                                         /*
3635                                                 このコマンドは、現在のチャンネルの発声を、指定 frame 単位で ON OFF する機能です。
3636                                                 例えば、T[ontime][offtime] の様に記述します。
3637                                                 x=ontime, y=offtime とすると、x frame の間ボリューム値は変化せず、
3638                                                 その後 y frame の間ミュート状態(無音)になります。
3639                                                 ontime / offtime の正確な持続時間は MOD / XM / S3M / IT の間で異なるので注意です。 
3640                                         */
3641                                         if(     NowCommand == 0x1D0 ){
3642                                                 pCHANSTAT->bTremorMute = FALSE ;
3643
3644                                                 if(     bFirstTrigger ){
3645                                                         /* x y 共に 0 の時のみ continue */
3646                                                         if(     NowParam ){
3647                                                                 pCHANSTAT->TremorOnTime = ((NowParam >> 4) & 0xF) + 1 ;
3648                                                                 pCHANSTAT->TremorOffTime = (NowParam & 0xF) + 1 ;
3649                                                         }
3650                                                         pCHANSTAT->TremorCount = 0 ;
3651
3652                                                 } else {
3653                                                         /*
3654                                                                 TickPerRow = (TremorOnTime + TremorOffTime) * n + 1
3655                                                                 を満たさない場合、ModPlug では安定しない動作をする(バグ?)が、
3656                                                                 そこまでは再現できていない。かなり無意味っぽいので、妥協決定。
3657                                                         */
3658
3659                                                         if(     pCHANSTAT->TremorCount >= pCHANSTAT->TremorOnTime ){
3660                                                                 pCHANSTAT->bTremorMute = TRUE ;
3661                                                         }
3662
3663                                                         pCHANSTAT->TremorCount++ ;
3664                                                         if( pCHANSTAT->TremorCount >= pCHANSTAT->TremorOnTime + pCHANSTAT->TremorOffTime ){
3665                                                                 pCHANSTAT->TremorCount = 0 ;
3666                                                         }
3667                                                 }
3668                                         } else {
3669                                                 pCHANSTAT->bTremorMute = FALSE ;
3670                                         }
3671
3672                                         /* Extended XM Effects (コマンド Xxy) */
3673                                         if(     (NowCommand & 0xFF0) == 0x210 ){
3674                                                 switch( NowCommand ){
3675                                                         /* X1x : Extra Fine Portamento Up */
3676                                                         /* X2x : Extra Fine Portamento Down */
3677                                                         case 0x211 :
3678                                                         case 0x212 :{
3679                                                                 if(     bFirstTrigger ){
3680                                                                         if(     NowParam ){
3681                                                                                 pCHANSTAT->ExtraFinePortamentoInc = NowParam ;
3682                                                                         }
3683                                                                         if(     NowCommand == 0x211 ){
3684                                                                                 pCHANSTAT->PlayingPeriod_ -= pCHANSTAT->ExtraFinePortamentoInc << SFT ;
3685                                                                         }
3686                                                                         if(     NowCommand == 0x212 ){
3687                                                                                 pCHANSTAT->PlayingPeriod_ += pCHANSTAT->ExtraFinePortamentoInc << SFT ;
3688                                                                         }
3689                                                                 }
3690                                                         } break ;
3691
3692                                                         /* X5x : Panbrello wave form */
3693                                                         case 0x215 :{
3694                                                                 pCHANSTAT->PanbrelloType = NowParam ;
3695                                                         } break ;
3696
3697                                                         /* X6x : Fine pattern delay */
3698                                                         case 0x216 :{
3699                                                                 if(     bFirstTrigger ){
3700                                                                         pMOD->FinePatternDelay = NowParam ;
3701                                                                 }
3702                                                         } break ;
3703
3704                                                         /* X9x : Surround control */
3705                                                         case 0x219 :{
3706                                                                 switch( NowParam ){
3707                                                                         /* X90 : Surround Off */
3708                                                                         case 0x0 :{
3709                                                                                 pCHANSTAT->bSurround            = FALSE ;
3710                                                                         } break ;
3711
3712                                                                         /* X91 : Surround On */
3713                                                                         case 0x1 :{
3714                                                                                 pCHANSTAT->PlayingPanning_      = (0xFF << SFT) / 2 ;
3715                                                                                 pCHANSTAT->bSurround            = TRUE ;
3716                                                                         } break ;
3717
3718                                                                         /* X98 : Reverb Off */
3719                                                                         case 0x8 :{
3720                                                                                 //      !! 未対応
3721                                                                                 #if (WARNING_LEVEL >= 1)
3722                                                                                         LogMsg(pMOD->Instance,
3723                                                                                                 "MOD__PlaySong : 警告 \n"
3724                                                                                                 "       未対応のコマンド %03X です。\n"
3725                                                                                                 ,NowCommand
3726                                                                                         );
3727                                                                                 #endif
3728                                                                         } break ;
3729
3730                                                                         /* X99 : Reverb On */
3731                                                                         case 0x9 :{
3732                                                                                 //      !! 未対応
3733                                                                                 #if (WARNING_LEVEL >= 1)
3734                                                                                         LogMsg(pMOD->Instance,
3735                                                                                                 "MOD__PlaySong : 警告 \n"
3736                                                                                                 "       未対応のコマンド %03X です。\n"
3737                                                                                                 ,NowCommand
3738                                                                                         );
3739                                                                                 #endif
3740                                                                         } break ;
3741
3742                                                                         /* X9A : Center surround */
3743                                                                         case 0xA :{
3744                                                                                 //      !! 未対応
3745                                                                                 #if (WARNING_LEVEL >= 1)
3746                                                                                         LogMsg(pMOD->Instance,
3747                                                                                                 "MOD__PlaySong : 警告 \n"
3748                                                                                                 "       未対応のコマンド %03X です。\n"
3749                                                                                                 ,NowCommand
3750                                                                                         );
3751                                                                                 #endif
3752                                                                         } break ;
3753
3754                                                                         /* X9B : Quad surround */
3755                                                                         case 0xB :{
3756                                                                                 //      !! 未対応
3757                                                                                 #if (WARNING_LEVEL >= 1)
3758                                                                                         LogMsg(pMOD->Instance,
3759                                                                                                 "MOD__PlaySong : 警告 \n"
3760                                                                                                 "       未対応のコマンド %03X です。\n"
3761                                                                                                 ,NowCommand
3762                                                                                         );
3763                                                                                 #endif
3764                                                                         } break ;
3765
3766                                                                         /* X9C : Grobal filters */
3767                                                                         case 0xC :{
3768                                                                                 //      !! 未対応
3769                                                                                 #if (WARNING_LEVEL >= 1)
3770                                                                                         LogMsg(pMOD->Instance,
3771                                                                                                 "MOD__PlaySong : 警告 \n"
3772                                                                                                 "       未対応のコマンド %03X です。\n"
3773                                                                                                 ,NowCommand
3774                                                                                         );
3775                                                                                 #endif
3776                                                                         } break ;
3777
3778                                                                         /* X9D : Local filters */
3779                                                                         case 0xD :{
3780                                                                                 //      !! 未対応
3781                                                                                 #if (WARNING_LEVEL >= 1)
3782                                                                                         LogMsg(pMOD->Instance,
3783                                                                                                 "MOD__PlaySong : 警告 \n"
3784                                                                                                 "       未対応のコマンド %03X です。\n"
3785                                                                                                 ,NowCommand
3786                                                                                         );
3787                                                                                 #endif
3788                                                                         } break ;
3789
3790                                                                         /* X9E : Play Forward */
3791                                                                         case 0xE :{
3792                                                                                 //      !! 未対応
3793                                                                                 #if (WARNING_LEVEL >= 1)
3794                                                                                         LogMsg(pMOD->Instance,
3795                                                                                                 "MOD__PlaySong : 警告 \n"
3796                                                                                                 "       未対応のコマンド %03X です。\n"
3797                                                                                                 ,NowCommand
3798                                                                                         );
3799                                                                                 #endif
3800                                                                         } break ;
3801
3802                                                                         /* X9F : Play Backward */
3803                                                                         case 0xF :{
3804                                                                                 //      !! 未対応
3805                                                                                 #if (WARNING_LEVEL >= 1)
3806                                                                                         LogMsg(pMOD->Instance,
3807                                                                                                 "MOD__PlaySong : 警告 \n"
3808                                                                                                 "       未対応のコマンド %03X です。\n"
3809                                                                                                 ,NowCommand
3810                                                                                         );
3811                                                                                 #endif
3812                                                                         } break ;
3813                                                                 }
3814                                                         } break ;
3815
3816                                                         /* XAx : Set high offset */
3817                                                         case 0x21A :{
3818                                                                 pCHANSTAT->SampleHighOffset = NowParam ;
3819                                                         } break ;
3820                                                 }
3821                                         }
3822
3823                                         /* Panbrello(コマンド Yxy)*/
3824                                         if(     NowCommand == 0x220 ){
3825                                                 if(     bFirstTrigger ){
3826                                                         /* Depth Rate 個別に、0 なら continue */
3827                                                         if(     NowParam & 0x0F ){
3828                                                                 pCHANSTAT->PanbrelloDepth = NowParam & 0x0F ;
3829                                                         }
3830                                                         if(     NowParam & 0xF0 ){
3831                                                                 pCHANSTAT->PanbrelloRate = (NowParam & 0xF0) >> 4 ;
3832                                                         }
3833                                                 }
3834                                                 bPanbrello = TRUE ;
3835                                         }
3836
3837                                         /* Midi macro(コマンド Zxy)*/
3838                                         if(     NowCommand == 0x230 ){
3839                                                 //      !!      未対応
3840                                                 #if (WARNING_LEVEL >= 1)
3841                                                         LogMsg(pMOD->Instance,
3842                                                                 "MOD__PlaySong : 警告 \n"
3843                                                                 "       未対応のコマンド %03X です。\n"
3844                                                                 ,NowCommand
3845                                                         );
3846                                                 #endif
3847                                         }
3848
3849                                 }
3850
3851
3852                                 /* パンの最終値を求める */
3853                                 if(     pCHANSTAT->pPlayingXM_INSTRUMENT != NULL
3854                                 &&      pCHANSTAT->pPlayingXM_SAMPLE != NULL
3855                                 ){
3856                                         XM_INSTRUMENT   *pXM_INSTRUMENT = pCHANSTAT->pPlayingXM_INSTRUMENT ;
3857                                         S32     FinalPanning_ ;
3858
3859                                         /* 値を有効範囲内に */
3860                                         if(     pCHANSTAT->PlayingPanning_ <            0  ) pCHANSTAT->PlayingPanning_ =  0 ;
3861                                         if(     pCHANSTAT->PlayingPanning_ > (0xFF << SFT) ) pCHANSTAT->PlayingPanning_ = (0xFF << SFT) ;
3862
3863                                         /* 0x000 ~ 0x0FF -> 0x000 ~ 0x100 */
3864                                         FinalPanning_ = pCHANSTAT->PlayingPanning_ * 0x100 / 0xFF ;
3865
3866                                         /*
3867                                                 Panbrello の反映
3868                                                 ModfyVal_ の倍率は反映しないのが正しい。
3869                                                 ちなみに、Panbrello 波形には、リスタートの概念が無いようだ。
3870                                         */
3871                                         if(     bPanbrello ){
3872                                                 S32     Val =   (       (       _aaWaveTable[
3873                                                                                                 _aPanbrelloWaveType[
3874                                                                                                         pCHANSTAT->PanbrelloType & 3
3875                                                                                                 ]
3876                                                                                         ][
3877                                                                                                 ((pCHANSTAT->PanbrelloPosition + 0x10) >> 2) & 0x3F
3878                                                                                         ] * pCHANSTAT->PanbrelloDepth
3879                                                                                 ) + 2
3880                                                                         ) >> 3 ;
3881                                                 pCHANSTAT->PanbrelloPosition += pCHANSTAT->PanbrelloRate ;
3882
3883                                                 FinalPanning_ += Val << SFT ;
3884
3885                                                 /* 値を有効範囲内に */
3886                                                 if(     FinalPanning_ > (0x100 << SFT) ) FinalPanning_ = 0x100 << SFT ;
3887                                                 if(     FinalPanning_ <  0             ) FinalPanning_ = 0 ;
3888                                         }
3889
3890                                         /* パンエンベロープ処理 */
3891                                         if(     pXM_INSTRUMENT->PanningType & ENV_ON ){
3892                                                 if(     pCHANSTAT->idxPanningEnvelopeTable > 324 ) pCHANSTAT->idxPanningEnvelopeTable = 324 ;
3893
3894                                                 {
3895                                                         S32     Val = pXM_INSTRUMENT->PanningEnvelopeTable[ pCHANSTAT->idxPanningEnvelopeTable ];
3896                                                         if(     FinalPanning_ >= (0x80 << SFT) ){
3897                                                                 FinalPanning_ += (Val - 32) * ((0x100 << SFT) - FinalPanning_) / 32 ;
3898                                                         } else {
3899                                                                 FinalPanning_ += (Val - 32) * FinalPanning_ / 32 ;
3900                                                         }
3901                                                 }
3902
3903                                                 /* 値を有効範囲内に */
3904                                                 if(     FinalPanning_ > (0x100 << SFT) ) FinalPanning_ = 0x100 << SFT ;
3905                                                 if(     FinalPanning_ <  0             ) FinalPanning_ = 0 ;
3906
3907                                                 if(     !(      pXM_INSTRUMENT->PanningType & ENV_SUSTAIN
3908                                                         &&      pCHANSTAT->bFadeOut == FALSE
3909                                                         &&      pCHANSTAT->idxPanningEnvelopeTable == pXM_INSTRUMENT->PanningSustainPoint
3910                                                         )
3911                                                 ){
3912                                                         pCHANSTAT->idxPanningEnvelopeTable++ ;
3913                 
3914                                                         if(     pXM_INSTRUMENT->PanningType & ENV_LOOP ){
3915                                                                 if(     pCHANSTAT->idxPanningEnvelopeTable >= pXM_INSTRUMENT->PanningLoopEndPoint ){
3916                                                                         pCHANSTAT->idxPanningEnvelopeTable = pXM_INSTRUMENT->PanningLoopStartPoint ;
3917                                                                 }
3918                                                         }
3919                                                 }
3920
3921                                                 /* 値を有効範囲内に */
3922                                                 if(     FinalPanning_ > (0x100 << SFT) ) FinalPanning_ = 0x100 << SFT ;
3923                                                 if(     FinalPanning_ <  0             ) FinalPanning_ = 0 ;
3924                                         }
3925
3926                                         pCHANSTAT->FinalPanning_ = FinalPanning_ ;
3927                                 }
3928
3929                                 /* 音量の最終値を求める */
3930                                 if(     pCHANSTAT->pPlayingXM_INSTRUMENT != NULL
3931                                 &&      pCHANSTAT->pPlayingXM_SAMPLE != NULL
3932                                 ){
3933                                         XM_INSTRUMENT   *pXM_INSTRUMENT = pCHANSTAT->pPlayingXM_INSTRUMENT ;
3934                                         S32     FinalVolume_ ;
3935
3936                                         /* 値を有効範囲内に */
3937                                         if(     pCHANSTAT->PlayingVolume_ > (0x40 << SFT) ) pCHANSTAT->PlayingVolume_ = 0x40 << SFT ;
3938                                         if(     pCHANSTAT->PlayingVolume_ < 0             ) pCHANSTAT->PlayingVolume_ = 0 ;
3939                                         if(     pMOD->GlobalVolume_       > (0x40 << SFT) ) pMOD->GlobalVolume_       = 0x40 << SFT ;
3940                                         if(     pMOD->GlobalVolume_       < 0             ) pMOD->GlobalVolume_       = 0 ;
3941
3942                                         FinalVolume_ = pCHANSTAT->PlayingVolume_ ;
3943
3944                                         /* Tremolo の反映 */
3945                                         if(     bTremolo ){
3946                                                 S32     Val =   _aaWaveTable[
3947                                                                                 _aTremoloWaveType[ pCHANSTAT->TremoloType & 3 ]
3948                                                                         ][
3949                                                                                 (pCHANSTAT->TremoloPosition_ >> SFT) & 0x3F
3950                                                                         ];
3951                                                 pCHANSTAT->TremoloPosition_ += pCHANSTAT->TremoloRate * ModifyVal_ ;
3952
3953                                                 /* MOD 形式では、最大振幅は -0x1F ~ +0x1F */
3954                                                 if(     pMOD->FormatType == TYPE_MOD ){
3955                                                         FinalVolume_ += (Val << (SFT - 6)) * pCHANSTAT->TremoloDepth ;
3956                                                 }
3957
3958                                                 /* XM 形式では、最大振幅は -0x3F ~ +0x3F */
3959                                                 if(     pMOD->FormatType == TYPE_XM ){
3960                                                         FinalVolume_ += (Val << (SFT - 5)) * pCHANSTAT->TremoloDepth ;
3961                                                 }
3962
3963                                                 /* 値を有効範囲内に */
3964                                                 if(     FinalVolume_ > (0x40 << SFT) ) FinalVolume_ = 0x40 << SFT ;
3965                                                 if(     FinalVolume_ < 0             ) FinalVolume_ = 0 ;
3966                                         }
3967
3968                                         /* Tremoro の反映 */
3969                                         if(     pCHANSTAT->bTremorMute ) FinalVolume_ = 0 ;
3970
3971                                         /* キーオフ フェードアウト処理 */
3972                                         {
3973                                                 if(     pCHANSTAT->bFadeOut == TRUE ){
3974                                                         if(     (pCHANSTAT->pPlayingXM_INSTRUMENT->VolumeType & ENV_ON) == 0 ){
3975                                                         /* ボリュームエンベロープが無効の場合は、瞬時に音量 0 となる */
3976                                                                 pCHANSTAT->PlayingVolume_ = 0 ;
3977                                                                 FinalVolume_ = 0 ;
3978                                                                 pCHANSTAT->bFadeOut = FALSE ;
3979                                                         } else {
3980                                                         /* ボリュームエンベロープが有効の場合はフェードアウト */
3981                                                                 pCHANSTAT->FadeOutVolume_1_15_16 -= (S32)pXM_INSTRUMENT->VolumeFadeout * 2 ;
3982                                                                 if(     pCHANSTAT->FadeOutVolume_1_15_16 < 0 ) pCHANSTAT->FadeOutVolume_1_15_16 = 0 ;
3983                                                         }
3984                                                 } else {
3985                                                         pCHANSTAT->FadeOutVolume_1_15_16 = 1 << 16 ;
3986                                                 }
3987                                                 FinalVolume_ = (FinalVolume_ * (pCHANSTAT->FadeOutVolume_1_15_16 >> 8)) >> 8 ;
3988                                         }
3989
3990                                         /* ボリュームエンベロープ処理 */
3991                                         if(     pXM_INSTRUMENT->VolumeType & ENV_ON ){
3992                                                 if(     pCHANSTAT->idxVolumeEnvelopeTable > 324 ) pCHANSTAT->idxVolumeEnvelopeTable = 324 ;
3993                                                 FinalVolume_ =  (       FinalVolume_
3994                                                                                 *       pXM_INSTRUMENT->VolumeEnvelopeTable[ pCHANSTAT->idxVolumeEnvelopeTable ]
3995                                                                                 ) >> 6 ;
3996
3997                                                 if(     !(      pXM_INSTRUMENT->VolumeType & ENV_SUSTAIN
3998                                                         &&      pCHANSTAT->bFadeOut == FALSE
3999                                                         &&      pCHANSTAT->idxVolumeEnvelopeTable == pXM_INSTRUMENT->VolumeSustainPoint
4000                                                         )
4001                                                 ){
4002                                                         pCHANSTAT->idxVolumeEnvelopeTable++ ;
4003
4004                                                         if(     pXM_INSTRUMENT->VolumeType & ENV_LOOP ){
4005                                                                 if(     pCHANSTAT->idxVolumeEnvelopeTable >= pXM_INSTRUMENT->VolumeLoopEndPoint ){
4006                                                                         pCHANSTAT->idxVolumeEnvelopeTable = pXM_INSTRUMENT->VolumeLoopStartPoint ;
4007                                                                 }
4008                                                         }
4009                                                 }
4010
4011                                                 /* 値を有効範囲内に */
4012                                                 if(     FinalVolume_ > (0x40 << SFT) ) FinalVolume_ = 0x40 << SFT ;
4013                                                 if(     FinalVolume_ < 0             ) FinalVolume_ = 0 ;
4014                                         }
4015
4016                                         /* グローバルボリュームの反映 */
4017                                         FinalVolume_ = (FinalVolume_ >> 6) * (pMOD->GlobalVolume_ >> 6) >> (SFT - 6) ;
4018
4019                                         /* 独自の音量スケーリング */
4020                                         FinalVolume_ = (FinalVolume_ >> 6) * pCHANSTAT->VolumeScale_ >> (SFT - 6) ;
4021                                         FinalVolume_ = (FinalVolume_ >> 6) * pMOD->GlobalVolumeScale_ >> (SFT - 6) ;
4022
4023                                         /* L R 別に最終値を求める */
4024                                         pCHANSTAT->FinalVolume_         = FinalVolume_ ;
4025                                         pCHANSTAT->FinalVolume_R_       = FinalVolume_ * (pCHANSTAT->FinalPanning_ >> SFT) >> 8 ;
4026                                         pCHANSTAT->FinalVolume_L_       = FinalVolume_ - pCHANSTAT->FinalVolume_R_ ;
4027
4028                                         /* Surround が有効なら、左チャンネルの位相を反転 */
4029                                         if(     pCHANSTAT->bSurround ){
4030                                                 pCHANSTAT->FinalVolume_L_ = -pCHANSTAT->FinalVolume_L_ ;
4031                                         }
4032                                 }
4033
4034                                 /* Period の最終値を求める */
4035                                 if(     pCHANSTAT->pPlayingXM_INSTRUMENT != NULL
4036                                 &&      pCHANSTAT->pPlayingXM_SAMPLE != NULL
4037                                 ){
4038                                         /* 値を有効範囲内に */
4039                                         if( pCHANSTAT->PlayingPeriod_ > pCHANSTAT->PeriodHighLimit_ ){
4040                                                 pCHANSTAT->PlayingPeriod_ = pCHANSTAT->PeriodHighLimit_ ;
4041                                         }
4042                                         if( pCHANSTAT->PlayingPeriod_ < pCHANSTAT->PeriodLowLimit_ ){
4043                                                 pCHANSTAT->PlayingPeriod_ = pCHANSTAT->PeriodLowLimit_ ;
4044                                         }
4045
4046                                         pCHANSTAT->FinalPeriod_ = pCHANSTAT->PlayingPeriod_ ;
4047
4048                                         /* Arpeggio が有効ならその処理をここで */
4049                                         if(     bArpeggio ){
4050                                                 if(     pCHANSTAT->idxArpeggio == 1 ){
4051                                                         pCHANSTAT->FinalPeriod_ = pCHANSTAT->ArpeggioPeriod_[0] ;
4052                                                 }
4053                                                 if(     pCHANSTAT->idxArpeggio == 2 ){
4054                                                         pCHANSTAT->FinalPeriod_ = pCHANSTAT->ArpeggioPeriod_[1] ;
4055                                                 }
4056                                                 if(     ++pCHANSTAT->idxArpeggio >= 3 ) pCHANSTAT->idxArpeggio = 0 ;
4057                                         }
4058
4059                                         /* Grissando が有効なら、最寄の半音階へ */
4060                                         if( pCHANSTAT->bGrissando ){
4061                                                 S32     FineTune = pCHANSTAT->PlayingFineTune ;
4062                                                 pCHANSTAT->FinalPeriod_
4063                                                 =       MOD__KeyToPeriod_(
4064                                                                  pMOD
4065                                                                 ,MOD__Period_ToKey( pMOD ,pCHANSTAT->FinalPeriod_ , FineTune )
4066                                                                 ,FineTune
4067                                                         );
4068                                         }
4069
4070                                         /*
4071                                                 Vibrato の反映(Grissando 処理後に行う)
4072                                                 ModPlug では、VolumeColumn の Uxx Hxx の作用と、
4073                                                 メジャーコマンドの 4xy の作用は、互いに加算されない。
4074                                         */
4075                                         if(     bVibrato ){
4076                                                 S32     Val =   _aaWaveTable[
4077                                                                                 _aVibratoWaveType[ pCHANSTAT->VibratoType & 3 ]
4078                                                                         ][
4079                                                                                 (pCHANSTAT->VibratoPosition_ >> SFT) & 0x3F
4080                                                                         ];
4081                                                 pCHANSTAT->VibratoPosition_ += pCHANSTAT->VibratoRate * ModifyVal_ ;
4082
4083                                                 /*
4084                                                         AmigaPeriod モード時、線形周波数モード時、
4085                                                         ともに、最大振幅は -0x7F ~ +0x7F
4086                                                 */
4087                                                 pCHANSTAT->FinalPeriod_ += (Val << (SFT - 4)) * pCHANSTAT->VibratoDepth ;
4088                                         }
4089
4090                                         /*
4091                                                 Auto-Vibrato の反映
4092                                                 ModfyVal_ の倍率は反映しないのが正しい。
4093                                         */
4094                                         {
4095                                                 S32     InstAutoVibratoType      = pCHANSTAT->pPlayingXM_INSTRUMENT->AutoVibratoType ;
4096                                                 S32     InstAutoVibratoSweep = pCHANSTAT->pPlayingXM_INSTRUMENT->AutoVibratoSweep ;
4097                                                 S32     InstAutoVibratoDepth = pCHANSTAT->pPlayingXM_INSTRUMENT->AutoVibratoDepth ;
4098                                                 S32     InstAutoVibratoRate      = pCHANSTAT->pPlayingXM_INSTRUMENT->AutoVibratoRate ;
4099
4100                                                 if(     InstAutoVibratoDepth
4101                                                 &&      InstAutoVibratoRate
4102                                                 ){
4103                                                         if(     InstAutoVibratoSweep ){
4104                                                                 if(     pCHANSTAT->bFadeOut == FALSE ){
4105                                                                         pCHANSTAT->AutoVibratoDepth_ += (InstAutoVibratoDepth << SFT) / InstAutoVibratoSweep ;
4106                                                                         if(     pCHANSTAT->AutoVibratoDepth_ > (InstAutoVibratoDepth << SFT) ){
4107                                                                                 pCHANSTAT->AutoVibratoDepth_ = (InstAutoVibratoDepth << SFT) ;
4108                                                                         }
4109                                                                 }
4110                                                         } else {
4111                                                                 pCHANSTAT->AutoVibratoDepth_ = (InstAutoVibratoDepth << SFT) ;
4112                                                         }
4113                                                         pCHANSTAT->AutoVibratoPosition += InstAutoVibratoRate ;
4114
4115                                                         /* 最大振幅 -AutoVibratoDepth ~ +AutoVibratoDepth */
4116                                                         {
4117                                                                 if(     InstAutoVibratoType > 4 ) InstAutoVibratoType = 0 ;
4118                                                                 if(     InstAutoVibratoType == 4 ){
4119                                                                         /* 例外的に、波形速度に依存しないランダム波を使用 */
4120                                                                         pCHANSTAT->FinalPeriod_ += ((rand() & 0x1FF) - 0x100) * pCHANSTAT->AutoVibratoDepth_ >> 7 ;
4121                                                                 } else {
4122                                                                         pCHANSTAT->FinalPeriod_ +=      (       _aaWaveTable[
4123                                                                                                                                                 _aAutoVibratoWaveType[ InstAutoVibratoType ]
4124                                                                                                                                         ][
4125                                                                                                                                                 (pCHANSTAT->AutoVibratoPosition >> 2) & 0x3F
4126                                                                                                                                         ] * pCHANSTAT->AutoVibratoDepth_
4127                                                                                                                                 ) >> 7 ;
4128                                                                 }
4129                                                         }
4130                                                 }
4131                                         }
4132                                 }
4133
4134                                 /* 周波数算出 */
4135                                 if(     pCHANSTAT->pPlayingXM_SAMPLE != NULL ){
4136                                         if(     pCHANSTAT->FinalPeriod_
4137                                         &&      pMOD->nWavePerSec
4138                                         ){
4139                                                 F64     f64Freq ;
4140
4141                                                 if(     pMOD->XmHeader.Flags & LINEAR_FREQUENCY ){
4142                                                 /* 線形周波数モード */
4143                                                         f64Freq =       (F64)8363
4144                                                                         *       pow( 2 , ((F64)(6*12*16*4) - (F64)pCHANSTAT->FinalPeriod_ / (F64)ONE) / (F64)(12*16*4) );
4145                                                 } else {
4146                                                 /* AmigaPeriod モード */
4147                                                         F64     AmigaClock = 3579364 ;
4148                                                         if(     pMOD->FormatType == TYPE_MOD ) AmigaClock = 3546894.6 ;
4149                                                         f64Freq = AmigaClock * 4 / ((F64)pCHANSTAT->FinalPeriod_ / (F64)ONE) ;
4150                                                 }
4151
4152                                                 pCHANSTAT->SampleRate_ = (U32)(f64Freq * (F64)ONE / (F64)pMOD->nWavePerSec) ;
4153                                         }
4154                                 }
4155
4156                         }       /* end of for */
4157
4158                         break ;         /* 強制脱出 */
4159                 }       /* end of while */
4160
4161                 pMOD->TickCount++ ;
4162
4163                 /* 一定時間で 1 Row 進む */
4164                 if(     pMOD->TickCount >= pMOD->nTickPerRow * (1 + pMOD->PatternDelay) + pMOD->FinePatternDelay ){
4165                         #if (WARNING_LEVEL >= 3)
4166                                 LogMsg(pMOD->Instance,
4167                                         "\n"
4168                                 );
4169                         #endif
4170
4171                         pMOD->TickCount                 = 0 ;
4172                         pMOD->PatternDelay              = 0 ;
4173                         pMOD->FinePatternDelay  = 0 ;
4174
4175                         /* Sequence の分岐 */
4176                         if(     pMOD->BreakSequence != -1 ){
4177                                 pMOD->idxSequenceData   = pMOD->BreakSequence ;
4178                                 pMOD->BreakSequence             = -1 ;
4179                                 pMOD->Row                               = -1 ;  /* 直後にインクリメントされるので -1 */
4180                                 MOD__InitPatternLoop( pMOD );
4181                         }
4182
4183                         /* Row の分岐 */
4184                         if(     pMOD->BreakRow != -1 ){
4185                                 pMOD->Row               = pMOD->BreakRow ;
4186                                 pMOD->BreakRow  = -1 ;
4187                         } else {
4188                                 pMOD->Row++ ;
4189                         }
4190
4191                         /* パターン末端に達した場合の処理 */
4192                         {
4193                                 XM_PATTERN *pXM_PATTERN
4194                                 =       pMOD->apXM_PATTERN[ pMOD->XmHeader.aPatternOrderTable[ pMOD->idxSequenceData ] ];
4195                                 if(     pXM_PATTERN != NULL ){
4196                                         if(     pMOD->Row >= pXM_PATTERN->NumberOfRowsInPattern ){
4197                                                 pMOD->Row = 0 ;
4198                                                 pMOD->idxSequenceData++ ;
4199                                                 MOD__InitPatternLoop( pMOD );
4200                                         }
4201                                 } else {
4202                                         /* 万が一 NULL なら終点に達したとみなす */
4203                                         pMOD->bDone = TRUE ;
4204                                 }
4205                         }
4206
4207                         /* 終点に達した? */
4208                         if(     pMOD->idxSequenceData >= 256 ){
4209                                 pMOD->bDone = TRUE ;
4210                         } else
4211                         if(     pMOD->XmHeader.aPatternOrderTable[ pMOD->idxSequenceData ] == 0xFF
4212                         ||      pMOD->idxSequenceData >= pMOD->XmHeader.SongLength
4213                         ){
4214                                 pMOD->bDone = TRUE ;            /* 最後まで再生しきった */
4215                         }
4216                 }
4217
4218
4219                 /*
4220                         ここまでたどり着いた時点で、1 tick 分の波形の出力が許される。
4221
4222                         実は、1 tick 分の波形数を調整することで、正確な BPM を再現する仕組み。
4223                         nWavePerTick の算式は様々なプレイヤーで同一のモノ。内容はイマイチ良く分からない。
4224                 */
4225                 pMOD->nWavePerTick      = (pMOD->nWavePerSec * 5) / (pMOD->BPM * 2);
4226                 pMOD->nRestWave += pMOD->nWavePerTick ;
4227         }
4228 }
4229
4230
4231
4232 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4233 ▼     MOD 構造体の破棄
4234
4235         戻値・TRUE  = 成功
4236                 ・FALSE = 失敗
4237 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
4238 S32 MOD__Destruct(
4239         MOD     *p              /* this ポインター */
4240 ){
4241         if(     p == NULL ) return( FALSE );
4242
4243         if(     MOD__ReleaseSong( p ) == FALSE ) return( FALSE );
4244         FreeMemory( p );
4245         return( TRUE );
4246 }
4247
4248
4249
4250 /*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4251 ▼     MOD 構造体の確保と初期化
4252
4253         戻値:       確保した構造体へのポインター
4254                         NULL なら失敗
4255 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
4256 MOD *MOD__Create(void* Instance){
4257         size_t  i ;
4258         size_t  size = sizeof( MOD );
4259         MOD     *p = reinterpret_cast<MOD*>(AllocMemory( size ));
4260
4261         if( p == NULL ) return( NULL );
4262
4263         /* 面倒なので0でクリア */
4264         for( i=0 ; i<size ; i++ ) ((U8*)p)[i] = 0 ;
4265
4266         /* メンバーの初期値 */
4267         p->FormatType                   = TYPE_NOTAVAILABLE ;
4268         p->nWavePerSec                  = 44100 ;
4269         p->bLoopMode                    = TRUE ;
4270         p->bAutoGainControl             = TRUE ;
4271         p->GlobalVolumeScale_   = ONE ;
4272         for( i=0 ; i<MAX_PATTERNS ; i++ ) p->apXM_PATTERN[ i ] = NULL ;
4273         for( i=0 ; i<MAX_INSTRUMENTS ; i++ ) p->apXM_INSTRUMENT[ i ] = NULL ;
4274         for( i=0 ; i<MAX_SAMPLES ; i++ ) p->apXM_SAMPLE[ i ] = NULL ;
4275   p->Instance = Instance;
4276         return( p );
4277 }