Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

sndfile.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "context.h"
#include <sndfile.h>


u_long id = 1235598744;
u_long options = BE_NONE;


static char *file = NULL;
static SF_INFO    sfi;
static SNDFILE *sf = NULL;

/* compteur : nombre de frames restant a lire */
static sf_count_t frames;

/* taille du buffer Input */
static u_short bufsize;

/* loop on the file */
static u_char loop = 0;


static void
open_file()
{
  /* ouvrir le fichier avec sndfile */
  sf = sf_open((const char *)file, SFM_READ, &sfi);

  if (NULL == sf)
    xerror("sndfile: '%s': %s\n", file, sf_strerror(sf));

  /* initialiser le compteur de frames a lire */
  frames = sfi.frames;
}


void
create(Context_t *ctx)
{
  char *loop_env = NULL;

  file = getenv("BINIOU_SNDFILE");

  if (NULL == file)
    xerror("sndfile: no BINIOU_SNDFILE environment variable specified !\n");
  else
    printf("[i] Reading file '%s'\n", file);

  loop_env = getenv("BINIOU_SNDFILE_LOOP");
  if (NULL != loop_env)
    loop = 1;

  open_file();

  /* creer une Input */
  bufsize = (u_short)((double)sfi.samplerate / ctx->max_fps);
  /* printf("[i] Input buffer size = %u\n", bufsize); */
  ctx->input = Input_new(bufsize);
}


void
destroy(Context_t *ctx)
{
  /* detruire l'input */
  Input_delete(ctx->input);

  /* fermer le fichier avec sndfile */
  sf_close(sf);
}


void
run(Context_t *ctx)
{
  /* la frame (sample[]) doit avoir, au moins, le meme nombre de canaux que le son a lire,
     meme si ce son a plus que 2 canaux, sinon sf_readf_double() crashe:
     depassement du buffer sample[] */
  double sample[sfi.channels];
  u_short idx;

  /* lire des datas du fichier et les coller dans l'Input */
  for (idx = 0; idx < bufsize; idx++) {
    /* lecture d'une frame du son en entree, au format double (comme pour l'Input) */
    if (frames > 0) {
      (void)sf_readf_double(sf, sample, 1);
      frames--;
    } else {
      /* plus de frames a lire, mettre les samples pour la fin du buffer a 0 */
      u_short ch;
      
      for (ch = 0; ch < sfi.channels; ch++)
      sample[ch] = 0;
    }

    /* copier les samples de la frame lue dans le buffer input */
    if (sfi.channels < 2) {
      /* son mono : dupliquer le 1er sample dans les 2 canaux */
      ctx->input->data[A_LEFT][idx] = ctx->input->data[A_RIGHT][idx] = sample[0];
    } else {
      /* son stereo (ou plus) : ne prendre que les 2 premiers canaux */
      ctx->input->data[A_LEFT][idx] = sample[0];
      ctx->input->data[A_RIGHT][idx] = sample[1];
    }
  }
  /* printf("[i] frames restant a lire = %llu\n", frames); */
  
  /* buffer pret, demander les FFT/u_data... */
  Input_set(ctx->input, A_STEREO);

  /* si lecture finie: on recommence ou on exit */
  if (frames < 1) {
    if (loop) {
      printf("[i] sndfile: restarting stream '%s'\n", file);
      /* rewind */
      if (-1 == sf_seek(sf, 0, SEEK_SET))
      xerror("sf_seek\n");
      frames = sfi.frames;
    } else {
      ctx->running = 0;
      printf("[i] sndfile: end of stream '%s'\n", file);
    }
  }
}


Generated by  Doxygen 1.6.0   Back to index