Пример #1
0
void sfopenout(CSOUND *csound)                  /* init for sound out       */
{                                               /* (not called if nosound)  */
    OPARMS  *O = csound->oparms;
    char    *s, *fName, *fullName;
    SF_INFO sfinfo;
    int     osfd = 1;   /* stdout */

    alloc_globals(csound);
    if (O->outfilename == NULL) {
      switch (O->filetyp) {
      case TYP_WAV:
      case TYP_W64:
      case TYP_WAVEX:
      case TYP_RF64:
        O->outfilename = "test.wav";
        break;
      case TYP_AIFF:
        O->outfilename = "test.aif";
        break;
      case TYP_AU:
        O->outfilename = "test.au";
        break;
      case TYP_PAF:
        O->outfilename = "test.paf";
        break;
      case TYP_SVX:
        O->outfilename = "test.svx";
        break;
      case TYP_NIST:
        O->outfilename = "test.sph";
        break;
      case TYP_VOC:
        O->outfilename = "test.voc";
        break;
      /* case TYP_IRCAM: */
      /*   O->outfilename = ""; */
      /*   break; */
      /* case TYP_MAT4: */
      /*   O->outfilename = ""; */
      /*   break;  */
      /* case TYP_MAT5: */
      /*   O->outfilename = ""; */
      /*   break;  */
      /* case TYP_PVF: */
      /*   O->outfilename = ""; */
      /*   break;   */
      case TYP_XI:
        O->outfilename = "test.xi";
        break;
      /* case TYP_HTK: */
      /*   O->outfilename = ""; */
      /*   break;   */
      /* case TYP_SDS: */
      /*   O->outfilename = "test.sds"; */
      /*   break;   */
      case TYP_AVR:
        O->outfilename = "test.avr";
        break;
      case TYP_SD2:
        O->outfilename = "test.sd2";
        break;
      case TYP_FLAC:
        O->outfilename = "test.flac";
        break;
      case TYP_CAF:
        O->outfilename = "test.caf";
        break;
      case TYP_OGG:
        O->outfilename = "test.ogg";
        break;
      /* case TYP_MPC2K: */
      /*   O->outfilename = ""; */
      /*   break; */
      default:
        O->outfilename = "test";
        break;
      }
    }
    STA(sfoutname) = fName = O->outfilename;

    if (strcmp(fName, "stdout") == 0) {
      STA(pipdevout) = 1;
    }
#ifdef PIPES
    else if (fName[0] == '|') {
      STA(pout) = _popen(fName+1, "w");
      osfd = fileno(STA(pout));
      STA(pipdevout) = 1;
      if (O->filetyp == TYP_AIFF || O->filetyp == TYP_WAV) {
        char fmt_name[6];
        if (O->sfsampsize == 8) {
          strcpy(fmt_name, "AU");
          O->filetyp = TYP_AU;
        }
        else {
          strcpy(fmt_name, "IRCAM");
          O->filetyp = TYP_IRCAM;
        }
        csound->Message(csound, Str("Output file type changed to %s "
                                    "for use in pipe\n"), fmt_name);
      }
    }
#endif
    else {
      csRtAudioParams   parm;
      /* check for real time audio output, and get device name/number */
      parm.devNum = check_rtaudio_name(fName, &(parm.devName), 1);
      if (parm.devNum >= 0) {
        /* set device parameters */
        parm.bufSamp_SW   = (unsigned int) O->outbufsamps / csound->nchnls;
        parm.bufSamp_HW   = O->oMaxLag;
        parm.nChannels    = csound->nchnls;
        parm.sampleFormat = O->outformat;
        parm.sampleRate   = (float) csound->esr;
        csound->spoutran  = spoutsf;
        /* open devaudio for output */
        if (UNLIKELY(csound->playopen_callback(csound, &parm) != 0))
          csoundDie(csound, Str("Failed to initialise real time audio output"));
        /*  & redirect audio puts  */
        csound->audtran = csound->rtplay_callback;
        STA(outbufrem)  = parm.bufSamp_SW * parm.nChannels;
        STA(pipdevout)  = 2;      /* no backward seeks !   */
        if (O->realtime == 1)     /* set realtime priority mode */
          csound->realtime_audio_flag = 1;
        goto outset;              /* no header needed      */
      }
      else if (strcmp(fName, "null") == 0) {
        STA(outfile) = NULL;
        if (csound->dither_output && csound->oparms->outformat!=AE_FLOAT &&
            csound->oparms->outformat!=AE_DOUBLE) {
          if (csound->oparms->outformat==AE_SHORT)
            if (csound->dither_output==1)
              csound->audtran = writesf_dither_16;
            else
              csound->audtran = writesf_dither_u16;
          else if (csound->oparms->outformat==AE_CHAR)
            if (csound->dither_output==1)
              csound->audtran = writesf_dither_8;
            else
              csound->audtran = writesf_dither_u8;
          else
            csound->audtran = writesf;
        }
        else
          csound->audtran = writesf;
        goto outset;
      }
    }
    /* set format parameters */
    memset(&sfinfo, 0, sizeof(SF_INFO));
    //sfinfo.frames     = 0;
    sfinfo.samplerate = (int) MYFLT2LRND(csound->esr);
    sfinfo.channels   = csound->nchnls;
    sfinfo.format     = TYPE2SF(O->filetyp) | FORMAT2SF(O->outformat);
    /* open file */
    if (STA(pipdevout)) {
      STA(outfile) = sf_open_fd(osfd, SFM_WRITE, &sfinfo, 0);
#ifdef PIPES
      if (STA(outfile) == NULL) {
        char fmt_name[6];
        if (O->sfsampsize == 8) {
          if (UNLIKELY(O->filetyp == TYP_AU))
            csoundDie(csound, Str("sfinit: cannot open fd %d\n%s"), osfd,
                      Str(sf_strerror(NULL)));
          strcpy(fmt_name, "AU");
          O->filetyp = TYP_AU;
        }
        else {
          if (UNLIKELY(O->filetyp == TYP_IRCAM))
            csoundDie(csound, Str("sfinit: cannot open fd %d\n%s"), osfd,
                      Str(sf_strerror(NULL)));
          strcpy(fmt_name, "IRCAM");
          O->filetyp = TYP_IRCAM;
        }
        csound->Message(csound, Str("Output file type changed to %s "
                                    "for use in pipe\n"), fmt_name);
        sfinfo.format = TYPE2SF(O->filetyp) | FORMAT2SF(O->outformat);
        STA(outfile) = sf_open_fd(osfd, SFM_WRITE, &sfinfo, 0);
      }
#endif
      if (UNLIKELY(STA(outfile) == NULL))
        csoundDie(csound, Str("sfinit: cannot open fd %d\n%s"), osfd,
                  Str(sf_strerror(NULL)));
      sf_command(STA(outfile), SFC_SET_VBR_ENCODING_QUALITY,
                 &O->quality, sizeof(double));
    }
    else {
      fullName = csoundFindOutputFile(csound, fName, "SFDIR");
      if (UNLIKELY(fullName == NULL))
        csoundDie(csound, Str("sfinit: cannot open %s"), fName);
      STA(sfoutname) = fullName;
      STA(outfile)   = sf_open(fullName, SFM_WRITE, &sfinfo);
      if (UNLIKELY(STA(outfile) == NULL))
        csoundDie(csound, Str("sfinit: cannot open %s\n%s"),
                  fullName, sf_strerror (NULL));
      sf_command(STA(outfile), SFC_SET_VBR_ENCODING_QUALITY,
                 &O->quality, sizeof(double));
      /* only notify the host if we opened a real file, not stdout or a pipe */
      csoundNotifyFileOpened(csound, fullName,
                              type2csfiletype(O->filetyp, O->outformat), 1, 0);
    }
    /* IV - Feb 22 2005: clip integer formats */
    if (O->outformat != AE_FLOAT && O->outformat != AE_DOUBLE)
      sf_command(STA(outfile), SFC_SET_CLIPPING, NULL, SF_TRUE);
    sf_command(STA(outfile), SFC_SET_ADD_PEAK_CHUNK,
               NULL, (csound->peakchunks ? SF_TRUE : SF_FALSE));
#ifdef SOME_FINE_DAY
    if (csound->dither_output) {        /* This may not be written yet!! */
      SF_DITHER_INFO  ditherInfo;
      memset(&ditherInfo, 0, sizeof(SF_DITHER_INFO));
      ditherInfo.type  = SFD_TRIANGULAR_PDF | SFD_DEFAULT_LEVEL;
      ditherInfo.level = 1.0;
      ditherInfo.name  = (char*) NULL;
      sf_command(STA(outfile), SFC_SET_DITHER_ON_WRITE,
                 &ditherInfo, sizeof(SF_DITHER_INFO));
    }
#endif
    if (!(O->outformat == AE_FLOAT || O->outformat == AE_DOUBLE) ||
        (O->filetyp == TYP_WAV || O->filetyp == TYP_AIFF ||
         O->filetyp == TYP_W64))
      csound->spoutran = spoutsf;       /* accumulate output */
    else
      csound->spoutran = spoutsf_noscale;
    if (csound->dither_output && csound->oparms->outformat!=AE_FLOAT &&
        csound->oparms->outformat!=AE_DOUBLE) {
      if (csound->oparms->outformat==AE_SHORT)
        csound->audtran = writesf_dither_16;
      else if (csound->oparms->outformat==AE_CHAR)
        csound->audtran = writesf_dither_8;
      else
        csound->audtran = writesf;
    }
    else
      csound->audtran = writesf;
    /* Write any tags. */
    if ((s = csound->SF_id_title) != NULL && *s != '\0')
      sf_set_string(STA(outfile), SF_STR_TITLE, s);
    if ((s = csound->SF_csd_licence) == NULL || *s == '\0')
      s = csound->SF_id_copyright;
    if (s != NULL && *s != '\0')
      sf_set_string(STA(outfile), SF_STR_COPYRIGHT, s);
    else if (csound->SF_id_scopyright>=0) {
      char buff[256];
      time_t tt = time(NULL);
      strftime(buff, 256, "Copyright %Y: ", gmtime(&tt));
      strncat(buff,copyrightcode(csound->SF_id_scopyright), 255);
      buff[255] = '\0';
      sf_set_string(STA(outfile), SF_STR_COPYRIGHT, buff);
    }
    if ((s = csound->SF_id_software) != NULL && *s != '\0')
      sf_set_string(STA(outfile), SF_STR_SOFTWARE, s);
    if ((s = csound->SF_id_artist) != NULL && *s != '\0')
      sf_set_string(STA(outfile), SF_STR_ARTIST, s);
    if ((s = csound->SF_id_comment) != NULL && *s != '\0')
      sf_set_string(STA(outfile), SF_STR_COMMENT, s);
    if ((s = csound->SF_id_date) != NULL && *s != '\0')
      sf_set_string(STA(outfile), SF_STR_DATE, s);
    /* file is now open */
    STA(osfopen) = 1;

 outset:
    O->sfsampsize = (int) sfsampsize(FORMAT2SF(O->outformat));
    /* calc outbuf size & alloc bufspace */
    STA(outbufsiz) = O->outbufsamps * sizeof(MYFLT);
    STA(outbufp)   = STA(outbuf) = csound->Malloc(csound, STA(outbufsiz));
    if (STA(pipdevout) == 2)
      csound->Message(csound,
                      Str("writing %d sample blks of %lu-bit floats to %s\n"),
                      O->outbufsamps, (unsigned long) sizeof(MYFLT)*8,
                      STA(sfoutname));
    else {
     csound->Message(csound, Str("writing %d-byte blks of %s to %s"),
                    O->outbufsamps * O->sfsampsize,
                    getstrformat(O->outformat), STA(sfoutname));

    if (O->sfheader == 0)
      csound->Message(csound, Str(" (raw)\n"));
    else
      csound->Message(csound, " (%s)\n", type2string(O->filetyp));
    }
    STA(osfopen)   = 1;
    STA(outbufrem) = O->outbufsamps;
}
Пример #2
0
static int srconv(CSOUND *csound, int argc, char **argv)
{
    MYFLT
      *input,     /* pointer to start of input buffer */
      *output,    /* pointer to start of output buffer */
      *nextIn,    /* pointer to next empty word in input */
      *nextOut,   /* pointer to next empty word in output */
      *fxval = 0, /* pointer to start of time-array for time-vary function */
      *fyval = 0, /* pointer to start of P-scale-array for time-vary func */
      *i0,        /* pointer */
      *i1;        /* pointer */

    float
      *window,    /* pointer to center of analysis window */
      *wj,        /* pointer to window */
      *wj1;       /* pointer to window */

    int
      M = 2401,   /* length of window impulse response */
      N = 120,    /* length of sinc period */
      L = 120,    /* internal sample rate is L*Rin */
      m,          /* current input sample in buffer */
      o,          /* current input at L*Rin mod L */
      del,        /* increment */
      WinLen,     /* half-length of window at L*Rin */
      wLen,       /* half-length of window at Rin */
      jMin,       /* initial offset in window */
      mMax;       /* maximum valid m */

    long
      n,                        /* current input sample */
      nMax = 2000000000;        /* last input sample (unless EOF) */

    MYFLT
      beta = FL(6.8),           /* parameter for Kaiser window */
      sum,                      /* scale factor for renormalizing windows */
      fdel,                     /* float del */
      idel,                     /* float del */
      fo,                       /* float o */
      of,                       /* fractional o */
      fL = (MYFLT) L,           /* float L */
      iw,                       /* interpolated window */
      tvx0 = 0,                 /* current x value of time-var function */
      tvx1 = 0,                 /* next x value of time-var function */
      tvdx,                     /* tvx1 - tvx0 */
      tvy0 = 0,                 /* current y value of time-var function */
      tvy1 = 0,                 /* next y value of time-var function */
      tvdy,                     /* tvy1 - tvy0 */
      tvslope = 0,              /* tvdy / tvdx */
      time,                     /* n / Rin */
      invRin,                   /* 1. / Rin */
      P = FL(0.0),              /* Rin / Rout */
      Rin = FL(0.0),            /* input sampling rate */
      Rout = FL(0.0);           /* output sample rate */

    int
      i,k,                      /* index variables */
      nread,                    /* number of bytes read */
      tvflg = 0,                /* flag for time-varying time-scaling */
      tvnxt = 0,                /* counter for stepping thru time-var func */
      tvlen,                    /* length of time-varying function */
      Chans = 1,                /* number of channels */
      chan,                     /* current channel */
      Q = 2;                    /* quality factor */

    FILE        *tvfp = NULL;   /* time-vary function file */
    SOUNDIN     *p;
    int         channel = ALLCHNLS;
    MYFLT       beg_time = FL(0.0), input_dur = FL(0.0), sr = FL(0.0);
    char        *infile = NULL, *bfile = NULL;
    SNDFILE     *inf = NULL;
    char        c, *s;
    const char  *envoutyp;
    char        outformch = 's';
    unsigned    outbufsiz = 0U;
    SNDFILE     *outfd = NULL;
    OPARMS      O;
    int         block = 0;
    char        err_msg[256];

    O.outformat = AE_SHORT;
    /* csound->e0dbfs = csound->dbfs_to_float = FL(1.0);*/

    if ((envoutyp = csound->GetEnv(csound, "SFOUTYP")) != NULL) {
      if (strcmp(envoutyp, "AIFF") == 0)
        O.filetyp = TYP_AIFF;
      else if (strcmp(envoutyp, "WAV") == 0)
        O.filetyp = TYP_WAV;
      else if (strcmp(envoutyp, "IRCAM") == 0)
        O.filetyp = TYP_IRCAM;
      else {
        snprintf(err_msg, 256, Str("%s not a recognized SFOUTYP env setting"),
                envoutyp);
        dieu(csound, err_msg);
        return -1;
      }
    }

    /* call getopt to interpret commandline */

    ++argv;
    while (--argc > 0) {
      s = *argv++;
      if (*s++ == '-') {                /* read all flags:  */
        while ((c = *s++) != '\0') {
          switch (c) {
          case 'o':
            FIND(Str("no outfilename"))
            O.outfilename = s;         /* soundout name */
            for ( ; *s != '\0'; s++) ;
            if (strcmp(O.outfilename, "stdin") == 0) {
              csound->ErrorMsg(csound, Str("-o cannot be stdin"));
              return -1;
            }
#if defined WIN32
            if (strcmp(O.outfilename, "stdout") == 0) {
              csound->ErrorMsg(csound, Str("stdout audio not supported"));
              return -1;
            }
#endif
            break;
          case 'A':
            O.filetyp = TYP_AIFF;      /* AIFF output request*/
            break;
          case 'J':
            O.filetyp = TYP_IRCAM;     /* IRCAM output request */
            break;
          case 'W':
            O.filetyp = TYP_WAV;       /* WAV output request */
            break;
          case 'h':
            O.filetyp = TYP_RAW;       /* skip sfheader  */
            break;
          case 'c':
          case '8':
          case 'a':
          case 'u':
          case 's':
          case 'l':
          case '3':
          case 'f':
            outformch = set_output_format(csound, c, outformch, &O);
            break;
          case 'R':
            O.rewrt_hdr = 1;
            break;
          case 'H':
            if (isdigit(*s)) {
              int n;
              sscanf(s, "%d%n", &O.heartbeat, &n);
              s += n;
            }
            else O.heartbeat = 1;
            break;
          case 'N':
            O.ringbell = 1;        /* notify on completion */
            break;
          case 'Q':
            FIND(Str("No Q argument"))
            sscanf(s,"%d", &Q);
            while (*++s);
            break;
          case 'P':
            FIND(Str("No P argument"))
#if defined(USE_DOUBLE)
            csound->sscanf(s,"%lf", &P);
#else
            csound->sscanf(s,"%f", &P);
#endif
            while (*++s);
            break;
          case 'r':
            FIND(Str("No r argument"))
#if defined(USE_DOUBLE)
            csound->sscanf(s,"%lf", &Rout);
#else
            csound->sscanf(s,"%f", &Rout);
#endif
            while (*++s);
            break;
          case 'i':
            FIND(Str("No break file"))
            tvflg = 1;
            bfile = s;
            while ((*s++)) {}; s--;
            break;
          default:
            csound->Message(csound, Str("Looking at %c\n"), c);
            usage(csound);    /* this exits with error */
            return -1;
          }
        }
      }
      else if (infile == NULL) {
        infile = --s;
        csound->Message(csound, Str("Infile set to %s\n"), infile);
      }
      else {
        csound->Message(csound, Str("End with %s\n"), s);
        usage(csound);
        return -1;
      }
    }
    if (infile == NULL) {
      csound->Message(csound, Str("No input given\n"));
      usage(csound);
      return -1;
    }
    if ((inf = csound->SAsndgetset(csound, infile, &p, &beg_time,
                                   &input_dur, &sr, channel)) == NULL) {
      csound->ErrorMsg(csound, Str("error while opening %s"), infile);
      return -1;
    }
    if (Rin == FL(0.0))
      Rin = (MYFLT)p->sr;
    if (Chans == 0)
      Chans = (int) p->nchanls;
    if (Chans == 0)
      Chans = 1;

    if ((P != FL(0.0)) && (Rout != FL(0.0))) {
      strncpy(err_msg, Str("srconv: cannot specify both -r and -P"), 256);
      goto err_rtn_msg;
    }
    if (P != FL(0.0))
      Rout = Rin / P;
    else if (Rout == FL(0.0))
      Rout = Rin;

    if (tvflg) {
      P = FL(0.0);        /* will be reset to max in time-vary function */
      if ((tvfp = fopen(bfile, "r")) == NULL) {
        strncpy(err_msg,
                Str("srconv: cannot open time-vary function file"), 256);
        goto err_rtn_msg;
      }
      /* register file to be closed by csoundReset() */
      (void) csound->CreateFileHandle(csound, &tvfp, CSFILE_STD, bfile);
      if (UNLIKELY(fscanf(tvfp, "%d", &tvlen) != 1))
        csound->Message(csound, Str("Read failure\n"));
      if(tvlen <= 0) {
            strncpy(err_msg, Str("srconv: tvlen <= 0 "), 256);
            goto err_rtn_msg;
       }
      fxval = (MYFLT*) csound->Malloc(csound, tvlen * sizeof(MYFLT));
      fyval = (MYFLT*) csound->Malloc(csound, tvlen * sizeof(MYFLT));
      i0 = fxval;
      i1 = fyval;
      for (i = 0; i < tvlen; i++, i0++, i1++) {
#ifdef USE_DOUBLE
        if ((fscanf(tvfp, "%lf %lf", i0, i1)) != 2)
#else
        if ((fscanf(tvfp, "%f %f", i0, i1)) != 2)
#endif
          {
            strncpy(err_msg, Str("srconv: too few x-y pairs "
                                 "in time-vary function file"), 256);
            goto err_rtn_msg;
          }
        if (*i1 > P)
          P = *i1;
      }
      Rout = Rin / P;    /* this is min Rout */
      tvx0 = fxval[0];
      tvx1 = fxval[1];
      tvy0 = fyval[0];
      tvy1 = fyval[1];
      tvdx = tvx1 - tvx0;
      if (tvx0 != FL(0.0)) {
        strncpy(err_msg, Str("srconv: first x value "
                             "in time-vary function must be 0"), 256);
        goto err_rtn_msg;
      }
      if (tvy0 <= FL(0.0)) {
        strncpy(err_msg, Str("srconv: invalid initial y value "
                             "in time-vary function"),256);
        goto err_rtn_msg;
      }
      if (tvdx <= FL(0.0)) {
        strncpy(err_msg,
                       Str("srconv: invalid x values in time-vary function"),
                       256);
        goto err_rtn_msg;
      }
      tvdy = tvy1 - tvy0;
      tvslope = tvdy / tvdx;
      tvnxt = 1;
    }
    /* This is not right *********  */
    if (P != FL(0.0)) {
      csound->SetUtilSr(csound,Rin);
    }
    if (P == FL(0.0)) {
      csound->SetUtilSr(csound,Rout);
    }

    if (O.outformat == 0)
      O.outformat = AE_SHORT;//p->format;
    O.sfsampsize = csound->sfsampsize(FORMAT2SF(O.outformat));
    if (O.filetyp == TYP_RAW) {
      O.sfheader = 0;
      O.rewrt_hdr = 0;
    }
    else
      O.sfheader = 1;
#ifdef NeXT
    if (O.outfilename == NULL && !O.filetyp)
      O.outfilename = "test.snd";
    else if (O.outfilename == NULL)
      O.outfilename = "test";
#else
    if (O.outfilename == NULL) {
      if (O.filetyp == TYP_WAV)
        O.outfilename = "test.wav";
      else if (O.filetyp == TYP_AIFF)
        O.outfilename = "test.aif";
      else
        O.outfilename = "test";
    }
#endif
    {
      SF_INFO sfinfo;
      char    *name;
      memset(&sfinfo, 0, sizeof(SF_INFO));
      sfinfo.samplerate = (int) ((double) Rout + 0.5);
      sfinfo.channels = (int) p->nchanls;
      //printf("filetyp=%x outformat=%x\n", O.filetyp, O.outformat);
      sfinfo.format = TYPE2SF(O.filetyp) | FORMAT2SF(O.outformat);
      if (strcmp(O.outfilename, "stdout") != 0) {
        name = csound->FindOutputFile(csound, O.outfilename, "SFDIR");
        if (name == NULL) {
          snprintf(err_msg, 256, Str("cannot open %s."), O.outfilename);
          goto err_rtn_msg;
        }
        outfd = sf_open(name, SFM_WRITE, &sfinfo);
        if (outfd != NULL)
          csound->NotifyFileOpened(csound, name,
                                   csound->type2csfiletype(O.filetyp,
                                                           O.outformat),
                                   1, 0);
        else {
          snprintf(err_msg, 256, Str("libsndfile error: %s\n"), sf_strerror(NULL));
          goto err_rtn_msg;
        }
        csound->Free(csound, name);
      }
      else
        outfd = sf_open_fd(1, SFM_WRITE, &sfinfo, 1);
      if (outfd == NULL) {
        snprintf(err_msg, 256, Str("cannot open %s."), O.outfilename);
        goto err_rtn_msg;
      }
      /* register file to be closed by csoundReset() */
      (void) csound->CreateFileHandle(csound, &outfd, CSFILE_SND_W,
                                      O.outfilename);
      sf_command(outfd, SFC_SET_CLIPPING, NULL, SF_TRUE);
    }
    csound->SetUtilSr(csound, (MYFLT)p->sr);
    csound->SetUtilNchnls(csound, Chans = p->nchanls);

    outbufsiz = OBUF * O.sfsampsize;                   /* calc outbuf size */
    csound->Message(csound, Str("writing %d-byte blks of %s to %s"),
                    outbufsiz, csound->getstrformat(O.outformat),
                    O.outfilename);
    csound->Message(csound, " (%s)\n", csound->type2string(O.filetyp));

 /* this program performs arbitrary sample-rate conversion
    with high fidelity.  the method is to step through the
    input at the desired sampling increment, and to compute
    the output points as appropriately weighted averages of
    the surrounding input points.  there are two cases to
    consider: 1) sample rates are in a small-integer ratio -
    weights are obtained from table, 2) sample rates are in
    a large-integer ratio - weights are linearly
    interpolated from table.  */

 /* calculate increment: if decimating, then window is impulse response of low-
    pass filter with cutoff frequency at half of Rout; if interpolating,
    then window is ipulse response of lowpass filter with cutoff frequency
    at half of Rin. */

    fdel = ((MYFLT) (L * Rin) / Rout);
    del = (int) ((double) fdel + 0.5);
    idel = (MYFLT) del;
    if (del > L)
      N = del;
    if ((Q >= 1) && (Q <= 8))
      M = Q * N * 10 + 1;
    if (tvflg)
      fdel = tvy0 * L;

    invRin  =  FL(1.0) / Rin;

    /* make window: the window is the product of a kaiser and a sin(x)/x */
    window = (float*) csound->Calloc(csound, (size_t) (M + 2) * sizeof(float));
    WinLen = (M-1)/2;
    window += WinLen;
    wLen = (M/2 - L) / L;

    kaiser(M, window, WinLen, 1, (double) beta);

    for (i = 1; i <= WinLen; i++) {
      double  tmp = (double) N;
      tmp = tmp * sin(PI * (double) i / tmp) / (PI * (double) i);
      window[i] = (float) ((double) window[i] * tmp);
    }

    if (Rout < Rin) {
#if 0
      sum = (MYFLT) window[0];
      for (i = L-1; i <= WinLen; i += L)
        sum += (MYFLT) window[i];
      sum = FL(2.0) / sum;
#else
      sum = Rout / (Rin * (MYFLT) window[0]);
#endif
    }
    else
      sum = FL(1.0) / (MYFLT) window[0];

    window[0] = (float) ((double) window[0] * (double) sum);
    for (i = 1; i <= WinLen; i++) {
      window[i] = (float) ((double) window[i] * (double) sum);
      *(window - i) = window[i];
    }

    window[WinLen + 1] = 0.0f;

 /* set up input buffer:  nextIn always points to the next empty
    word in the input buffer.  If the buffer is full, then
    nextIn jumps back to the beginning, and the old values
    are written over. */

    input = (MYFLT*) csound->Calloc(csound, (size_t) IBUF * sizeof(MYFLT));

 /* set up output buffer:  nextOut always points to the next empty
    word in the output buffer.  If the buffer is full, then
    it is flushed, and nextOut jumps back to the beginning. */

    output = (MYFLT*) csound->Calloc(csound, (size_t) OBUF * sizeof(MYFLT));
    nextOut = output;

 /* initialization: */

    nread = csound->getsndin(csound, inf, input, IBUF2, p);
    for(i=0; i < nread; i++)
       input[i] *= 1.0/csound->Get0dBFS(csound);
    nMax = (long)(input_dur * p->sr);
    nextIn = input + nread;
    for (i = nread; i < IBUF2; i++)
      *(nextIn++) = FL(0.0);
    jMin = -(wLen + 1) * L;
    mMax = IBUF2;
    o = n = m = 0;
    fo = FL(0.0);

 /* main loop:   If nMax is not specified it is assumed to be very large
    and then readjusted when read detects the end of input. */

    while (n < nMax) {

      time = n * invRin;

      /* case 1:  (Rin / Rout) * 120 = integer  */

      if ((tvflg == 0) && (idel == fdel)) {
        /* apply window (window is sampled at L * Rin) */

        for (chan = 0; chan < Chans; chan++) {
          *nextOut = FL(0.0);
          k = Chans * (m - wLen) + chan - Chans;
          if (k < 0)
            k += IBUF;
          wj = window + jMin - o;
          for (i = -wLen; i <= wLen+1; i++){
            wj += L;
            k += Chans;
            if (k >= IBUF)
              k -= IBUF;
            *nextOut += (MYFLT) *wj * *(input + k);
          }
          nextOut++;
          if (nextOut >= (output + OBUF)) {
            nextOut = output;
            writebuffer(csound, output, &block, outfd, OBUF, &O);
          }
        }

        /* move window (window advances by del samples at L*Rin sample rate) */

        o += del;
        while (o >= L) {
          o -= L;
          n++;
          m++;
          if ((Chans * (m + wLen + 1)) >= mMax) {
            if (!csound->CheckEvents(csound))
              csound->LongJmp(csound, 1);
            mMax += IBUF2;
            if (nextIn >= (input + IBUF))
              nextIn = input;
            nread = csound->getsndin(csound, inf, nextIn, IBUF2, p);
            for(i=0; i < nread; i++)
               input[i] *= 1.0/csound->Get0dBFS(csound);
            nextIn += nread;
            if (nread < IBUF2)
              nMax = n + wLen + (nread / Chans) + 1;
            for (i = nread; i < IBUF2; i++)
              *(nextIn++) = FL(0.0);
          }
          if ((Chans * m) >= IBUF) {
            m = 0;
            mMax = IBUF2;
          }
        }
      }

      /* case 2: (Rin / Rout) * 120 = non-integer constant */

      else {

        /* apply window (window values are linearly interpolated) */

        for (chan = 0; chan < Chans; chan++) {
          *nextOut = FL(0.0);
          o = (int)fo;
          of = fo - o;
          wj = window + jMin - o;
          wj1 = wj + 1;
          k = Chans * (m - wLen) + chan - Chans;
          if (k < 0)
            k += IBUF;
          for (i = -wLen; i <= wLen+1; i++) {
            wj += L;
            wj1 += L;
            k += Chans;
            if (k >= IBUF)
              k -= IBUF;
            iw = (MYFLT) *wj + of * ((MYFLT) *wj1 - (MYFLT) *wj);
            *nextOut += iw * *(input + k);
          }
          nextOut++;
          if (nextOut >= (output + OBUF)) {
            nextOut = output;
            writebuffer(csound, output, &block, outfd, OBUF, &O);
          }
        }

        /* move window */

        fo += fdel;
        while (fo >= fL) {
          fo -= fL;
          n++;
          m++;
          if ((Chans * (m + wLen + 1)) >= mMax) {
            if (!csound->CheckEvents(csound))
              csound->LongJmp(csound, 1);
            mMax += IBUF2;
            if (nextIn >= (input + IBUF))
              nextIn = input;
            nread = csound->getsndin(csound, inf, nextIn, IBUF2, p);
            for(i=0; i < nread; i++)
               input[i] *= 1.0/csound->Get0dBFS(csound);
            nextIn += nread;
            if (nread < IBUF2)
              nMax = n + wLen + (nread / Chans) + 1;
            for (i = nread; i < IBUF2; i++)
              *(nextIn++) = FL(0.0);
          }
          if ((Chans * m) >= IBUF) {
            m = 0;
            mMax = IBUF2;
          }
        }

        if (tvflg && (time > FL(0.0))) {
          while (tvflg && (time >= tvx1)) {
            if (++tvnxt >= tvlen)
              tvflg = 0;
            else {
              tvx0 = tvx1;
              tvx1 = fxval[tvnxt];
              tvy0 = tvy1;
              tvy1 = fyval[tvnxt];
              tvdx = tvx1 - tvx0;
              if (tvdx <= FL(0.0)) {
                strncpy(err_msg, Str("srconv: invalid x values "
                                     "in time-vary function"), 256);
                goto err_rtn_msg;
              }
              tvdy = tvy1 - tvy0;
              tvslope = tvdy / tvdx;
            }
          }
          P = tvy0 + tvslope * (time - tvx0);
          fdel = (MYFLT) L * P;
        }
      }

    }
    nread = nextOut - output;
    writebuffer(csound, output, &block, outfd, nread, &O);
    csound->Message(csound, "\n\n");
    if (O.ringbell)
      csound->MessageS(csound, CSOUNDMSG_REALTIME, "\a");
    return 0;

 err_rtn_msg:
    csound->ErrorMsg(csound, err_msg);
    return -1;
}
Пример #3
0
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;
}
Пример #4
0
static int dnoise(CSOUND *csound, int argc, char **argv)
{
     OPARMS  O;
     csound->GetOParms(csound, &O);

    MYFLT   beg = -FL(1.0), end = -FL(1.0);
    long    Beg = 0, End = 99999999;

    MYFLT
        *ibuf1,     /* pointer to start of input buffer */
        *ibuf2,     /* pointer to start of input buffer */
        *obuf1,     /* pointer to start of output buffer */
        *obuf2,     /* pointer to start of output buffer */
        *fbuf,      /* pointer to start of FFT buffer */
        *aWin,      /* pointer to center of analysis window */
        *sWin,      /* pointer to center of synthesis window */
        *i0,        /* pointer to real channels */
        *i1,        /* pointer to imaginary channels */
        *j0,        /* pointer to real channels */
        *j1,        /* pointer to imaginary channels */
        *f,         /* pointer to FFT buffer */
        *f0,        /* pointer to real channels */
        *f1,        /* pointer to imaginary channels */
        *w,         /* pointer to window */
        *mbuf,      /* m most recent frames of FFT */
        *nbuf,      /* m most recent frames of FFT */
        *nref,      /* noise reference buffer */
        *rsum,      /* running sum of magnitude-squared spectrum */
        *ssum,      /* running sum of magnitude-squared spectrum */
        *ibp,       /* pointer to next input to be read */
        *ib0,       /* pointer to output buffer */
        *ib1,       /* pointer to output buffer */
        *ib2,       /* pointer to output buffer */
        *obp,       /* pointer to next output to be read */
        *ob0,       /* pointer to output buffer */
        *ob1,       /* pointer to output buffer */
        *ob2;       /* pointer to output buffer */

    int
        N = 0,      /* number of phase vocoder channels (bands) */
        Np2,        /* N+2 */
        M = 0,      /* length of aWin impulse response */
        L = 0,      /* length of sWin impulse response */
        D = 0,      /* decimation factor (default will be M/8) */
        I = 0,      /* interpolation factor (default will be I=D)*/
        W = -1,     /* filter overlap factor (determines M, L) */
        ibuflen,    /* size of ibuf */
        obuflen,    /* size of obuf */
        aLen,       /* half-length of analysis window */
        sLen;       /* half-length of synthesis window */

    long
        oCnt = 0L,  /* number of samples written to output */
        nI,         /* current input (analysis) sample */
        nO,         /* current output (synthesis) sample */
        nImodR,     /* current input sample mod R */
        nMaxOut,    /* last output (synthesis) sample */
        nMin,       /* first input (analysis) sample */
        nMax,       /* last input sample (unless EOF) */
        lnread,     /* total input samples read */
        lj,         /* to satisfy lame Microsoft compiler */
        lk;         /* to satisfy lame Microsoft compiler */

    SNDFILE *fp = NULL; /* noise reference file */

    MYFLT
        Ninv,       /* 1. / N */
      //RoverTwoPi, /* R/D divided by 2*Pi */
      //TwoPioverR, /* 2*Pi divided by R/I */
        sum,        /* scale factor for renormalizing windows */
      //rIn,        /* decimated sampling rate */
      //rOut,       /* pre-interpolated sampling rate */
        invR,       /* 1. / srate */
        time,       /* nI / srate */
        gain,       /* gain of noise gate */
        g0 = -FL(40.0),/* minimum gain for noise gate */
        g0m,        /* 1. - g0 */
        th = FL(30.0), /* threshold above noise reference (dB) */
        avg,        /* average square energy */
        fac,        /* factor in gain computation */
        minv,       /* 1 / m */
        R = -FL(1.0);  /* input sampling rate */

    int    i,j,k,   /* index variables */
        ibs,        /* current starting location in input buffer */
        ibc,        /* current location in input buffer */
        obs,        /* current starting location in output buffer */
        obc,        /* current location in output buffer */
        m = 5,      /* number of frames to save in mbuf */
        mi = 0,     /* frame offset index in mbuf */
        mj,         /* delayed offset index in mbuf */
        md,         /* number of frames of delay in mbuf (m/2) */
        mp,         /* mi * Np2 */
        sh = 1,     /* sharpness control for noise gate gain */
        nread,      /* number of bytes read */
        N2,         /* N/2 */
        Meven = 0,  /* flag for even M */
        Leven = 0,  /* flag for even L */
        Verbose = 0,/* flag for verbose output to stderr */
        Chans = -1, /* number of audio input channels (stereo = 2) */
        chan,       /* channel counter */
        flag = 1,   /* end-of-input flag */
        first = 0;  /* first-time-thru flag */

    SOUNDIN     *p, *pn;
    char        *infile = NULL, *nfile = NULL;
    SNDFILE     *inf = NULL, *outfd = NULL;
    char        c, *s;
    int         channel = ALLCHNLS;
    MYFLT       beg_time  = FL(0.0), input_dur  = FL(0.0), sr  = FL(0.0);
    MYFLT       beg_ntime = FL(0.0), input_ndur = FL(0.0), srn = FL(0.0);
    const char  *envoutyp = NULL;
    unsigned int  outbufsiz = 0U;
    int         nrecs = 0;

    /* audio is now normalised after call to getsndin  */
    /* csound->e0dbfs = csound->dbfs_to_float = FL(1.0); */

    if ((envoutyp = csound->GetEnv(csound, "SFOUTYP")) != NULL) {
      if (strcmp(envoutyp, "AIFF") == 0)
        O.filetyp = TYP_AIFF;
      else if (strcmp(envoutyp, "WAV") == 0)
        O.filetyp = TYP_WAV;
      else if (strcmp(envoutyp, "IRCAM") == 0)
        O.filetyp = TYP_IRCAM;
      else {
        csound->Message(csound, Str("%s not a recognised SFOUTYP env setting"),
                                envoutyp);
        return -1;
      }
    }
    {
      ++argv;
      while (--argc>0) {
        s = *argv++;
        if (*s++ == '-') {                        /* read all flags:  */
          while ((c = *s++) != '\0') {
            switch (c) {
            case 'o':
              FIND("no outfilename");
              O.outfilename = s;                 /* soundout name */
              for ( ; *s != '\0'; s++) ;
              if (strcmp(O.outfilename, "stdin") == 0) {
                csound->Message(csound, Str("-o cannot be stdin\n"));
                return -1;
              }
              break;
            case 'i':
              FIND("no noisefilename");
              nfile = s;
              for ( ; *s != '\0'; s++) ;
              break;
            case 'A':
              if (O.filetyp == TYP_WAV)
                csound->Warning(csound,
                                Str("-A overriding local default WAV out"));
              O.filetyp = TYP_AIFF;    /* AIFF output request*/
              break;
            case 'J':
              if (O.filetyp == TYP_AIFF || O.filetyp == TYP_WAV)
                csound->Warning(csound, Str("-J overriding local default "
                                            "AIFF/WAV out"));
              O.filetyp = TYP_IRCAM;   /* IRCAM output request */
              break;
            case 'W':
              if (O.filetyp == TYP_AIFF)
                csound->Warning(csound,
                                Str("-W overriding local default AIFF out"));
              O.filetyp = TYP_WAV;      /* WAV output request */
              break;
            case 'h':
              O.filetyp = TYP_RAW;
              O.sfheader = 0;           /* skip sfheader  */
              break;
            case 'c':
              O.outformat = AE_CHAR;     /* 8-bit char soundfile */
              break;
            case '8':
              O.outformat = AE_UNCH;     /* 8-bit unsigned char file */
              break;
            case 'a':
              O.outformat = AE_ALAW;     /* a-law soundfile */
              break;
            case 'u':
              O.outformat = AE_ULAW;     /* mu-law soundfile */
              break;
            case 's':
              O.outformat = AE_SHORT;    /* short_int soundfile */
              break;
            case 'l':
              O.outformat = AE_LONG;     /* long_int soundfile */
              break;
            case 'f':
              O.outformat = AE_FLOAT;    /* float soundfile */
              break;
            case 'R':
              O.rewrt_hdr = 1;
              break;
            case 'H':
              if (isdigit(*s)) {
                int n;
                sscanf(s, "%d%n", &O.heartbeat, &n);
                s += n;
              }
              else O.heartbeat = 1;
              break;
            case 't':
              FIND(Str("no t argument"));
#if defined(USE_DOUBLE)
              csound->sscanf(s,"%lf",&th);
#else
              csound->sscanf(s,"%f",&th);
#endif
              while (*++s);
              break;
            case 'S':
              FIND("no s arg");
              sscanf(s,"%d", &sh);
              while (*++s);
              break;
            case 'm':
              FIND("no m arg");
#if defined(USE_DOUBLE)
              csound->sscanf(s,"%lf",&g0);
#else
              csound->sscanf(s,"%f",&g0);
#endif
              while (*++s);
              break;
            case 'n':
              FIND(Str("no n argument"));
              sscanf(s,"%d", &m);
              while (*++s);
              break;
            case 'b':
              FIND(Str("no b argument"));
#if defined(USE_DOUBLE)
              csound->sscanf(s,"%lf",&beg);
#else
              csound->sscanf(s,"%f",&beg);
#endif
              while (*++s);
              break;
            case 'B': FIND(Str("no B argument"));
              sscanf(s,"%ld", &Beg);
              while (*++s);
              break;
            case 'e': FIND("no e arg");
#if defined(USE_DOUBLE)
              csound->sscanf(s,"%lf",&end);
#else
              csound->sscanf(s,"%f",&end);
#endif
              while (*++s);
              break;
            case 'E': FIND(Str("no E argument"));
              sscanf(s,"%ld", &End);
              while (*++s);
              break;
            case 'N': FIND(Str("no N argument"));
              sscanf(s,"%d", &N);
              while (*++s);
              break;
            case 'M': FIND(Str("no M argument"));
              sscanf(s,"%d", &M);
              while (*++s);
              break;
            case 'L': FIND(Str("no L argument"));
              sscanf(s,"%d", &L);
              while (*++s);
              break;
            case 'w': FIND(Str("no w argument"));
              sscanf(s,"%d", &W);
              while (*++s);
              break;
            case 'D': FIND(Str("no D argument"));
              sscanf(s,"%d", &D);
              while (*++s);
              break;
            case 'V':
              Verbose = 1; break;
            default:
              csound->Message(csound, Str("Looking at %c\n"), c);
              return dnoise_usage(csound, -1);  /* this exits with error */
            }
          }
        }
        else if (infile==NULL) {
          infile = --s;
          csound->Message(csound, Str("Infile set to %s\n"), infile);
        }
        else {
          csound->Message(csound, Str("End with %s\n"), s);
          return dnoise_usage(csound, -1);
        }
      }
    }
    if (infile == NULL) {
      csound->Message(csound, Str("dnoise: no input file\n"));
      return dnoise_usage(csound, -1);
    }
    if (nfile == NULL) {
      csound->Message(csound, Str("Must have an example noise file (-i name)\n"));
      return -1;
    }
    if ((inf = csound->SAsndgetset(csound, infile, &p, &beg_time,
                                   &input_dur, &sr, channel)) == NULL) {
      csound->Message(csound, Str("error while opening %s"), infile);
      return -1;
    }
    if (O.outformat == 0) O.outformat = p->format;
    O.sfsampsize = csound->sfsampsize(FORMAT2SF(O.outformat));
    if (O.filetyp == TYP_RAW) {
      O.sfheader = 0;
      O.rewrt_hdr = 0;
    }
    else
      O.sfheader = 1;
    if (O.outfilename == NULL)
      O.outfilename = "test";
    {
      SF_INFO sfinfo;
      char    *name;
      memset(&sfinfo, 0, sizeof(SF_INFO));
      sfinfo.samplerate = (int) p->sr;
      sfinfo.channels = (int) p->nchanls;
      sfinfo.format = TYPE2SF(O.filetyp) | FORMAT2SF(O.outformat);
      if (strcmp(O.outfilename, "stdout") != 0) {
        name = csound->FindOutputFile(csound, O.outfilename, "SFDIR");
        if (name == NULL) {
          csound->Message(csound, Str("cannot open %s.\n"), O.outfilename);
          return -1;
        }
        outfd = sf_open(name, SFM_WRITE, &sfinfo);
        if (outfd != NULL)
          csound->NotifyFileOpened(csound, name,
                      csound->type2csfiletype(O.filetyp, O.outformat), 1, 0);
        csound->Free(csound, name);
      }
      else
        outfd = sf_open_fd(1, SFM_WRITE, &sfinfo, 1);
      if (outfd == NULL) {
        csound->Message(csound, Str("cannot open %s."), O.outfilename);
        return -1;
      }
      /* register file to be closed by csoundReset() */
      (void)csound->CreateFileHandle(csound, &outfd, CSFILE_SND_W,
                                     O.outfilename);
      sf_command(outfd, SFC_SET_CLIPPING, NULL, SF_TRUE);
    }

    csound->SetUtilSr(csound, (MYFLT)p->sr);
    csound->SetUtilNchnls(csound, Chans = p->nchanls);

    /* read header info */
    if (R < FL(0.0))
      R = (MYFLT)p->sr;
    if (Chans < 0)
      Chans = (int) p->nchanls;
    p->nchanls = Chans;

    if (Chans > 2) {
      csound->Message(csound, Str("dnoise: input MUST be mono or stereo\n"));
      return -1;
    }

    /* read noise reference file */

    if ((fp = csound->SAsndgetset(csound, nfile, &pn, &beg_ntime,
                                  &input_ndur, &srn, channel)) == NULL) {
      csound->Message(csound, Str("dnoise: cannot open noise reference file\n"));
      return -1;
    }

    if (sr != srn) {
      csound->Message(csound, Str("Incompatible sample rates\n"));
      return -1;
    }
    /* calculate begin and end times in NOISE file */
    if (beg >= FL(0.0)) Beg = (long) (beg * R);
    if (end >= FL(0.0)) End = (long) (end * R);
    else if (End == 99999999) End = (long) (input_ndur * R);

    nMin = Beg * Chans;            /* total number of samples to skip */
    nMax = End - Beg;            /* number of samples per channel to process */

    /* largest valid FFT size is 8192 */
    if (N == 0)
      N = 1024;
    for (i = 1; i < 4096; i *= 2)
      if (i >= N)
        break;
    if (i != N)
      csound->Message(csound,
                      Str("dnoise: warning - N not a valid power of two; "
                          "revised N = %d\n"),i);
    N = i;
    N2 = N / 2;
    Np2 = N + 2;
    Ninv = FL(1.0) / N;

    if (W != -1) {
      if (M != 0)
        csound->Message(csound,
                        Str("dnoise: warning - do not specify both M and W\n"));
      else if (W == 0)
        M = 4*N;
      else if (W == 1)
        M = 2*N;
      else if (W == 2)
        M = N;
      else if (W == 3)
        M = N2;
      else
        csound->Message(csound, Str("dnoise: warning - invalid W ignored\n"));
    }

    if (M == 0)
      M = N;
    if ((M%2) == 0)
      Meven = 1;

    if (L == 0)
      L = M;
    if ((L%2) == 0)
      Leven = 1;

    if (M < 7) {
      csound->Message(csound, Str("dnoise: warning - M is too small\n"));
      exit(~1);
    }
    if (D == 0)
      D = M / 8;

    I = D;

    lj = (long) M + 3 * (long) D;
    lj *= (long) Chans;
    if (lj > 32767) {
      csound->Message(csound, Str("dnoise: M too large\n"));
      return -1;
    }
    lj = (long) L + 3 * (long) I;
    lj *= (long) Chans;
    if (lj > 32767) {
      csound->Message(csound, Str("dnoise: L too large\n"));
      return -1;
    }

    ibuflen = Chans * (M + 3 * D);
    obuflen = Chans * (L + 3 * I);
    outbufsiz = obuflen * sizeof(MYFLT);                 /* calc outbuf size */
#if 0
    outbuf = csound->Malloc(csound, (size_t) outbufsiz); /* & alloc bufspace */
#endif
    csound->Message(csound, Str("writing %u-byte blks of %s to %s"),
                    outbufsiz, csound->getstrformat(O.outformat),
                    O.outfilename);
    csound->Message(csound, " (%s)\n", csound->type2string(O.filetyp));
/*  spoutran = spoutsf; */

    minv = FL(1.0) / (MYFLT)m;
    md = m / 2;
    g0 = (MYFLT) pow(10.0,(double)(0.05*(double)g0));
    g0m = FL(1.0) - g0;
    th = (MYFLT) pow(10.0,(double)(0.05*(double)th));

    /* set up analysis window: The window is assumed to be symmetric
        with M total points.  After the initial memory allocation,
        aWin always points to the midpoint of the window (or one
        half sample to the right, if M is even); aLen is half the
        true window length (rounded down).  If the window duration
        is longer than the transform (M > N), then the window is
        multiplied by a sin(x)/x function to meet the condition:
        aWin[Ni] = 0 for i != 0.  In either case, the
        window is renormalized so that the phase vocoder amplitude
        estimates are properly scaled.  */

    if ((aWin = (MYFLT*) csound->Calloc(csound,
                                        (M+Meven) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

    aLen = M/2;
    aWin += aLen;

    hamming(aWin, aLen, Meven);
    for (i = 1; i <= aLen; i++) {
      aWin[-i] = aWin[i-1];
    }

    if (M > N) {
      if (Meven)
        *aWin *= (MYFLT)N * (MYFLT) sin(PI*0.5/(double)N) /( PI_F*FL(0.5));
      for (i = 1; i <= aLen; i++)
        aWin[i] *= (MYFLT) (N * sin(PI * ((double) i + 0.5 * (double) Meven)
                                    / (double) N)
                            / (PI * (i + 0.5 * (double) Meven)));
      for (i = 1; i <= aLen; i++)
        aWin[-i] = aWin[i - Meven];
    }

    sum = FL(0.0);
    for (i = -aLen; i <= aLen; i++)
      sum += aWin[i];

    sum = FL(2.0) / sum;    /* factor of 2 comes in later in trig identity */

    for (i = -aLen; i <= aLen; i++)
      aWin[i] *= sum;

    /* set up synthesis window:  For the minimal mean-square-error
        formulation (valid for N >= M), the synthesis window
        is identical to the analysis window (except for a
        scale factor), and both are even in length.  If N < M,
        then an interpolating synthesis window is used. */

    if ((sWin = (MYFLT*) csound->Calloc(csound,
                                        (L+Leven) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

    sLen = L/2;
    sWin += sLen;

    if (M <= N) {
      hamming(sWin, sLen, Leven);
      for (i = 1; i <= sLen; i++)
        sWin[-i] = sWin[i - Leven];

      for (i = -sLen; i <= sLen; i++)
        sWin[i] *= sum;

      sum = FL(0.0);
      for (i = -sLen; i <= sLen; i+=I)
        sum += sWin[i] * sWin[i];

      sum = FL(1.0) / sum;

      for (i = -sLen; i <= sLen; i++)
        sWin[i] *= sum;
    }
    else {
      hamming(sWin, sLen, Leven);
      for (i = 1; i <= sLen; i++)
        sWin[-i] = sWin[i - Leven];

      if (Leven)
        *sWin *= (MYFLT) (I * sin(PI*0.5/(double) I) / (PI*0.5));
      for (i = 1; i <= sLen; i++)
        sWin[i] *= (MYFLT)(I * sin(PI * ((double) i + 0.5 * (double) Leven)
                                   / (double) I)
                           / (PI * ((double) i + 0.5 * (double) Leven)));
      for (i = 1; i <= sLen; i++)
        sWin[i] = sWin[i - Leven];

      sum = FL(1.0) / sum;

      for (i = -sLen; i <= sLen; i++)
        sWin[i] *= sum;
    }

    /* set up input buffer:  nextIn always points to the next empty
        word in the input buffer (i.e., the sample following
        sample number (n + aLen)).  If the buffer is full,
        then nextIn jumps back to the beginning, and the old
        values are written over. */

    if ((ibuf1 = (MYFLT *) csound->Calloc(csound,
                                          ibuflen * sizeof(MYFLT))) == NULL) {
      ERR("dnoise: insufficient memory\n");
    }
    if ((ibuf2 = (MYFLT *) csound->Calloc(csound,
                                          ibuflen * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

    /* set up output buffer:  nextOut always points to the next word
        to be shifted out.  The shift is simulated by writing the
        value to the standard output and then setting that word
        of the buffer to zero.  When nextOut reaches the end of
        the buffer, it jumps back to the beginning.  */

    if ((obuf1 = (MYFLT*) csound->Calloc(csound,
                                         obuflen * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }
    if ((obuf2 = (MYFLT*) csound->Calloc(csound,
                                         obuflen * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

    /* set up analysis buffer for (N/2 + 1) channels: The input is real,
        so the other channels are redundant. */

    if ((fbuf = (MYFLT*) csound->Calloc(csound, Np2 * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

/* noise reduction: calculate noise reference by taking as many
        consecutive FFT's as possible in noise soundfile, and
        averaging them all together.  Multiply by th*th to
        establish threshold for noise-gating in each bin. */

    if ((nref = (MYFLT*) csound->Calloc(csound,
                                        (N2 + 1) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

    if ((mbuf = (MYFLT*) csound->Calloc(csound,
                                        (m * Np2) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }
    if ((nbuf = (MYFLT*) csound->Calloc(csound,
                                        (m * Np2) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }
    if ((rsum = (MYFLT*) csound->Calloc(csound,
                                        (N2 + 1) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }
    if ((ssum = (MYFLT*) csound->Calloc(csound,
                                        (N2 + 1) * sizeof(MYFLT))) == NULL) {
      ERR(Str("dnoise: insufficient memory\n"));
    }

    /* skip over nMin samples */
    while (nMin > (long)ibuflen) {
      if (!csound->CheckEvents(csound))
        csound->LongJmp(csound, 1);
      nread = csound->getsndin(csound, fp, ibuf1, ibuflen, pn);
      for(i=0; i < nread; i++)
        ibuf1[i] *= 1.0/csound->Get0dBFS(csound);
      if (nread < ibuflen) {
        ERR(Str("dnoise: begin time is greater than EOF of noise file!"));
      }
      nMin -= (long) ibuflen;
    }
    if (!csound->CheckEvents(csound))
      csound->LongJmp(csound, 1);
    i = (int) nMin;
    nread = csound->getsndin(csound, fp, ibuf1, i, pn);
    for(i=0; i < nread; i++)
        ibuf1[i] *= 1.0/csound->Get0dBFS(csound);
    if (nread < i) {
      ERR(Str("dnoise: begin time is greater than EOF of noise file!"));
    }
    k = 0;
    lj = Beg;  /* single channel only */
    while (lj < End) {
      if (!csound->CheckEvents(csound))
        csound->LongJmp(csound, 1);
      lj += (long) N;
      nread = csound->getsndin(csound, fp, fbuf, N, pn);
      for(i=0; i < nread; i++)
        fbuf[i] *= 1.0/csound->Get0dBFS(csound);
      if (nread < N)
        break;

      fbuf[N] = FL(0.0);
      fbuf[N + 1] = FL(0.0);

      fast(csound, fbuf, N);

      f = fbuf;
      for (i = 0; i <= N+1; i++, f++)
        *f  *= Ninv;

      f = nref;
      i0 = fbuf;
      i1 = i0 + 1;
      for (i = 0; i <= N2; i++, f++, i0 += 2, i1 += 2) {
        fac = *i0 * *i0;        /* fac = fbuf[2*i] * fbuf[2*i]; */
        fac += *i1 * *i1;       /* fac += fbuf[2*i+1] * fbuf[2*i+1]; */
        *f += fac;              /* nref[i] += fac; */
      }
      k++;
    }
    if (k == 0) {
      ERR(Str("dnoise: not enough samples of noise reference\n"));
    }
    fac = th * th / k;
    f = nref;
    for (i = 0; i <= N2; i++, f++)
      *f *= fac;                   /* nref[i] *= fac; */

    /* initialization: input time starts negative so that the rightmost
        edge of the analysis filter just catches the first non-zero
        input samples; output time equals input time. */

    /* zero ibuf1 to start */
    f = ibuf1;
    for (i = 0; i < ibuflen; i++, f++)
      *f = FL(0.0);
    if (!csound->CheckEvents(csound))
      csound->LongJmp(csound, 1);
    /* fill ibuf2 to start */
    nread = csound->getsndin(csound, inf, ibuf2, ibuflen, p);
/*     nread = read(inf, ibuf2, ibuflen*sizeof(MYFLT)); */
/*     nread /= sizeof(MYFLT); */
    for(i=0; i < nread; i++)
        ibuf2[i] *= 1.0/csound->Get0dBFS(csound);
    lnread = nread;
    f = ibuf2 + nread;
    for (i = nread; i < ibuflen; i++, f++)
      *f = FL(0.0);

    //rIn = ((MYFLT) R / D);
    //rOut = ((MYFLT) R / I);
    invR = FL(1.0) / R;
    nI = -(aLen / D) * D;    /* input time (in samples) */
    nO = nI;                 /* output time (in samples) */
    ibs = ibuflen + Chans * (nI - aLen - 1);    /* starting position in ib1 */
    ib1 = ibuf1;        /* filled with zeros to start */
    ib2 = ibuf2;        /* first buffer of speech */
    obs = Chans * (nO - sLen - 1);    /* starting position in ob1 */
    while (obs < 0) {
      obs += obuflen;
      first++;
    }
    ob1 = obuf1;        /* filled with garbage to start */
    ob2 = obuf2;        /* first output buffer */
    nImodR = nI;        /* for reporting progress */
    mi = 0;
    mj = m - md;
    if (mj >= m)
      mj = 0;
    mp = mi * Np2;

    nMax =  (long)(input_dur * R);          /* Do it all */
    nMaxOut = (long) (nMax * Chans);
    while (nI < (nMax + aLen)) {

      time = nI * invR;

      for (chan = 0; chan < Chans; chan++) {

    /* prepare for analysis: always begin reading from ib1 */
    /*                         always begin writing to ob1 */

        if (ibs >= ibuflen) {    /* done reading from ib1 */
          if (!csound->CheckEvents(csound))
            csound->LongJmp(csound, 1);
          /* swap buffers */
          ib0 = ib1;
          ib1 = ib2;
          ib2 = ib0;
          ibs -= ibuflen;
          /* fill ib2 */
          nread = csound->getsndin(csound, inf, ib2, ibuflen, p);
          for(i=0; i < nread; i++)
               ibuf2[i] *= 1.0/csound->Get0dBFS(csound);
          lnread += nread;
          f = ib2 + nread;
          for (i = nread; i < ibuflen; i++, f++)
            *f = FL(0.0);
        }
        ibc = ibs + chan;
        ibp = ib1 + ibs + chan;

        if (obs >= obuflen) {    /* done writing to ob1 */
          /* dump ob1 (except at beginning) */
          if (first > 0) {
            first--;
          }
          else {
            if ((oCnt + obuflen) < nMaxOut) {
              oCnt += writebuffer(csound, outfd, ob1, obuflen, &nrecs, &O);
            }
            else {
              i = (int) (nMaxOut - oCnt);
              oCnt += writebuffer(csound, outfd, ob1, i, &nrecs, &O);
            }
          }
          /* zero ob1 */
          f = ob1;
          for (i = 0; i < obuflen; i++, f++)
            *f = FL(0.0);
          /* swap buffers */
          ob0 = ob1;
          ob1 = ob2;
          ob2 = ob0;
          obs -= obuflen;
        }
        obc = obs + chan;
        obp = ob1 + obs + chan;

    /* analysis: The analysis subroutine computes the complex output at
        time n of (N/2 + 1) of the phase vocoder channels.  It operates
        on input samples (n - aLen) thru (n + aLen).
        It expects aWin to point to the center of a
        symmetric window of length (2 * aLen + 1).  It is the
        responsibility of the main program to ensure that these values
        are correct.  The results are returned in fbuf as succesive
        pairs of real and imaginary values for the lowest (N/2 + 1)
        channels.   The subroutine fast implements an
        efficient FFT call for a real input sequence.  */

        f = fbuf;
        for (i = 0; i < N+2; i++, f++)
          *f = FL(0.0);

        lk = nI - (long) aLen - 1;            /*time shift*/
        while ((long) lk < 0L)
          lk += (long) N;
        k = (int) (lk % (long) N);

        f = fbuf + k;
        w = aWin - aLen;
        for (i = -aLen; i <= aLen; i++, k++, f++, w++) {
          ibp += Chans;
          ibc += Chans;
          if (ibc >= ibuflen) {
            ibc = chan;
            ibp = ib2 + chan;
          }
          if (k >= N) {
            k = 0;
            f = fbuf;
          }
          *f += *w * *ibp;
        }

        fast(csound, fbuf, N);

        /* noise reduction: for each bin, calculate average magnitude-squared
            and calculate corresponding gain.  Apply this gain to delayed
            FFT values in mbuf[mj*Np2 + i?]. */

        if (chan == 0) {
          f = rsum;
          i0 = mbuf + mp;
          i1 = i0 + 1;
          j0 = mbuf + mj * Np2;
          j1 = j0 + 1;
          f0 = fbuf;
          f1 = f0 + 1;
          for (i = 0; i <= N2;
               i++, f++, i0+=2, i1+=2, f0+=2, f1+=2, j0+=2, j1+=2) {
            /*
             *  ii0 = 2 * i;
             *  ii1 = ii0 + 1;
             *
             *  rsum[i] -= mbuf[mp + ii0] * mbuf[mp + ii0];
             *  rsum[i] -= mbuf[mp + ii1] * mbuf[mp + ii1];
             *  rsum[i] += fbuf[ii0] * fbuf[ii0];
             *  rsum[i] += fbuf[ii1] * fbuf[ii1];
             */
            *f -= *i0 * *i0;
            *f -= *i1 * *i1;
            *f += *f0 * *f0;
            *f += *f1 * *f1;
            avg = minv * *f;        /* avg = minv * rsum[i]; */
            if (avg < FL(0.0))
              avg = FL(0.0);
            if (avg == FL(0.0))
              fac = FL(0.0);
            else
              fac = avg / (avg + nref[i]);
            for (j = 1; j < sh; j++)
              fac *= fac;
            gain = g0m * fac + g0;
            /*
             * mbuf[mp + ii0] = fbuf[ii0];
             * mbuf[mp + ii1] = fbuf[ii1];
             * fbuf[ii0] = gain * mbuf[mj*Np2 + ii0];
             * fbuf[ii1] = gain * mbuf[mj*Np2 + ii1];
             */
            *i0 = *f0;
            *i1 = *f1;
            *f0 = gain * *j0;
            *f1 = gain * *j1;
          }
        }
        else {
          f = ssum;
          i0 = nbuf + mp;
          i1 = i0 + 1;
          j0 = nbuf + mj * Np2;
          j1 = j0 + 1;
          f0 = fbuf;
          f1 = f0 + 1;
          for (i = 0; i <= N2;
               i++, f++, i0+=2, i1+=2, f0+=2, f1+=2, j0+=2, j1+=2) {
            /*
             *  ii0 = 2 * i;
             *  ii1 = ii0 + 1;
             *
             * ssum[i] -= nbuf[mp + ii0] * nbuf[mp + ii0];
             * ssum[i] -= nbuf[mp + ii1] * nbuf[mp + ii1];
             * ssum[i] += fbuf[ii0] * fbuf[ii0];
             * ssum[i] += fbuf[ii1] * fbuf[ii1];
             */
            *f -= *i0 * *i0;
            *f -= *i1 * *i1;
            *f += *f0 * *f0;
            *f += *f1 * *f1;
            avg = minv * *f;      /* avg = minv * ssum[i]; */
            if (avg < FL(0.0))
              avg = FL(0.0);
            if (avg == FL(0.0))
              fac = FL(0.0);
            else
              fac = avg / (avg + nref[i]);
            for (j = 1; j < sh; j++)
              fac *= fac;
            gain = g0m * fac + g0;
            /*
             * nbuf[mp + ii0] = fbuf[ii0];
             * nbuf[mp + ii1] = fbuf[ii1];
             * fbuf[ii0] = gain * nbuf[mj*Np2 + ii0];
             * fbuf[ii1] = gain * nbuf[mj*Np2 + ii1];
             */
            *i0 = *f0;
            *i1 = *f1;
            *f0 = gain * *j0;
            *f1 = gain * *j1;
          }
        }

        if (chan == (Chans - 1)) {
          if (++mi >= m)
            mi = 0;
          if (++mj >= m)
            mj = 0;
          mp = mi * Np2;
        }

    /* synthesis: The synthesis subroutine uses the Weighted Overlap-Add
        technique to reconstruct the time-domain signal.  The (N/2 + 1)
        phase vocoder channel outputs at time n are inverse Fourier
        transformed, windowed, and added into the output array. */

        fsst(csound, fbuf, N);

        lk = nO - (long) sLen - 1;            /*time shift*/
        while (lk < 0)
          lk += (long) N;
        k = (int) (lk % (long) N);

        f = fbuf + k;
        w = sWin - sLen;
        for (i = -sLen; i <= sLen; i++, k++, f++, w++) {
          obp += Chans;
          obc += Chans;
          if (obc >= obuflen) {
            obc = chan;
            obp = ob2 + chan;
          }
          if (k >= N) {
            k = 0;
            f = fbuf;
          }
          *obp += *w * *f;
        }

        if (flag) {
          if (nread < ibuflen) { /* EOF detected */
            flag = 0;
            if ((lnread / Chans) < nMax)
              nMax = (lnread / Chans);
          }
        }

      }

      ibs += (Chans * D);            /* starting point in ibuf */
      obs += (Chans * I);            /* starting point in obuf */

      nI += (long) D;                /* increment time */
      nO += (long) I;

      if (Verbose) {
        nImodR += D;
        if (nImodR > (long) R) {
          nImodR -= (long) R;
          csound->Message(csound,
                          Str("%5.1f seconds of input complete\n"),(time+D*invR));
        }
      }

    }

    nMaxOut = (long) (nMax * Chans);
    i = (int) (nMaxOut - oCnt);
    if (i > obuflen) {
      writebuffer(csound, outfd, ob1, obuflen, &nrecs, &O);
      i -= obuflen;
      ob1 = ob2;
    }
    if (i > 0)
      writebuffer(csound, outfd, ob1, i, &nrecs, &O);

/*  csound->rewriteheader(outfd); */
    csound->Message(csound, "\n\n");
    if (Verbose) {
      csound->Message(csound, Str("processing complete\n"));
      csound->Message(csound, "N = %d\n", N);
      csound->Message(csound, "M = %d\n", M);
      csound->Message(csound, "L = %d\n", L);
      csound->Message(csound, "D = %d\n", D);
    }
    return 0;
}
Пример #5
0
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;
}
Пример #6
0
PUBLIC int csoundStart(CSOUND *csound) // DEBUG
{
    OPARMS  *O = csound->oparms;
    int     n;

    /* if a CSD was not used, check options */
    if(csound->csdname == NULL)
          checkOptions(csound);

   if(csound->engineStatus & CS_STATE_COMP){
       csound->Message(csound, "Csound is already started, call csoundReset()\n"
                                "before starting again \n");
       return CSOUND_ERROR;
    }

   { /* test for dummy module request */
    char *s;
     if((s = csoundQueryGlobalVariable(csound, "_RTAUDIO")) != NULL)
       if(strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 ||
           strcmp(s, "NULL") == 0) {
        csound->Message(csound, Str("setting dummy interface\n"));
      csound->SetPlayopenCallback(csound, playopen_dummy);
      csound->SetRecopenCallback(csound, recopen_dummy);
      csound->SetRtplayCallback(csound, rtplay_dummy);
      csound->SetRtrecordCallback(csound, rtrecord_dummy);
      csound->SetRtcloseCallback(csound, rtclose_dummy);
      csound->SetAudioDeviceListCallback(csound, audio_dev_list_dummy);
        }

     /* and midi */
  if(csound->enableHostImplementedMIDIIO == 0){
  if((s = csoundQueryGlobalVariable(csound, "_RTMIDI")) != NULL)
    if(strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 ||
     strcmp(s, "NULL") == 0) {
     csound->SetMIDIDeviceListCallback(csound, midi_dev_list_dummy);
     csound->SetExternalMidiInOpenCallback(csound, DummyMidiInOpen);
     csound->SetExternalMidiReadCallback(csound,  DummyMidiRead);
     csound->SetExternalMidiInCloseCallback(csound, NULL);
     csound->SetExternalMidiOutOpenCallback(csound,  DummyMidiOutOpen);
     csound->SetExternalMidiWriteCallback(csound, DummyMidiWrite);
     csound->SetExternalMidiOutCloseCallback(csound, NULL);
     }
     }
  else {
   s = csoundQueryGlobalVariable(csound, "_RTMIDI");
   strcpy(s, "hostbased");
   csoundSetConfigurationVariable(csound,"rtmidi", s);
  }
   }


   /* VL 30-12-12 csoundInitModules is always called here now to enable
       Csound to start without calling csoundCompile, but directly from
       csoundCompileOrc() and csoundReadSco()
    */
   if(csound->modules_loaded == 0){
    csoundLoadExternals(csound);    /* load plugin opcodes */
    if (csoundInitModules(csound) != 0)
           csound->LongJmp(csound, 1);
    csound->modules_loaded = 1;
    }
    if (csound->instr0 == NULL) { /* compile dummy instr0 to allow csound to
                                     start with no orchestra */
        csoundCompileOrc(csound, "idummy = 0 \n");
     }

    if ((n = setjmp(csound->exitjmp)) != 0) {
      return ((n - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS);
    }



    /* if sound file type is still not known, check SFOUTYP */
    if (O->filetyp <= 0) {
      const char  *envoutyp;
      envoutyp = csoundGetEnv(csound, "SFOUTYP");
      if (envoutyp != NULL && envoutyp[0] != '\0') {
        if (strcmp(envoutyp, "AIFF") == 0)
          O->filetyp = TYP_AIFF;
        else if (strcmp(envoutyp, "WAV") == 0 || strcmp(envoutyp, "WAVE") == 0)
          O->filetyp = TYP_WAV;
        else if (strcmp(envoutyp, "IRCAM") == 0)
          O->filetyp = TYP_IRCAM;
        else if (strcmp(envoutyp, "RAW") == 0)
          O->filetyp = TYP_RAW;
        else {
          dieu(csound, Str("%s not a recognised SFOUTYP env setting"),
               envoutyp);
        }
      }
      else
#if !defined(__MACH__)
        O->filetyp = TYP_WAV;   /* default to WAV if even SFOUTYP is unset */
#else
      O->filetyp = TYP_AIFF;  /* ... or AIFF on the Mac */
#endif
    }
    /* everything other than a raw sound file has a header */
    O->sfheader = (O->filetyp == TYP_RAW ? 0 : 1);
    if (O->Linein || O->Midiin || O->FMidiin)
      O->RTevents = 1;
    if (!O->sfheader)
      O->rewrt_hdr = 0;         /* cannot rewrite header of headerless file */
    /* VL 9 04 15: these not need occur jointly anymore */
    /* 
    if (O->sr_override || O->kr_override) {
      if (!O->sr_override || !O->kr_override)
        dieu(csound, Str("srate and krate overrides must occur jointly"));
    } */
    if (!O->outformat)                      /* if no audioformat yet  */
      O->outformat = AE_SHORT;              /*  default to short_ints */
    O->sfsampsize = sfsampsize(FORMAT2SF(O->outformat));
    O->informat = O->outformat;             /* informat default */


    if (O->numThreads > 1) {
      void csp_barrier_alloc(CSOUND *, pthread_barrier_t **, int);
      int i;
      THREADINFO *current = NULL;

      csound->multiThreadedBarrier1 = csound->CreateBarrier(O->numThreads);
      csound->multiThreadedBarrier2 = csound->CreateBarrier(O->numThreads);

      csp_barrier_alloc(csound, &(csound->barrier1), O->numThreads);
      csp_barrier_alloc(csound, &(csound->barrier2), O->numThreads);

      csound->multiThreadedComplete = 0;

      for (i = 1; i < O->numThreads; i++) {
        THREADINFO *t = csound->Malloc(csound, sizeof(THREADINFO));

        t->threadId = csound->CreateThread(&kperfThread, (void *)csound);
        t->next = NULL;

        if (current == NULL) {
          csound->multiThreadedThreadInfo = t;
        }
        else {
          current->next = t;
        }
        current = t;
      }

      csound->WaitBarrier(csound->barrier2);
    }
    csound->engineStatus |= CS_STATE_COMP;
    if(csound->oparms->daemon > 1)
        UDPServerStart(csound,csound->oparms->daemon);


    return musmon(csound);
}
Пример #7
0
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;
}