function DetectLoopMarkers( buffer ) {

    var nLoopStart_ = 0;
    var nLoopEnd_ = 0;
    var nMarked_ = true;

    /*
     * Length of PRE and POSTFIX Silence used in Loop Marking
     */
    var PREPOSTFIX_LEN = 5000;

    /*
     * Length of PRE and POSTFIX Silence used in Loop Marking
     */
    var DEFAULT_SAMPLING_RATE = 44100;

    /*
     * Threshold for Spike Detection in Loop Marking
     */
    var SPIKE_THRESH = 0.5;

    /*
     * Index bounds for searching for Loop Markers and Silence.
     */
    var MAX_MP3_SILENCE = 20000;

    /*
     * Threshold for Silence Detection
     */
    var SILENCE_THRESH = 0.01;

    /*
     * Length for which the channel has to be empty
     */
    var EMPTY_CHECK_LENGTH = 1024;

    /*
     * Length samples to ignore after the spike
     */
    var IGNORE_LENGTH = 16;

    /*
     * Array of all Channel Data
     */
    var channels_ = [];

    /*
     * Number of samples in the buffer
     */
    var numSamples_ = 0;

    /**
     * A helper method to help find the silence in across multiple channels
     *
     * @private
     * @method silenceCheckGenerator_
     * @param {Number} testIndex The index of the sample which is being checked.
     * @return {Function} A function which can check if the specific sample is beyond the silence threshold
     */
    var isChannelEmptyAfter = function ( channel, position ) {
        log.debug( "Checking for loop marks at " + position );
        var sum = 0;
        for ( var sIndex = position + IGNORE_LENGTH; sIndex < position + IGNORE_LENGTH + EMPTY_CHECK_LENGTH; ++sIndex ) {
            sum += Math.abs( channel[ sIndex ] );
        }

        return ( sum / EMPTY_CHECK_LENGTH ) < SILENCE_THRESH;
    };

    /**
     * A helper method to help find the spikes in across multiple channels
     *
     * @private
     * @method silenceCheckGenerator_
     * @param {Number} testIndex The index of the sample which is being checked.
     * @return {Function} A function which can check if the specific sample is beyond the spike threshold
     */
    var thresholdCheckGenerator_ = function ( testIndex ) {
        return function ( prev, thisChannel, index ) {
            var isSpike;
            if ( index % 2 === 0 ) {
                isSpike = thisChannel[ testIndex ] > SPIKE_THRESH;
            } else {
                isSpike = thisChannel[ testIndex ] < -SPIKE_THRESH;
            }
            return prev && isSpike;
        };
    };

    /**
     * A helper method to help find the markers in an Array of Float32Arrays made from an AudioBuffer.
     *
     * @private
     * @method findSilence_
     * @param {Array} channels An array of buffer data in Float32Arrays within which markers needs to be detected.
     * @return {Boolean} If Loop Markers were found.
     */
    var findMarkers_ = function ( channels ) {
        var startSpikePos = null;
        var endSpikePos = null;

        nLoopStart_ = 0;
        nLoopEnd_ = numSamples_;

        // Find marker near start of file
        var pos = 0;

        while ( startSpikePos === null && pos < numSamples_ && pos < MAX_MP3_SILENCE ) {
            if ( channels.reduce( thresholdCheckGenerator_( pos ), true ) &&
                ( channels.length !== 1 || isChannelEmptyAfter( channels[ 0 ], pos ) ) ) {
                // Only check for emptiness at the start to ensure that it's indeed marked
                startSpikePos = pos;
                break;
            } else {
                pos++;
            }
        }

        // Find marker near end of file
        pos = numSamples_;

        while ( endSpikePos === null && pos > 0 && numSamples_ - pos < MAX_MP3_SILENCE ) {
            if ( channels.reduce( thresholdCheckGenerator_( pos ), true ) ) {
                endSpikePos = pos;
                break;
            } else {
                pos--;
            }
        }
        // If both markers found
        var correctedPostfixLen = Math.round( ( PREPOSTFIX_LEN / 2 ) * buffer.sampleRate / DEFAULT_SAMPLING_RATE );
        if ( startSpikePos !== null && endSpikePos !== null && endSpikePos > startSpikePos + correctedPostfixLen ) {
            // Compute loop start and length
            nLoopStart_ = startSpikePos + correctedPostfixLen;
            nLoopEnd_ = endSpikePos - correctedPostfixLen;
            log.debug( "Found loop between " + nLoopStart_ + " - " + nLoopEnd_ );
            log.debug( "Spikes at  " + startSpikePos + " - " + endSpikePos );
            return true;
        } else {
            // Spikes not found!
            log.debug( "No loop found" );
            return false;
        }
    };

    /**
     * A helper method to help find the silence in across multiple channels
     *
     * @private
     * @method silenceCheckGenerator_
     * @param {Number} testIndex The index of the sample which is being checked.
     * @return {Function} A function which can check if the specific sample is beyond the silence threshold
     */
    var silenceCheckGenerator_ = function ( testIndex ) {
        return function ( prev, thisChannel ) {
            return prev && ( Math.abs( thisChannel[ testIndex ] ) < SILENCE_THRESH );
        };
    };

    /**
     * A helper method to help find the silence in an AudioBuffer. Used of Loop Markers are not
     * found in the AudioBuffer. Updates nLoopStart_ and nLoopEnd_ directly.
     *
     * @private
     * @method findSilence_
     * @param {Array} channels channel An array of buffer data in Float32Arrays within which silence needs to be detected.
     */
    var findSilence_ = function ( channels ) {

        var allChannelsSilent = true;

        nLoopStart_ = 0;
        while ( nLoopStart_ < MAX_MP3_SILENCE && nLoopStart_ < numSamples_ ) {

            allChannelsSilent = channels.reduce( silenceCheckGenerator_( nLoopStart_ ), true );

            if ( allChannelsSilent ) {
                nLoopStart_++;
            } else {
                break;
            }
        }

        nLoopEnd_ = numSamples_;
        while ( numSamples_ - nLoopEnd_ < MAX_MP3_SILENCE &&
            nLoopEnd_ > 0 ) {

            allChannelsSilent = channels.reduce( silenceCheckGenerator_( nLoopEnd_ ), true );

            if ( allChannelsSilent ) {
                nLoopEnd_--;
            } else {
                break;
            }
        }

        if ( nLoopEnd_ < nLoopStart_ ) {
            nLoopStart_ = 0;
        }
    };

    numSamples_ = buffer.length;
    for ( var index = 0; index < buffer.numberOfChannels; index++ ) {
        channels_.push( new Float32Array( buffer.getChannelData( index ) ) );
    }

    if ( ( !findMarkers_( channels_ ) ) ) {
        findSilence_( channels_ );
        nMarked_ = false;
    }

    // return the markers which were found
    return {
        marked: nMarked_,
        start: nLoopStart_,
        end: nLoopEnd_
    };
}
/**
/**
 *Detector for Loop Marker or Silence. This method helps to detect and trim given AudioBuffer based on Sonoport Loop Markers or based on silence detection.
 *
 *
 * @class DetectLoopMarkers
 * @param {AudioBuffer} buffer A buffer to be trimmed to Loop Markers or Silence.
 * @return {Object} An object with `start` and `end` properties containing the index of the detected start and end points.
 */
Detector for Loop Marker or Silence. This method helps to detect and trim given AudioBuffer based on Sonoport Loop Markers or based on silence detection.
@class DetectLoopMarkers
@param {AudioBuffer} buffer A buffer to be trimmed to Loop Markers or Silence.
@return {Object} An object with `start` and `end` properties containing the index of the detected start and end points.
Detector for Loop Marker or Silence . This method helps to detect and trim given AudioBuffer based on Sonoport Loop Markers or based on silence detection . @class DetectLoopMarkers @param { AudioBuffer } buffer A buffer to be trimmed to Loop Markers or Silence . @return { Object } An object with ` start ` and ` end ` properties containing the index of the detected start and end points .
function DetectLoopMarkers( buffer ) {
    var nLoopStart_ = 0;
    var nLoopEnd_ = 0;
    var nMarked_ = true;
    var PREPOSTFIX_LEN = 5000;
    var DEFAULT_SAMPLING_RATE = 44100;
    var SPIKE_THRESH = 0.5;
    var MAX_MP3_SILENCE = 20000;
    var SILENCE_THRESH = 0.01;
    var EMPTY_CHECK_LENGTH = 1024;
    var IGNORE_LENGTH = 16;
    var channels_ = [];
    var numSamples_ = 0;
    var isChannelEmptyAfter = function ( channel, position ) {
        log.debug( "Checking for loop marks at " + position );
        var sum = 0;
        for ( var sIndex = position + IGNORE_LENGTH; sIndex < position + IGNORE_LENGTH + EMPTY_CHECK_LENGTH; ++sIndex ) {
            sum += Math.abs( channel[ sIndex ] );
        }
        return ( sum / EMPTY_CHECK_LENGTH ) < SILENCE_THRESH;
    };
    var thresholdCheckGenerator_ = function ( testIndex ) {
        return function ( prev, thisChannel, index ) {
            var isSpike;
            if ( index % 2 === 0 ) {
                isSpike = thisChannel[ testIndex ] > SPIKE_THRESH;
            } else {
                isSpike = thisChannel[ testIndex ] < -SPIKE_THRESH;
            }
            return prev && isSpike;
        };
    };
    var findMarkers_ = function ( channels ) {
        var startSpikePos = null;
        var endSpikePos = null;
        nLoopStart_ = 0;
        nLoopEnd_ = numSamples_;
        var pos = 0;
        while ( startSpikePos === null && pos < numSamples_ && pos < MAX_MP3_SILENCE ) {
            if ( channels.reduce( thresholdCheckGenerator_( pos ), true ) &&
                ( channels.length !== 1 || isChannelEmptyAfter( channels[ 0 ], pos ) ) ) {
                startSpikePos = pos;
                break;
            } else {
                pos++;
            }
        }
        pos = numSamples_;
        while ( endSpikePos === null && pos > 0 && numSamples_ - pos < MAX_MP3_SILENCE ) {
            if ( channels.reduce( thresholdCheckGenerator_( pos ), true ) ) {
                endSpikePos = pos;
                break;
            } else {
                pos--;
            }
        }
        var correctedPostfixLen = Math.round( ( PREPOSTFIX_LEN / 2 ) * buffer.sampleRate / DEFAULT_SAMPLING_RATE );
        if ( startSpikePos !== null && endSpikePos !== null && endSpikePos > startSpikePos + correctedPostfixLen ) {
            nLoopStart_ = startSpikePos + correctedPostfixLen;
            nLoopEnd_ = endSpikePos - correctedPostfixLen;
            log.debug( "Found loop between " + nLoopStart_ + " - " + nLoopEnd_ );
            log.debug( "Spikes at  " + startSpikePos + " - " + endSpikePos );
            return true;
        } else {
            log.debug( "No loop found" );
            return false;
        }
    };
    var silenceCheckGenerator_ = function ( testIndex ) {
        return function ( prev, thisChannel ) {
            return prev && ( Math.abs( thisChannel[ testIndex ] ) < SILENCE_THRESH );
        };
    };
    var findSilence_ = function ( channels ) {
        var allChannelsSilent = true;
        nLoopStart_ = 0;
        while ( nLoopStart_ < MAX_MP3_SILENCE && nLoopStart_ < numSamples_ ) {
            allChannelsSilent = channels.reduce( silenceCheckGenerator_( nLoopStart_ ), true );
            if ( allChannelsSilent ) {
                nLoopStart_++;
            } else {
                break;
            }
        }
        nLoopEnd_ = numSamples_;
        while ( numSamples_ - nLoopEnd_ < MAX_MP3_SILENCE &&
            nLoopEnd_ > 0 ) {
            allChannelsSilent = channels.reduce( silenceCheckGenerator_( nLoopEnd_ ), true );
            if ( allChannelsSilent ) {
                nLoopEnd_--;
            } else {
                break;
            }
        }
        if ( nLoopEnd_ < nLoopStart_ ) {
            nLoopStart_ = 0;
        }
    };
    numSamples_ = buffer.length;
    for ( var index = 0; index < buffer.numberOfChannels; index++ ) {
        channels_.push( new Float32Array( buffer.getChannelData( index ) ) );
    }
    if ( ( !findMarkers_( channels_ ) ) ) {
        findSilence_( channels_ );
        nMarked_ = false;
    }
    return {
        marked: nMarked_,
        start: nLoopStart_,
        end: nLoopEnd_
    };
}
function DetectLoopMarkers ( buffer ) { var nLoopStart_ = 0 ; var nLoopEnd_ = 0 ; var nMarked_ = true ; var PREPOSTFIX_LEN = 5000 ; var DEFAULT_SAMPLING_RATE = 44100 ; var SPIKE_THRESH = 0.5 ; var MAX_MP3_SILENCE = 20000 ; var SILENCE_THRESH = 0.01 ; var EMPTY_CHECK_LENGTH = 1024 ; var IGNORE_LENGTH = 16 ; var channels_ = [ ] ; var numSamples_ = 0 ; var isChannelEmptyAfter = function ( channel , position ) { log . debug ( "Checking for loop marks at " + position ) ; var sum = 0 ; for ( var sIndex = position + IGNORE_LENGTH ; sIndex < position + IGNORE_LENGTH + EMPTY_CHECK_LENGTH ; ++ sIndex ) { sum += Math . abs ( channel [ sIndex ] ) ; } return ( sum / EMPTY_CHECK_LENGTH ) < SILENCE_THRESH ; } ; var thresholdCheckGenerator_ = function ( testIndex ) { return function ( prev , thisChannel , index ) { var isSpike ; if ( index % 2 === 0 ) { isSpike = thisChannel [ testIndex ] > SPIKE_THRESH ; } else { isSpike = thisChannel [ testIndex ] < - SPIKE_THRESH ; } return prev && isSpike ; } ; } ; var findMarkers_ = function ( channels ) { var startSpikePos = null ; var endSpikePos = null ; nLoopStart_ = 0 ; nLoopEnd_ = numSamples_ ; var pos = 0 ; while ( startSpikePos === null && pos < numSamples_ && pos < MAX_MP3_SILENCE ) { if ( channels . reduce ( thresholdCheckGenerator_ ( pos ) , true ) && ( channels . length !== 1 || isChannelEmptyAfter ( channels [ 0 ] , pos ) ) ) { startSpikePos = pos ; break ; } else { pos ++ ; } } pos = numSamples_ ; while ( endSpikePos === null && pos > 0 && numSamples_ - pos < MAX_MP3_SILENCE ) { if ( channels . reduce ( thresholdCheckGenerator_ ( pos ) , true ) ) { endSpikePos = pos ; break ; } else { pos -- ; } } var correctedPostfixLen = Math . round ( ( PREPOSTFIX_LEN / 2 ) * buffer . sampleRate / DEFAULT_SAMPLING_RATE ) ; if ( startSpikePos !== null && endSpikePos !== null && endSpikePos > startSpikePos + correctedPostfixLen ) { nLoopStart_ = startSpikePos + correctedPostfixLen ; nLoopEnd_ = endSpikePos - correctedPostfixLen ; log . debug ( "Found loop between " + nLoopStart_ + " - " + nLoopEnd_ ) ; log . debug ( "Spikes at  " + startSpikePos + " - " + endSpikePos ) ; return true ; } else { log . debug ( "No loop found" ) ; return false ; } } ; var silenceCheckGenerator_ = function ( testIndex ) { return function ( prev , thisChannel ) { return prev && ( Math . abs ( thisChannel [ testIndex ] ) < SILENCE_THRESH ) ; } ; } ; var findSilence_ = function ( channels ) { var allChannelsSilent = true ; nLoopStart_ = 0 ; while ( nLoopStart_ < MAX_MP3_SILENCE && nLoopStart_ < numSamples_ ) { allChannelsSilent = channels . reduce ( silenceCheckGenerator_ ( nLoopStart_ ) , true ) ; if ( allChannelsSilent ) { nLoopStart_ ++ ; } else { break ; } } nLoopEnd_ = numSamples_ ; while ( numSamples_ - nLoopEnd_ < MAX_MP3_SILENCE && nLoopEnd_ > 0 ) { allChannelsSilent = channels . reduce ( silenceCheckGenerator_ ( nLoopEnd_ ) , true ) ; if ( allChannelsSilent ) { nLoopEnd_ -- ; } else { break ; } } if ( nLoopEnd_ < nLoopStart_ ) { nLoopStart_ = 0 ; } } ; numSamples_ = buffer . length ; for ( var index = 0 ; index < buffer . numberOfChannels ; index ++ ) { channels_ . push ( new Float32Array ( buffer . getChannelData ( index ) ) ) ; } if ( ( ! findMarkers_ ( channels_ ) ) ) { findSilence_ ( channels_ ) ; nMarked_ = false ; } return { marked : nMarked_ , start : nLoopStart_ , end : nLoopEnd_ } ; }
Detector for Loop Marker or Silence.
Detector for Loop Marker or Silence .
/*
     * Length of PRE and POSTFIX Silence used in Loop Marking
     */ /*
     * Length of PRE and POSTFIX Silence used in Loop Marking
     */ /*
     * Threshold for Spike Detection in Loop Marking
     */ /*
     * Index bounds for searching for Loop Markers and Silence.
     */ /*
     * Threshold for Silence Detection
     */ /*
     * Length for which the channel has to be empty
     */ /*
     * Length samples to ignore after the spike
     */ /*
     * Array of all Channel Data
     */ /*
     * Number of samples in the buffer
     */ /**
     * A helper method to help find the silence in across multiple channels
     *
     * @private
     * @method silenceCheckGenerator_
     * @param {Number} testIndex The index of the sample which is being checked.
     * @return {Function} A function which can check if the specific sample is beyond the silence threshold
     */ /**
     * A helper method to help find the spikes in across multiple channels
     *
     * @private
     * @method silenceCheckGenerator_
     * @param {Number} testIndex The index of the sample which is being checked.
     * @return {Function} A function which can check if the specific sample is beyond the spike threshold
     */ /**
     * A helper method to help find the markers in an Array of Float32Arrays made from an AudioBuffer.
     *
     * @private
     * @method findSilence_
     * @param {Array} channels An array of buffer data in Float32Arrays within which markers needs to be detected.
     * @return {Boolean} If Loop Markers were found.
     */ // Find marker near start of file // Only check for emptiness at the start to ensure that it's indeed marked // Find marker near end of file // If both markers found // Compute loop start and length // Spikes not found! /**
     * A helper method to help find the silence in across multiple channels
     *
     * @private
     * @method silenceCheckGenerator_
     * @param {Number} testIndex The index of the sample which is being checked.
     * @return {Function} A function which can check if the specific sample is beyond the silence threshold
     */ /**
     * A helper method to help find the silence in an AudioBuffer. Used of Loop Markers are not
     * found in the AudioBuffer. Updates nLoopStart_ and nLoopEnd_ directly.
     *
     * @private
     * @method findSilence_
     * @param {Array} channels channel An array of buffer data in Float32Arrays within which silence needs to be detected.
     */ // return the markers which were found