예제 #1
0
파일: trim.c 프로젝트: Amalerd/SoxPlayer
/*
 * Process options
 */
static int sox_trim_getopts(sox_effect_t * effp, int argc, char **argv)
{
    char *end;
    priv_t * trim = (priv_t *) effp->priv;
  --argc, ++argv;

    /* Do not know sample rate yet so hold off on completely parsing
     * time related strings.
     */
    switch (argc) {
        case 2:
            end = argv[1];
            if (*end == '=') {
                trim->end_is_absolute = sox_true;
                end++;
            } else trim->end_is_absolute = sox_false;
            trim->end_str = lsx_malloc(strlen(end)+1);
            strcpy(trim->end_str, end);
            /* Do a dummy parse to see if it will fail */
            if (lsx_parsesamples(0., trim->end_str, &trim->length, 't') == NULL)
              return lsx_usage(effp);
        case 1:
            trim->start_str = lsx_malloc(strlen(argv[0])+1);
            strcpy(trim->start_str,argv[0]);
            /* Do a dummy parse to see if it will fail */
            if (lsx_parsesamples(0., trim->start_str, &trim->start, 't') == NULL)
              return lsx_usage(effp);
            break;
        default:
            return lsx_usage(effp);

    }
    return (SOX_SUCCESS);
}
예제 #2
0
파일: trim.c 프로젝트: Emisense/eTracks
/*
 * Process options
 */
static int sox_trim_getopts(sox_effect_t * effp, int n, char **argv)
{
    priv_t * trim = (priv_t *) effp->priv;

    /* Do not know sample rate yet so hold off on completely parsing
     * time related strings.
     */
    switch (n) {
    case 2:
        trim->length_str = lsx_malloc(strlen(argv[1])+1);
        strcpy(trim->length_str,argv[1]);
        /* Do a dummy parse to see if it will fail */
        if (lsx_parsesamples(0., trim->length_str, &trim->length, 't') == NULL)
            return lsx_usage(effp);
    case 1:
        trim->start_str = lsx_malloc(strlen(argv[0])+1);
        strcpy(trim->start_str,argv[0]);
        /* Do a dummy parse to see if it will fail */
        if (lsx_parsesamples(0., trim->start_str, &trim->start, 't') == NULL)
            return lsx_usage(effp);
        break;
    default:
        return lsx_usage(effp);

    }
    return (SOX_SUCCESS);
}
예제 #3
0
파일: mcompand.c 프로젝트: DeathOfMe/sox
/*
 * Process options
 *
 * Don't do initialization now.
 * The 'info' fields are not yet filled in.
 */
static int sox_mcompand_getopts_1(comp_band_t * l, size_t n, char **argv)
{
      char *s;
      size_t rates, i, commas;

      /* Start by checking the attack and decay rates */

      for (s = argv[0], commas = 0; *s; ++s)
        if (*s == ',') ++commas;

      if (commas % 2 == 0) /* There must be an even number of
                              attack/decay parameters */
      {
        lsx_fail("compander: Odd number of attack & decay rate parameters");
        return (SOX_EOF);
      }

      rates = 1 + commas/2;
      l->attackRate = lsx_malloc(sizeof(double) * rates);
      l->decayRate  = lsx_malloc(sizeof(double) * rates);
      l->volume = lsx_malloc(sizeof(double) * rates);
      l->expectedChannels = rates;
      l->delay_buf = NULL;

      /* Now tokenise the rates string and set up these arrays.  Keep
         them in seconds at the moment: we don't know the sample rate yet. */

      s = strtok(argv[0], ","); i = 0;
      do {
        l->attackRate[i] = atof(s); s = strtok(NULL, ",");
        l->decayRate[i]  = atof(s); s = strtok(NULL, ",");
        ++i;
      } while (s != NULL);

      if (!lsx_compandt_parse(&l->transfer_fn, argv[1], n>2 ? argv[2] : 0))
        return SOX_EOF;

      /* Set the initial "volume" to be attibuted to the input channels.
         Unless specified, choose 1.0 (maximum) otherwise clipping will
         result if the user has seleced a long attack time */
      for (i = 0; i < l->expectedChannels; ++i) {
        double v = n>=4 ? pow(10.0, atof(argv[3])/20) : 1.0;
        l->volume[i] = v;

        /* If there is a delay, store it. */
        if (n >= 5) l->delay = atof(argv[4]);
        else l->delay = 0.0;
      }
    return (SOX_SUCCESS);
}
예제 #4
0
static int sox_silence_start(sox_effect_t * effp)
{
    priv_t *silence = (priv_t *)effp->priv;
    uint64_t temp;

    /* When you want to remove silence, small window sizes are
     * better or else RMS will look like non-silence at
     * aburpt changes from load to silence.
     */
    silence->window_size = (effp->in_signal.rate / 50) * 
        effp->in_signal.channels;
    silence->window = lsx_malloc(silence->window_size * sizeof(double));

    clear_rms(effp);

    /* Now that we know sample rate, reparse duration. */
    if (silence->start)
    {
        if (lsx_parsesamples(effp->in_signal.rate, silence->start_duration_str,
                             &temp, 's') == NULL)
            return lsx_usage(effp);
        silence->start_duration = temp * effp->in_signal.channels;
    }
    if (silence->stop)
    {
        if (lsx_parsesamples(effp->in_signal.rate,silence->stop_duration_str,
                             &temp,'s') == NULL)
            return lsx_usage(effp);
        silence->stop_duration = temp * effp->in_signal.channels;
    }

    if (silence->start)
        silence->mode = SILENCE_TRIM;
    else
        silence->mode = SILENCE_COPY;

    silence->start_holdoff = lsx_malloc(sizeof(sox_sample_t)*silence->start_duration);
    silence->start_holdoff_offset = 0;
    silence->start_holdoff_end = 0;
    silence->start_found_periods = 0;

    silence->stop_holdoff = lsx_malloc(sizeof(sox_sample_t)*silence->stop_duration);
    silence->stop_holdoff_offset = 0;
    silence->stop_holdoff_end = 0;
    silence->stop_found_periods = 0;

    effp->out_signal.length = SOX_UNKNOWN_LEN; /* depends on input data */

    return(SOX_SUCCESS);
}
예제 #5
0
파일: formats.c 프로젝트: dmkrepo/libsox
static FILE * xfopen(char const * identifier, char const * mode, lsx_io_type * io_type)
{
  *io_type = lsx_io_file;

  if (*identifier == '|') {
    FILE * f = NULL;
#ifdef HAVE_POPEN
#ifndef POPEN_MODE
#define POPEN_MODE "r"
#endif
    f = popen(identifier + 1, POPEN_MODE);
    *io_type = lsx_io_pipe;
#else
    lsx_fail("this build of SoX cannot open pipes");
#endif
    return f;
  }
  else if (is_url(identifier)) {
    FILE * f = NULL;
#ifdef HAVE_POPEN
    char const * const command_format = "wget --no-check-certificate -q -O- \"%s\"";
    char * command = lsx_malloc(strlen(command_format) + strlen(identifier));
    sprintf(command, command_format, identifier);
    f = popen(command, POPEN_MODE);
    free(command);
    *io_type = lsx_io_url;
#else
    lsx_fail("this build of SoX cannot open URLs");
#endif
    return f;
  }
  return fopen(identifier, mode);
}
예제 #6
0
static event_t event_new()
{
    event_t ev = lsx_malloc(sizeof(struct event_tag));
    if (!ev) return 0;
    pthread_mutex_init(&ev->mutex, 0);
    pthread_cond_init(&ev->cond, 0);
    ev->triggered = sox_false;
    return ev;
}
예제 #7
0
파일: alsa.c 프로젝트: Amalerd/SoxPlayer
static int setup(sox_format_t * ft)
{
  priv_t                 * p = (priv_t *)ft->priv;
  snd_pcm_hw_params_t    * params = NULL;
  snd_pcm_format_mask_t  * mask = NULL;
  snd_pcm_uframes_t      min, max;
  unsigned               n;
  int                    err;

  _(snd_pcm_open, (&p->pcm, ft->filename, ft->mode == 'r'? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0));
  _(snd_pcm_hw_params_malloc, (&params));
  _(snd_pcm_hw_params_any, (p->pcm, params));
#if SND_LIB_VERSION >= 0x010009               /* Disable alsa-lib resampling: */
  _(snd_pcm_hw_params_set_rate_resample, (p->pcm, params, 0));
#endif
  _(snd_pcm_hw_params_set_access, (p->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));

  _(snd_pcm_format_mask_malloc, (&mask));           /* Set format: */
  snd_pcm_hw_params_get_format_mask(params, mask);
  _(select_format, (&ft->encoding.encoding, &ft->encoding.bits_per_sample, mask, &p->format));
  _(snd_pcm_hw_params_set_format, (p->pcm, params, p->format));
  snd_pcm_format_mask_free(mask), mask = NULL;

  n = ft->signal.rate;                              /* Set rate: */
  _(snd_pcm_hw_params_set_rate_near, (p->pcm, params, &n, 0));
  ft->signal.rate = n;

  n = ft->signal.channels;                          /* Set channels: */
  _(snd_pcm_hw_params_set_channels_near, (p->pcm, params, &n));
  ft->signal.channels = n;

  /* Set buf_len > > sox_globals.bufsiz for no underrun: */
  p->buf_len = sox_globals.bufsiz * 8 / NBYTES / ft->signal.channels;
  _(snd_pcm_hw_params_get_buffer_size_min, (params, &min));
  _(snd_pcm_hw_params_get_buffer_size_max, (params, &max));
  p->period = range_limit(p->buf_len, min, max) / 8;
  p->buf_len = p->period * 8;
  _(snd_pcm_hw_params_set_period_size_near, (p->pcm, params, &p->period, 0));
  _(snd_pcm_hw_params_set_buffer_size_near, (p->pcm, params, &p->buf_len));
  if (p->period * 2 > p->buf_len) {
    lsx_fail_errno(ft, SOX_EPERM, "buffer too small");
    goto error;
  }

  _(snd_pcm_hw_params, (p->pcm, params));           /* Configure ALSA */
  snd_pcm_hw_params_free(params), params = NULL;
  _(snd_pcm_prepare, (p->pcm));
  p->buf_len *= ft->signal.channels;                /* No longer in `frames' */
  p->buf = lsx_malloc(p->buf_len * NBYTES);
  return SOX_SUCCESS;

error:
  if (mask) snd_pcm_format_mask_free(mask);
  if (params) snd_pcm_hw_params_free(params);
  return SOX_EOF;
}
예제 #8
0
파일: mcompand.c 프로젝트: DeathOfMe/sox
/*
 * Processed signed long samples from ibuf to obuf.
 * Return number of samples processed.
 */
static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
                     size_t *isamp, size_t *osamp) {
  priv_t * c = (priv_t *) effp->priv;
  comp_band_t * l;
  size_t len = min(*isamp, *osamp);
  size_t band, i;
  sox_sample_t *abuf, *bbuf, *cbuf, *oldabuf, *ibuf_copy;
  double out;

  if (c->band_buf_len < len) {
    c->band_buf1 = lsx_realloc(c->band_buf1,len*sizeof(sox_sample_t));
    c->band_buf2 = lsx_realloc(c->band_buf2,len*sizeof(sox_sample_t));
    c->band_buf3 = lsx_realloc(c->band_buf3,len*sizeof(sox_sample_t));
    c->band_buf_len = len;
  }

  len -= len % effp->out_signal.channels;

  ibuf_copy = lsx_malloc(*isamp * sizeof(sox_sample_t));
  memcpy(ibuf_copy, ibuf, *isamp * sizeof(sox_sample_t));

  /* split ibuf into bands using filters, pipe each band through sox_mcompand_flow_1, then add back together and write to obuf */

  memset(obuf,0,len * sizeof *obuf);
  for (band=0,abuf=ibuf_copy,bbuf=c->band_buf2,cbuf=c->band_buf1;band<c->nBands;++band) {
    l = &c->bands[band];

    if (l->topfreq)
      crossover_flow(effp, &l->filter, abuf, bbuf, cbuf, len);
    else {
      bbuf = abuf;
      abuf = cbuf;
    }
    if (abuf == ibuf_copy)
      abuf = c->band_buf3;
    (void)sox_mcompand_flow_1(effp, c,l,bbuf,abuf,len, (size_t)effp->out_signal.channels);
    for (i=0;i<len;++i)
    {
      out = obuf[i] + abuf[i];
      SOX_SAMPLE_CLIP_COUNT(out, effp->clips);
      obuf[i] = out;
    }
    oldabuf = abuf;
    abuf = cbuf;
    cbuf = oldabuf;
  }

  *isamp = *osamp = len;

  free(ibuf_copy);

  return SOX_SUCCESS;
}
예제 #9
0
static int start(sox_effect_t * effp)
{
  priv_t * p = (priv_t *)effp->priv;
  size_t max_delay;

  if (!p->max_arg)
    return SOX_EFF_NULL;
  if (effp->flow < p->argc)
    lsx_parsesamples(effp->in_signal.rate, p->argv[effp->flow], &p->buffer_size, 't');
  lsx_parsesamples(effp->in_signal.rate, p->max_arg, &max_delay, 't');
  p->buffer_index = p->delay = 0;
  p->pad = max_delay - p->buffer_size;
  p->buffer = lsx_malloc(p->buffer_size * sizeof(*p->buffer));
  return SOX_SUCCESS;
}
예제 #10
0
파일: formats.c 프로젝트: dmkrepo/libsox
void sox_append_comments(sox_comments_t * comments, char const * comment)
{
  char * end;
  if (comment) {
    while ((end = strchr(comment, '\n'))) {
      size_t len = end - comment;
      char * c = lsx_malloc((len + 1) * sizeof(*c));
      strncpy(c, comment, len);
      c[len] = '\0';
      sox_append_comment(comments, c);
      comment += len + 1;
      free(c);
    }
    if (*comment)
      sox_append_comment(comments, comment);
  }
}
예제 #11
0
파일: util.c 프로젝트: Amalerd/SoxPlayer
int lsx_enum_option(int c, lsx_enum_item const * items)
{
  lsx_enum_item const * p = lsx_find_enum_text(lsx_optarg, items, sox_false);
  if (p == NULL) {
    size_t len = 1;
    char * set = lsx_malloc(len);
    *set = 0;
    for (p = items; p->text; ++p) {
      set = lsx_realloc(set, len += 2 + strlen(p->text));
      strcat(set, ", "); strcat(set, p->text);
    }
    lsx_fail("-%c: `%s' is not one of: %s.", c, lsx_optarg, set + 2);
    free(set);
    return INT_MAX;
  }
  return p->value;
}
예제 #12
0
static void start(sox_format_t * ft)
{
  priv_t * sf = (priv_t *)ft->priv;
  int subtype = ft_enc(ft->encoding.bits_per_sample? ft->encoding.bits_per_sample : ft->signal.precision, ft->encoding.encoding);
  sf->log_buffer_ptr = sf->log_buffer = lsx_malloc((size_t)LOG_MAX);
  sf->sf_info = lsx_calloc(1, sizeof(SF_INFO));

  /* Copy format info */
  if (subtype) {
    if (strcmp(ft->filetype, "sndfile") == 0)
      sf->sf_info->format = name_to_format(ft->filename) | subtype;
    else
      sf->sf_info->format = name_to_format(ft->filetype) | subtype;
  }
  sf->sf_info->samplerate = ft->signal.rate;
  sf->sf_info->channels = ft->signal.channels;
  if (ft->signal.channels)
    sf->sf_info->frames = ft->signal.length / ft->signal.channels;
}
예제 #13
0
static int open_audio(priv_t * ffmpeg, AVStream *st)
{
  AVCodecContext *c;
  AVCodec *codec;

  c = st->codec;

  /* find the audio encoder */
  codec = avcodec_find_encoder(c->codec_id);
  if (!codec) {
    lsx_fail("ffmpeg CODEC not found");
    return SOX_EOF;
  }

  /* open it */
  if (avcodec_open(c, codec) < 0) {
    lsx_fail("ffmpeg could not open CODEC");
    return SOX_EOF;
  }

  ffmpeg->audio_buf_raw = lsx_malloc((size_t)AVCODEC_MAX_AUDIO_FRAME_SIZE + 32);
  ffmpeg->audio_buf_aligned = ALIGN16(ffmpeg->audio_buf_raw);

  /* ugly hack for PCM codecs (will be removed ASAP with new PCM
     support to compute the input frame size in samples */
  if (c->frame_size <= 1) {
    ffmpeg->audio_input_frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE / c->channels;
    switch(st->codec->codec_id) {
    case CODEC_ID_PCM_S16LE:
    case CODEC_ID_PCM_S16BE:
    case CODEC_ID_PCM_U16LE:
    case CODEC_ID_PCM_U16BE:
      ffmpeg->audio_input_frame_size >>= 1;
      break;
    default:
      break;
    }
  } else
예제 #14
0
파일: mp3.c 프로젝트: IntelligentVoice/sox
static int startread(sox_format_t * ft)
{
  priv_t *p = (priv_t *) ft->priv;
  size_t ReadSize;
  sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
  int open_library_result;

  LSX_DLLIBRARY_OPEN(
      p,
      mad_dl,
      MAD_FUNC_ENTRIES,
      "MAD decoder library",
      mad_library_names,
      open_library_result);
  if (open_library_result)
    return SOX_EOF;

  p->mp3_buffer_size = sox_globals.bufsiz;
  p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);

  ft->signal.length = SOX_UNSPEC;
  if (ft->seekable) {
#ifdef USING_ID3TAG
    read_comments(ft);
    rewind((FILE*)ft->fp);
    if (!ft->signal.length)
#endif
      if (!ignore_length)
        ft->signal.length = mp3_duration_ms(ft);
  }

  p->mad_stream_init(&p->Stream);
  p->mad_frame_init(&p->Frame);
  p->mad_synth_init(&p->Synth);
  mad_timer_reset(&p->Timer);

  ft->encoding.encoding = SOX_ENCODING_MP3;

  /* Decode at least one valid frame to find out the input
   * format.  The decoded frame will be saved off so that it
   * can be processed later.
   */
  ReadSize = lsx_readbuf(ft, p->mp3_buffer, p->mp3_buffer_size);
  if (ReadSize != p->mp3_buffer_size && ferror((FILE*)ft->fp))
    return SOX_EOF;

  p->mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);

  /* Find a valid frame before starting up.  This makes sure
   * that we have a valid MP3 and also skips past ID3v2 tags
   * at the beginning of the audio file.
   */
  p->Stream.error = 0;
  while (p->mad_frame_decode(&p->Frame,&p->Stream))
  {
      /* check whether input buffer needs a refill */
      if (p->Stream.error == MAD_ERROR_BUFLEN)
      {
          if (sox_mp3_input(ft) == SOX_EOF)
              return SOX_EOF;

          continue;
      }

      /* Consume any ID3 tags */
      sox_mp3_inputtag(ft);

      /* FIXME: We should probably detect when we've read
       * a bunch of non-ID3 data and still haven't found a
       * frame.  In that case we can abort early without
       * scanning the whole file.
       */
      p->Stream.error = 0;
  }

  if (p->Stream.error)
  {
      lsx_fail_errno(ft,SOX_EOF,"No valid MP3 frame found");
      return SOX_EOF;
  }

  switch(p->Frame.header.mode)
  {
      case MAD_MODE_SINGLE_CHANNEL:
      case MAD_MODE_DUAL_CHANNEL:
      case MAD_MODE_JOINT_STEREO:
      case MAD_MODE_STEREO:
          ft->signal.channels = MAD_NCHANNELS(&p->Frame.header);
          break;
      default:
          lsx_fail_errno(ft, SOX_EFMT, "Cannot determine number of channels");
          return SOX_EOF;
  }

  p->FrameCount=1;

  p->mad_timer_add(&p->Timer,p->Frame.header.duration);
  p->mad_synth_frame(&p->Synth,&p->Frame);
  ft->signal.precision = MP3_MAD_PRECISION;
  ft->signal.rate=p->Synth.pcm.samplerate;
  if (ignore_length)
    ft->signal.length = SOX_UNSPEC;
  else {
    ft->signal.length = (uint64_t)(ft->signal.length * .001 * ft->signal.rate + .5);
    ft->signal.length *= ft->signal.channels;  /* Keep separate from line above! */
  }

  p->cursamp = 0;

  return SOX_SUCCESS;
}
예제 #15
0
static int sox_fade_getopts(sox_effect_t * effp, int argc, char **argv)
{

    priv_t * fade = (priv_t *) effp->priv;
    char t_char[2];
    int t_argno;
  --argc, ++argv;

    if (argc < 1 || argc > 4)
         return lsx_usage(effp);

    /* because sample rate is unavailable at this point we store the
     * string off for later computations.
     */

    if (sscanf(argv[0], "%1[qhltp]", t_char))
    {
        fade->in_fadetype = *t_char;
        fade->out_fadetype = *t_char;

        argv++;
        argc--;
    }
    else
    {
        /* No type given. */
        fade->in_fadetype = 'l';
        fade->out_fadetype = 'l';
    }

    fade->in_stop_str = lsx_malloc(strlen(argv[0])+1);
    strcpy(fade->in_stop_str,argv[0]);
    /* Do a dummy parse to see if it will fail */
    if (lsx_parsesamples(0., fade->in_stop_str, &fade->in_stop, 't') == NULL)
      return lsx_usage(effp);

    fade->out_start_str = fade->out_stop_str = 0;

    for (t_argno = 1; t_argno < argc && t_argno < 3; t_argno++)
    {
        /* See if there is fade-in/fade-out times/curves specified. */
        if(t_argno == 1)
        {
            fade->out_stop_str = lsx_malloc(strlen(argv[t_argno])+1);
            strcpy(fade->out_stop_str,argv[t_argno]);

            /* Do a dummy parse to see if it will fail */
            if (lsx_parsesamples(0., fade->out_stop_str,
                                &fade->out_stop, 't') == NULL)
              return lsx_usage(effp);
        }
        else
        {
            fade->out_start_str = lsx_malloc(strlen(argv[t_argno])+1);
            strcpy(fade->out_start_str,argv[t_argno]);

            /* Do a dummy parse to see if it will fail */
            if (lsx_parsesamples(0., fade->out_start_str,
                                &fade->out_start, 't') == NULL)
              return lsx_usage(effp);
        }
    } /* End for(t_argno) */

    return(SOX_SUCCESS);
}
예제 #16
0
파일: echo.c 프로젝트: 5in4/libsox.dll
/*
 * Prepare for processing.
 */
static int sox_echo_start(sox_effect_t * effp)
{
        priv_t * echo = (priv_t *) effp->priv;
        int i;
        float sum_in_volume;
        long j;

        echo->maxsamples = 0;
        if ( echo->in_gain < 0.0 )
        {
                lsx_fail("echo: gain-in must be positive!");
                return (SOX_EOF);
        }
        if ( echo->in_gain > 1.0 )
        {
                lsx_fail("echo: gain-in must be less than 1.0!");
                return (SOX_EOF);
        }
        if ( echo->out_gain < 0.0 )
        {
                lsx_fail("echo: gain-in must be positive!");
                return (SOX_EOF);
        }
        for ( i = 0; i < echo->num_delays; i++ ) {
                echo->samples[i] = echo->delay[i] * effp->in_signal.rate / 1000.0;
                if ( echo->samples[i] < 1 )
                {
                    lsx_fail("echo: delay must be positive!");
                    return (SOX_EOF);
                }
                if ( echo->samples[i] > (ptrdiff_t)DELAY_BUFSIZ )
                {
                        lsx_fail("echo: delay must be less than %g seconds!",
                                DELAY_BUFSIZ / effp->in_signal.rate );
                        return (SOX_EOF);
                }
                if ( echo->decay[i] < 0.0 )
                {
                    lsx_fail("echo: decay must be positive!" );
                    return (SOX_EOF);
                }
                if ( echo->decay[i] > 1.0 )
                {
                    lsx_fail("echo: decay must be less than 1.0!" );
                    return (SOX_EOF);
                }
                if ( echo->samples[i] > echo->maxsamples )
                        echo->maxsamples = echo->samples[i];
        }
        echo->delay_buf = lsx_malloc(sizeof (double) * echo->maxsamples);
        for ( j = 0; j < echo->maxsamples; ++j )
                echo->delay_buf[j] = 0.0;
        /* Be nice and check the hint with warning, if... */
        sum_in_volume = 1.0;
        for ( i = 0; i < echo->num_delays; i++ )
                sum_in_volume += echo->decay[i];
        if ( sum_in_volume * echo->in_gain > 1.0 / echo->out_gain )
                lsx_warn("echo: warning >>> gain-out can cause saturation of output <<<");
        echo->counter = 0;
        echo->fade_out = echo->maxsamples;

  effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */

        return (SOX_SUCCESS);
}
예제 #17
0
/*
 * Prepare processing.
 * Do all initializations.
 */
static int start(sox_effect_t* effp)
{
    priv_t* p = (priv_t*)effp->priv;
    int result = SOX_SUCCESS;
    spx_int32_t int_val;
    float float_val;

    if (p->samples_per_frame)
    {
        p->buffer_end = p->samples_per_frame;
    }
    else
    {
        p->buffer_end = effp->in_signal.rate / p->frames_per_second;
        if (!p->buffer_end)
        {
            lsx_fail("frames_per_second too large for the current sample rate.");
            return SOX_EOF;
        }
    }

    p->buffer_opos = p->buffer_end;
    effp->out_signal.precision = 16;

    p->buffer = lsx_malloc(p->buffer_end * sizeof(p->buffer[0]));
    if (!p->buffer)
    {
        result = SOX_ENOMEM;
        goto Done;
    }

    p->sps = speex_preprocess_state_init(p->buffer_end, effp->in_signal.rate);
    if (!p->sps)
    {
        lsx_fail("Failed to initialize preprocessor DSP.");
        result = SOX_EOF;
        goto Done;
    }

    int_val = p->agc ? 1 : 2;
    speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_AGC, &int_val);
    if (p->agc)
    {
        float_val = p->agc * 327.68f;
        speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_AGC_LEVEL, &float_val);
    }

    int_val = p->denoise ? 1 : 2;
    speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_DENOISE, &int_val);
    if (p->denoise)
    {
        int_val = -(spx_int32_t)p->denoise;
        speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &int_val);
    }

    int_val = p->dereverb ? 1 : 2;
    speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_DEREVERB, &int_val);

Done:
    if (result != SOX_SUCCESS)
        stop(effp);

    return result;
}
예제 #18
0
파일: sphere.c 프로젝트: CaptainHayashi/sox
static int start_read(sox_format_t * ft)
{
  unsigned long header_size_ul = 0, num_samples_ul = 0;
  sox_encoding_t encoding = SOX_ENCODING_SIGN2;
  size_t     header_size, bytes_read;
  size_t     num_samples = 0;
  unsigned       bytes_per_sample = 0;
  unsigned       channels = 1;
  unsigned       rate = 16000;
  char           fldname[64], fldtype[16], fldsval[128];
  char           * buf;

  /* Magic header */
  if (lsx_reads(ft, fldname, (size_t)8) || strncmp(fldname, "NIST_1A", (size_t)7) != 0) {
    lsx_fail_errno(ft, SOX_EHDR, "Sphere header does not begin with magic word `NIST_1A'");
    return (SOX_EOF);
  }

  if (lsx_reads(ft, fldsval, (size_t)8)) {
    lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
    return (SOX_EOF);
  }

  /* Determine header size, and allocate a buffer large enough to hold it. */
  sscanf(fldsval, "%lu", &header_size_ul);
  buf = lsx_malloc(header_size = header_size_ul);

  /* Skip what we have read so far */
  header_size -= 16;

  if (lsx_reads(ft, buf, header_size) == SOX_EOF) {
    lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
    free(buf);
    return (SOX_EOF);
  }

  header_size -= (strlen(buf) + 1);

  while (strncmp(buf, "end_head", (size_t)8) != 0) {
    if (strncmp(buf, "sample_n_bytes", (size_t)14) == 0)
      sscanf(buf, "%63s %15s %u", fldname, fldtype, &bytes_per_sample);
    else if (strncmp(buf, "channel_count", (size_t)13) == 0)
      sscanf(buf, "%63s %15s %u", fldname, fldtype, &channels);
    else if (strncmp(buf, "sample_count ", (size_t)13) == 0)
      sscanf(buf, "%53s %15s %lu", fldname, fldtype, &num_samples_ul);
    else if (strncmp(buf, "sample_rate ", (size_t)12) == 0)
      sscanf(buf, "%53s %15s %u", fldname, fldtype, &rate);
    else if (strncmp(buf, "sample_coding", (size_t)13) == 0) {
      sscanf(buf, "%63s %15s %127s", fldname, fldtype, fldsval);
      if (!strcasecmp(fldsval, "ulaw") || !strcasecmp(fldsval, "mu-law"))
        encoding = SOX_ENCODING_ULAW;
      else if (!strcasecmp(fldsval, "pcm"))
        encoding = SOX_ENCODING_SIGN2;
      else {
        lsx_fail_errno(ft, SOX_EFMT, "sph: unsupported coding `%s'", fldsval);
        free(buf);
        return SOX_EOF;
      }
    }
    else if (strncmp(buf, "sample_byte_format", (size_t)18) == 0) {
      sscanf(buf, "%53s %15s %127s", fldname, fldtype, fldsval);
      if (strcmp(fldsval, "01") == 0)         /* Data is little endian. */
        ft->encoding.reverse_bytes = MACHINE_IS_BIGENDIAN;
      else if (strcmp(fldsval, "10") == 0)    /* Data is big endian. */
        ft->encoding.reverse_bytes = MACHINE_IS_LITTLEENDIAN;
      else if (strcmp(fldsval, "1")) {
        lsx_fail_errno(ft, SOX_EFMT, "sph: unsupported coding `%s'", fldsval);
        free(buf);
        return SOX_EOF;
      }
    }

    if (lsx_reads(ft, buf, header_size) == SOX_EOF) {
      lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
      free(buf);
      return (SOX_EOF);
    }

    header_size -= (strlen(buf) + 1);
  }

  if (!bytes_per_sample)
    bytes_per_sample = encoding == SOX_ENCODING_ULAW? 1 : 2;

  while (header_size) {
    bytes_read = lsx_readbuf(ft, buf, header_size);
    if (bytes_read == 0) {
      free(buf);
      return (SOX_EOF);
    }
    header_size -= bytes_read;
  }
  free(buf);

  if (ft->seekable) {
    /* Check first four bytes of data to see if it's shorten compressed. */
    char           shorten_check[4];

    if (lsx_readchars(ft, shorten_check, sizeof(shorten_check)))
      return SOX_EOF;
    lsx_seeki(ft, -(off_t)sizeof(shorten_check), SEEK_CUR);

    if (!memcmp(shorten_check, "ajkg", sizeof(shorten_check))) {
      lsx_fail_errno(ft, SOX_EFMT,
                     "File uses shorten compression, cannot handle this.");
      return (SOX_EOF);
    }
  }

  num_samples = num_samples_ul;
  return lsx_check_read_params(ft, channels, (sox_rate_t)rate, encoding,
      bytes_per_sample << 3, (uint64_t)num_samples * channels, sox_true);
}
예제 #19
0
파일: flac.c 프로젝트: Emisense/eTracks
static int start_write(sox_format_t * const ft)
{
  priv_t * p = (priv_t *)ft->priv;
  FLAC__StreamEncoderState status;
  unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */

  if (ft->encoding.compression != HUGE_VAL) {
    compression_level = ft->encoding.compression;
    if (compression_level != ft->encoding.compression ||
        compression_level > MAX_COMPRESSION) {
      lsx_fail_errno(ft, SOX_EINVAL,
                 "FLAC compression level must be a whole number from 0 to %i",
                 MAX_COMPRESSION);
      return SOX_EOF;
    }
  }

  p->encoder = FLAC__stream_encoder_new();
  if (p->encoder == NULL) {
    lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder instance");
    return SOX_EOF;
  }
  p->decoded_samples = lsx_malloc(sox_globals.bufsiz * sizeof(FLAC__int32));

  p->bits_per_sample = ft->encoding.bits_per_sample;

  lsx_report("encoding at %i bits per sample", p->bits_per_sample);

  FLAC__stream_encoder_set_channels(p->encoder, ft->signal.channels);
  FLAC__stream_encoder_set_bits_per_sample(p->encoder, p->bits_per_sample);
  FLAC__stream_encoder_set_sample_rate(p->encoder, (unsigned)(ft->signal.rate + .5));

  { /* Check if rate is streamable: */
    static const unsigned streamable_rates[] =
      {8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
    size_t i;
    sox_bool streamable = sox_false;
    for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
       streamable = (streamable_rates[i] == ft->signal.rate);
    if (!streamable) {
      lsx_report("non-standard rate; output may not be streamable");
      FLAC__stream_encoder_set_streamable_subset(p->encoder, sox_false);
    }
  }

#if FLAC_API_VERSION_CURRENT >= 10
  FLAC__stream_encoder_set_compression_level(p->encoder, compression_level);
#else
  {
    static struct {
      unsigned blocksize;
      FLAC__bool do_exhaustive_model_search;
      FLAC__bool do_mid_side_stereo;
      FLAC__bool loose_mid_side_stereo;
      unsigned max_lpc_order;
      unsigned max_residual_partition_order;
      unsigned min_residual_partition_order;
    } const options[MAX_COMPRESSION + 1] = {
      {1152, sox_false, sox_false, sox_false, 0, 2, 2},
      {1152, sox_false, sox_true, sox_true, 0, 2, 2},
      {1152, sox_false, sox_true, sox_false, 0, 3, 0},
      {4608, sox_false, sox_false, sox_false, 6, 3, 3},
      {4608, sox_false, sox_true, sox_true, 8, 3, 3},
      {4608, sox_false, sox_true, sox_false, 8, 3, 3},
      {4608, sox_false, sox_true, sox_false, 8, 4, 0},
      {4608, sox_true, sox_true, sox_false, 8, 6, 0},
      {4608, sox_true, sox_true, sox_false, 12, 6, 0},
    };
#define SET_OPTION(x) do {\
  lsx_report(#x" = %i", options[compression_level].x); \
  FLAC__stream_encoder_set_##x(p->encoder, options[compression_level].x);\
} while (0)
    SET_OPTION(blocksize);
    SET_OPTION(do_exhaustive_model_search);
    SET_OPTION(max_lpc_order);
    SET_OPTION(max_residual_partition_order);
    SET_OPTION(min_residual_partition_order);
    if (ft->signal.channels == 2) {
      SET_OPTION(do_mid_side_stereo);
      SET_OPTION(loose_mid_side_stereo);
    }
#undef SET_OPTION
  }
#endif

  if (ft->signal.length != 0) {
    FLAC__stream_encoder_set_total_samples_estimate(p->encoder, (FLAC__uint64)(ft->signal.length / ft->signal.channels));

    p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
    if (p->metadata[p->num_metadata] == NULL) {
      lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table template");
      return SOX_EOF;
    }
    {
#if FLAC_API_VERSION_CURRENT >= 8
      if (!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(p->metadata[p->num_metadata], (unsigned)(10 * ft->signal.rate + .5), (FLAC__uint64)(ft->signal.length/ft->signal.channels))) {
#else
      size_t samples = 10 * ft->signal.rate;
      size_t total_samples = ft->signal.length/ft->signal.channels;
      if (!FLAC__metadata_object_seektable_template_append_spaced_points(p->metadata[p->num_metadata], total_samples / samples + (total_samples % samples != 0), (FLAC__uint64)total_samples)) {
#endif
        lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table points");
        return SOX_EOF;
      }
    }
    p->metadata[p->num_metadata]->is_last = sox_false; /* the encoder will set this for us */
    ++p->num_metadata;
  }

  if (ft->oob.comments) {     /* Make the comment structure */
    FLAC__StreamMetadata_VorbisComment_Entry entry;
    int i;

    p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
    for (i = 0; ft->oob.comments[i]; ++i) {
      static const char prepend[] = "Comment=";
      char * text = lsx_calloc(strlen(prepend) + strlen(ft->oob.comments[i]) + 1, sizeof(*text));
      /* Prepend `Comment=' if no field-name already in the comment */
      if (!strchr(ft->oob.comments[i], '='))
        strcpy(text, prepend);
      entry.entry = (FLAC__byte *) strcat(text, ft->oob.comments[i]);
      entry.length = strlen(text);
      FLAC__metadata_object_vorbiscomment_append_comment(p->metadata[p->num_metadata], entry, /*copy= */ sox_true);
      free(text);
    }
    ++p->num_metadata;
  }

  if (p->num_metadata)
    FLAC__stream_encoder_set_metadata(p->encoder, p->metadata, p->num_metadata);

#if FLAC_API_VERSION_CURRENT <= 7
  FLAC__stream_encoder_set_write_callback(p->encoder, flac_stream_encoder_write_callback);
  FLAC__stream_encoder_set_metadata_callback(p->encoder, flac_stream_encoder_metadata_callback);
  FLAC__stream_encoder_set_client_data(p->encoder, ft);
  status = FLAC__stream_encoder_init(p->encoder);
#else
  status = FLAC__stream_encoder_init_stream(p->encoder, flac_stream_encoder_write_callback,
      flac_stream_encoder_seek_callback, flac_stream_encoder_tell_callback, flac_stream_encoder_metadata_callback, ft);
#endif

  if (status != FLAC__STREAM_ENCODER_OK) {
    lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamEncoderStateString[status]);
    return SOX_EOF;
  }
  return SOX_SUCCESS;
}



static size_t write_samples(sox_format_t * const ft, sox_sample_t const * const sampleBuffer, size_t const len)
{
  priv_t * p = (priv_t *)ft->priv;
  unsigned i;

  for (i = 0; i < len; ++i) {
    long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips);
    p->decoded_samples[i] = pcm >> (32 - p->bits_per_sample);
    switch (p->bits_per_sample) {
      case  8: p->decoded_samples[i] =
          SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips);
        break;
      case 16: p->decoded_samples[i] =
          SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips);
        break;
      case 24: p->decoded_samples[i] = /* sign extension: */
          SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips) << 8;
        p->decoded_samples[i] >>= 8;
        break;
      case 32: p->decoded_samples[i] =
          SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips);
        break;
    }
  }
  FLAC__stream_encoder_process_interleaved(p->encoder, p->decoded_samples, (unsigned) len / ft->signal.channels);
  return FLAC__stream_encoder_get_state(p->encoder) == FLAC__STREAM_ENCODER_OK ? len : 0;
}
예제 #20
0
파일: pan.c 프로젝트: Amalerd/SoxPlayer
/*
 * Process either isamp or osamp samples, whichever is smaller.
 */
static int sox_pan_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
                size_t *isamp, size_t *osamp)
{
    priv_t * pan = (priv_t *) effp->priv;
    size_t len, done;
    sox_sample_t *ibuf_copy;
    char ich, och;
    double left, right, direction, hdir;

    ibuf_copy = lsx_malloc(*isamp * sizeof(sox_sample_t));
    memcpy(ibuf_copy, ibuf, *isamp * sizeof(sox_sample_t));

    direction   = pan->direction;    /* -1   <=  direction  <= 1   */
    hdir  = 0.5 * direction;  /* -0.5 <=  hdir <= 0.5 */
    left  = 0.5 - hdir; /*  0   <=  left <= 1   */
    right = 0.5 + hdir; /*  0   <= right <= 1   */

    ich = effp->in_signal.channels;
    och = effp->out_signal.channels;

    len = min(*osamp/och,*isamp/ich);

    /* report back how much is processed. */
    *isamp = len*ich;
    *osamp = len*och;

    /* 9 different cases to handle: (1,2,4) X (1,2,4) */
    switch (och) {
    case 1: /* pan on mono channel... not much sense. just avg. */
        switch (ich) {
        case 1: /* simple copy */
            for (done=0; done<len; done++)
                *obuf++ = *ibuf_copy++;
            break;
        case 2: /* average 2 */
            for (done=0; done<len; done++)
            {
                double f;
                f = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[1];
                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                *obuf++ = f;
                ibuf_copy += 2;
            }
            break;
        case 4: /* average 4 */
            for (done=0; done<len; done++)
            {
                double f;
                f = 0.25*ibuf_copy[0] + 0.25*ibuf_copy[1] +
                        0.25*ibuf_copy[2] + 0.25*ibuf_copy[3];
                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                *obuf++ = f;
                ibuf_copy += 4;
            }
            break;
        default:
            UNEXPECTED_CHANNELS;
            break;
        } /* end first switch in channel */
        break;
    case 2:
        switch (ich) {
        case 1: /* linear */
            for (done=0; done<len; done++)
            {
                double f;

                f = left * ibuf_copy[0];
                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                obuf[0] = f;
                f = right * ibuf_copy[0];
                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                obuf[1] = f;
                obuf += 2;
                ibuf_copy++;
            }
            break;
        case 2: /* linear panorama.
                 * I'm not sure this is the right way to do it.
                 */
            if (direction <= 0.0) /* to the left */
            {
                register double volume, cll, clr, cr;

                volume = 1.0 - 0.5*direction;
                cll = volume*(1.5-left);
                clr = volume*(left-0.5);
                cr  = volume*(1.0+direction);

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cll * ibuf_copy[0] + clr * ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[0] = f;
                    f = cr * ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[1] = f;
                    obuf += 2;
                    ibuf_copy += 2;
                }
            }
            else /* to the right */
            {
                register double volume, cl, crl, crr;

                volume = 1.0 + 0.5*direction;
                cl  = volume*(1.0-direction);
                crl = volume*(right-0.5);
                crr = volume*(1.5-right);

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cl * ibuf_copy[0];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[0] = f;
                    f = crl * ibuf_copy[0] + crr * ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[1] = f;
                    obuf += 2;
                    ibuf_copy += 2;
                }
            }
            break;
        case 4:
            if (direction <= 0.0) /* to the left */
            {
                register double volume, cll, clr, cr;

                volume = 1.0 - 0.5*direction;
                cll = volume*(1.5-left);
                clr = volume*(left-0.5);
                cr  = volume*(1.0+direction);

                for (done=0; done<len; done++)
                {
                    register double ibuf0, ibuf1, f;

                    /* build stereo signal */
                    ibuf0 = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[2];
                    ibuf1 = 0.5*ibuf_copy[1] + 0.5*ibuf_copy[3];

                    /* pan it */
                    f = cll * ibuf0 + clr * ibuf1;
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[0] = f;
                    f = cr * ibuf1;
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[1] = f;
                    obuf += 2;
                    ibuf_copy += 4;
                }
            }
            else /* to the right */
            {
                register double volume, cl, crl, crr;

                volume = 1.0 + 0.5*direction;
                cl  = volume*(1.0-direction);
                crl = volume*(right-0.5);
                crr = volume*(1.5-right);

                for (done=0; done<len; done++)
                {
                    register double ibuf0, ibuf1, f;

                    ibuf0 = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[2];
                    ibuf1 = 0.5*ibuf_copy[1] + 0.5*ibuf_copy[3];

                    f = cl * ibuf0;
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[0] = f;
                    f = crl * ibuf0 + crr * ibuf1;
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[1] = f;
                    obuf += 2;
                    ibuf_copy += 4;
                }
            }
            break;
        default:
            UNEXPECTED_CHANNELS;
            break;
        } /* end second switch in channel */
        break;
    case 4:
        switch (ich) {
        case 1: /* linear */
            {
                register double cr, cl;

                cl = 0.5*left;
                cr = 0.5*right;

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cl * ibuf_copy[0];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[2] = obuf[0] = f;
                    f = cr * ibuf_copy[0];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    ibuf_copy[3] = obuf[1] = f;
                    obuf += 4;
                    ibuf_copy++;
                }
            }
            break;
        case 2: /* simple linear panorama */
            if (direction <= 0.0) /* to the left */
            {
                register double volume, cll, clr, cr;

                volume = 0.5 - 0.25*direction;
                cll = volume * (1.5-left);
                clr = volume * (left-0.5);
                cr  = volume * (1.0+direction);

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cll * ibuf_copy[0] + clr * ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[2] = obuf[0] = f;
                    f = cr * ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    ibuf_copy[3] = obuf[1] = f;
                    obuf += 4;
                    ibuf_copy += 2;
                }
            }
            else /* to the right */
            {
                register double volume, cl, crl, crr;

                volume = 0.5 + 0.25*direction;
                cl  = volume * (1.0-direction);
                crl = volume * (right-0.5);
                crr = volume * (1.5-right);

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cl * ibuf_copy[0];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[2] = obuf[0] =f ;
                    f = crl * ibuf_copy[0] + crr * ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    ibuf_copy[3] = obuf[1] = f;
                    obuf += 4;
                    ibuf_copy += 2;
                }
            }
            break;
        case 4:
            /* maybe I could improve the formula to reverse...
               also, turn only by quarters.
             */
            if (direction <= 0.0) /* to the left */
            {
                register double cown, cright;

                cright = -direction;
                cown = 1.0 + direction;

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cown*ibuf_copy[0] + cright*ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[0] = f;
                    f = cown*ibuf_copy[1] + cright*ibuf_copy[3];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[1] = f;
                    f = cown*ibuf_copy[2] + cright*ibuf_copy[0];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[2] = f;
                    f = cown*ibuf_copy[3] + cright*ibuf_copy[2];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[3] = f;
                    obuf += 4;
                    ibuf_copy += 4;
                }
            }
            else /* to the right */
            {
                register double cleft, cown;

                cleft = direction;
                cown = 1.0 - direction;

                for (done=0; done<len; done++)
                {
                    double f;

                    f = cleft*ibuf_copy[2] + cown*ibuf_copy[0];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[0] = f;
                    f = cleft*ibuf_copy[0] + cown*ibuf_copy[1];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[1] = f;
                    f = cleft*ibuf_copy[3] + cown*ibuf_copy[2];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[2] = f;
                    f = cleft*ibuf_copy[1] + cown*ibuf_copy[3];
                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
                    obuf[3] = f;
                    obuf += 4;
                    ibuf_copy += 4;
                }
            }
            break;
        default:
            UNEXPECTED_CHANNELS;
            break;
        } /* end third switch in channel */
        break;
    default:
        UNEXPECTED_CHANNELS;
        break;
    } /* end switch out channel */

    free(ibuf_copy - len * ich);

    return SOX_SUCCESS;
}
예제 #21
0
/* common r/w initialization code */
static int ossinit(sox_format_t * ft)
{
    int sampletype, samplesize, dsp_stereo;
    int tmp, rc;
    priv_t *file = (priv_t *)ft->priv;

    if (ft->encoding.bits_per_sample == 8) {
        sampletype = AFMT_U8;
        samplesize = 8;
        if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
            ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
        if (ft->encoding.encoding != SOX_ENCODING_UNSIGNED) {
            lsx_report("OSS driver only supports unsigned with bytes");
            lsx_report("Forcing to unsigned");
            ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
        }
    }
    else if (ft->encoding.bits_per_sample == 16) {
        /* Attempt to use endian that user specified */
        if (ft->encoding.reverse_bytes)
            sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
        else
            sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
        samplesize = 16;
        if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
            ft->encoding.encoding = SOX_ENCODING_SIGN2;
        if (ft->encoding.encoding != SOX_ENCODING_SIGN2) {
            lsx_report("OSS driver only supports signed with words");
            lsx_report("Forcing to signed linear");
            ft->encoding.encoding = SOX_ENCODING_SIGN2;
        }
    }
    else {
        /* Attempt to use endian that user specified */
        if (ft->encoding.reverse_bytes)
            sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
        else
            sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
        samplesize = 16;
        ft->encoding.bits_per_sample = 16;
        ft->encoding.encoding = SOX_ENCODING_SIGN2;
        lsx_report("OSS driver only supports bytes and words");
        lsx_report("Forcing to signed linear word");
    }

    if (ft->signal.channels > 2) ft->signal.channels = 2;

    if (ioctl(fileno(ft->fp), (size_t) SNDCTL_DSP_RESET, 0) < 0)
    {
        lsx_fail_errno(ft,SOX_EOF,"Unable to reset OSS driver.  Possibly accessing an invalid file/device");
        return(SOX_EOF);
    }

    /* Query the supported formats and find the best match
     */
    rc = ioctl(fileno(ft->fp), SNDCTL_DSP_GETFMTS, &tmp);
    if (rc == 0) {
        if ((tmp & sampletype) == 0)
        {
            /* is 16-bit supported? */
            if (samplesize == 16 && (tmp & (AFMT_S16_LE|AFMT_S16_BE)) == 0)
            {
                /* Must not like 16-bits, try 8-bits */
                ft->encoding.bits_per_sample = 8;
                ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
                lsx_report("OSS driver doesn't like signed words");
                lsx_report("Forcing to unsigned bytes");
                tmp = sampletype = AFMT_U8;
                samplesize = 8;
            }
            /* is 8-bit supported */
            else if (samplesize == 8 && (tmp & AFMT_U8) == 0)
            {
                ft->encoding.bits_per_sample = 16;
                ft->encoding.encoding = SOX_ENCODING_SIGN2;
                lsx_report("OSS driver doesn't like unsigned bytes");
                lsx_report("Forcing to signed words");
                sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
                samplesize = 16;
            }
            /* determine which 16-bit format to use */
            if (samplesize == 16 && (tmp & sampletype) == 0)
            {
                /* Either user requested something not supported
                 * or hardware doesn't support machine endian.
                 * Force to opposite as the above test showed
                 * it supports at least one of the two endians.
                 */
                sampletype = (sampletype == AFMT_S16_BE) ? AFMT_S16_LE : AFMT_S16_BE;
                ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
            }

        }
        tmp = sampletype;
        rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SETFMT, &tmp);
    }
    /* Give up and exit */
    if (rc < 0 || tmp != sampletype)
    {
        lsx_fail_errno(ft,SOX_EOF,"Unable to set the sample size to %d", samplesize);
        return (SOX_EOF);
    }

    if (ft->signal.channels == 2) dsp_stereo = 1;
    else dsp_stereo = 0;

    tmp = dsp_stereo;
    if (ioctl(fileno(ft->fp), SNDCTL_DSP_STEREO, &tmp) < 0)
    {
        lsx_warn("Couldn't set to %s", dsp_stereo?  "stereo":"mono");
        dsp_stereo = 0;
    }

    if (tmp != dsp_stereo)
        ft->signal.channels = tmp + 1;

    tmp = ft->signal.rate;
    if (ioctl (fileno(ft->fp), SNDCTL_DSP_SPEED, &tmp) < 0 ||
        (int)ft->signal.rate != tmp) {
        /* If the rate the sound card is using is not within 1% of what
         * the user specified then override the user setting.
         * The only reason not to always override this is because of
         * clock-rounding problems. Sound cards will sometimes use
         * things like 44101 when you ask for 44100.  No need overriding
         * this and having strange output file rates for something that
         * we can't hear anyways.
         */
        if ((int)ft->signal.rate - tmp > (tmp * .01) ||
            tmp - (int)ft->signal.rate > (tmp * .01))
            ft->signal.rate = tmp;
    }

    /* Find out block size to use last because the driver could compute
     * its size based on specific rates/formats.
     */
    file->size = 0;
    ioctl (fileno(ft->fp), SNDCTL_DSP_GETBLKSIZE, &file->size);
    if (file->size < 4 || file->size > 65536) {
            lsx_fail_errno(ft,SOX_EOF,"Invalid audio buffer size %lu", (unsigned long)file->size);
            return (SOX_EOF);
    }
    file->count = 0;
    file->pos = 0;
    file->buf = lsx_malloc(file->size);

    if (ioctl(fileno(ft->fp), (size_t) SNDCTL_DSP_SYNC, NULL) < 0) {
        lsx_fail_errno(ft,SOX_EOF,"Unable to sync dsp");
        return (SOX_EOF);
    }

    /* Change to non-buffered I/O */
    setvbuf(ft->fp, NULL, _IONBF, sizeof(char) * file->size);
    return(SOX_SUCCESS);
}