示例#1
0
/* ------------------------------------------------------------------ die --- */
int
die(const char *inst_name, const char *format, ...)
{
   char     buf[BUFSIZE];
   va_list  args;

   va_start(args, format);
   vsnprintf(buf, BUFSIZE, format, args);
   va_end(args);

#ifndef MAXMSP
   if (inst_name)
      fprintf(stderr, PREFIX "FATAL ERROR [%s]:  %s\n", inst_name, buf);
   else
      fprintf(stderr, PREFIX "FATAL ERROR:  %s\n", buf);

#else // MAXMSP
   if (inst_name) {
      int nchars = sprintf(get_mm_print_ptr(), "FATAL ERROR [%s]:  %s\n", inst_name, buf);
      set_mm_print_ptr(nchars+1);
   }
   else {
      int nchars = sprintf(get_mm_print_ptr(), "FATAL ERROR:  %s\n", buf);
   }
#endif // MAXMSP

   if (get_bool_option(kOptionExitOnError)) {
      if (!rtsetparams_was_called())
         closesf_noexit();
      exit(1);
      return 0;	/*NOTREACHED*/
   }
   else
      return DONT_SCHEDULE;
}
示例#2
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;
}
示例#3
0
/* Minc function that sets output sampling rate (p0), maximum number of
   output channels (p1), and (optionally) I/O buffer size (p2).

   On SGI, the optional p3 lets you specify the output port as a string
   (e.g., "LINE", "DIGITAL", etc.).

   Based on this information, rtsetparams allocates a mono output buffer
   for each of the output channels, and opens output devices.
*/
double
RTcmix::rtsetparams(float p[], int n_args, double pp[])
{
   int         i, status;
   int         verbose = Option::print();
   int         play_audio = Option::play();
   int         record_audio = Option::record();
#ifdef SGI
   static char *out_port_str = NULL;
#endif /* SGI */

   if (rtsetparams_was_called()) {
      die("rtsetparams", "You can only call rtsetparams once!");
	  return -1;
   }

// FIXME: Need better names for NCHANS and RTBUFSAMPS. -JGG

   SR = p[0];
   NCHANS = (int) p[1];
   RTBUFSAMPS = n_args > 2 ? (int) p[2] : (int) Option::bufferFrames();
   int numBuffers = Option::bufferCount();

   if (n_args > 3 && pp[3] != 0.0) {
#ifdef SGI
      /* Cast Minc double to char ptr to get string. */
      int iarg = (int) pp[3];
      out_port_str = (char *) iarg;
 	  advise("rtsetparams", "Playing through output port '%s'", out_port_str);
#endif /* SGI */
   }
   
   if (SR <= 0.0) {
	   die("rtsetparams", "Sampling rate must be greater than 0.");
	   return -1;
   }

   if (NCHANS > MAXBUS) {
      die("rtsetparams", "You can only have up to %d output channels.", MAXBUS - 1);
	  return -1;
   }

   /* play_audio is true unless user has called set_option("audio_off") before
      rtsetparams. This would let user run multiple jobs, as long as only one
      needs the audio drivers.  -JGG

	  record_audio is false unless user has called set_option("full_duplex_on")
	  or has explicity turned record on by itself via set_option("record_on"),
	  or has already called rtinput("AUDIO").  -DS
   */
   if (play_audio || record_audio) {
      int nframes = RTBUFSAMPS;
		
	  if ((audioDevice = create_audio_devices(record_audio, play_audio, 
	  						   NCHANS, SR, &nframes, numBuffers)) == NULL)
	  	return -1;

      /* This may have been reset by driver. */
      RTBUFSAMPS = nframes;
   }

   /* inTraverse waits for this. Set it even if play_audio is false! */
   pthread_mutex_lock(&audio_config_lock);
   audio_config = 1;
   pthread_mutex_unlock(&audio_config_lock);

   if (verbose)
      printf("Audio set:  %g sampling rate, %d channels\n", SR, NCHANS);

   /* Allocate output buffers. Do this *after* opening audio devices,
      in case OSS changes our buffer size, for example.
   */
   for (i = 0; i < NCHANS; i++) {
      allocate_out_buffer(i, RTBUFSAMPS);
   }

#ifdef MULTI_THREAD
	InputFile::createConversionBuffers(RTBUFSAMPS);
#endif
	
   rtsetparams_called = 1;	/* Put this at end to allow re-call due to error */

   return 0;
}
示例#4
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;
}