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

MIDIConverter.C

/* tuneit.c -- Detect fundamental frequency of a sound
 * Copyright (C) 2004, 2005  Mario Lang <mlang@delysid.org>
 *
 * Modified for rakarrack by Daniel Vidal & Josep Andreu 
 * MIDIConverter.C  MIDI Converter class
 * This is free software, placed under the terms of the
 * GNU General Public License, as published by the Free Software Foundation.
 * Please see the file COPYING for details.
 */
#include "MIDIConverter.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "global.h"


MIDIConverter::MIDIConverter (REALTYPE * efxoutl_, REALTYPE * efxoutr_)
{

  float aFreq = 440.0;
  int i;
  velocity = 100;
  channel = 0;
  lanota = -1;
  preparada = 0;
  nota_actual = -1;
  TrigVal = .25;
  hay = 0;
  ponla = 0;
  schmittBuffer = NULL;
  schmittPointer = NULL;
  static const char *englishNotes[12] =
    { "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#" };
  notes = englishNotes;
  note = 0;
  nfreq = 0;
  afreq = 0;
  freqs[0] = aFreq;
  lfreqs[0] = logf (freqs[0]);
  for (i = 1; i < 12; i++)
    {
      freqs[i] = freqs[i - 1] * D_NOTE;
      lfreqs[i] = lfreqs[i - 1] + LOG_D_NOTE;
    }
  schmittInit (36);


  // Open Alsa Seq

  int alsaport_out;



  int err = snd_seq_open (&port, "default", SND_SEQ_OPEN_OUTPUT, 0);
  if (err < 0)
    printf ("Cannot activate ALSA seq client\n");
  snd_seq_set_client_name (port, "rakarrack");
  snd_config_update_free_global ();



  char portname[50];

  // Create Alsa Seq Client

  sprintf (portname, "rakarrack MC OUT");
  alsaport_out = snd_seq_create_simple_port (port, portname,
                                   SND_SEQ_PORT_CAP_READ |
                                   SND_SEQ_PORT_CAP_SUBS_READ,
                                   SND_SEQ_PORT_TYPE_APPLICATION);





};


MIDIConverter::~MIDIConverter ()
{
  snd_seq_close (port);
}


void
MIDIConverter::displayFrequency (float freq)
{
  float ldf, mldf;
  float lfreq;
  int i;
  int noteoff = 0;
  int octave = 4;

  if (freq < 1E-15)
    freq = 1E-15;
  lfreq = logf (freq);
  while (lfreq < lfreqs[0] - LOG_D_NOTE * .5)
    lfreq += LOG_2;
  while (lfreq >= lfreqs[0] + LOG_2 - LOG_D_NOTE * .5)
    lfreq -= LOG_2;
  mldf = LOG_D_NOTE;
  for (i = 0; i < 12; i++)
    {
      ldf = fabsf (lfreq - lfreqs[i]);
      if (ldf < mldf)
      {
        mldf = ldf;
        note = i;
      }
    }
  nfreq = freqs[note];
  while (nfreq / freq > D_NOTE_SQRT)
    {
      nfreq *= .5;
      octave--;
      if (octave < -2)
      {
        noteoff = 1;
        break;
      }

    }
  while (freq / nfreq > D_NOTE_SQRT)
    {
      nfreq *= 2.0;
      octave++;
      if (octave > 9)
      {
        noteoff = 1;
        break;
      }
    }


  cents = (int) (1200 * (logf (freq / nfreq) / LOG_2));
  lanota = 24 + (octave * 12) + note - 3;


  if ((noteoff) & (hay))
    {
      MIDI_Send_Note_Off (nota_actual);
      hay = 0;
      nota_actual = -1;
    }

  if ((preparada == lanota) && (lanota != nota_actual))
    {

      hay = 1;
      if (nota_actual != -1)
      {
        MIDI_Send_Note_Off (nota_actual);
      }

      MIDI_Send_Note_On (lanota);
      nota_actual = lanota;
    }


  if ((lanota > 0 && lanota < 128) && (lanota != nota_actual))
    preparada = lanota;




};

void
MIDIConverter::schmittInit (int size)
{
  blockSize = SAMPLE_RATE / size;
  schmittBuffer =
    (signed short int *) malloc (blockSize * sizeof (signed short int));
  schmittPointer = schmittBuffer;
};



void
MIDIConverter::schmittS16LE (int nframes, signed short int *indata)
{
  int i, j;
  float trigfact = 0.6;


  for (i = 0; i < nframes; i++)
    {
      *schmittPointer++ = indata[i];
      if (schmittPointer - schmittBuffer >= blockSize)
      {
        int endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered;

        schmittPointer = schmittBuffer;

        for (j = 0, A1 = 0, A2 = 0; j < blockSize; j++)
          {
            if (schmittBuffer[j] > 0 && A1 < schmittBuffer[j])
            A1 = schmittBuffer[j];
            if (schmittBuffer[j] < 0 && A2 < -schmittBuffer[j])
            A2 = -schmittBuffer[j];
          }
        t1 = (int) (A1 * trigfact + 0.5);
        t2 = -(int) (A2 * trigfact + 0.5);
        startpoint = 0;
        for (j = 1; schmittBuffer[j] <= t1 && j < blockSize; j++);
        for (; !(schmittBuffer[j] >= t2 &&
               schmittBuffer[j + 1] < t2) && j < blockSize; j++);
        startpoint = j;
        schmittTriggered = 0;
        endpoint = startpoint + 1;
        for (j = startpoint, tc = 0; j < blockSize; j++)
          {
            if (!schmittTriggered)
            {
              schmittTriggered = (schmittBuffer[j] >= t1);
            }
            else if (schmittBuffer[j] >= t2 && schmittBuffer[j + 1] < t2)
            {
              endpoint = j;
              tc++;
              schmittTriggered = 0;
            }
          }
        if (endpoint > startpoint)
          {
            afreq =
            (float) SAMPLE_RATE *(tc / (float) (endpoint - startpoint));
            displayFrequency (afreq);

          }
      }
    }
};

void
MIDIConverter::schmittFree ()
{
  free (schmittBuffer);
};

void
MIDIConverter::schmittFloat (int nframes, float *indatal, float *indatar)
{
  signed short int buf[nframes];
  int i;
  for (i = 0; i < nframes; i++)
    {
      buf[i] =
      (short) ((TrigVal * indatal[i] + TrigVal * indatar[i]) * 32768);
    }
  schmittS16LE (nframes, buf);
};


void
MIDIConverter::MIDI_Send_Note_On (int nota)
{


  int k;


  k = (int) ((val_sum + 48) * 2);
  if ((k > 0) && (k < 127))
    velocity = (int) (k * VelVal);

  if (velocity > 127)
    velocity = 127;
  if (velocity < 1)
    velocity = 1;


  snd_seq_event_t ev;
  snd_seq_ev_clear (&ev);
  snd_seq_ev_set_noteon (&ev, channel, nota, velocity);
  snd_seq_ev_set_subs (&ev);
  snd_seq_ev_set_direct (&ev);
  snd_seq_event_output_direct (port, &ev);

};


void
MIDIConverter::MIDI_Send_Note_Off (int nota)
{



  snd_seq_event_t ev;
  snd_seq_ev_clear (&ev);
  snd_seq_ev_set_noteoff (&ev, channel, nota, 0);
  snd_seq_ev_set_subs (&ev);
  snd_seq_ev_set_direct (&ev);
  snd_seq_event_output_direct (port, &ev);

};


void
MIDIConverter::panic ()
{
  int i;

  for (i = 0; i < 127; i++)
    MIDI_Send_Note_Off (i);
  hay = 0;
  nota_actual = -1;
}


void
MIDIConverter::setmidichannel (int chan)
{
  channel = chan - 1;

};


int
MIDIConverter::getmidichannel (int chan)
{
  return (channel + 1);

};



void
MIDIConverter::setTriggerAdjust (int val)
{

  TrigVal = 1.0 / val;

};


float
MIDIConverter::getTriggerAdjust (int val)
{
  return (1.0 / TrigVal);

};


void
MIDIConverter::setVelAdjust (int val)
{

  VelVal = 100.0 / val;

};


float
MIDIConverter::getVelAdjust (int val)
{
  return (100.0 / VelVal);

};

Generated by  Doxygen 1.6.0   Back to index