33require_once 'IO/SoundFont.php ' ;
44require_once 'sample/makeWaveData.php ' ;
55
6- if ($ argc !== 2 ) {
7- echo "Usage: php sfextractsample.php <sffile> " .PHP_EOL ;
8- echo "ex) php sample/sfextractsample.php emuaps_8mb.sf2 " .PHP_EOL ;
6+ if ($ argc < 2 ) {
7+ echo "Usage: php sfextractsample.php <sffile> [<looptime>] " .PHP_EOL ;
8+ echo "ex) php sample/sfextractsample.php emuaps_8mb.sf2 3 " .PHP_EOL ;
99 exit (1 );
1010}
1111
1212$ sfdata = file_get_contents ($ argv [1 ]);
13+ if ($ argc == 2 ) {
14+ $ looptime = null ;
15+ } else {
16+ $ looptime = $ argv [2 ];
17+ }
18+
1319$ sf = new IO_SoundFont ();
1420$ sf ->parse ($ sfdata );
1521$ sf ->analyze ();
2834 $ genNdxEnd = $ presetBag ['_GenNdxEnd ' ];
2935 $ modNdxStart = $ presetBag ['ModNdx ' ];
3036 $ modNdxEnd = $ presetBag ['_ModNdxEnd ' ];
31- extractBag ($ presetBag , 'pgen ' , $ genNdxStart , $ genNdxEnd );
37+ extractBag ($ presetBag , 'pgen ' , $ genNdxStart , $ genNdxEnd, $ looptime );
3238 }
3339 }
3440}
3541
36- function extractBag ($ bag , $ genChunkId , $ genNdxStart , $ genNdxEnd ) {
42+ function extractBag ($ bag , $ genChunkId , $ genNdxStart , $ genNdxEnd, $ looptime ) {
3743 global $ sf ;
3844 for ($ genIdx = $ genNdxStart ; $ genIdx <= $ genNdxEnd ; $ genIdx ++) {
3945 $ gen = $ sf ->pdtaMap [$ genChunkId ][$ genIdx ];
4046// echo "Gen: idx:$genIdx ".PHP_EOL;
41- extractGenerator ($ gen );
47+ extractGenerator ($ gen, $ looptime );
4248 }
4349}
4450
45- function extractGenerator ($ gen ) {
51+ function extractGenerator ($ gen, $ looptime ) {
4652 global $ sf ;
4753 $ genOper = $ gen ['sfGenOper ' ];
4854 if ($ genOper === 41 ) { // instrument
4955 $ instIdx = $ gen ['Amount ' ];
5056 $ inst = $ sf ->pdtaMap ['inst ' ][$ instIdx ];
51- extractInstrument ($ inst ) ;
57+ extractInstrument ($ inst, $ looptime ) ;
5258 } else if ($ genOper === 53 ) { // sampleID
5359 $ sampleIdx = $ gen ['Amount ' ];
5460 $ sample = $ sf ->pdtaMap ['shdr ' ][$ sampleIdx ];
5561 echo IO_SoundFont_Sample::string ($ sample ).PHP_EOL ;
5662 //
57- $ name = $ sample ['SampleName ' ];
58- $ start = $ sample ['Start ' ];
59- $ end = $ sample ['End ' ];
60- $ sampleData = substr ($ sf ->sfbk ['sdta ' ]['smpl ' ]->data , $ start * 2 , ($ end -$ start + 1 ) * 2 );
63+ $ name = $ sample ['SampleName ' ];
6164 $ sampleRate = $ sample ['SampleRate ' ];
65+
66+ $ start = $ sample ['Start ' ];
67+ $ end = $ sample ['End ' ];
68+ $ data = $ sf ->sfbk ['sdta ' ]['smpl ' ]->data ;
69+ if (is_null ($ looptime )) {
70+ $ sampleData = substr ($ data , $ start * 2 , ($ end -$ start + 1 ) * 2 );
71+ } else {
72+ $ startLoop = $ sample ['StartLoop ' ];
73+ $ endLoop = $ sample ['EndLoop ' ];
74+ $ loopCount = $ looptime * $ sampleRate / ($ endLoop - $ startLoop + 1 );
75+ $ loopCount = ceil ($ loopCount ); // round up
76+ $ sampleData = substr ($ data , $ start * 2 , ($ startLoop - $ start ) * 2 );
77+ $ sampleData .= str_repeat (substr ($ data , $ startLoop * 2 , ($ endLoop - $ startLoop /*+ 1*/ ) * 2 ), $ loopCount );
78+ $ sampleData .= substr ($ data , ($ endLoop /*+ 1*/ ) * 2 , ($ end - $ endLoop + 1 ) * 2 );
79+ }
6280 $ nChannel = 1 ; // 1:monoral, 2:stereo
6381 $ sampleBits = 16 ; // 8 or 16
6482 $ waveData = makeWaveData ($ sampleData , $ nChannel , $ sampleBits , $ sampleRate );
6583 file_put_contents ($ name .".wav " , $ waveData );
6684 }
6785}
6886
69- function extractInstrument ($ inst ) {
87+ function extractInstrument ($ inst, $ looptime ) {
7088 global $ sf ;
7189 $ instName = $ inst ['InstName ' ];
7290 $ instBagNdxStart = $ inst ['InstBagNdx ' ];
@@ -79,6 +97,6 @@ function extractInstrument($inst) {
7997 $ genNdxEnd = $ instBag ['_GenNdxEnd ' ];
8098 $ modNdxStart = $ instBag ['ModNdx ' ];
8199 $ modNdxEnd = $ instBag ['_ModNdxEnd ' ];
82- extractBag ($ instBag , 'igen ' , $ genNdxStart , $ genNdxEnd );
100+ extractBag ($ instBag , 'igen ' , $ genNdxStart , $ genNdxEnd, $ looptime );
83101 }
84102}
0 commit comments