示例#1
0
void fill_linebrk_table(const Arg args[], const int nargs, double *array,
	const int len)
{
	double amp2 = args[0];
	int i = 0;
	for (int k = 1; k < nargs; k += 2) {
		const double amp1 = amp2;
		amp2 = args[k + 1];
		const int j = i + 1;
		i = j + (int) args[k] - 1;
		for (int l = j; l <= i; l++) {
			if (l <= len) {
				array[l - 1] = amp1
									+ (amp2 - amp1) * (double) (l - j) / (i - j + 1);
			}
			else {
				rtcmix_warn("maketable (linebrk)", "The number of points requested "
						"exceeds the table size...ignoring the excess.");
				k = nargs; // force the loop to exit
				break;
			}
		}
	}

	// fill the rest of the array with the last value if all locs weren't used
	if (i < len)
		for (int m = i; m < len; m++)
			array[m] = args[nargs - 1];

}
示例#2
0
文件: utils.cpp 项目: RTcmix/RTcmix
void
unrefHandle(Handle h)
{
#ifdef DEBUG_MEMORY
    rtcmix_print("unrefHandle(%p): %d -> %d\n", h, h->refcount, h->refcount-1);
#endif
	assert(h->refcount >= 0);
	--h->refcount;
    if (h->refcount == 0)
    {
#ifdef DEBUG_MEMORY
        rtcmix_print("\tfreeing Handle %p\n", h);
		h->refcount = 0xdeaddead;	// for debugging
#endif
		if (h->type == PFieldType) {
#ifdef DEBUG_MEMORY
			rtcmix_print("\tunrefing PField %p\n", h->ptr);
#endif
			RefCounted::unref((RefCounted *)h->ptr);
		}
		else if (h->type == InstrumentPtrType) {
#ifdef DEBUG_MEMORY
			rtcmix_print("\tnot yet unrefing inst %p\n", h->ptr);
#endif
		}
		else {
			rtcmix_warn("unrefHandle", "unrefHandle: unknown handle type!");
			return;
		}
        free(h);
    }
}	
示例#3
0
int SPECTEQ2::subinit(double p[], int n_args)
{
	int eqtablen;
	_eqtable = (double *) getPFieldTable(8, &eqtablen);
	if (!_eqtable)
		_eqconst = p[8];
	else
		_control_table_size = eqtablen;

	int len;
	double *binmaptable = (double *) getPFieldTable(11, &len);
	if (binmaptable) {
		if (len != eqtablen)
			die(instname(), "The bin-mapping table (p11) must be the same size as "
			                "the EQ table (p8).");
		set_binmap_table(binmaptable);
		if (p[9] != 0.0 || (p[10] != 0.0 || p[10] != _nyquist))
			rtcmix_warn(instname(), "Use of the bin-mapping table ignores the freq. "
			                 "range set in p9-10.");
	}

	set_ringdur(0.0f);

	return 0;
}
double
matrix(float p[], int n_args)
{
   int   i, j;
   float amp;

   amp = p[0];

   if (amp) {
	  if (n_args == 1)
	  {
	   	_Matrix_Gain = amp;
		rtcmix_advise("matrix", "Default matrix.  Gain set to %g", amp);
		return 0;
	  }
   	  else if (n_args != 145)
	  {
	  	rtcmix_warn("matrix", "Incorrect number of args.  Ignoring matrix.");
		return 0;
	  }
      /* loop for 12 by 12 args */
      for (i = 0; i < 12; i++) {
         for (j = 0; j < 12; j++) {
            _Matrix[i][j] = p[12*i+j+1] * amp;
         }
      }
      rtcmix_advise("matrix", "Loaded 12x12 values.\n");
      matrix_flag = 1;
   }
   else
      matrix_flag = 0;

   return 0.0;
}
/* ----------------------------------------------------------- rtgetsamps --- */
void
RTcmix::rtgetsamps(AudioDevice *inputDevice)
{
	assert(Option::record() == true);

#ifndef MAXMSP
	if (inputDevice->getFrames(audioin_buffer, RTBUFSAMPS) < 0)
	{
		rtcmix_warn("rtgetsamps", "%s\n", inputDevice->getLastError());
	}

#else // MAXMSP
// BGG mm
// maxmsp_inbuf is a pointer to a max/msp buffer, passed via maxmsp_rtsetparams
#ifdef IOS
	short *in = maxmsp_inbuf;
#else
	float *in = maxmsp_inbuf;
#endif

	for(int i = 0; i < RTBUFSAMPS; i++)
		for (int j = 0; j < chans(); j++)
#ifdef IOS
			audioin_buffer[j][i] = *in++;
#else
			audioin_buffer[j][i] = *in++ * IN_GAIN_FACTOR;
#endif

	return;
#endif // MAXMSP
}
示例#6
0
/* ------------------------------------------------------- parse_bus_name --- */
ErrCode
parse_bus_name(char *busname, BusType *type, int *startchan, int *endchan)
{
   char     *p;
   ErrCode  status = NO_ERR;

   if (busname == NULL)
	   status = INVAL_BUS_ERR;
   else switch (busname[0]) {
      case 'i':                                      /* "in*" */
         *type = BUS_IN;
         p = &busname[2];                            /* skip over "in" */
         status = parse_bus_chan(p, startchan, endchan);
         break;
      case 'o':                                      /* "out*" */
         *type = BUS_OUT;
         p = &busname[3];                            /* skip over "out" */
         status = parse_bus_chan(p, startchan, endchan);
         break;
      case 'a':                                      /* "aux*" */
         if (strchr(busname, 'i'))
            *type = BUS_AUX_IN;
         else if (strchr(busname, 'o'))
            *type = BUS_AUX_OUT;
         else
            return INVAL_BUS_ERR;
         p = &busname[3];                            /* skip over "aux" */
         status = parse_bus_chan(p, startchan, endchan);
         break;
	  case 'c':										 /* "chain*" */
		p = &busname[5];                            /* skip over "chain" */
		if (strchr(p, 'i'))
		   *type = BUS_NONE_IN;
		else if (strchr(p, 'o'))
		   *type = BUS_NONE_OUT;
		else
		   return INVAL_BUS_ERR;
		status = parse_bus_chan(p, startchan, endchan);
		break;
      default:
	  	 rtcmix_warn("bus_config", "Invalid bus specifier: '%s'", busname);
         return INVAL_BUS_ERR;
   }
   if (status != NO_ERR)
		rtcmix_warn("bus_config", "Invalid bus specifier: '%s'", busname);
   return status;
}
示例#7
0
int
setnote(float start, float dur, int fno)
{
	int nsamps,offset;
	int i;

	if(!isopen[fno]) {
		rtcmix_warn("setnote","You haven't opened file %d yet!\n",fno);
		closesf();
	}
	if(start > 0.) /* if start < 0 it indicates number of samples to skip*/
	        offset = (int) (start * SR() + .5) * sfchans(&sfdesc[fno])
	    		* sfclass(&sfdesc[fno]);

	else    offset = -start * sfchans(&sfdesc[fno]) * sfclass(&sfdesc[fno]);

		/* make sure it falls on channel/block boundary */
	offset -= offset % (sfchans(&sfdesc[fno]) * sfclass(&sfdesc[fno]));
	offset = (offset < 0) ? 0 : offset;

	nsamps = (dur > 0.) ? (int)((start+dur) * SR() -
	(offset/(sfchans(&sfdesc[fno])*sfclass(&sfdesc[fno])))+ .5) : (int)-dur;

	if(!istape[fno]) {
		if((filepointer[fno] = 
		   lseek(sfd[fno],offset+headersize[fno],0)) == -1) {
			rtcmix_warn("setnote", "CMIX: bad lseek in setnote\n");
			closesf();
		}
	}
	pointer[fno] = 0;

	_readit(fno);   /* read in first buffer */

	for(i=0; i<(sfchans(&sfdesc[fno]) * FLOAT); i++)
		*(peak[fno] + i) = 0;

	wipe_is_off[fno] = 1;          /* for wipeout */

	starttime[fno] = (start<0) ? -start/SR() : start;

	times(&clockin[fno]);       /* read in starting time */

	return(nsamps);
}
示例#8
0
int RTcmix::startAudio(AudioDeviceCallback renderCallback, AudioDeviceCallback doneCallback, void *inContext)
{
	rtcmix_debug(NULL, "RTcmix::startAudio entered");
	if (audioDevice && audioDevice->isOpen()) {
		// Set done callback on device.
		if (doneCallback != NULL)
			audioDevice->setStopCallback(doneCallback, inContext);
		// Start audio output device, handing it our render callback.
		if (audioDevice->start(renderCallback, inContext) != 0) {
			rtcmix_warn(NULL, "Audio device failed to start: %s", audioDevice->getLastError());
			audioDevice->close();
			return -1;
		}
		return 0;	// Playing, thru HW and/or to FILE.
	}
	rtcmix_warn(NULL, "Audio device was NULL or not open");
	return -1;
}
示例#9
0
void
_forward(int fno)     /* utility routine to forwardspace one 'record' */
{
	if((filepointer[fno] = lseek(sfd[fno],(long)nbytes,1)) < 0) {
		rtcmix_warn("CMIX", "bad forward space  in file %d\n",fno);
		perror("lseek");
		closesf();
	}
}
int MULTEQ :: init(double p[], int n_args)
{
   nargs = n_args;
   const float ringdur = 0.1;
   float outskip = p[0];
   float inskip = p[1];
   float dur = p[2];

   if (rtsetinput(inskip, this) == -1)
      return DONT_SCHEDULE;
   insamps = (int) (dur * SR + 0.5);

   if (rtsetoutput(outskip, dur + ringdur, this) == -1)
      return DONT_SCHEDULE;

   if (inputChannels() > MAXCHAN)
      return die("MULTEQ",
               "Input and output must have no more than %d channels.", MAXCHAN);
   if (outputChannels() != inputChannels())
      return die("MULTEQ", "Input and output must have same number of "
                           "channels, no more than %d.", MAXCHAN);

   if ((nargs - FIRST_BAND_PF) % BAND_PFS)
      return die("MULTEQ",
                 "For each band, need type, freq, Q, gain and bypass.");

   numbands = 0;
   int band = 0;
   for (int i = FIRST_BAND_PF; i < nargs; i += BAND_PFS, band += MAXCHAN) {
      if (numbands == MAXBAND) {
         rtcmix_warn("MULTEQ", "You can only have %d EQ bands.", MAXBAND);
         break;
      }

      OeqType type = getEQType(true, i);
      if (type == OeqInvalid)
         return die("MULTEQ", "Invalid EQ type string or code.");
      float freq = p[i + 1];
      float Q = p[i + 2];
      float gain = p[i + 3];
      bool bypass = (bool) p[i + 4];

      for (int c = 0; c < inputChannels(); c++) {
         eq[band + c] = new EQBand(SR, type, freq, Q, gain, bypass);
         if (eq[band + c] == NULL)
            return die("MULTEQ", "Can't allocate EQ band.");
      }

      numbands++;
   }

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

   return nSamps();
}
示例#11
0
void RTcmix::run()
{
	int retcode;
	if (!Option::play() && !Option::record() && rtfileit == 1) {
		/* Create scheduling/audio thread. */
		rtcmix_debug(NULL, "RTcmix::run calling runMainLoop()");
		retcode = runMainLoop();
		if (retcode != 0) {
			rtcmix_warn(NULL, "RTcmix::run: runMainLoop() failed");
		}
		else {
			/* Wait for audio thread. */
			rtcmix_debug(NULL, "RTcmix::run calling waitForMainLoop()");
			retcode = waitForMainLoop();
			if (retcode != 0) {
				rtcmix_warn(NULL, "RTcmix::run: waitForMailLoop() failed");
			}
		}
	}
}
示例#12
0
void
_backup(int fno)     /* utility routine to backspace one 'record' */
{
	if(play_is_on >= 2) return; 

	if((filepointer[fno] = lseek(sfd[fno],(long)-nbytes,SEEK_CUR)) < 0) {
		rtcmix_warn("CMIX", "bad back space in file %d\n",fno);
		perror("lseek");
		closesf();
	}
}
示例#13
0
double set_hnfactor(float *p, int n_args)
{
	if (p[0] < .01)
	{
		rtcmix_warn("set_hnfactor", "hnfactor must be greater than 0.01...ignoring");
		return hnfactor;
	}
	hnfactor = p[0];
	::rtcmix_advise("set_hnfactor", "Harmonic count factor set to %g", hnfactor);
	return p[0];
}
示例#14
0
文件: rtQueue.cpp 项目: RTcmix/RTcmix
Instrument *	RTQueue::pop(FRAMETYPE *pChunkStart)
{
	if (mInstrumentList.empty()) {
		rtcmix_warn("rtQueue", "attempt to pop empty RTQueue\n");
		return NULL;
	}
	*pChunkStart = mInstrumentList.back().first;	// frame loc
	Instrument *outInst = mInstrumentList.back().second;	// inst
	outInst->unref();
	mInstrumentList.pop_back();
	return outInst;
}
示例#15
0
文件: rtgetin.cpp 项目: eriser/RTcmix
/* Change rt input sound file position pointer, in preparation for a
   subsequent call to rtgetin.  Designed for use by instruments that
   want to reposition the input file arbitrarily (like REVMIX, which
   reads a file backwards).

   <whence> works just as in lseek: it specifies the point from which
   to move <frames> number of frames.  <frames> can be negative.
   Values of <whence> are SEEK_SET, SEEK_CUR and SEEK_END, all defined
   in <unistd.h>.

   This function doesn't actually do an lseek on the file yet -- that
   happens inside of rtgetin -- this merely updates the instrument's
   <fileOffset> for the next read.
*/
int
Instrument::rtinrepos(Instrument *inst, int frames, int whence)
{
    int   fdindex;
    off_t offset;

    fdindex = inst->_input.fdIndex;

    if (fdindex == NO_DEVICE_FDINDEX || RTcmix::isInputAudioDevice(fdindex)) {
        rtcmix_warn("rtinrepos", "request to reposition input, but input is not a file.");
        return -1;
    }

    offset = RTcmix::seekInputFile(fdindex, frames, inst->_input.inputchans, whence);

    switch (whence) {
    case SEEK_SET:
        assert(offset >= 0);
        inst->_input.fileOffset = offset;
        break;
    case SEEK_CUR:
        inst->_input.fileOffset += offset;
        break;
    case SEEK_END:
        rtcmix_warn("rtinrepos", "SEEK_END unimplemented\n");
#ifndef MAXMSP
        exit(1);
#endif
        break;
    default:
        rtcmix_warn("rtinrepos", "invalid <whence>\n");
#ifndef MAXMSP
        exit(1);
#endif
        break;
    }

    return 0;
}
示例#16
0
文件: DataSet.cpp 项目: RTcmix/RTcmix
int
DataSet::getFrame(float frameno, float *pCoeffs)
{
	int i,j;
	int frame = (int)frameno;
	float fraction = frameno - (float)frame;
	if (!((frame >= _oldframe) && (frame < _endframe))) {
		int bytesRead, framesRead = _fprec;
    	if (::lseek(_fdesc, _lpHeaderSize+(frame*_bpframe), 0) == -1)
		{
            	rtcmix_warn("LPC", "bad lseek on analysis file");
            	return(-1);
    	}
#ifdef debug
		printf("Reading frames %d - %d from file\n", frame, frame + 22);
#endif
		/* Quit if we read less than one complete frame */
    	if ((bytesRead = ::read(_fdesc, _array, _bprec)) < _bpframe)
		{
            	rtcmix_warn("LPC","reached eof on analysis file");
            	return(-1);
    	}
		framesRead = bytesRead / _bpframe;
    	_oldframe = frame;
    	_endframe = _oldframe + framesRead - 1;
	}
	for(i=(frame-_oldframe)*_framsize,j=0; j<_framsize; i++,j++) {
		float first = _array[i];
		float second = _array[i+_framsize];
		if (_swapped) {
			byte_reverse4(&first);
			byte_reverse4(&second);
		}
		pCoeffs[j] = first + fraction * (second - first);
	}
	return(0);
}
示例#17
0
文件: timeset.c 项目: RTcmix/RTcmix
/* -------------------------------------------------------------- timeset --- */
double
timeset(float p[], int n_args)
{
   if (_ntimes < TIME_ARRAY_SIZE) {
      _timepts[_ntimes] = p[0];
      _xvals[_ntimes] = p[1];
      _yvals[_ntimes] = p[2];
      _ntimes++;
   }
   else
      rtcmix_warn("MROOM", "Can only have %d timeset calls for each MROOM.",
                                                            TIME_ARRAY_SIZE);

   return 0.0;
}
示例#18
0
/* Instruments call this to set their input file pointer (like setnote in cmix).
   Returns 0 if ok, -1 if error.
*/
int
Instrument::rtsetinput(float start_time, Instrument *inst)
{
   int   auxin_count = inst->getBusSlot()->auxin_count;
   int   in_count = inst->getBusSlot()->in_count;
   const char  *inst_name = inst->name();

   if (start_time < 0.0) {
      return die(inst_name, "rtsetinput: Input skip must be >= 0.0");
   }

   if (auxin_count == 0 && in_count == 0) {
      return die(inst_name, "rtsetinput: This instrument requires input from either an in bus "
                      "or an aux bus.\nChange this with bus_config().");
   }
   else if (auxin_count > 0) {
      if (start_time != 0.0) {
         return die(inst_name, "rtsetinput: Input skip must be 0 when reading from an aux bus.");
      }
   }

   if (in_count > 0) {
      int src_chans;
	  
	  int status = RTcmix::attachInput(start_time, &inst->_input);
	  
	  switch (status) {
	  case RT_NO_INPUT_SRC:
         return die(inst_name, "No input source open for this instrument!");
      case RT_ILLEGAL_DEV_OFFSET:
         return die(inst_name, "Input start must be 0 when reading from the "
                           "real-time audio device.");
      case RT_INPUT_EOF:
         rtcmix_warn(inst_name, "Attempt to read past end of input file '%s'\n",
              RTcmix::getInputPath(inst->_input.fdIndex));
		 break;
	  case RT_INPUT_CHANS_MISMATCH:
#ifdef NOMORE // pointless ifdef IGNORE_BUS_COUNT_FOR_FILE_INPUT in InputFile.cpp
         rtcmix_advise(inst_name, INCHANS_DISCREPANCY_WARNING, inst->_input.inputchans,
                                                        src_chans, src_chans);
#endif
	  default:
	     break;
	  }
      inst->sfile_on = 1;
   }
   return 0;
}
void GVERB::doupdate()
{
	double pfs[11];

	update(pfs, 11);

	amp = pfs[3];

	if (pfs[4] != p->roomsize) {
		if (pfs[4] < 1.0 || pfs[4] > p->maxroomsize) 
			rtcmix_warn("GVERB", "bogus roomsize: %f\n", pfs[4]);
		gverb_set_roomsize(p, pfs[4]); // sets p->roomsize
	}

	if (pfs[5] != p->revtime) {
		if (pfs[5] < 0.1 || pfs[5] > 360.0)
			rtcmix_warn("GVERB", "bad revtime: %f\n", pfs[5]);
		gverb_set_revtime(p, pfs[5]);
	}

	if (pfs[6] != p->fdndamping) {
		if (pfs[6] < 0.0 || pfs[6] > 1.0)
			rtcmix_warn("GVERB", "incorrect damping: %f\n", pfs[6]);
		gverb_set_damping(p, pfs[6]);
	}

	if (pfs[7] != p->inputbandwidth) {
		if (pfs[7] < 0.0 || pfs[7] > 1.0)
			rtcmix_warn("GVERB", "input bandwith problem: %f\n", pfs[7]);
		gverb_set_inputbandwidth(p, pfs[7]);
	}

	if (DB_CO(pfs[8]) != p->drylevel) {
		if (pfs[8] < -90.0 || pfs[8] > 0.0)
			rtcmix_warn("GVERB", "dry level wrong: %f\n", pfs[8]);
		gverb_set_drylevel(p, pfs[8]);
	}

	if (DB_CO(pfs[9]) != p->earlylevel) {
		if (pfs[9] < -90.0 || pfs[9] > 0.0)
			rtcmix_warn("GVERB", "problem with early reflection level: %f\n", pfs[9]);
			gverb_set_earlylevel(p, pfs[9]);
	}

	if (DB_CO(pfs[10]) != p->taillevel) {
		if (pfs[10] < -90.0 || pfs[10] > 0.0)
			rtcmix_warn("GVERB", "bogus tail level: %f\n", pfs[10]);
		gverb_set_taillevel(p, pfs[10]);
	}
}
示例#20
0
文件: STEREO.cpp 项目: RTcmix/RTcmix
void STEREO::updatePans(double p[])
{
	const int inchans = inputChannels();
	for (int i = 0; i < inchans; i++) {
		double val = -1.0;
		if (i < outslots)
			val = p[i + MATRIX_PFIELD_OFFSET];
		if (val > 1.0) {
			if (warnInvalid) {
				rtcmix_warn("STEREO", "One or more pan values were greater than 1.");
				warnInvalid = false;
			}
			val = 1.0;
		}
		outPan[i] = val;
	}
}
示例#21
0
int 
RTcmix::registerFunction(const char *funcName, const char *dsoPath)
{
	const char *path;
	if ((path = ::getDSOPath(_functionRegistry, funcName)) == NULL) {
		FunctionEntry *newEntry = new FunctionEntry(funcName, dsoPath);
		newEntry->next = _functionRegistry;
		_functionRegistry = newEntry;
		printf("RTcmix::registerFunction: registered function '%s' for dso '%s'\n", 
				funcName, dsoPath);
		return 0;
	}
	else {
		rtcmix_warn("RTcmix::registerFunction",
			  "'%s' already registered for DSO '%s'", funcName, path);
		return -1;
	}
}
double
gen3(struct gen *gen)
{
   float val;
   int fno, i = 0;
   FILE *in_desc;

   fno = (int) gen->pvals[0];
   if (fno < 1 || fno > MAX_INFILE_DESC)
      return die("gen3", "Data file number must be between 1 and %d",
                                                             MAX_INFILE_DESC);

   in_desc = infile_desc[fno];
   if (in_desc == NULL)
      return die("gen3", "Call infile() to open the data file before using gen3.");

   /* read input file until EOF */

   while (fread(&val, sizeof(val), 1, in_desc)) {
      if (i >= gen->size)
         break;
      gen->array[i] = (double) val;
      i++;
   }
   rewind(in_desc);

   if (i > gen->size)
      rtcmix_warn("gen3", "Table not large enough to hold all the data in file.");

   rtcmix_advise("gen3", "%d values loaded into table.",
                (i <= gen->size) ? i : gen->size);

   i--;
   while (++i < gen->size)      /* fill remainder (if any) with zeros */
      gen->array[i] = 0.0;

   /* fnscl(gen); */ /* no rescaling of this gen */

   return 0.0;
}
int REVMIX::init(double p[], int n_args)
{
   nargs = n_args;

   float outskip = p[0];
   float inskip = p[1];
   float dur = p[2];
   inchan = n_args > 4 ? (int) p[4] : 0;        // default is chan 0

   if (inskip == 0)
      return die("REVMIX", "Input start time must be greater than zero.");

   if (dur > inskip) {
      rtcmix_warn("REVMIX", "Duration must be greater than input start time. "
                     "Adjusting...");
      dur = inskip;
   }

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

   if (inchan >= inputChannels())
      return die("REVMIX", "You asked for channel %d of a %d-channel file.",
                                                      inchan, inputChannels());

   amparray = floc(1);
   if (amparray) {
      int amplen = fsize(1);
      tableset(SR, dur, amplen, amptabs);
   }

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

   return nSamps();
}
int LOOP::calculateLoop(double *pArray)
{
	if (pArray[5] < 0.0) {
		_loopStart = (int) (0.5 + pArray[5] * SR);
	}
	else {
		_loopStart = (int) pArray[5];
	}
	
	float loopLength = (int) pArray[6];
	
	if (loopLength < 0.0) {
		loopLength = (int) (0.5 + loopLength * SR);
	}
	
	if (loopLength < kMinLoopLen) {
		loopLength = kMinLoopLen;
		rtcmix_warn("LOOP", "Loop length limited to %d frames", kMinLoopLen);
	}
	
	_loopEnd = _loopStart + loopLength - 1;
	
	return 0;
}
INLINE double octlet(unsigned char *let)
{
	//                    A  B   C  D  E  F  G
	int let2semitone[] = {9, 11, 0, 2, 4, 5, 7};
	int octave = -9999;
	int semitones = -9999;
	long cents = 0;
	int state = 0;

	unsigned char *p = let;
	while (*p) {
		if (*p == ' ')                // eat spaces
			p++;
		else {
			if (state == 0) {
				int index = *p - 65;    // 65 is ASCII code for 'A'
				if (index < 0 || index > 6)
					goto err;
				semitones = let2semitone[index];
				p++;
				state++;
			}
			else if (state == 1) {
				if (*p == '#') {        // sharp
					semitones++;
					p++;
				}
				else if (*p == 'b') {   // flat
					semitones--;
					p++;
				}
				else if (*p == 'x') {   // double sharp
					semitones += 2;
					p++;
				}
				state++;
			}
			else if (state == 2) {
				if (*p == 'b') {        // double flat (w/ 'b' from state 1)
					semitones--;
					p++;
				}
				state++;
			}
			else if (state == 3) {
				octave = *p - 48;       // 48 is ASCII code for '0' (zero)
				if (octave < 0 || octave > 9)
					goto err;
				octave += 4;            // ANSI octave to linoct octave
				p++;
				state++;
			}
			else {
				char *pos = NULL;
				errno = 0;
				cents = strtol((char *) p, &pos, 10);
				if (pos == (char *) p || *pos != 0 || errno == ERANGE)
					goto err;
				if (cents < -100 || cents > 100)
					goto err;
				break;
			}
		}
	}
	if (semitones > -4) {   // lowest: "Cbb4 -100" ... dbl flat -100 cents
		double frac = semitones * SEMITONE_LINOCT;
		double linoct = octave + frac;
		if (cents)
			linoct += cents * (SEMITONE_LINOCT * 0.01);
		return linoct;
	}

err:
	// NB: Avoid using die() here to simplify linking for pchcps, etc. utils
#ifdef MAXMSP
	rtcmix_warn("pitch conversion", "Invalid pitch representation \"%s\".", let);
#else
	fprintf(stderr, "Invalid pitch representation \"%s\".", let);
#endif
	return 8.00;
}
示例#26
0
off_t
_readit(int fno)
{
	int i;
	off_t n, maxread;
	short tisamp,*tibuf;
	float tfsamp,*tfbuf;

	/* check to see if we are attempting to read beyond current
	 * EOF, and if so adjust amount to be read and flush rest of buffer
	 */

	/* From make warnings */
	n=0;

	if(filepointer[fno] > originalsize[fno])
		maxread = 0;
	else if((filepointer[fno]+nbytes) > originalsize[fno]) 
		maxread = originalsize[fno]-filepointer[fno];
	else
		maxread = nbytes;
	
	if((play_is_on <  3) || (status[fno] == 0)) {
		if((n = read(sfd[fno],sndbuf[fno],maxread)) != maxread) {
			if(!n) {
				/*if(istape[fno] && n) continue;*/
				perror("read");
				rtcmix_warn("CMIX", "Bad UNIX read, nbytes = %lld\n",(long long)n);
				rtcmix_warn(NULL, " sfd[fno]= %d\n",sfd[fno]);
			        closesf();
			}
		}
	}
	if(((play_is_on==2) && !maxread) || ((play_is_on==3) && (status[fno])))
	      memset(sndbuf[fno],'\0',nbytes);  /* clean buffer out if not readin */

	/* Swap input buffer */
 	if(maxread && swap_bytes[fno]) {
		/* SHORT file */
		if(sfclass(&sfdesc[fno]) == SF_SHORT) {
			tibuf = (short *)sndbuf[fno]; 
			for (i=0;i<nbytes/SF_SHORT;i++) {
				tisamp = *(tibuf+i);
				*(tibuf+i) = reverse_int2(&tisamp);
			}
		}
		/* FLOAT file */
		if(sfclass(&sfdesc[fno]) == SF_FLOAT) {
			tfbuf = (float *)sndbuf[fno]; 
			for (i=0;i<nbytes/SF_FLOAT;i++) {
				/* byte_reverse4(tfbuf+i); */
				/* tfsamp = *(tfbuf+i); */
				/* *(tfbuf+i) = (float)reverse_int4(&tfsamp); */
				tfsamp = *(tfbuf+i);
				byte_reverse4(&tfsamp);
				*(tfbuf+i) = tfsamp;
			}
		}
	}

	/*  if we haven't read in full buffer, zero out rest of buffer,
	 *  and adjust filepointer with lseek.  Otherwise just update 
	 *  filepointer.  This will position pointer properly for any
	 *  situation.  Only a write will change physical size of file.
	 */
	if(play_is_on < 2) {        		
		if(maxread < nbytes) {
			for(n=maxread; n<nbytes; n++) *(sndbuf[fno] + n) = 0;
			filepointer[fno] = lseek(sfd[fno],(nbytes-maxread),1);
		}               
		else filepointer[fno] += nbytes;
	}
	else filepointer[fno] += nbytes;
	return(maxread ? n : maxread);
}
示例#27
0
int TRANSBEND :: init(double p[], int n_args)
{
   float outskip, inskip, dur, transp, interval = 0, total_indur, dur_to_read;
   float averageInc;
   int pgen;

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

   outskip = p[0];
   inskip = p[1];
   dur = p[2];
   amp = p[3];
   pgen = (int) p[4];
   inchan = (n_args > 5) ? (int) p[5] : 0;
   pctleft = (n_args > 6) ? p[6] : 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;

   if (inchan >= inputChannels()) {
      return die("TRANSBEND", "You asked for channel %d of a %d-channel file.",
												   inchan, inputChannels());
	}
   pitchtable = floc(pgen);
   if (pitchtable) {
      int plen = fsize(pgen);
      float isum = 0;
      for (int loc = 0; loc < plen; loc++) {
          float pch = pitchtable[loc];
	      isum += octpch(pch);
      }
      interval = isum / plen;
#ifdef DEBUG
      printf("average interval: %g\n", interval);
#endif
      tableset(SR, dur, plen, ptabs);
   }
   else {
      die("TRANSBEND", "Unable to load pitch curve (table %d)!", pgen);
		return(DONT_SCHEDULE);
	}

   averageInc = (double) cpsoct(10.0 + interval) / cpsoct(10.0);

#ifdef NOTYET
   total_indur = (float) m_DUR(NULL, 0);
   dur_to_read = dur * averageInc;
   if (inskip + dur_to_read > total_indur) {
      rtcmix_warn("TRANSBEND", "This note will read off the end of the input file.\n"
                    "You might not get the envelope decay you "
                    "expect from setline.\nReduce output duration.");
      /* no exit() */
   }
#endif

   /* total number of frames to read during life of inst */
   in_frames_left = (int) (nSamps() * averageInc + 0.5);

   /* to trigger first read in run() */
   inframe = RTBUFSAMPS;

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

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

   return nSamps();
}
示例#28
0
off_t
_writeit(int fno)
{
	int i;
	off_t n=0;
	short tisamp,*tibuf;
	float tfsamp,*tfbuf;
	float peakval;

	if(!status[fno]) {
		rtcmix_warn(NULL, "File %d is write-protected!\n",fno);
		closesf();
	}
  
#ifdef OLDRT
	/*  to play before writing */
	if((sfclass(&sfdesc[fno]) == SF_SHORT) && play_is_on)
		playbuf(sndbuf[fno],nbytes/SF_SHORT);
  
	/* swap and/or play floating point files */
	if(play_is_on && (sfclass(&sfdesc[fno]) == SF_FLOAT)) {
		peakval = getpeakval(peakflag,fno);
		playfbuf(sndbuf[fno],peakval,swap_bytes[fno],nbytes/SF_FLOAT);
	}
	else {	/* just swap if necessary */
		if(swap_bytes[fno] && (sfclass(&sfde sc[fno]) == SF_FLOAT))
		bytrev4(sndbuf[fno],nbytes);
	}
#endif

	if(swap_bytes[fno]) {
		/* SHORT file */
		if(sfclass(&sfdesc[fno]) == SF_SHORT) {
			tibuf = (short *)sndbuf[fno]; 
			for (i=0;i<nbytes/SF_SHORT;i++) {
				tisamp = *(tibuf+i);
				*(tibuf+i) = (short) reverse_int2(&tisamp);
			}
		}
		/* FLOAT file */
		if(sfclass(&sfdesc[fno]) == SF_FLOAT) {
			tfbuf = (float *)sndbuf[fno]; 
			for (i=0;i<nbytes/SF_FLOAT;i++) {
				/* byte_reverse4(tfbuf+i); */
				/* tfsamp = *(tfbuf+i); */
				/* *(tfbuf+i) = (float) reverse_int4(&tfsamp); */
				tfsamp = *(tfbuf+i);
				byte_reverse4(&tfsamp);
				*(tfbuf+i) = tfsamp;
			}
		}
	}

	if(play_is_on < 2) {
		if((n = write(sfd[fno],sndbuf[fno],nbytes)) != nbytes) {
			rtcmix_warn("CMIX", "Bad UNIX write, file %d, nbytes = %lld\n",fno,(long long)n);
			perror("write");
			closesf();
		}
		/* update output file size */
		if((filepointer[fno] += nbytes) > originalsize[fno]) 
			originalsize[fno] = filepointer[fno];
	}
  
	if(!play_is_on)
		printf(".");

	return(n);
}
示例#29
0
inline void FREEVERB :: updateRvb(double p[])
{
   if (p[4] != roomsize) {
      roomsize = p[4];
      if (roomsize < 0.0 || roomsize > max_roomsize) {
         if (warn_roomsize) {
            rtcmix_warn("FREEVERB", "Room size must be between 0 and %g. Adjusting...",
                                                                  max_roomsize);
            warn_roomsize = false;
         }
         roomsize = roomsize < 0.0 ? 0.0 : max_roomsize;
      }
      rvb->setroomsize(roomsize);
   }
   if (p[5] != predelay_time) {
      predelay_time = p[5];
      int predelay_samps = (int) ((predelay_time * SR) + 0.5);
      if (predelay_samps > max_predelay_samps) {
         if (warn_predelay) {
            rtcmix_warn("FREEVERB", "Pre-delay must be between 0 and %g seconds. "
                             "Adjusting...", (float) max_predelay_samps / SR);
            warn_predelay = false;
         }
         predelay_samps = max_predelay_samps;
      }
      rvb->setpredelay(predelay_samps);
   }
   if (p[7] != damp) {
      damp = p[7];
      if (damp < 0.0 || damp > 100.0) {
         if (warn_damp) {
            rtcmix_warn("FREEVERB", "Damp must be between 0 and 100%%. Adjusting...");
            warn_damp = false;
         }
         damp = damp < 0.0 ? 0.0 : 100.0;
      }
      rvb->setdamp(damp * 0.01);
   }
   if (p[8] != dry) {
      dry = p[8];
      if (dry < 0.0 || dry > 100.0) {
         if (warn_dry) {
            rtcmix_warn("FREEVERB", "Dry signal level must be between 0 and 100%%. "
                                                               "Adjusting...");
            warn_dry = false;
         }
         dry = dry < 0.0 ? 0.0 : 100.0;
      }
      rvb->setdry(dry * 0.01);
   }
   if (p[9] != wet) {
      wet = p[9];
      if (wet < 0.0 || wet > 100.0) {
         if (warn_wet) {
            rtcmix_warn("FREEVERB", "Wet signal level must be between 0 and 100%%. "
                                                               "Adjusting...");
            warn_wet = false;
         }
         wet = wet < 0.0 ? 0.0 : 100.0;
      }
      rvb->setwet(wet * 0.01);
   }
   if (p[10] != width) {
      width = p[10];
      if (width < 0.0 || width > 100.0) {
         if (warn_width) {
            rtcmix_warn("FREEVERB", "Width must be between 0 and 100%%. Adjusting...");
            warn_width = false;
         }
         width = width < 0.0 ? 0.0 : 100.0;
      }
      rvb->setwidth(width * 0.01);
   }
// printf("rmsz=%f, predel=%f, damp=%f, dry=%f, wet=%f, width=%f\n", roomsize, predelay_time, damp, dry, wet, width);
}
示例#30
0
/* -------------------------------------------------------------- pre_init -- */
int TVSPECTACLE :: pre_init(double p[], int n_args)
{
   wetdry = n_args > 9 ? p[9] : 1.0;            /* default is 1 */
   inchan = n_args > 10 ? (int) p[10] : 0;      /* default is chan 0 */
   pctleft = n_args > 11 ? p[11] : 0.5;         /* default is center */

   if (wetdry < 0.0 || wetdry > 1.0)
      return die(instname(), "Wet/dry must be between 0 and 1.");

   eqtableA = floc(3);
   if (eqtableA) {
      int len = fsize(3);
      eqtableA = resample_functable(eqtableA, len, half_fft_len);
   }
   else
      return die(instname(), "You haven't made EQ function A (table 3).");

   eqtableB = floc(6);
   if (eqtableB) {
      int len = fsize(6);
      eqtableB = resample_functable(eqtableB, len, half_fft_len);
   }
   else
      return die(instname(), "You haven't made EQ function B (table 6).");

   deltimetableA = floc(4);
   if (deltimetableA) {
      int len = fsize(4);
      deltimetableA = resample_functable(deltimetableA, len, half_fft_len);
   }
   else
      return die(instname(),
                        "You haven't made delay time function A (table 4).");

   deltimetableB = floc(7);
   if (deltimetableB) {
      int len = fsize(7);
      deltimetableB = resample_functable(deltimetableB, len, half_fft_len);
   }
   else
      return die(instname(),
                        "You haven't made delay time function B (table 7).");

   /* Compute maximum delay lag and create delay lines for FFT magnitude
      and phase values.  Make ringdur at least as long as the longest
      delay time.  Remember that these delays function at the decimation
      rate, not at audio rate.
   */
   maxdelsamps = (long) (MAXDELTIME * SR / decimation + 0.5);
   float maxtime = 0.0;
   for (int i = 0; i < half_fft_len; i++) {

      /* Check delay time table A. */
      float deltime = deltimetableA[i];
      if (deltime < 0.0 || deltime > MAXDELTIME)
         return die(instname(),
                    "Delay times must be >= 0 and <= %g. (The value in "
                    "table A at %d is %g.)", MAXDELTIME, i, deltime);
      float samps = deltime * SR / (float) decimation;
      assert(samps <= maxdelsamps);
      if (deltime > maxtime)
         maxtime = deltime;

      /* Check delay time table B. */
      deltime = deltimetableB[i];
      if (deltime < 0.0 || deltime > MAXDELTIME)
         return die(instname(),
                    "Delay times must be >= 0 and <= %g. (The value in "
                    "table B at %d is %g.)", MAXDELTIME, i, deltime);
      samps = deltime * SR / (float) decimation;
      assert(samps <= maxdelsamps);
      if (deltime > maxtime)
         maxtime = deltime;

      mag_delay[i] = new DLineN(maxdelsamps);
      phase_delay[i] = new DLineN(maxdelsamps);
   }
   if (ringdur < maxtime)
      ringdur = maxtime;   /* but will still cut off any trailing feedback */

   DPRINT3("decimation=%d, maxdelsamps=%ld, ringdur=%g\n",
                                 decimation, maxdelsamps, ringdur);

   feedbacktableA = floc(5);
   if (feedbacktableA) {
      int len = fsize(5);
      feedbacktableA = resample_functable(feedbacktableA, len, half_fft_len);
   }
   else
      return die(instname(),
                     "You haven't made delay feedback function A (table 5).");

   feedbacktableB = floc(8);
   if (feedbacktableB) {
      int len = fsize(8);
      feedbacktableB = resample_functable(feedbacktableB, len, half_fft_len);
   }
   else
      return die(instname(),
                     "You haven't made delay feedback function B (table 8).");

   eqcurve = floc(9);
   if (eqcurve) {
      int len = fsize(9);
      if (check_curve(eqcurve, len, 0.0, 1.0))
         rtcmix_warn(instname(), "EQ curve values must be between 0 and 1.\n"
                          "Fixing...");
      tableset(SR, inputdur + ringdur, len, eqcurvetabs);
      eq_curve_weight = eqcurve[0];
   }
   else {
      rtcmix_advise(instname(), "Setting EQ table curve to all 0's (no table 9).");
      eq_curve_weight = 0.0;
   }

   deltimecurve = floc(10);
   if (deltimecurve) {
      int len = fsize(10);
      if (check_curve(deltimecurve, len, 0.0, 1.0))
         rtcmix_warn(instname(), "Delay time curve values must be between 0 and 1.\n"
                          "Fixing...");
      tableset(SR, inputdur + ringdur, len, deltimecurvetabs);
      deltime_curve_weight = deltimecurve[0];
   }
   else {
      rtcmix_advise(instname(), "Setting EQ table curve to all 0's (no table 10).");
      deltime_curve_weight = 0.0;
   }

   feedbackcurve = floc(11);
   if (feedbackcurve) {
      int len = fsize(11);
      if (check_curve(feedbackcurve, len, 0.0, 1.0))
         rtcmix_warn(instname(), "Feedback curve values must be between 0 and 1.\n"
                          "Fixing...");
      tableset(SR, inputdur + ringdur, len, feedbackcurvetabs);
      feedback_curve_weight = feedbackcurve[0];
   }
   else {
      rtcmix_advise(instname(), "Setting EQ table curve to all 0's (no table 11).");
      feedback_curve_weight = 0.0;
   }

//printf("deltimecurvetabs: %f, %f\n", deltimecurvetabs[0], deltimecurvetabs[1]);
   return 0;
}