<commit_before>/* SCRUB - transpose a mono input signal using sync interpolation

   p0 = output start time
   p1 = input start time
   p2 = output duration (time to end if negative)
   p3 = amplitude multiplier
   p4 = transposition factor (literal)
   p5 = sync width in samples
   p6 = sync oversampling
   p7 = input channel [optional, default is 0]
   p8 = percent to left [optional, default is .5]

   Processes only one channel at a time.

   Assumes function table 1 is amplitude curve for the note.
   You can call setline for this.

   SCRUB was written by <NAME>.  Interpolation code and most of the I/O
   was written by <NAME>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ugens.h>
#include <mixerr.h>
#include "SCRUB.h"
#include <rt.h>
#include <math.h>
#include <string.h>

#undef DEBUG
#undef DEBUG_FULL

#ifdef DEBUG
#define PRINT printf
#else
#define PRINT if (0) printf
#endif

// Set buffer segment size to a power of two to be able to test most
// efficiently for out-of-bounds conditions of the read pointer
// (cf. EnsureRawFramesIdxInbound() below).  An inbound read pointer has
// bit log (gkRingBufSegmentSize << 1) set but bit 
//        2
// log (gkRingBufSegmentSize << 2) cleared.  A pointer to the right segment,
//    2
// on the other hand, has these bits inverted, and a pointer to the left
// segment has both bits cleared.

static const int gkRingBufSegmentSize = 1024;
static const int gkOutOfBoundsTestMask = (gkRingBufSegmentSize << 1 &
					  gkRingBufSegmentSize << 2);
static const int gkOutOfBoundsLeft = 0;
static const int gkOutOfBoundsRight = gkRingBufSegmentSize << 2;

static const int gkNrRawFrames = 3 * gkRingBufSegmentSize;

static const float cpsoct10 = cpsoct(10.0);

SCRUB::SCRUB(int sincWidth, int sincOversampling) : Instrument(),
  kSincWidth(sincWidth), kSincOversampling(sincOversampling),
  pSincTable(NULL), pSincTableDiffs(NULL), fFrameCount(0), fChannels(1),
  pRawFrames(NULL), fCurRawFramesIdx(0.0f), fFileChunkStartFrame(0), fFileChunkEndFrame(0)
{
   _initialized = false;
   _startFrame = 0;
   in = NULL;
   branch = 0;
}


SCRUB::~SCRUB()
{
	delete[] pRawFrames;
	delete[] pSincTable;
	delete[] pSincTableDiffs;
	delete [] in;
}


int SCRUB::init(double p[], int n_args)
{
	float outskip, inskip, dur, dur_to_read;

	if (n_args < 5) {
	  die("SCRUB", "Wrong number of args.");
		return(DONT_SCHEDULE);
	}

	outskip = p[0];
	inskip = p[1];
	dur = p[2];
	amp = p[3];
	speed = p[4];
	if (n_args > 5)
		kSincWidth = (int) p[5];
	if (n_args > 6)
		kSincOversampling = (int) p[6];
	inchan = (n_args > 7) ? (int) p[7] : 0;
	pctleft = (n_args > 8) ? p[8] : 0.5;

	if (dur < 0.0)
	  dur = -dur - inskip;

	if (rtsetoutput(outskip, dur, this) == -1)
		return DONT_SCHEDULE;
	if (rtsetinput(inskip, this) == -1)
		return DONT_SCHEDULE;

	fChannels = inputChannels();
	
	if (inchan >= fChannels) {
		return die("SCRUB", "You asked for channel %d of a %d-channel file.",
				   inchan, fChannels);
	}
	
	_startFrame = (int) (0.5 + inskip * SR);

	amptable = floc(1);
	if (amptable) {
		int amplen = fsize(1);
		tableset(SR, dur, amplen, tabs);
	}
	else
		rtcmix_advise("SCRUB", "Setting phrase curve to all 1's.");
	aamp = amp;

	skip = (int) (SR / (float) resetval);

	return nSamps();
}

int SCRUB::configure()
{
	in = new float[inputChannels() * RTBUFSAMPS];
	int length = (int)(kSincWidth * kSincOversampling);
	pSincTable = new float[length + 1]; // store the last 0.0, too
	pSincTableDiffs = new float[length];
	if (pSincTable && pSincTableDiffs) {
		MakeSincTable();
	}
	else {
		delete [] in;
		in = NULL;
	}
	pRawFrames = new float[gkNrRawFrames * fChannels];
	return in && pRawFrames ? 0 : -1;
}

int SCRUB::run()
{
	const int frameCount = framesToRun();
	int       i, inChans = inputChannels();
	float     *outp;

	// HACK
	if (!_initialized) {
		Initialize();
		_initialized = 1;
	}
	
	outp = outbuf;               /* point to inst private out buffer */

	GetFrames(in, frameCount, speed);

	PRINT("run: writing %d frames to output\n", frameCount);
	
	for (i = 0; i < frameCount; i++) {
		if (--branch < 0) {
			double 	p[6];
			update(p, 6);
			amp = p[3];
			speed = p[4];
			if (amptable) {
#ifdef EMBEDDED
				aamp = rtcmix_table(currentFrame(), amptable, tabs) * amp;
#else
				aamp = table(currentFrame(), amptable, tabs) * amp;
#endif
			}
            else {
                aamp = amp;
            }
			branch = skip;
		}

		double newsig = in[(i * inChans) + inchan];
		outp[0] = newsig * aamp;

		if (outputchans == 2) {
			outp[1] = outp[0] * (1.0 - pctleft);
			outp[0] *= pctleft;
		}

		outp += outputchans;
		increment();
	}<commit_msg>Added dynamic pan to SCRUB.<commit_after>/* SCRUB - transpose a mono input signal using sync interpolation

   p0 = output start time
   p1 = input start time
   p2 = output duration (time to end if negative)
   p3 = amplitude multiplier
   p4 = transposition factor (literal)
   p5 = sync width in samples
   p6 = sync oversampling
   p7 = input channel [optional, default is 0]
   p8 = percent to left [optional, default is .5]

   Processes only one channel at a time.

   Assumes function table 1 is amplitude curve for the note.
   You can call setline for this.

   SCRUB was written by <NAME>.  Interpolation code and most of the I/O
   was written by <NAME>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ugens.h>
#include <mixerr.h>
#include "SCRUB.h"
#include <rt.h>
#include <math.h>
#include <string.h>

#undef DEBUG
#undef DEBUG_FULL

#ifdef DEBUG
#define PRINT printf
#else
#define PRINT if (0) printf
#endif

// Set buffer segment size to a power of two to be able to test most
// efficiently for out-of-bounds conditions of the read pointer
// (cf. EnsureRawFramesIdxInbound() below).  An inbound read pointer has
// bit log (gkRingBufSegmentSize << 1) set but bit 
//        2
// log (gkRingBufSegmentSize << 2) cleared.  A pointer to the right segment,
//    2
// on the other hand, has these bits inverted, and a pointer to the left
// segment has both bits cleared.

static const int gkRingBufSegmentSize = 1024;
static const int gkOutOfBoundsTestMask = (gkRingBufSegmentSize << 1 &
					  gkRingBufSegmentSize << 2);
static const int gkOutOfBoundsLeft = 0;
static const int gkOutOfBoundsRight = gkRingBufSegmentSize << 2;

static const int gkNrRawFrames = 3 * gkRingBufSegmentSize;

static const float cpsoct10 = cpsoct(10.0);

SCRUB::SCRUB(int sincWidth, int sincOversampling) : Instrument(),
  kSincWidth(sincWidth), kSincOversampling(sincOversampling),
  pSincTable(NULL), pSincTableDiffs(NULL), fFrameCount(0), fChannels(1),
  pRawFrames(NULL), fCurRawFramesIdx(0.0f), fFileChunkStartFrame(0), fFileChunkEndFrame(0)
{
   _initialized = false;
   _startFrame = 0;
   in = NULL;
   branch = 0;
}


SCRUB::~SCRUB()
{
	delete[] pRawFrames;
	delete[] pSincTable;
	delete[] pSincTableDiffs;
	delete [] in;
}


int SCRUB::init(double p[], int n_args)
{
	float outskip, inskip, dur, dur_to_read;

	if (n_args < 5) {
	  die("SCRUB", "Wrong number of args.");
		return(DONT_SCHEDULE);
	}

	outskip = p[0];
	inskip = p[1];
	dur = p[2];
	amp = p[3];
	speed = p[4];
	if (n_args > 5)
		kSincWidth = (int) p[5];
	if (n_args > 6)
		kSincOversampling = (int) p[6];
	inchan = (n_args > 7) ? (int) p[7] : 0;
	pctleft = (n_args > 8) ? p[8] : 0.5;

	if (dur < 0.0)
	  dur = -dur - inskip;

	if (rtsetoutput(outskip, dur, this) == -1)
		return DONT_SCHEDULE;
	if (rtsetinput(inskip, this) == -1)
		return DONT_SCHEDULE;

	fChannels = inputChannels();
	
	if (inchan >= fChannels) {
		return die("SCRUB", "You asked for channel %d of a %d-channel file.",
				   inchan, fChannels);
	}
	
	_startFrame = (int) (0.5 + inskip * SR);

	amptable = floc(1);
	if (amptable) {
		int amplen = fsize(1);
		tableset(SR, dur, amplen, tabs);
	}
	else
		rtcmix_advise("SCRUB", "Setting phrase curve to all 1's.");
	aamp = amp;

	skip = (int) (SR / (float) resetval);

	return nSamps();
}

int SCRUB::configure()
{
	in = new float[inputChannels() * RTBUFSAMPS];
	int length = (int)(kSincWidth * kSincOversampling);
	pSincTable = new float[length + 1]; // store the last 0.0, too
	pSincTableDiffs = new float[length];
	if (pSincTable && pSincTableDiffs) {
		MakeSincTable();
	}
	else {
		delete [] in;
		in = NULL;
	}
	pRawFrames = new float[gkNrRawFrames * fChannels];
	return in && pRawFrames ? 0 : -1;
}

int SCRUB::run()
{
	const int frameCount = framesToRun();
	int       i, inChans = inputChannels();
	float     *outp;

	// HACK
	if (!_initialized) {
		Initialize();
		_initialized = 1;
	}
	
	outp = outbuf;               /* point to inst private out buffer */

	GetFrames(in, frameCount, speed);

	PRINT("run: writing %d frames to output\n", frameCount);
	
	for (i = 0; i < frameCount; i++) {
		if (--branch < 0) {
			double 	p[9];
			update(p, 8);
			amp = p[3];
			speed = p[4];
            pctleft = p[8];
			if (amptable) {
#ifdef EMBEDDED
				aamp = rtcmix_table(currentFrame(), amptable, tabs) * amp;
#else
				aamp = table(currentFrame(), amptable, tabs) * amp;
#endif
			}
            else {
                aamp = amp;
            }
			branch = skip;
		}

		double newsig = in[(i * inChans) + inchan];
		outp[0] = newsig * aamp;

		if (outputchans == 2) {
			outp[1] = outp[0] * (1.0 - pctleft);
			outp[0] *= pctleft;
		}

		outp += outputchans;
		increment();
	}
{'fraction_non_alphanumeric': 0.13289783679588776, 'fraction_numerical': 0.018098093810237737, 'mean_word_length': 3.3376683697166745, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4300484', 'n_tokens_mistral': 3821, 'n_tokens_neox': 3543, 'n_words': 1048}