= $min_duration; $duration--) { /* Ninjatracker */ //$gs_frequency = floor(32 / 1645 * (1 / (($duration - 2) * 2.79365E-07))); /* Ninjatrackerplus */ $amiga_freq = 7093789.2 / ($duration * 2); $gs_frequency = round((32 * $amiga_freq) / 1645); $durations[] = $duration; $frequencies[] = $gs_frequency; } echo str_pad('max_finetune_ptr', 24) . '= '.(count($frequencies) * 2 - 2)."\n"; echo output_values('freq_finetune', $frequencies)."\n\n"; /* for every finetuned set of octaves, find the duration of each note in the frequency table so that we have, for every note, a pointer into the frequency table */ echo str_pad('note_freq_ptrs', 24) . '= *'."\n"; foreach($pt_durations_finetune as $finetune_index => $octave) { $ptr_into_freq = [0]; /* note 0 is only a dummy */ foreach($octave as $duration) { $pos = array_search($duration, $durations); if($pos === false) { die('Duration (period) not found: '.$duration); } $ptr = $pos * 2; $ptr_into_freq[] = $ptr; } $label = 'note_freq_ptrs_'.dechex($finetune_index); echo output_values($label, $ptr_into_freq)."\n"; $labels[$finetune_index] = $label; } echo str_pad('max_freq_ptr', 24) . '= '.(count($ptr_into_freq) * 2 - 2)."\n"; echo str_pad('note_freq_ptrs_offset', 24) . '= *'."\n"; foreach($pt_durations_finetune as $finetune_index => $octave) { echo str_repeat(' ', 24) . 'dw '.$labels[$finetune_index].'-note_freq_ptrs'."\n"; } echo "\n"; /* Nostalgia - The original Basic program from 1994 1 REM Make Finetune Table for Soundsmith Player 5 DIM A(3 * 12),B(3 * 12),C(3 * 12) 7 PRINT CHR$ (4)"opendeath": PRINT CHR$ (4)"writedeath" 10 DATA 858,808,762,720,678,640,604,570,538,508,480,453 20 DATA 428,404,381,360,339,320,302,285,269,254,240,226 30 DATA 214,202,190,180,170,160,151,143,135,127,120,113 35 FOR I = 1 TO 36: READ A(I): NEXT 40 K = 1:D = A(1): PRINT " dw "; 50 C = C + 1 55 REM (D+4) oder (D-2) 70 X = INT (32 / 1645 * (1 / ((D + 4) * 2.79365E - 07))): PRINT X;: IF C < 12 THEN PRINT ",";: GOTO 90 80 C = 0: PRINT : PRINT " dw "; 90 IF K < 37 THEN IF D = A(K) THEN B(K) = D2:C(K) = X:K = K + 1 100 D2 = D2 + 2:D = D - 1 110 IF D > 90 THEN 50 115 C = 12: FOR I = 1 TO 36:C = C + 1: IF C > 11 THEN C = 0: PRINT : PRINT " dw "; 116 PRINT B(I);: IF C < 11 THEN PRINT ","; 117 NEXT 118 C = 12: FOR I = 1 TO 36:C = C + 1: IF C > 11 THEN C = 0: PRINT : PRINT " dw "; 119 PRINT C(I);: IF C < 11 THEN PRINT ","; 120 NEXT 130 PRINT CHR$ (4)"close" */ /* --------------------------------------------------------------------------------------------------------------------- */ /* waveforms for vibrato and tremolo */ $table_length = 2 * 64 * 16; $offset_sine_tbl = 0; $offset_ramp_tbl = $offset_sine_tbl + $table_length; $offset_square_tbl = $offset_ramp_tbl + $table_length; echo str_pad('waveforms', 24).'dw '.$offset_sine_tbl.','.$offset_ramp_tbl.','.$offset_square_tbl.','.$offset_square_tbl.' ;random=square in protracker!'."\n\n"; $max_x = 64; /* sine waveforms for vibrato and tremolo */ echo str_pad('sine_tbl', 24).'= *'."\n"; for($amplitude = 0; $amplitude < 16; $amplitude++) { $list = []; for($x = 0; $x < $max_x; $x++) { $y = 2 * ((int) round($amplitude * sin($x / $max_x * 2 * M_PI))); $word = ($y >= 0) ? $y : (65536 + $y); $word_str = $word < 10 ? $word : '$'.dechex($word); $list[] = $word_str; } echo str_repeat(' ', 24).'dw '.implode(',', $list)."\n"; } echo "\n"; /* ramp down waveforms for vibrato and tremolo */ echo str_pad('ramp_tbl', 24).'= *'."\n"; for($amplitude = 0; $amplitude < 16; $amplitude++) { $list = []; for($x = 0; $x < $max_x; $x++) { $y = 2 * (round($amplitude * ($max_x / 2 - $x) / ($max_x / 2))); $word = abs(($y >= 0) ? $y : (65536 + $y)); $word_str = $word < 10 ? $word : '$'.dechex($word); $list[] = $word_str; } echo str_repeat(' ', 24).'dw '.implode(',', $list)."\n"; } echo "\n"; /* square waveforms for vibrato and tremolo */ echo str_pad('square_tbl', 24).'= *'."\n"; for($amplitude = 0; $amplitude < 16; $amplitude++) { $list = []; for($x = 0; $x < $max_x; $x++) { $y = 2 * $amplitude * ($x < ($max_x / 2) ? 1 : -1); $word = ($y >= 0) ? $y : (65536 + $y); $word_str = $word < 10 ? $word : '$'.dechex($word); $list[] = $word_str; } echo str_repeat(' ', 24).'dw '.implode(',', $list)."\n"; } echo "\n"; /* --------------------------------------------------------------------------------------------------------------------- */ /* pattern break pointers */ $pointers = []; for($i = 0; $i <= 255; $i++) { $h = str_pad(dechex($i), 2, '0', STR_PAD_LEFT); $x = hexdec(substr($h,0,1)); $y = hexdec(substr($h,1,1)); if($x <= 6 && $y <= 9) { $p = $x * 10 + $y; if($x === 6 && $y >= 4) { $p = 0; /* only values from 00 to 63 needed */ } $pointers[] = $p; } else { $pointers[] = 0; } } echo output_values('pattern_break_ptrs', $pointers, 'dfb')."\n\n"; /* --------------------------------------------------------------------------------------------------------------------- */ /* beats per minute * * The value of 125 means a 50 Hz interrupt. * The value of 150 means a 60 Hz interrupt. * * According to the formula in the IIGS hardware reference: * output_freq = SR / (2 ^ (17 + RES)) * FHL * with: SR = 894886 Hz / (OSC + 2) * * In our case, the interrupt uses a 256 byte wave, so RES = 0. * We have 32 oscillators enabled, so OSC = 32. * Our interrupt should be by default 50 Hz, so FHL = 249. * * Now we need values for every parameter of the set speed command. */ $factor = 34 * 131072 / 894886; /* from the formula above */ $values = []; for($bpm_value = 32; $bpm_value <= 255; $bpm_value++) { $output_freq = $bpm_value * 50 / 125; $FHL = $factor * $output_freq; $values[] = round($FHL); } echo output_values('bpm_to_freq', $values)."\n\n"; /* --------------------------------------------------------------------------------------------------------------------- */ /* quick lookup tables for registers */ foreach([32 => 'freqhi', 64 => 'vol', 128 => 'ptr', 160 => 'ctl', 192 => 'siz'] as $start => $label_part) { $values = []; for($i = 0; $i < 30; $i += 2) { $values[] = $start + $i; } echo output_values('reg_tbl_'.$label_part, $values)."\n"; } echo "\n";