@@ -134,6 +134,7 @@ function initOscillator (URL, name, id, color) {
134134 channelDataB : [ ] ,
135135 computedChannelData : [ ] ,
136136 algorithm : URL [ id + 'al' ] || 'p' ,
137+ cycles : urlVal ( URL [ id + 'c' ] , 1 ) ,
137138 amount : urlVal ( URL [ id + 'a' ] , 75 ) ,
138139 detune : urlVal ( URL [ id + 'd' ] , 0 ) ,
139140 octave : urlVal ( URL [ id + 'o' ] , 0 ) ,
@@ -172,14 +173,10 @@ let initialState = initializeState(urlData)
172173function MasterReducer ( state , action ) {
173174 state = state || initialState . Master
174175 switch ( action . type ) {
175- case 'SLIDER_CHANGED' :
176- if ( action . id === 'master' ) {
177- state . volume = action . value
178- updateURL ( 'mv' , action . value )
179- return Object . assign ( { } , state )
180- } else {
181- return state
182- }
176+ case 'MASTER_GAIN_CHANGED' :
177+ state . volume = Number ( action . value )
178+ updateURL ( 'mv' , action . value )
179+ return Object . assign ( { } , state )
183180 default :
184181 return state
185182 }
@@ -337,17 +334,37 @@ function computeWaveform (channelDataA, channelDataB, algorithm) {
337334 return [ ]
338335 }
339336
340- return channelDataB . map ( function ( data , index ) {
341- if ( algorithm === 'p' ) {
342- return limit ( - 1 , 1 , channelDataA [ index ] + channelDataB [ index ] )
343- } else if ( algorithm === 'm' ) {
344- return limit ( - 1 , 1 , channelDataA [ index ] - channelDataB [ index ] )
345- } else if ( algorithm === 'd' ) {
346- return limit ( - 1 , 1 , channelDataA [ index ] / ( channelDataB [ index ] * 2 ) )
347- } else if ( algorithm === 'x' ) {
348- return limit ( - 1 , 1 , channelDataA [ index ] * channelDataB [ index ] )
349- }
350- } )
337+ let cycles = 256 // 1 can be min. 1024 might be a good max.
338+ let samplesCount = ( 600 * cycles ) // - (overlap * cycles)
339+ let interpolatedData = new Float32Array ( samplesCount * 2 )
340+ let time = 0
341+
342+ // Interpolate from A to B.
343+ for ( let i = 0 ; i < samplesCount ; i ++ ) {
344+ time = i / samplesCount
345+ interpolatedData [ i ] = slerp ( channelDataA [ i % 600 ] , channelDataB [ i % 600 ] , time , algorithm )
346+ }
347+
348+ // Interpolate from B to A ( mirrors the previous ).
349+ for ( let k = samplesCount ; k < samplesCount * 2 ; k ++ ) {
350+ time = ( k - samplesCount ) / ( samplesCount ) // Time starts at half way point.
351+ interpolatedData [ k ] = slerp ( channelDataB [ k % 600 ] , channelDataA [ k % 600 ] , time , algorithm )
352+ }
353+ return interpolatedData
354+ }
355+
356+ // Modified lerp function based on algorithm chosen.
357+ // The 'minus' algorithm uses the normal lerp function.
358+ function slerp ( v0 , v1 , t , algorithm ) {
359+ if ( algorithm === 'p' ) {
360+ return limit ( - 1 , 1 , v0 * ( 1 + t ) + v1 * t ) || 0.00001
361+ } else if ( algorithm === 'm' ) {
362+ return limit ( - 1 , 1 , v0 * ( 1 - t ) + v1 * t ) || 0.00001 // Normal lerp function.
363+ } else if ( algorithm === 'd' ) {
364+ return limit ( - 1 , 1 , v0 * ( 1 / t ) + v1 * t ) || 0.00001
365+ } else if ( algorithm === 'x' ) {
366+ return limit ( - 1 , 1 , v0 * ( 1 * t ) + v1 * t ) || 0.00001
367+ }
351368}
352369
353370function OscillatorsReducer ( state , action ) {
@@ -399,7 +416,7 @@ function OscillatorsReducer (state, action) {
399416 } )
400417 return [ ...state ]
401418
402- // The +, -, /, * selected operator was changed.
419+ // The +, -, /, * selected operator was changed, or the number of cycles changed .
403420 case 'OSC_ALGORITHM_CHANGED' :
404421 state = state . map ( function ( osc ) {
405422 if ( osc . id === action . id ) {
@@ -420,11 +437,44 @@ function OscillatorsReducer (state, action) {
420437 return [ ...state ]
421438
422439 // Updates local osc values, detune, octave, and amt.
423- case 'SLIDER_CHANGED' :
440+ case 'OSC_CYCLES_CHANGED' :
441+ state = state . map ( function ( osc ) {
442+ if ( osc . id === action . id ) {
443+ osc . cycles = action . value
444+ const paramName = osc . id + 'c' // id + first letter of param.
445+ updateURL ( paramName , action . value )
446+ }
447+ return osc
448+ } )
449+ return [ ...state ]
450+
451+ case 'OSC_DETUNE_CHANGED' :
452+ state = state . map ( function ( osc ) {
453+ if ( osc . id === action . id ) {
454+ osc . detune = action . value
455+ const paramName = osc . id + 'd' // id + first letter of param.
456+ updateURL ( paramName , action . value )
457+ }
458+ return osc
459+ } )
460+ return [ ...state ]
461+
462+ case 'OSC_OCTAVE_CHANGED' :
463+ state = state . map ( function ( osc ) {
464+ if ( osc . id === action . id ) {
465+ osc . octave = action . value
466+ const paramName = osc . id + 'o' // id + first letter of param.
467+ updateURL ( paramName , action . value )
468+ }
469+ return osc
470+ } )
471+ return [ ...state ]
472+
473+ case 'OSC_AMOUNT_CHANGED' :
424474 state = state . map ( function ( osc ) {
425475 if ( osc . id === action . id ) {
426- osc [ action . name ] = action . value
427- const paramName = osc . id + action . name [ 0 ] // id + first letter of param.
476+ osc . amount = action . value
477+ const paramName = osc . id + 'a' // id + first letter of param.
428478 updateURL ( paramName , action . value )
429479 }
430480 return osc
0 commit comments