Ejemplo n.º 1
0
/* Send the contents of a makegen array to standard out or to an ASCII file.

   fdump(gennum [, "filename"])

   JGG, 2/13/02
*/
double
fdump(float p[], short n_args, double pp[])
{
   int   genslot;
   double *array;
   FILE  *f = NULL;

   genslot = p[0];
   if (n_args > 1) {
      char *fname = DOUBLE_TO_STRING(pp[1]);
      f = fopen(fname, "w+");
      if (f == NULL) {
         perror("fdump");
         return -1.0;
      }
   }
   else
      f = stdout;

   array = floc(genslot);
   if (array) {
      int i, len = fsize(genslot);
      printf("Dumping function table %d...\n", genslot);
      for (i = 0; i < len; i++)
         fprintf(f, "%d %.6f\n", i, array[i]);
   }
   else
      die(NULL, "You must make a gen before dumping it!");

   if (f != stdout)
      fclose(f);

   return 0.0;
}
Ejemplo n.º 2
0
/* Assemble path to the shared library, and pass back as <dsoPath>. */
static int
get_dso_path(double pfield, char dsoPath[])
{
    char *str;
#ifdef SHAREDLIBDIR
    const char *directory = SHAREDLIBDIR;
#else
    const char *directory = "/musr/lib";
#endif

    /* cast double to string pointer */
    str = DOUBLE_TO_STRING(pfield);

    if (!str || strlen(str) == 0) {
		die("load", "Bad argument for p[0]!");
		return -1;
    }
    /* if name contains a '/', assume it is a full or relative path */
    if (strchr(str, '/'))
		strcpy(dsoPath, str);
    /* if name does not start with "lib", add prefix and suffix */
    else if (strncmp(str, "lib", 3))
		sprintf(dsoPath, "%s/lib%s.so", directory, str);
    /* otherwise just prepend directory and use as is */
    else
		sprintf(dsoPath, "%s/%s", directory, str);

    return 0;
}
Ejemplo n.º 3
0
double dataset(float *p, int n_args, double *pp)
/* p1=dataset name, p2=npoles */
{
	int i, set;
	char *name=DOUBLE_TO_STRING(pp[0]);

	if (name == NULL) {
		rterror("dataset", "NULL file name");
		return -1;
	}

	// Search all open dataset slots for matching name
	for (set = 0; set < maxDataSets && strlen(g_dataset_names[set]); ++set) {
		if (strcmp(name, g_dataset_names[set]) == 0) {
			g_currentDataset = set;
			::rtcmix_advise("dataset", "Using already open dataset at slot %d", set);
			return g_datasets[g_currentDataset]->getFrameCount();
		}
	}
	if (set >= maxDataSets) {
		::rterror("dataset", "Maximum number of datasets exceeded");
		return -1;
	}

	// OK, this is a new set that we will put in a new slot

	g_currentDataset = set;

	strcpy(g_dataset_names[g_currentDataset],name);

	int npolesGuess = 0;
	if(n_args>1)	/* if no npoles specified, it will be retrieved from */
		npolesGuess= (int) p[1];	/* the header (if USE_HEADERS #defined) */

	DataSet *dataSet = new DataSet;
	
	int frms = dataSet->open(name, npolesGuess, RTcmix::sr());
	
	if (frms < 0)
	{
		if (dataSet->getNPoles() == 0) {
			::rterror("dataset",
				"For this file, you must specify the correct value for npoles in p[1].");
		}
		return -1;
	}

	::rtcmix_advise("dataset", "File has %d poles and %d frames.",
			dataSet->getNPoles(), frms);
	
	// Add to dataset list.
	g_datasets[g_currentDataset] = dataSet;

	dataSet->ref();	// Note:  For now, datasets are never destroyed during run.

	return (double) frms;
}
Ejemplo n.º 4
0
//--------------------------------------------------------------- set_option ---
double RTcmix::set_option(float *p, int nargs, double pp[])
{
	for (int i = 0; i < nargs; i++) {
		char *arg = DOUBLE_TO_STRING(pp[i]);		// cast pfield to string

		if (_parse_arg(arg, rtsetparams_was_called()) == -1)
			return -1.0;
	}
	return 0.0;
}
Ejemplo n.º 5
0
/* Return the passed in (double) argument as a string type.
 */
MincString
_minc_tostring(const MincValue args[], const int nargs)
{
	if (nargs != 1) {
		minc_warn("tostring: must have one argument");
		return NULL;
	}
	if (args[0].dataType() != MincFloatType) {
		minc_warn("tostring: argument must be float type");
		return NULL;
	}
	const char *convertedString = DOUBLE_TO_STRING((MincString)args[0]);
	return strdup(convertedString);
}
Ejemplo n.º 6
0
  /**
   * These pfields are standard for LUAINST instruments:
   * p0 = Lua instrument name (string, all others are doubles).
   * p1 = Output start time (outskip).
   * p2 = Input start time (inskip, must be zero if there is no input).
   * p3 = Duration.
   * p4 = Amplitude.
   * pN = User-defined optional parameters.
   */
  virtual int init(double *parameters, int parameterCount)
  {
    state.name = strdup(DOUBLE_TO_STRING(parameters[0]));
    state.parameters = new double[parameterCount];
    state.parameterCount = parameterCount;
    for (int parameterI = 0; parameterI < parameterCount; ++parameterI) 
      {
	state.parameters[parameterI] = parameters[parameterI];
      }
    if (rtsetoutput((float) parameters[1], (float) parameters[3], this) == -1) 
      {
	return DONT_SCHEDULE;
      }
    if (parameters[2] != 0.0) 
      {
	if (rtsetinput(parameters[1], this) == -1) {
	  return DONT_SCHEDULE;
	}
	state.inputChannelCount = inputChannels();
      }
    state.outputChannelCount = outputChannels();
    return nSamps();
  }
Ejemplo n.º 7
0
double
m_infile(float *p, short n_args, double *pp)
{
    FILE *descrip;
    char  *name;
    int   fno;

    name = DOUBLE_TO_STRING(pp[0]);
    fno = p[1];
    /* Reject fno = 0, because that's indicates stdin to gen2. */
    if (fno < 1 || fno > MAX_INFILE_DESC)
        return die("infile", "File number must be between 1 and %d.",
                   MAX_INFILE_DESC);

    descrip = fopen(name,"r");
    if (descrip == NULL)
        return die("infile", "Cannot find %s ... not opened.", name);
    else {
        infile_desc[fno] = descrip;
        rtcmix_advise("infile", "Datafile %s opened as file %d.", name, fno);
    }
    return fno;
}
Ejemplo n.º 8
0
 double lua_intro(float *p, int n, double *pp)
 {
   const char *NAME = DOUBLE_TO_STRING(pp[0]);
   const char *luacode = DOUBLE_TO_STRING(pp[1]);
   return (double) LUA_INTRO(NAME, luacode);
 }
Ejemplo n.º 9
0
/* ----------------------------------------------------------- bus_config --- */
double 
RTcmix::bus_config(float p[], int n_args, double pp[])
{
   ErrCode     err;
   int         i, j, k, startchan, endchan;
   char        *str, *instname, *busname;
   BusType     type;
   BusSlot     *bus_slot;
   char		   inbusses[80], outbusses[80];	// for verbose message

   if (n_args < 2)
      die("bus_config", "Wrong number of args.");

   bus_slot = new BusSlot;
   if (bus_slot == NULL)
      return -1.0;

   inbusses[0] = outbusses[0] = '\0';
   
   Lock localLock(&bus_slot_lock);	// This will unlock when going out of scope.

   /* do the old Minc casting rigamarole to get string pointers from a double */
   str = DOUBLE_TO_STRING(pp[0]);
   instname = strdup(str);	// Note:  If we exit nonfatally, we have to free.

   for (i = 1; i < n_args; i++) {
      busname = DOUBLE_TO_STRING(pp[i]);
      err = parse_bus_name(busname, &type, &startchan, &endchan);
      if (err)
         goto error;

      switch (type) {
         case BUS_IN:
			if (bus_slot->in_count > 0) strcat(inbusses, ", ");
			strcat(inbusses, busname);
            if (bus_slot->auxin_count > 0) {
                die("bus_config",
                      "Can't have 'in' and 'aux-in' buses in same bus_config.");
            }
            j = bus_slot->in_count;
            for (k = startchan; k <= endchan; k++)
               bus_slot->in[j++] = k;
            bus_slot->in_count += (endchan - startchan) + 1;
			/* Make sure max channel count set in rtsetparams can accommodate
               the highest input chan number in this bus config.
			*/
			if (endchan >= NCHANS) {
				die("bus_config", "You specified %d channels in rtsetparams,\n"
					"but this bus_config requires %d channels.",
					NCHANS, endchan + 1);
			}
			break;
			case BUS_OUT:
			if (bus_slot->out_count > 0) strcat(outbusses, ", ");
			strcat(outbusses, busname);
            if (bus_slot->auxout_count > 0) {
                die("bus_config",
                    "Can't have 'out' and 'aux-out' buses in same bus_config.");
            }
            j = bus_slot->out_count;
            for (k = startchan; k <= endchan; k++) {
               bus_slot->out[j++] = k;
			   pthread_mutex_lock(&out_in_use_lock);
               OutInUse[k] = YES;  // DJT added
			   pthread_mutex_unlock(&out_in_use_lock);
            }
            bus_slot->out_count += (endchan - startchan) + 1;

            /* Make sure max output chans set in rtsetparams can accommodate
               the highest output chan number in this bus config.
            */
            if (endchan >= NCHANS) {
               die("bus_config", "You specified %d output channels in rtsetparams,\n"
                         "but this bus_config requires %d channels.",
                         NCHANS, endchan + 1);
            }
            break;
         case BUS_AUX_IN:
			if (bus_slot->auxin_count > 0) strcat(inbusses, ", ");
			strcat(inbusses, busname);
            if (bus_slot->in_count > 0) {
                die("bus_config",
                      "Can't have 'in' and 'aux-in' buses in same bus_config.");
            }
            j = bus_slot->auxin_count;
            for (k = startchan; k <= endchan; k++)
               bus_slot->auxin[j++] = k;
            bus_slot->auxin_count += (endchan - startchan) + 1;
            break;
         case BUS_AUX_OUT:
			if (bus_slot->auxout_count > 0) strcat(outbusses, ", ");
			strcat(outbusses, busname);
            if (bus_slot->out_count > 0) {
                die("bus_config",
                    "Can't have 'out' and 'aux-out' buses in same bus_config.");
            }
            j = bus_slot->auxout_count;
            for (k = startchan; k <= endchan; k++) {
               bus_slot->auxout[j++] = k;
			   pthread_mutex_lock(&aux_out_in_use_lock);
               AuxOutInUse[k] = YES;
			   pthread_mutex_unlock(&aux_out_in_use_lock);
            }
            bus_slot->auxout_count += (endchan - startchan) + 1;
            break;
		 default:
		 	break;
      }
   }

   err = check_bus_inst_config(bus_slot, YES);
   if (!err) {
      err = insert_bus_slot(instname, bus_slot);
   }
   if (err)
// BGG mm -- print an error, don't exit
		die("bus_config", "couldn't configure the busses");
//      exit(1);        /* This is probably what user wants? */

   /* Make sure specified aux buses have buffers allocated. */
   for (i = 0; i < bus_slot->auxin_count; i++)
      allocate_aux_buffer(bus_slot->auxin[i], RTBUFSAMPS);
   for (i = 0; i < bus_slot->auxout_count; i++)
      allocate_aux_buffer(bus_slot->auxout[i], RTBUFSAMPS);


#ifdef PRINTALL
   print_children();
   print_parents();
#endif
   create_play_order();
#ifdef PRINTPLAY
   print_play_order();
#endif
#ifdef DEBUG
   err = print_inst_bus_config();
#endif

   rtcmix_advise("bus_config", "(%s) => %s => (%s)", inbusses, instname, outbusses);
   free(instname);
   return 0.0;

 error:
   free(instname);
   die("bus_config", "Cannot parse arguments.");
   return -1.0;
}
Ejemplo n.º 10
0
double m_open(float *p, short n_args, double *pp) 
{
	char  *name,*cp,*getsfcode();
	int   fno,i,inew;
	float *opk;

	name = DOUBLE_TO_STRING(pp[0]);
	fno = p[1];
// JGG: will name ptr be valid for entire program run? Is its memory held by
// parser? If not, we should malloc sfname[fno] below (with other mallocs)
	sfname[fno] = name;
	status[fno] = (n_args == 3) ? (int)p[2] : 2;

	if((fno >=  NFILES) || (fno < 0)) {
		rtcmix_warn("m_open", "Only %d files allowed\n", NFILES);
		closesf();
		}
	inew = 0;
	if(isopen[fno]) {
		close(sfd[fno]);
	}
	else inew = 1;

	istape[fno] = (n_args == 4) ? 1 : 0;
			/* in the case of a tape, there will be a 
			   4th argument listing the file number */

	rwopensf(name,sfd[fno],sfdesc[fno],sfst[fno],"CMIX",i,status[fno]);
	if (i < 0)
		closesf();

	if (status[fno] == O_RDWR
			&& !WRITEABLE_HEADER_TYPE(sfheadertype(&sfdesc[fno]))) {
		rtcmix_warn("m_open", "can't write this type of header.\n");
		closesf();
	}

	isopen[fno] = 1;

	swap_bytes[fno] = swap;  /* swap and isNext set in rwopensf */
	is_Next[fno] = isNext;
	headersize[fno] = getheadersize(&sfdesc[fno]);

	rtcmix_advise(NULL, "name: %s   sr: %.3f  nchans: %d  class: %d\n",name,
		sfsrate(&sfdesc[fno]),sfchans(&sfdesc[fno]), sfclass(&sfdesc[fno]));
	rtcmix_advise(NULL, "Soundfile type: %s\n",
			mus_header_type_name(sfheadertype(&sfdesc[fno])));
	rtcmix_advise(NULL, "   data format: %s\n",
			mus_data_format_name(sfdataformat(&sfdesc[fno])));
	rtcmix_advise(NULL, "Duration of file is %f seconds.\n",
		(float)(sfst[fno].st_size - headersize[fno])/(float)sfclass(&sfdesc[fno])/(float)sfchans(&sfdesc[fno])/sfsrate(&sfdesc[fno]));

	originalsize[fno] = istape[fno] ? 999999999 : sfst[fno].st_size;
	/*
	sfstats(sfd[fno]);
	*/
	if(inew) {
		if((sndbuf[fno] = (char *)malloc((unsigned)nbytes)) == NULL) {
			rtcmix_warn("CMIX", "malloc sound buffer error\n");
			closesf();
		}
		if((peakloc[fno] = (char *)malloc((unsigned)(sfchans(&sfdesc[fno]) * 
			LONG))) == NULL) {
			rtcmix_warn("CMIX", "malloc ovpeak buffer error\n");
			closesf();
		}
		if((peak[fno] = 
			(char *)malloc((unsigned)(sfchans(&sfdesc[fno])* FLOAT))) 
			== NULL) {
			rtcmix_warn("CMIX", "malloc peak buffer error!\n");
			closesf();
		}
		peakoff[fno] = 0; /* default to peakcheckon when opening file*/
		punch[fno] = 0; /* default to no punch when opening file*/
	}
	if(sfclass(&sfdesc[fno]) == SHORT) {
		addoutpointer[fno] = _iaddout;
		layoutpointer[fno] = _ilayout;
		wipeoutpointer[fno] = _iwipeout;
		getinpointer[fno] = _igetin;
	}
	else 			        {   
		addoutpointer[fno] = _faddout;
		layoutpointer[fno] = _flayout;
		wipeoutpointer[fno] = _fwipeout;
		getinpointer[fno] = _fgetin;
	}

	if(!SR()) set_SR(sfsrate(&sfdesc[fno]));	

	if(sfsrate(&sfdesc[fno])!= SR())
		rtcmix_advise("CMIX", "Note--> SR reset to %f\n",SR());

	/* read in former peak amplitudes, make sure zero'ed out to start.*/

	/* In the sndlib version, we store peak stats differently. See
	   comments in sndlibsupport.c for an explanation. The sndlib
	   version of rwopensf reads peak stats, so here we just have to
	   copy these into the sfm[fno] array. (No swapping necessary.)
	*/
	memcpy(&sfm[fno], &(sfmaxampstruct(&sfdesc[fno])), sizeof(SFMAXAMP));

	for(opk = (float *)peak[fno], i = 0; i<sfchans(&sfdesc[fno]); i++) 
		*(opk+i) = sfmaxamp(&sfm[fno],i);
	bufsize[fno] = nbytes / sfclass(&sfdesc[fno]);/* set size in words */

	return 0.0;
}
/* -------------------------------------------------- parse_rtoutput_args --- */
int
RTcmix::parse_rtoutput_args(int nargs, double pp[])
{
   int   i, j, matched;
   int   normfloat_requested;
   char  *arg;

   if (nargs == 0) {
      rterror("rtoutput", "you didn't specify a file name!");
      return -1;
   }

   rtoutsfname = DOUBLE_TO_STRING(pp[0]);
   if (rtoutsfname == NULL)
   {
      rterror("rtoutput", "NULL file name!");
      return -1;
   }

   output_header_type = header_type_from_filename(rtoutsfname);
   if (output_header_type == -1)
      return -1;
   if (output_header_type == -2)
      output_header_type = DEFAULT_HEADER_TYPE;
   output_data_format = DEFAULT_DATA_FORMAT;

   normfloat_requested = 0;

   for (i = 1; i < nargs; i++) {
      arg = DOUBLE_TO_STRING(pp[i]);

      matched = 0;
      for (j = 0; j < num_params; j++) {
         if (strcasecmp(param_list[j].arg, arg) == 0) {
            matched = 1;
            break;
         }
      }
      if (!matched) {
         rterror("rtoutput", "unrecognized argument \"%s\"", arg);
         return -1;
      }

      switch (param_list[j].type) {
         case HEADER_TYPE:
            output_header_type = param_list[j].value;
            break;
         case DATA_FORMAT:
            output_data_format = param_list[j].value;
            if (output_data_format == MUS_BFLOAT
                           && strcasecmp(param_list[j].arg, "normfloat") == 0)
               normfloat_requested = 1;
            break;
         case ENDIANNESS:  /* currently unused */
            break;
         default:
            break;
      }
   }

   /* Handle some special cases. */

   /* If "wav", make data format little-endian. */
   if (output_header_type == MUS_RIFF) {
      switch (output_data_format) {
         case MUS_BSHORT:
            output_data_format = MUS_LSHORT;
            break;
         case MUS_B24INT:
            output_data_format = MUS_L24INT;
            break;
         case MUS_BFLOAT:
            output_data_format = MUS_LFLOAT;
            break;
      }
   }

   /* If AIFF, use AIFC only if explicitly requested, or if
      the data format is float.
   */
   if (output_header_type == MUS_AIFF && output_data_format == MUS_BFLOAT)
      output_header_type = MUS_AIFC;

   /* If writing to a float file, decide whether to normalize the
      samples, i.e., to divide them all by 32768 so as to make the
      normal range fall between -1.0 and +1.0. This is what Snd
      and sndlib like to see, but it's not the old cmix way.
   */
   if (normfloat_requested)
      normalize_output_floats = 1;

   is_float_format = IS_FLOAT_FORMAT(output_data_format);

#ifdef ALLBUG
   fprintf(stderr, "name: %s, head: %d, data: %d, norm: %d\n",
                   rtoutsfname, output_header_type, output_data_format,
                   normalize_output_floats);
#endif

   return 0;
}
Ejemplo n.º 12
0
double
RTcmix::rtinput(float p[], int n_args, double pp[])
{
	int            audio_in, p1_is_audioport, start_pfield, fd;
	int            is_open, header_type, data_format, data_location, nchans;
#ifdef INPUT_BUS_SUPPORT
	int            startchan, endchan;
	short          busindex, buslist[MAXBUS];
	BusType        type;
#endif /* INPUT_BUS_SUPPORT */
	double         srate, dur;
	char           *sfname, *str;
	AudioPortType  port_type = MIC;

	header_type = MUS_UNSUPPORTED;
	data_format = MUS_UNSUPPORTED;
	data_location = 0;
	dur = 0.0;

	audio_in = 0;
	p1_is_audioport = 0;
	is_open = 0;

	sfname = DOUBLE_TO_STRING(pp[0]);

	/* Catch stoopid NULL filenames */
	if (sfname == NULL) {
		rterror("rtinput", "NULL filename!");
		return -1;
	}

	if (strcmp(sfname, "AUDIO") == 0) {
		audio_in = 1;

		if (n_args > 1 && pp[1] != 0.0) {
			p1_is_audioport = 1;
			str = DOUBLE_TO_STRING(pp[1]);
			if (strcmp(str, "MIC") == 0)
				port_type = MIC;
			else if (strcmp(str, "LINE") == 0)
				port_type = LINE;
			else if (strcmp(str, "DIGITAL") == 0)
				port_type = DIGITAL;
			else
				p1_is_audioport = 0;		/* p[1] might be a bus spec. */
		}

		/* This signals inTraverse() to grab buffers from the audio device. */
		rtrecord = 1;

// FIXME: need to replace this with the bus spec scheme below... -JGG
		audioNCHANS = (n_args > 2) ? (int) p[2] : NCHANS;
		nchans = audioNCHANS;
		srate = SR;
	}

#ifdef MAXMSP
// this segment is to allow rtcmix to access sample data from the
// max/msp [buffer~] object.
	if (strcmp(sfname, "MMBUF") == 0) {
			int i;

			str = DOUBLE_TO_STRING(pp[1]);
			for (i = 0; i < n_mm_bufs; i++) {
				if (strcmp(str, mm_bufs[i].name) == 0) {
					mm_buf_input = i; // used in rtsetinput() for buf ID
					break;
				}
			}
			if (i == n_mm_bufs) {
				die("rtinput", "no max/msp buffer named %s is set", str);
				mm_buf_input = -1; // we are NOT using [buffer~] input, even if set
				return -1;
			}
			audio_in = 1; // I think I need this to initialize some vars...

// FIXME: need to replace this with the bus spec scheme below... -JGG
		audioNCHANS =  NCHANS;
		nchans = audioNCHANS;
		srate = SR;
		} else {
			mm_buf_input = -1; // we are NOT using [buffer~] input, even if set
		}
#endif // MAXMSP

#ifdef INPUT_BUS_SUPPORT
	/* Parse bus specification. */

	busindex = 0;
	for (i = 0; i < MAXBUS; i++)
		buslist[i] = -1;

	type = BUS_IN;
	startchan = endchan = -1;

	start_pfield = p1_is_audioport ? 2 : 1;

	for (i = start_pfield; i < n_args; i++) {
		ErrCode  err;

		str = DOUBLE_TO_STRING(pp[i]);
		if (str == NULL) {
			rterror("rtinput", "NULL bus name!");
			rtrecord = 0;
			return -1;
		}

		err = parse_bus_name(str, &type, &startchan, &endchan);
		if (err) {
			rterror("rtinput", "Invalid bus name specification.");
			rtrecord = 0;
			return -1;
		}
		if (type != BUS_IN) {
			rterror("rtinput", "You have to use an \"in\" bus with rtinput.");
			rtrecord = 0;
			return -1;
		}

		for (j = startchan; j <= endchan; j++)
			buslist[busindex++] = j;
	}

	if (startchan == -1) {           /* no bus specified */
	}
#endif /* INPUT_BUS_SUPPORT */
    long i;
    
	/* See if this audio device or file has already been opened. */
	for (i = 0; i < max_input_fds; i++) {
		if (inputFileTable[i].isOpen()) {
			if (inputFileTable[i].hasFile(sfname)) {
				last_input_index = i;
				is_open = 1;
				break;
			}
		}
	}
	if (!is_open) {			/* if not, open input audio device or file. */
		long nsamps = 0;
		if (audio_in) {
			if (rtsetparams_was_called()) {
				// If audio *playback* was disabled, but there is a request for
				// input audio, create the audio input device here.
				if (!audioDevice && !Option::play()) {
					int nframes = RTBUFSAMPS;
					if ((audioDevice = create_audio_devices(true, false,
											 NCHANS, SR, &nframes,
											 Option::bufferCount())) == NULL)
					{
						rtrecord = 0;	/* because we failed */
						return -1;
					}
					Option::record(true);
					RTBUFSAMPS = nframes;
					rtcmix_advise("Input audio set",  "%g sampling rate, %d channels\n", SR, NCHANS);
				}
				// If record disabled during rtsetparams(), we cannot force it on here.
				else if (!Option::record()) {
					die("rtinput", "Audio already configured for playback only via rtsetparams()");
					rtrecord = 0;	/* because we failed */
					return -1;
				}
			}
			else {
				// This allows rtinput("AUDIO") to turn on record
				Option::record(1);
				rtrecord = 1;
			}
			fd = 1;  /* we don't use this; set to 1 so rtsetinput() will work */
			for (i = 0; i < nchans; i++) {
				allocate_audioin_buffer(i, RTBUFSAMPS);
			}
#ifdef INPUT_BUS_SUPPORT
#endif /* INPUT_BUS_SUPPORT */
		}
		else {
			rtrecord = 0;
			fd = ::open_sound_file("rtinput", sfname, &header_type, &data_format,
							&data_location, &srate, &nchans, &nsamps);
			if (fd == -1)
				return -1;

#ifdef INPUT_BUS_SUPPORT
			if (startchan == -1) {     /* no bus specified above */
				startchan = 0;
				endchan = nchans - 1;
			}
			else {
				if (endchan - startchan >= nchans) {
					rtcmix_warn("rtinput", "You specifed more input buses than "
							"input file '%s' has channels.", sfname);
					rtcmix_warn("rtinput", "Using in buses %d", foo);
					endchan = (startchan + nchans) - 1;
				}
			}
#endif /* INPUT_BUS_SUPPORT */

			dur = (double) (nsamps / nchans) / srate;
			rtcmix_advise(NULL, "Input file set for reading:\n");
			rtcmix_advise(NULL, "      name:  %s\n", sfname);
			rtcmix_advise(NULL, "      type:  %s\n", mus_header_type_name(header_type));
			rtcmix_advise(NULL, "    format:  %s\n", mus_data_format_name(data_format));
			rtcmix_advise(NULL, "     srate:  %g\n", srate);
			rtcmix_advise(NULL, "     chans:  %d\n", nchans);
			rtcmix_advise(NULL, "  duration:  %g\n", dur);
#ifdef INPUT_BUS_SUPPORT
#endif /* INPUT_BUS_SUPPORT */

			if (srate != SR) {
				rtcmix_warn("rtinput", "The input file sampling rate is %g, but "
							"the output rate is currently %g.", srate, SR);
			}
		}

		/* Put new file descriptor into the first available slot in the
			inputFileTable.  Also copy the filename for later checking, and
			fill in the other fields in the InputFile struct (see InputFile.h).

			last_input_index is the value that will be used by any instrument
			created after this call to rtinput().
		*/
		for (i = 0; i < max_input_fds; i++) {
			if (!inputFileTable[i].isOpen()) {
                inputFileTable[i].init(fd, sfname, audio_in, header_type, data_format, data_location, nsamps, (float)srate, nchans, dur);
				last_input_index = i;
				break;
			}
		}

		/* If this is true, we've used up all input descriptors in our array. */
		if (i == max_input_fds)
			die("rtinput", "You have exceeded the maximum number of input "
												"files (%ld)!", max_input_fds);
	}

	/* Return this to Minc, so user can pass it to functions. */
	return (double) last_input_index;
}
Ejemplo n.º 13
0
double
NPAN_set_speakers(float p[], int nargs, double pp[])
{
   if (nargs < 5 || !(nargs % 2))
      return usage();

   if (_num_speakers > 0) {
      for (int i = 0; i < _num_speakers; i++) // delete ones from previous call
         delete _speakers[i];
      delete [] _speakers;
   }

   _num_speakers = (nargs - 1) / 2;
   if (_num_speakers < 2)
      return die("NPANspeakers", "Must have at least 2 speakers.");
   if (_num_speakers > MAX_SPEAKERS)
      return die("NPANspeakers", "Can't have more than %d speakers.",
                                                            MAX_SPEAKERS);

   _speakers = new Speaker * [_num_speakers];

   char *modestr = DOUBLE_TO_STRING(pp[0]);
   if (strncmp(modestr, "pol", 3) == 0) {          // polar coordinates
      // Convert from user coordinates by adding 90 degrees, then convert
      // to radians.  Finally, normalize radians to [-PI, PI].
      int j = 1;
      for (int i = 0; i < _num_speakers; i++, j += 2) {
         const double degrees = pp[j] + 90.0;      // user to internal degrees
         double angle = M_PI * 2 * (degrees / 360.0);    // to radians
         angle = atan2(sin(angle), cos(angle));    // normalize
         const double distance = pp[j + 1];
         _speakers[i] = new Speaker(i, angle, distance);
      }
   }
   else {                                          // cartesian coordinates
      int j = 1;
      for (int i = 0; i < _num_speakers; i++, j += 2) {
         const double x = pp[j];
         const double y = pp[j + 1];
         const double angle = atan2(y, x);
         const double distance = sqrt((x * x) + (y * y));
         _speakers[i] = new Speaker(i, angle, distance);
      }
   }

   // sort speaker array by ascending angle
   qsort(_speakers, _num_speakers, sizeof(Speaker *), compare_speaker_angles);

   // cache angle of adjacent speaker
   for (int i = 0; i < _num_speakers; i++) {
      if (i == 0)
         _speakers[i]->setPrevAngle(_speakers[_num_speakers - 1]->angle()
                                                                  - TWO_PI);
      else
         _speakers[i]->setPrevAngle(_speakers[i - 1]->angle());
      if (i == _num_speakers - 1)
         _speakers[i]->setNextAngle(_speakers[0]->angle() + TWO_PI);
      else
         _speakers[i]->setNextAngle(_speakers[i + 1]->angle());
   }

   // check for two speakers having same angle
   for (int i = 0; i < _num_speakers; i++) {
      if (_speakers[i]->nextAngle() == _speakers[i]->angle())
         return die("NPANspeakers", "Can't put two speakers in same location.");
   }

   return 0.0;
}