// ----
// ---- file   : CustomSynth.cpp
// ---- author : Bastian Spiegel <bs@tkscript.de>
// ---- legal  : (c) 2011 by Bastian Spiegel. 
// ----          Distributed under terms of the GNU LESSER GENERAL PUBLIC LICENSE (LGPL). See 
// ----          http://www.gnu.org/licenses/licenses.html#LGPL or COPYING for further information.
// ----
// ---- info   : This is part of the "syntracker" midi sequencer.
// ----
// ---- created: 06Apr2011
// ----          
// ---- changed: 
// ----          
// ----
// ----

#include "tkcustomsynth.h"


CustomSynth::CustomSynth(void) {
   freq_table = NULL;
   voices     = NULL;
   num_voices = 0;
   volume     = 1.0f;

   mix_rate = 48000.0f;
}

CustomSynth::~CustomSynth() {
   freeVoices();
}

void CustomSynth::freeVoices(void) {
   if(NULL != voices)
   {
      delete [] voices;
      voices = NULL;
      num_voices = 0;
   }
}

void CustomSynth::_setMixRate(sF32 _rate) {
   mix_rate = _rate;
}

void CustomSynth::_setVolume(sF32 _vol) {
   volume = _vol;
}

sF32 CustomSynth::_getVolume(void) {
   return volume;
}

void CustomSynth::_setFreqTable(YAC_Object *_fa) {
   if(YAC_BCHK(_fa, YAC_CLID_FLOATARRAY))
   {
      YAC_CAST_ARG(YAC_FloatArray, ft, _fa);

      freq_table = ft->elements;
   }
}

void CustomSynth::_allocVoices(sUI _polyphony) {
   freeVoices();

   voices = new SynthVoice[_polyphony];
   num_voices = _polyphony;

   sUI i;
   for(i=0; i<num_voices; i++)
   {
      SynthVoice *v = &voices[i];

      v->init(this);
   }
}

void CustomSynth::_resetVoices(void) {
   sUI i;
   for(i=0; i<num_voices; i++)
   {
      SynthVoice *v = &voices[i];
      v->reset();
   }
}

void CustomSynth::_stopVoice(sSI _voiceNr) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];
      v->reset();
   }
}

void CustomSynth::_setVoiceBaseNote(sSI _voiceNr, sF32 _baseNote) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->base_note = _baseNote;
   }
}

void CustomSynth::_setVoiceVolume(sSI _voiceNr, sF32 _volume) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->volume = _volume;
   }
}

void CustomSynth::_setVoicePan(sSI _voiceNr, sF32 _pan) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->panning = _pan;
   }
}

void CustomSynth::_setVoicePitchbend(sSI _voiceNr, sF32 _pitchbend) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->freq = _pitchbend;
   }
}

void CustomSynth::_setVoicePressure(sSI _voiceNr, sF32 _pressure) {
}

void CustomSynth::_restartVoice(sSI _voiceNr) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->phase = 0.0f;

      v->b_active = 1;
   }
}

void CustomSynth::_initStartedVoice(sSI _voiceNr) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->b_active = 1;
   }
}

void CustomSynth::_noteOff(sSI _voiceNr, sF32 _vel) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->b_active = 0;
   }
}

void CustomSynth::_setVoiceAltVolume(sSI _voiceNr, sF32 _altVolume) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->alt_volume = _altVolume;
   }
}

void CustomSynth::_setVoicePulseWidth(sSI _voiceNr, sF32 _pulseWidth) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->pulse_width = _pulseWidth;
   }
}

void CustomSynth::_setVoiceBrilliance(sSI _voiceNr, sF32 _brilliance) {
   if(((sUI)_voiceNr) < num_voices)
   {
      SynthVoice *v = &voices[_voiceNr];

      v->brilliance = _brilliance;
   }
}

void CustomSynth::_render(YAC_Object *_fa) {
   if(YAC_BCHK(_fa, YAC_CLID_FLOATARRAY))
   {
      YAC_CAST_ARG(YAC_FloatArray, fa, _fa);

      sUI numFrames = fa->num_elements / 2;

      sF32 *d = fa->elements;

      sUI i;
      for(i=0; i<num_voices; i++)
      {
         SynthVoice *v = &voices[i];
         if(v->b_active)
         {
            v->render(d, numFrames);
         }
      }
   }
}
