1 /**
  2  * This file is part of the Web Enabled Audio and Sound Enhancement Library (aka the Weasel audio library) Copyright 2011 - 2013 Warren Willmey. It is covered by the GNU General Public License version 3 as published by the Free Software Foundation, you should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
  3  */
  4 
  5 if( undefined == window.weasel ) window.weasel = {};
  6 
  7 // ---------------------------------------------------------------------------
  8 /** Create a Mahoney & Kaktus's Noisetracker 2.0 module out of the provided data (which has already passed the module sniffer test).
  9  * 
 10  * @constructor
 11  * @extends weasel.NoiseTracker11
 12  * 
 13  * @param {Array|Uint8Array} aModuleData = The Mahoney & Kaktus Noisetracker 2.0 module as a byte array that MUST have passed the module sniffer test.
 14  * @param {int} iPlaybackFrequency = The playback frequency in hertz to use (e.g. 44100 ).
 15  * @param {weasel.Sample.prototype.SampleScannerMode} iSampleScannerMode = Scan for IFF Header corruption residue?.
 16  * 
 17  * @author Warren Willmey 2013
 18  */
 19 weasel.NoiseTracker20 = function( aModuleData, iPlaybackFrequency, iSampleScannerMode )
 20 {
 21 	this.parent = weasel.NoiseTracker11;
 22 
 23 	// Needed for prototype Inheritance.
 24 	//
 25 	if( aModuleData === undefined || !(( aModuleData instanceof Array ) || ( window.Uint8Array && aModuleData instanceof Uint8Array )) )
 26 		return;
 27 
 28 
 29 	this.parent( aModuleData, iPlaybackFrequency, iSampleScannerMode );
 30 
 31 	// Set Noisetracker 2.0 Vibrato mode.
 32 	//
 33 	this.setVibratoMode( true );
 34 	this.sModuleType = weasel.ModuleSniffer.prototype.SupportedModules.NoiseTracker20;
 35 
 36 };
 37 
 38 weasel.NoiseTracker20.prototype = new weasel.NoiseTracker11;
 39 
 40 // ---------------------------------------------------------------------------
 41 /** Sequence table tick speed reader, reads tick speed from pattern during .
 42  * 
 43  * @param {int} iEffectData = The effect data of the pattern cell.
 44  * 
 45  * @return {int} The Tick Speed.
 46  * 
 47  * @protected
 48  * @override
 49  */
 50 weasel.NoiseTracker20.prototype._sequenceTableTickSpeedReader = function( iEffectData )
 51 {
 52 	if( iEffectData > 31 )
 53 		return 31;
 54 	else if( iEffectData <= 0 )
 55 		return 1;
 56 	else
 57 		return iEffectData;
 58 };
 59 
 60 // ---------------------------------------------------------------------------
 61 /** Set the row tick speed.
 62  * 
 63  * @param {int} iTickSpeed = The new row tick speed to use (0-31), a value of 0 is converted into a value of 1.
 64  * 
 65  * @override
 66  */
 67 weasel.NoiseTracker20.prototype.setTickSpeed = function( iTickSpeed )
 68 {
 69 	this.iTickSpeed = this._sequenceTableTickSpeedReader( iTickSpeed );
 70 };
 71 
 72 // ---------------------------------------------------------------------------
 73 /** Some Soundtrackers have effects that need processing out of the normal order,
 74  * such as the Note Portamento command in Noisetracker.
 75  * 
 76  * @param {weasel.Channel} oChannel = The Channel to process for effects.
 77  * @param {int} iNotePeriod = The note period yet to be set for this oChannel object.
 78  *
 79  * @return {bool} =	false : the fetch row process should continue for this oChannel object, 
 80  * 					true  : stop the fetch row process for this oChannel object but continue for the other channels..
 81  * 
 82  * @protected
 83  * @override
 84  */
 85 weasel.NoiseTracker20.prototype._exceptionPreprocessEffects = function( oChannel, iNotePeriod )
 86 {
 87 	var iEffectNumber = oChannel.getEffectNumber();
 88 
 89 	switch( iEffectNumber )
 90 	{
 91 		case weasel.FormatNoiseTracker11.Effects.TonePortamento :
 92 			// Command Fall through!
 93 			//
 94 		case weasel.FormatNoiseTracker20.Effects.TonePortamentoAndVolumeSlide :
 95 			oChannel.setNotePortamentoTarget( iNotePeriod );
 96 			return true;
 97 
 98 		default:
 99 		break;
100 	}
101 
102 	return false;
103 };
104 
105 // ---------------------------------------------------------------------------
106 /** Process a channel's effects.
107  * 
108  * @param {weasel.Channel} oChannel = The Channel to process for effects.
109  * 
110  * @protected
111  * @override
112  */
113 weasel.NoiseTracker20.prototype._processChannelEffect = function( oChannel )
114 {
115 	switch( oChannel.getEffectNumber() )
116 	{
117 		case weasel.FormatDOCSoundTracker9.Effects.Arpeggio :
118 
119 				if( oChannel.getEffectParameter() == 0 )
120 				{
121 					// Restore the (shadow) note period when no effect occurs.
122 					//
123 					oChannel.setNotePeriod( oChannel.getShadowNotePeriod() );
124 					break;
125 				}
126 
127 				oChannel.arpeggio( this.iCurrentTick, weasel.Channel.prototype.ArpeggioMode.Noisetracker );
128 
129 			break;
130 
131 		case weasel.FormatDOCSoundTracker9.Effects.PitchbendUp :
132 
133 				oChannel.pitchBend( this.iCurrentTick, 0, oChannel.getEffectParameter() );
134 				oChannel.setShadowNotePeriod( this._clampNotePeriod( oChannel.getShadowNotePeriod() ) );
135 				oChannel.setNotePeriod( oChannel.getShadowNotePeriod() );
136 
137 			break;
138 
139 		case weasel.FormatDOCSoundTracker9.Effects.PitchbendDown :
140 
141 				oChannel.pitchBend( this.iCurrentTick, oChannel.getEffectParameter(), 0 );
142 				oChannel.setShadowNotePeriod( this._clampNotePeriod( oChannel.getShadowNotePeriod() ) );
143 				oChannel.setNotePeriod( oChannel.getShadowNotePeriod() );
144 
145 			break;
146 
147 		case weasel.FormatNoiseTracker11.Effects.TonePortamento :
148 
149 				oChannel.setNotePortamentoSpeed( oChannel.getEffectParameter() );
150 				oChannel.notePortamento( this.iCurrentTick );
151 				oChannel.setNotePeriod( this._clampNotePeriod( oChannel.getNotePeriod() ) );
152 			break;
153 
154 		case weasel.FormatNoiseTracker11.Effects.Vibrato :
155 
156 				oChannel.vibrato( this.iCurrentTick, true, this.getVibratoMode() );
157 			break;
158 
159 
160 		case weasel.FormatNoiseTracker20.Effects.TonePortamentoAndVolumeSlide :
161 
162 				oChannel.notePortamento( this.iCurrentTick );
163 				oChannel.setNotePeriod( this._clampNotePeriod( oChannel.getNotePeriod() ) );
164 				oChannel.volumeSlide( this.iCurrentTick );
165 			break;
166 
167 		case weasel.FormatNoiseTracker20.Effects.VibratoAndVolumeSlide :
168 
169 				oChannel.vibrato( this.iCurrentTick, false, this.getVibratoMode() );
170 				oChannel.volumeSlide( this.iCurrentTick );
171 			break;
172 
173 		case weasel.FormatSpreadpointSoundTracker23.Effects.VolumeSlide :
174 
175 				// Restore (shadow) note period when a Effect Command 10 occurs.
176 				//
177 				oChannel.setNotePeriod( oChannel.getShadowNotePeriod() );
178 
179 				oChannel.volumeSlide( this.iCurrentTick );
180 
181 			break;
182 
183 		default :
184 					// Restore the note period when a Effect Command
185 					// that is not processed on a non tick 0 occurs. Such as
186 					// Set Volume Command.
187 					// Commands 7, 8, 9, 10, 11, 12, 13, 14, 15 restore the
188 					// period value. This value is taken from the Shadow Note Period
189 					// as the pitch bend/Portamento period value is maintained.
190 					//
191 					oChannel.setNotePeriod( oChannel.getShadowNotePeriod() );
192 
193 			break;
194 	}
195 };