コード例 #1
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;
}
コード例 #2
0
ファイル: rtinput.cpp プロジェクト: CreativeInquiry/RTcmix
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;
}