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

twip.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"

u_long id = 1253393977;
u_long options = BE_NONE; /* synchronized input -- as with sndfile */

#define INSIZE    256
#define FACT      0.40
#define DEVICE    "/dev/urandom"

#define SAMPLES_PER_SECOND  4410.0
#define MIN_FREQUENCY       80.0
#define MAX_FREQUENCY       (SAMPLES_PER_SECOND / 2)

#define MIN_SPEED  0.1
#define MAX_SPEED  (MAX_FREQUENCY / 100)

#define CHANNELS       2
#define CHANNEL_LEFT   0
#define CHANNEL_RIGHT  1

00040 typedef struct {
  float  sample[CHANNELS];
} StereoSample;

static int  urandfd = -1;

static float  frequency[CHANNELS];
static float  scale[CHANNELS];
static float  speed[CHANNELS];
static float  xtime[CHANNELS];

/* return a random float number from 0.0 to 1.0 (included) */
static inline float
Rndq(void)
{
  u_long  a, b;
  int  n = read(urandfd, (void *)&a, sizeof(u_long));
  b = (~0);
  return (((float)a) / ((float)b));
}

/* return a random float number from 0.0 to x (included) */
static inline float
Rnd(float x)
{
  return (Rndq() * x);
}

/* return a random float number from x1 to x2 (included) */
static inline float
RangeRnd(float x1, float x2)
{
  return (Rnd(x2 - x1) + x1);
}

/* return a random u_long number, from 0 to ULONG_MAX */
static inline u_long
Randq(void)
{
  u_long  a;
  int  n = read(urandfd, (void *)&a, sizeof(u_long));
  return a;
}

/* return a random u_long number, from 0 to (range - 1) */
static inline u_long
Rand(u_long range)
{
  u_long  a = Randq();
  if (range != 0)
    a %= range;

  return a;
}

/* return a random u_long number, from n1 to n2 (included) */
/*static inline u_long
  RangeRand(u_long n1, u_long n2)
  {
  u_long  mi, ma;
  mi = (n1 <= n2 ? n1 : n2); // min of (n1,n2)
  ma = (n1 >= n2 ? n1 : n2); // max of (n1,n2)
  return (Rand(ma - mi + 1) + mi);
  } <-- unused here */

void
create(Context_t *ctx)
{
  int  i;
  urandfd = open(DEVICE, O_RDONLY);
  if (urandfd == -1)
    xerror("Unable to open `%s'\n", DEVICE);

  ctx->input = Input_new(INSIZE);
  /* initialize twip */
  for (i = 0; i < CHANNELS; i++) {
    frequency[i] = RangeRnd(MIN_FREQUENCY, MAX_FREQUENCY);
    scale[i] = RangeRnd(-1, 1);
    speed[i] = RangeRnd(MIN_SPEED, MAX_SPEED);
    xtime[i] = Rndq();
  }
}

void
destroy(Context_t *ctx)
{
  Input_delete(ctx->input);
  if (urandfd != -1) {
    close(urandfd);
    urandfd = -1;
  }
}

void
run(Context_t *ctx)
{
  int  j;
  for (j = 0; j < INSIZE; j++) {
    StereoSample  smp;
    int  i;
    for (i = 0; i < CHANNELS; i++) {
      float  fr, newfr, sc, sp, t, y;
      /* get twip values */
      fr = frequency[i];
      sc = scale[i];
      sp = speed[i];
      t = xtime[i];
      /* compute sample */
      smp.sample[i] = sinf(t * 2 * M_PI) * FACT;
      /* modify speed */
      if (Rand(SAMPLES_PER_SECOND / 100) == nearbyintf(MAX_FREQUENCY / 200)) {
        y = RangeRnd(-1, 1) / SAMPLES_PER_SECOND;
        sp += y;
        if ((sp > MAX_SPEED) || (sp < MIN_SPEED))
          sp -= (y * 2);
      }
      /* modify frequency and/or scale */
      while (1) {
        newfr = powf(2, sc * sp / SAMPLES_PER_SECOND / 12) * fr;
        if (newfr < MIN_FREQUENCY)
          sc = Rndq();
        else if (newfr > MAX_FREQUENCY)
          sc = -Rndq();
        else if (Rand(SAMPLES_PER_SECOND / 10) == nearbyintf(MAX_FREQUENCY / 20))
          sc = RangeRnd(-1, 1);
        else
          break;
      }
      /* update twip */
      frequency[i] = newfr;
      scale[i] = sc;
      speed[i] = sp;
      t += (newfr / SAMPLES_PER_SECOND);
      xtime[i] = (t - floorf(t));
    }
    ctx->input->data[A_LEFT ][j] = smp.sample[CHANNEL_LEFT ];
    ctx->input->data[A_RIGHT][j] = smp.sample[CHANNEL_RIGHT];
  }
  /* buffer written, build FFTs, etc. */
  Input_set(ctx->input, A_STEREO);
  /* that's all, folks ! */
}

Generated by  Doxygen 1.6.0   Back to index