void sfopenin(CSOUND *csound) /* init for continuous soundin */ { OPARMS *O = csound->oparms; char *sfname, *fullName; SF_INFO sfinfo; int fileType = (int) TYP_RAW; int isfd = 0; /* stdin */ alloc_globals(csound); STA(inbufrem) = (uint32) 0; /* start with empty buffer */ sfname = O->infilename; if (UNLIKELY(sfname == NULL || sfname[0] == '\0')) csound->Die(csound, Str("error: no input file name")); if (strcmp(sfname, "stdin") == 0) { STA(pipdevin) = 1; } #ifdef PIPES else if (sfname[0] == '|') { STA(pin) = _popen(sfname + 1, "r"); isfd = fileno(STA(pin)); STA(pipdevin) = 1; } #endif else { csRtAudioParams parm; /* check for real time audio input, and get device name/number */ parm.devNum = check_rtaudio_name(sfname, &(parm.devName), 0); if (parm.devNum >= 0) { /* set device parameters */ parm.bufSamp_SW = (unsigned int) O->inbufsamps / (unsigned int) csound->inchnls; parm.bufSamp_HW = O->oMaxLag; parm.nChannels = csound->inchnls; parm.sampleFormat = O->informat; parm.sampleRate = (float) csound->esr; /* open devaudio for input */ if (UNLIKELY(csound->recopen_callback(csound, &parm) != 0)) csoundDie(csound, Str("Failed to initialise real time audio input")); /* & redirect audio gets */ csound->audrecv = csound->rtrecord_callback; STA(pipdevin) = 2; /* no backward seeks ! */ goto inset; /* no header processing */ } } /* open file */ memset(&sfinfo, 0, sizeof(SF_INFO)); if (STA(pipdevin)) { STA(infile) = sf_open_fd(isfd, SFM_READ, &sfinfo, 0); if (UNLIKELY(STA(infile) == NULL)) { /* open failed: possibly raw file, but cannot seek back to try again */ const char *sfError = Str(sf_strerror(NULL)); csoundDie(csound, Str("isfinit: cannot open %s -- %s"), sfname, sfError); } } else { fullName = csoundFindInputFile(csound, sfname, "SFDIR;SSDIR"); if (UNLIKELY(fullName == NULL)) /* if not found */ csoundDie(csound, Str("isfinit: cannot open %s"), sfname); STA(infile) = sf_open(fullName, SFM_READ, &sfinfo); if (STA(infile) == NULL) { /* open failed: maybe raw file ? */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int) MYFLT2LRND(csound->esr); sfinfo.channels = csound->nchnls; /* FIXME: assumes input sample format is same as output */ sfinfo.format = TYPE2SF(TYP_RAW) | FORMAT2SF(O->outformat); STA(infile) = sf_open(fullName, SFM_READ, &sfinfo); /* try again */ } if (UNLIKELY(STA(infile) == NULL)) { const char *sfError = Str(sf_strerror(NULL)); csoundDie(csound, Str("isfinit: cannot open %s -- %s"), fullName, sfError); } /* only notify the host if we opened a real file, not stdin or a pipe */ csoundNotifyFileOpened(csound, fullName, sftype2csfiletype(sfinfo.format), 0, 0); sfname = fullName; } /* chk the hdr codes */ if (sfinfo.samplerate != (int) MYFLT2LRND(csound->esr)) { csound->Warning(csound, Str("audio_in %s has sr = %d, orch sr = %d"), sfname, (int) sfinfo.samplerate, (int) MYFLT2LRND(csound->esr)); } if (sfinfo.channels != csound->inchnls) { csound->Warning(csound, Str("audio_in %s has %d chnls, orch %d chnls_i"), sfname, (int) sfinfo.channels, csound->inchnls); } /* Do we care about the format? Can assume float?? */ O->informat = SF2FORMAT(sfinfo.format); fileType = (int) SF2TYPE(sfinfo.format); csound->audrecv = readsf; /* will use standard audio gets */ if ((O->informat == AE_FLOAT || O->informat == AE_DOUBLE) && !(fileType == TYP_WAV || fileType == TYP_AIFF || fileType == TYP_W64)) { /* do not scale "raw" floating point files */ csound->spinrecv = sndfilein_noscale; } inset: /* calc inbufsize reqd */ STA(inbufsiz) = (unsigned) (O->inbufsamps * sizeof(MYFLT)); STA(inbuf) = (MYFLT*) csound->Calloc(csound, STA(inbufsiz)); /* alloc inbuf space */ if (STA(pipdevout) == 2) csound->Message(csound, Str("reading %d sample blks of %lu-bit floats from %s\n"), O->inbufsamps * O->sfsampsize, (unsigned long) sizeof(MYFLT)*8, sfname); else { csound->Message(csound, Str("reading %d-byte blks of %s from %s (%s)\n"), O->inbufsamps * (int) sfsampsize(FORMAT2SF(O->informat)), getstrformat(O->informat), sfname, type2string(fileType)); } STA(isfopen) = 1; }
/* type should be one of libsndfile's format values. */ int sftype2csfiletype(int type) { /* mask out the endian-ness bits */ int typemod = type & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK); return type2csfiletype(SF2TYPE(typemod), SF2FORMAT(typemod)); }
SNDMEMFILE *csoundLoadSoundFile(CSOUND *csound, const char *fileName, void *sfi) { SF_INFO *sfinfo = sfi; SNDFILE *sf; void *fd; SNDMEMFILE *p = NULL; SF_INFO tmp; if (UNLIKELY(fileName == NULL || fileName[0] == '\0')) return NULL; /* check if file is already loaded */ if (csound->sndmemfiles != NULL) { p = cs_hash_table_get(csound, csound->sndmemfiles, (char*)fileName); } else { csound->sndmemfiles = cs_hash_table_create(csound); } if (p != NULL) { /* if file was loaded earlier: */ if (sfinfo != NULL) { memset(sfinfo, 0, sizeof(SF_INFO)); sfinfo->frames = (sf_count_t) p->nFrames; sfinfo->samplerate = ((int) p->sampleRate + 0.5); sfinfo->channels = p->nChannels; sfinfo->format = FORMAT2SF(p->sampleFormat) | TYPE2SF(p->fileType); } return p; } /* open file */ if (sfinfo == NULL) { memset(&tmp, 0, sizeof(SF_INFO)); sfinfo = &tmp; } fd = csound->FileOpen2(csound, &sf, CSFILE_SND_R, fileName, sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(fd == NULL)) { csound->ErrorMsg(csound, Str("csoundLoadSoundFile(): failed to open '%s'"), fileName); return NULL; } p = (SNDMEMFILE*) csound->Malloc(csound, sizeof(SNDMEMFILE) + (size_t) sfinfo->frames * sizeof(float)); /* set parameters */ p->name = (char*) csound->Malloc(csound, strlen(fileName) + 1); strcpy(p->name, fileName); p->fullName = (char*) csound->Malloc(csound, strlen(csound->GetFileName(fd)) + 1); strcpy(p->fullName, csound->GetFileName(fd)); p->sampleRate = (double) sfinfo->samplerate; p->nFrames = (size_t) sfinfo->frames; p->nChannels = sfinfo->channels; p->sampleFormat = SF2FORMAT(sfinfo->format); p->fileType = SF2TYPE(sfinfo->format); /* set defaults for sampler information */ p->loopMode = 0; p->startOffs = 0.0; p->loopStart = 0.0; p->loopEnd = 0.0; p->baseFreq = 1.0; p->scaleFac = 1.0; { SF_INSTRUMENT lpd; if (sf_command(sf, SFC_GET_INSTRUMENT, &lpd, sizeof(SF_INSTRUMENT)) != 0) { if (lpd.loop_count > 0 && lpd.loops[0].mode != SF_LOOP_NONE) { /* set loop mode and loop points */ p->loopMode = (lpd.loops[0].mode == SF_LOOP_FORWARD ? 2 : (lpd.loops[0].mode == SF_LOOP_BACKWARD ? 3 : 4)); p->loopStart = (double) lpd.loops[0].start; p->loopEnd = (double) lpd.loops[0].end; } else { /* loop mode: off */ p->loopMode = 1; } p->baseFreq = pow(2.0, (double) (((int) lpd.basenote - 69) * 100 + (int) lpd.detune) / 1200.0) * 440.0; p->scaleFac = pow(10.0, (double) lpd.gain * 0.05); } } if ((size_t) sf_readf_float(sf, &(p->data[0]), (sf_count_t) p->nFrames) != p->nFrames) { csound->FileClose(csound, fd); csound->Free(csound, p->name); csound->Free(csound, p->fullName); csound->Free(csound, p); csound->ErrorMsg(csound, Str("csoundLoadSoundFile(): error reading '%s'"), fileName); return NULL; } p->data[p->nFrames] = 0.0f; csound->FileClose(csound, fd); csound->Message(csound, Str("File '%s' (sr = %d Hz, %d channel(s), %lu " "sample frames) loaded into memory\n"), p->fullName, (int) sfinfo->samplerate, (int) sfinfo->channels, (uint32) sfinfo->frames); /* link into database */ cs_hash_table_put(csound, csound->sndmemfiles, (char*)fileName, p); /* return with pointer to file structure */ return p; }
void *sndgetset(CSOUND *csound, void *p_) { SOUNDIN *p = (SOUNDIN*) p_; int n; int framesinbuf, skipframes; char *sfname; SF_INFO sfinfo; sfname = &(p->sfname[0]); /* IV - Feb 26 2005: should initialise sfinfo structure */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.format = (p->format ? /* store default sample format, */ ((int) FORMAT2SF(p->format) | SF_FORMAT_RAW) : 0); sfinfo.channels = 1; /* number of channels, */ if (p->analonly) /* and sample rate */ sfinfo.samplerate = (int) p->sr; else sfinfo.samplerate = (int) ((double) csound->esr + 0.5); if (sfinfo.samplerate < 1) sfinfo.samplerate = (int) ((double) DFLT_SR + 0.5); /* open with full dir paths */ p->fd = csound->FileOpen2(csound, &(p->sinfd), CSFILE_SND_R, sfname, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(p->fd == NULL)) { csound->ErrorMsg(csound, Str("soundin cannot open %s"), sfname); goto err_return; } /* & record fullpath filnam */ sfname = csound->GetFileName(p->fd); /* copy type from headata */ p->format = SF2FORMAT(sfinfo.format); p->sampframsiz = (int) sfsampsize(sfinfo.format) * (int) sfinfo.channels; p->nchanls = sfinfo.channels; framesinbuf = (int) SNDINBUFSIZ / (int) p->nchanls; p->bufsmps = framesinbuf * p->nchanls; p->endfile = 0; p->filetyp = SF2TYPE(sfinfo.format); if (p->analonly) { /* anal: if sr param val */ if (p->sr != 0 && p->sr != sfinfo.samplerate) { /* use it */ csound->Warning(csound, Str("-s %d overriding soundfile sr %d"), (int) p->sr, (int) sfinfo.samplerate); sfinfo.samplerate = p->sr; } } else if (sfinfo.samplerate != (int) ((double) csound->esr + 0.5)) { csound->Warning(csound, /* non-anal: cmp w. esr */ "%s sr = %d, orch sr = %7.1f", sfname, (int) sfinfo.samplerate, csound->esr); } if (UNLIKELY(p->channel != ALLCHNLS && p->channel > sfinfo.channels)) { csound->ErrorMsg(csound, Str("error: req chan %d, file %s has only %d"), (int) p->channel, sfname, (int) sfinfo.channels); goto err_return; } p->sr = (int) sfinfo.samplerate; if (csound->oparms_.msglevel & 3) { csound->Message(csound, Str("audio sr = %d, "), (int) p->sr); switch (p->nchanls) { case 1: csound->Message(csound, Str("monaural")); break; case 2: csound->Message(csound, Str("stereo")); break; case 4: csound->Message(csound, Str("quad")); break; case 6: csound->Message(csound, Str("hex")); break; case 8: csound->Message(csound, Str("oct")); break; default: csound->Message(csound, Str("%d-channels"), (int) p->nchanls); } if (p->nchanls > 1) { if (p->channel == ALLCHNLS) csound->Message(csound, Str(", reading %s channels"), (p->nchanls == 2 ? Str("both") : Str("all"))); else csound->Message(csound, Str(", reading channel %d"), (int) p->channel); } csound->Message(csound, Str("\nopening %s infile %s\n"), type2string(p->filetyp), sfname); } p->audrem = (int64_t) sfinfo.frames * (int64_t) sfinfo.channels; p->framesrem = (int64_t) sfinfo.frames; /* find frames rem */ skipframes = (int) ((double) p->skiptime * (double) p->sr + (p->skiptime >= FL(0.0) ? 0.5 : -0.5)); if (skipframes < 0) { n = -skipframes; if (UNLIKELY(n > framesinbuf)) { csound->ErrorMsg(csound, Str("soundin: invalid skip time")); goto err_return; } n *= (int) sfinfo.channels; p->inbufp = &(p->inbuf[0]); p->bufend = p->inbufp; do { *(p->bufend++) = FL(0.0); } while (--n); } else if (skipframes < framesinbuf) { /* if sound within 1st buf */ n = sreadin(csound, p->sinfd, p->inbuf, p->bufsmps, p); p->bufend = &(p->inbuf[0]) + n; p->inbufp = &(p->inbuf[0]) + (skipframes * (int) sfinfo.channels); if (p->inbufp >= p->bufend) { p->inbufp = p->bufend; p->audrem = (int64_t) 0; p->endfile = 1; } } else if ((int64_t) skipframes >= p->framesrem) { n = framesinbuf * (int) sfinfo.channels; p->inbufp = &(p->inbuf[0]); p->bufend = p->inbufp; do { *(p->bufend++) = FL(0.0); } while (--n); p->audrem = (int64_t) 0; p->endfile = 1; } else { /* for greater skiptime: */ /* else seek to bndry */ if (UNLIKELY(sf_seek(p->sinfd, (sf_count_t) skipframes, SEEK_SET) < 0)) { csound->ErrorMsg(csound, Str("soundin seek error")); goto err_return; } /* now rd fulbuf */ if ((n = sreadin(csound, p->sinfd, p->inbuf, p->bufsmps, p)) == 0) p->endfile = 1; p->inbufp = p->inbuf; p->bufend = p->inbuf + n; } if (p->framesrem != (int64_t) -1) p->framesrem -= (int64_t) skipframes; /* sampleframes to EOF */ return p->sinfd; /* return the active fd */ err_return: if (p->fd != NULL) csound->FileClose(csound, p->fd); p->sinfd = NULL; p->fd = NULL; return NULL; }