boolean srcUsed = false;
boolean writeMix = false;
int chunkLen, chunkLen2, deltaChunk;
int cpToMixStart = 0;
int cpToMixStop = bufLen;
Span chunkSpan, chunkSpan2;
// for each chunk there are two scenarios (indicated by the value of writeMix):
// 1. we are in a chunk that contains a crossfade.
// in this case, output is found in mixBuf by reading in mixBuf from this
// trail and applying fades, then mixing (adding) the source trail from mappedSrcBuf.
// it is possible that both fadeIn and fadeOut are contained in one chunk, hence
// the two separate if-blocks below in the main loop and the tracking of the "dry" portion
// using variables cpToMixStart and cpToMixStop. Note that we chose not the opposite
// way of mixing mixBuf to mappedSrcBuf because we might be duplicating source trail
// channels (e.g. paste mono track to stereo file)!
// 2. we are in a chunk that does not contain fades.
// in this case, we simply write mappedSrcBuf as output. we have ensured that this
// works by filling unused channels with emptyBuf.
//
// to properly deal with channel duplication, we have created a separate buffer
// srcFadeBuf that prevents the blend context from accidentally fading the
// same channel twice
for( int i = 0; i < trackMap.length; i++ ) {
if( trackMap[ i ] >= 0 ) {
if( srcBuf[ trackMap[ i ]] == null ) {
srcBuf[ trackMap[ i ]] = new float[ bufLen ];
srcUsed = true;
srcFadeBuf[ i ] = srcBuf[ trackMap[ i ]];
}
mappedSrcBuf[ i ] = srcBuf[ trackMap[ i ]];
} else {
if( empty == null ) empty = new float[ bufLen ];
mappedSrcBuf[ i ] = empty;
}
}
for( long framesWritten = 0, remaining = len; remaining > 0; ) {
chunkLen = (int) Math.min( bufLen, remaining );
if( srcUsed ) {
// newSrcStart = srcStart + chunkLen;
chunkSpan = new Span( srcStart + framesWritten, srcStart + framesWritten + chunkLen );
//System.err.println( "A srcTrail.readFrames( srcBuf, 0, " + chunkSpan + " )" );
srcTrail.readFrames( srcBuf, 0, chunkSpan ); // null channel bufs allowed!
// srcStart = newSrcStart;
if( framesWritten < preLen ) { // fade source in
//System.err.println( "A bc.fadeIn : srcFadeBuf in [ 0 ... " + ((int) Math.min( chunkLen, preLen - framesWritten )) + " ], offset = "+framesWritten );
bcPre.fadeIn( framesWritten, srcFadeBuf, 0, srcFadeBuf, 0, (int) Math.min( chunkLen, preLen - framesWritten ));
}
if( remaining - chunkLen < postLen ) { // fade source out
deltaChunk = (int) Math.max( 0, remaining - postLen ); // this is the amount of space before the actual fade begins!
chunkLen2 = chunkLen - deltaChunk;
//System.err.println( "A bc.fadeOut : srcFadeBuf in [ " + deltaChunk + " ... " + chunkLen2 + " ], offset = "+(postLen - remaining + deltaChunk) );
bcPost.fadeOut( postLen - remaining + deltaChunk, srcFadeBuf, deltaChunk, srcFadeBuf, deltaChunk, chunkLen2 );
}
}
// newInsPos = insertPos + chunkLen;
// chunkSpan = new Span( insertPos, newInsPos );
chunkSpan = new Span( insertPos + framesWritten, insertPos + framesWritten + chunkLen );
if( framesWritten < preLen ) { // fade this out
chunkLen2 = (int) Math.min( chunkLen, preLen - framesWritten );
deltaChunk = chunkLen - chunkLen2;
chunkSpan2 = deltaChunk > 0 ? chunkSpan.replaceStop( chunkSpan.stop - deltaChunk ) : chunkSpan;
//System.err.println( "B this.readFrames( mixBuf, 0, " + chunkSpan2 + " )" );
this.readFrames( mixBuf, 0, chunkSpan2 );
//System.err.println( "B bc.fadeOut : mixBuf in [ 0 ... " + chunkLen2 + " ], offset = "+framesWritten );
bcPre.fadeOut( framesWritten, mixBuf, 0, mixBuf, 0, chunkLen2 );
for( int i = 0; i < mixBuf.length; i++ ) {
if( mappedSrcBuf[ i ] != empty ) add( mixBuf[ i ], 0, mappedSrcBuf[ i ], 0, chunkLen2 );
}
cpToMixStart= chunkLen2;
cpToMixStop = chunkLen;
writeMix = true;
}
//len - framesWritten != blendLen
//framesWritten != len - blendLen;
//fadeOutPos = origInsertPos - blendLen - (len - blendLen) = origInsertPos - len
// check if after this chunk we have entered the fadein
if( remaining - chunkLen < postLen ) { // fade this in
deltaChunk = (int) Math.max( 0, remaining - postLen ); // this is the amount of space before the actual fade begins!
chunkLen2 = chunkLen - deltaChunk;
chunkSpan2 = new Span( fadeOutOffset + framesWritten + deltaChunk, fadeOutOffset + framesWritten + chunkLen );
//System.err.println( "CCC . framesWritten = "+framesWritten+"; len = "+len+"; postLen = "+postLen+"; insertPos now "+insertPos+ "; remaining = "+remaining+"; deltaChunk = "+deltaChunk+"; chunkLen2 = "+chunkLen2 );
//System.err.println( "C this.readFrames( mixBuf, " + deltaChunk + ", " + chunkSpan2 + " )" );
this.readFrames( mixBuf, deltaChunk, chunkSpan2 );
//System.err.println( "C bc.fadeIn : mixBuf in [ " + deltaChunk + " ... " + chunkLen2 + " ], offset = "+(postLen - remaining + deltaChunk) );
bcPost.fadeIn( postLen - remaining + deltaChunk, mixBuf, deltaChunk, mixBuf, deltaChunk, chunkLen2 );