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

spectrum.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 = 1051738767;
u_long options = BE_SFX2D;
u_long mode = OVERLAY;
char desc[] = "Display the spectrum";


static float *fft_copy = NULL;
static u_short *v_start = NULL, *v_end = NULL;


inline static u_short float_to_ushort(float x, u_short minval, u_short maxval)
{
  u_short n;
  x = floor(x); /* rounded to lower int */
  if (x < minval)
    n = minval;
  else if (x > maxval)
    n = maxval;
  else
    n = (ushort)x;
  return n;
}


inline static u_short float_to_nearest_ushort(float x, u_short minval, u_short maxval)
{
  return float_to_ushort(x + 0.5 /* will be rounded to nearest int */, minval, maxval);
}


void
create(Context_t *ctx)
{
  if (ctx->input == NULL)
    options |= BEQ_DISABLED;
  else {
    u_short k;
    float da_log;

    v_start = xcalloc(ctx->input->spectrum_size, sizeof(u_short));
    v_end   = xcalloc(ctx->input->spectrum_size, sizeof(u_short));

    fft_copy = xcalloc(ctx->input->spectrum_size, sizeof(float));
      
    da_log = logf(ctx->input->spectrum_size - 1) / logf(10.0);
    for (k = 1; k < ctx->input->spectrum_size; k++) {
      v_start[k] = float_to_nearest_ushort( logf((float) k) / logf(10.0) / da_log * MAXX, 0, MAXX);
      v_end[k]   = float_to_nearest_ushort(log1p((float) k) / logf(10.0) / da_log * MAXX, 0, MAXX); /* log1p(x)=logf(x+1) */
    }
  }
}


void
destroy(Context_t *ctx)
{
  if (ctx->input != NULL) {
    xfree(fft_copy);
    xfree(v_start);
    xfree(v_end);
  }
}


/* make a copy of the spectrum data locally
 * ie:
 * lock() copy_data() unlock() process(local_spectrum)
 * instead of
 * lock() process(global_spectrum) unlock()
 */
inline static void copy_spectrum(Context_t *ctx)
{
  u_short i;

  pthread_mutex_lock(&ctx->input->mutex);

  for (i = 1; i < ctx->input->spectrum_size; i++)
    fft_copy[i] = ctx->input->spectrum_log_norme[A_MONO][i];

  pthread_mutex_unlock(&ctx->input->mutex);
}


void
run(Context_t *ctx)
{
  Buffer8_t *dst;

  /* should not happen, safety check */
  if (NULL == ctx->input)
    return;

  dst = passive_buffer(ctx);
  Buffer8_clear(dst);

  copy_spectrum(ctx);
  {
    u_short i;

    for (i = 1; i < ctx->input->spectrum_size; i++) {
      u_short top, ye;

      top = float_to_nearest_ushort(MAXY * fft_copy[i], 0, MAXY);
      for (ye = 0; ye < top; ye++) {
        Pixel_t color = (Pixel_t)floor((float)ye / top * 255.0);
        h_line_nc(dst, ye, v_start[i], v_end[i], color);
      }
    }
  }
}


Generated by  Doxygen 1.6.0   Back to index