double RTcmix::input_sr(float *p, int n_args) /* returns rate for rtinput() files */ { int index = get_last_input_index(); if (index < 0) { fprintf(stderr, "There are no currently opened input files!\n"); return 0.0; } // if (inputFileTable[index].is_audio_dev) { // fprintf(stderr, "WARNING: Requesting duration of audio input device " // "(not sound file)!\n"); // return 0.0; // } return (inputFileTable[index].sampleRate()); }
double RTcmix::input_dur(float *p, int n_args) /* returns duration for rtinput() files */ { int index = get_last_input_index(); if (index < 0) { fprintf(stderr, "There are no currently opened input files!\n"); return 0.0; } if (inputFileTable[index].isAudioDevice()) { fprintf(stderr, "WARNING: Requesting duration of audio input device " "(not sound file)!\n"); return 0.0; } return (inputFileTable[index].duration()); }
double RTcmix::input_chans(float *p, int n_args) /* returns chans for rtinput() files */ { int index = get_last_input_index(); if (index < 0) { fprintf(stderr, "There are no currently opened input files!\n"); return 0.0; } if (inputFileTable[index].is_audio_dev) { fprintf(stderr, "WARNING: Requesting channels of audio input device " "(not sound file)!\n"); return 0.0; } return (inputFileTable[index].chans); }
int RTcmix::attachInput(float start_time, InputState *input) { int index = get_last_input_index(); #ifdef SGI if (index < 0) { return RT_NO_INPUT_SRC; } if ((!inputFileTable[index].isOpen()) && (inputFileTable[index].getFD() != AUDIO_DEVICE_FD)) { return RT_NO_INPUT_SRC; } #else if (index < 0 || !inputFileTable[index].isOpen()) { return RT_NO_INPUT_SRC; } #endif int src_chans; int status = RT_NO_ERROR; /* File or audio device was opened in rtinput(). Here we store the index into the inputFileTable for the file or device. */ input->fdIndex = index; /* Fill in relevant data members of instrument class. */ input->inputsr = inputFileTable[index].sampleRate(); src_chans = inputFileTable[index].channels(); if (inputFileTable[index].isAudioDevice()) { if (start_time != 0.0) { return RT_ILLEGAL_DEV_OFFSET; } } else { int datum_size; if (input->inputchans != src_chans) { status = RT_INPUT_CHANS_MISMATCH; // nonfatal input->inputchans = src_chans; } // This is now rounded to the nearest frame -- DS int inskip_frames = (int) (0.5 + start_time * input->inputsr); datum_size = ::mus_data_format_to_bytes_per_sample(inputFileTable[index].dataFormat()); /* Offset is measured from the header size determined in rtinput(). */ input->fileOffset = inputFileTable[index].dataLocation() + (inskip_frames * input->inputchans * datum_size); assert(input->fileOffset >= 0); if (start_time >= inputFileTable[index].duration()) status = RT_INPUT_EOF; // not fatal -- just produces warning } /* Increment the reference count for this file. */ inputFileTable[index].reference(); return status; }
/* Given an instrument name, return a pointer to the most recently created BusSlot node for that instrument name. If no instrument name match, return a pointer to the default node. */ BusSlot * RTcmix::get_bus_config(const char *inst_name) { BusSlot *slot, *default_bus_slot; BusQueue *q; ErrCode err; int index,in_chans,i; assert(inst_name != NULL); slot = NULL; Lock lock(&bus_slot_lock); // unlocks when out of scope /* Maybe also need to lock q since it's accessing a BusSlot */ /* that intraverse might also be checking? */ /* But the values don't change, so I don't see why */ pthread_mutex_lock(&inst_bus_config_lock); for (q = Inst_Bus_Config; q; q = q->next) { if (strcmp(inst_name, q->instName()) == 0) { pthread_mutex_unlock(&inst_bus_config_lock); return q->slot; } } pthread_mutex_unlock(&inst_bus_config_lock); /* Default bus_config for backwards compatibility with < 3.0 scores */ warn(NULL, "No bus_config defined, setting default (in/out)."); /* Some init stuff normally done in check_bus_inst_config */ Bus_Config_Status.lock(); if (Bus_Config_Status == NO) { for (i=0;i<MAXBUS;i++) { pthread_mutex_lock(&aux_to_aux_lock); AuxToAuxPlayList[i] = -1; pthread_mutex_unlock(&aux_to_aux_lock); pthread_mutex_lock(&to_aux_lock); ToAuxPlayList[i] = -1; pthread_mutex_unlock(&to_aux_lock); pthread_mutex_lock(&to_out_lock); ToOutPlayList[i] = -1; pthread_mutex_unlock(&to_out_lock); pthread_mutex_lock(&out_in_use_lock); OutInUse[i] = NO; pthread_mutex_unlock(&out_in_use_lock); // Added this initialization as well -- DS 5/2005 CheckNode *t_node = new CheckNode; pthread_mutex_lock(&bus_in_config_lock); Bus_In_Config[i] = t_node; t_node->ref(); pthread_mutex_unlock(&bus_in_config_lock); } Bus_Config_Status = YES; } Bus_Config_Status.unlock(); for(i=0;i<NCHANS;i++) { pthread_mutex_lock(&out_in_use_lock); OutInUse[i] = YES; pthread_mutex_unlock(&out_in_use_lock); pthread_mutex_lock(&to_out_lock); ToOutPlayList[i] = i; pthread_mutex_unlock(&to_out_lock); } default_bus_slot = new BusSlot; /* Grab input chans from file descriptor table */ index = get_last_input_index(); /* Otherwise grab from audio device, if active */ if (index == -1) { if (Option::record() && Option::play()) in_chans = NCHANS; else in_chans = 0; } else in_chans = inputFileTable[index].chans; default_bus_slot->in_count = in_chans; default_bus_slot->out_count = NCHANS; for(i=0;i<in_chans;i++) { default_bus_slot->in[i] = i; } for(i=0;i<NCHANS;i++) { default_bus_slot->out[i] = i; } err = check_bus_inst_config(default_bus_slot, YES); if (!err) { err = insert_bus_slot((char *)inst_name, default_bus_slot); } if (err) // BGG mm -- print an error, don't exit die("bus_config", "couldn't get_bus_config, this is not good"); // exit(1); /* This is probably what user wants? */ return default_bus_slot; }
/* Returns peak for <chan> of current RT input file, between <start> and <end> times (in seconds). If <chan> is -1, returns the highest peak of all the channels. If <end> is 0, sets <end> to duration of file. */ float RTcmix::get_peak(float start, float end, int chan) { int n, fd, result, nchans, srate, dataloc, format; int index, file_stats_valid=0; long startframe, endframe, nframes, loc; long peakloc[MAXCHANS]; float peak[MAXCHANS]; double ampavg[MAXCHANS], dcavg[MAXCHANS], rms[MAXCHANS]; SFComment sfc; index = get_last_input_index(); if (index < 0) { fprintf(stderr, "There are no currently opened input files!\n"); return 0.0; } if (inputFileTable[index].isAudioDevice()) { fprintf(stderr, "WARNING: Requesting peak of audio input device " "(not sound file)!\n"); return 0.0; } if (end == 0.0) end = inputFileTable[index].duration(); /* use end time of file */ fd = inputFileTable[index].getFD(); // *** If end - start is, say, 60 seconds, less trouble to just analyze file // than to dig through file header? /* Try to use peak stats in file header. */ if (sndlib_get_header_comment(fd, &sfc) == -1) return -0.0; /* this call prints an err msg */ if (SFCOMMENT_PEAKSTATS_VALID(&sfc) && sfcomment_peakstats_current(&sfc, fd)) file_stats_valid = 1; else file_stats_valid = 0; /* file written since peak stats were updated */ format = inputFileTable[index].dataFormat(); dataloc = inputFileTable[index].dataLocation(); srate = (int) inputFileTable[index].sampleRate(); // note: casting to int nchans = inputFileTable[index].channels(); startframe = (long)(start * srate + 0.5); endframe = (long)(end * srate + 0.5); nframes = (endframe - startframe) + 1; if (file_stats_valid) { int c = 0; if (chan == ALL_CHANS) { float max = 0.0; for (n = 0; n < nchans; n++) { if (sfc.peak[n] > max) { max = sfc.peak[n]; c = n; } } loc = sfc.peakloc[c]; } else { loc = sfc.peakloc[chan]; c = chan; } if (loc >= startframe && loc <= endframe) return sfc.peak[c]; } /* NOTE: Might get here even if file_stats_valid. */ result = sndlib_findpeak(fd, -1, dataloc, -1, format, nchans, startframe, nframes, peak, peakloc, ampavg, dcavg, rms); if (chan == ALL_CHANS) { float max = 0.0; for (n = 0; n < nchans; n++) { if (peak[n] > max) max = peak[n]; } return max; } else return peak[chan]; }