/*
Copyright (C) 2010-2012 Florian Jung
This file is part of flo's FM synth.
flo's FM synth 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 3 of the License, or
(at your option) any later version.
flo's FM synth 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 flo's FM synth. If not, see .
*/
//TODO: auf unbenutzte envelopes achten!
#include
#include
#include "parser.h"
#include "programs.h"
#include "util.h"
#include "../synth/fixed.h"
using namespace std;
ostream &out=cout;
ostream &comment=cout;
program_t prog;
void write_empty_line()
{
out << "\n";
}
void include_file(string file)
{
file="templates/"+file;
ifstream in;
in.open(file.c_str());
if (!in.good())
throw string ("include: could not open '"+file+"'");
char tempbuf[2000];
while (!in.eof())
{
in.getline(tempbuf, sizeof(tempbuf));
out << tempbuf << "\n";
}
}
void write_env_decs()
{
for (int i=0;iwave_len, osc"<samp_rate);\n";
else
out << "ONE * PHASE_INIT;\n";
}
out << "\t\n"
"\tdo_ksl();\n"
"\t\n"
"\t\n";
if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
{
//a filter_params and orig.filter_params member exist
out << "\tfilter_params=prg.filter_settings;\n"
"\torig.filter_params=prg.filter_settings;\n";
if (prog.filter.enabled_const==false)
{
out << "\tif (filter_params.enabled)\n"
"\t{\n";
tabtmp="\t";
}
out << tabtmp << "\tfilter_envelope=new Envelope(filter_params.env_settings);\n" <<
tabtmp << "\tfilter_update_counter=filter_update_frames;\n";
if (prog.filter.enabled_const==false)
out << "\t}\n";
tabtmp="";
out << "\t\n"
"\t\n";
}
if ((prog.sync_factor!=0) || (prog.sync_factor_const==false))
out << "\tsync_factor=prg.sync_factor;\n"
"\tsync_phase=0;\n"
"\t\n"
"\t\n";
include_file("ctor.foot");
}
void write_dtor()
{
int i;
out << "Note::~Note()\n"
"{\n";
for (i=0;ipfactor.filter_env, vel);\n"
"\tpfactor.filter_res=calc_pfactor(curr_prg->pfactor.filter_res, vel);\n"
"\tpfactor.filter_offset=calc_pfactor(curr_prg->pfactor.filter_offset, vel);\n"
"\t\n";
}
out << "\tfor (int i=0;i<"<pfactor.out[i], vel) * volume_factor;\n"
"\t\t\n"
"\t\tfor (int j=0;j<"<pfactor.fm[i][j], vel);\n"
"\t}\n";
out << "}\n";
}
void write_apply_pfactor()
{
out << "void Note::apply_pfactor()\n"
"{\n";
if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
out << "\tfilter_params.env_amount=orig.filter_params.env_amount*pfactor.filter_env /ONE;\n"
"\tfilter_params.freqfactor_offset=orig.filter_params.freqfactor_offset*pfactor.filter_offset /ONE;\n"
"\tfilter_params.resonance=orig.filter_params.resonance*pfactor.filter_res /ONE;\n"
"\t\n";
for (int i=0;i>SCALE;\n"
"\tfor (int i=0;i<"<>SCALE;\n";
}
out << "}\n";
}
void write_still_active()
{
out << "bool Note::still_active()\n"
"{\n";
out << "\tif ( ";
if (prog.env[0].enabled)
out << " ((osc"<<0<<".output>0) && (env"<<0<<"->still_active()))";
else
out << " // envelope"<<0<<" is disabled";
for (int i=1;i0) && (env"<still_active()))";
else
out << "\n\t /* envelope"<release_key();\n";
else
comment << "\t//envelope"<release_key();\n";
else if (prog.filter.enabled_const==false)
out << "\n\tif (filter_params.enabled)\n"
"\t\tfilter_envelope->release_key();\n";
out << "}\n";
}
void write_release_quickly()
{
out << "void Note::release_quickly(jack_nframes_t maxt)\n"
"{\n";
for (int i=0;iget_release() > maxt)\n"
"\t\tenv"<set_release(maxt);\n"
"\tenv"<release_key();\n"
"\t\n";
else
comment << "\t//envelope"<reattack();\n";
else
comment << "\t//envelope"<reattack();\n";
else if (prog.filter.enabled_const==false)
out << "\n\tif (filter_params.enabled)\n"
"\t\tfilter_envelope->reattack();\n";
out << "}\n";
}
void write_do_ksr()
{
out << "void Note::do_ksr()\n"
"{\n";
for (int i=0;iset_ratefactor(1.0 / pow(freq>>SCALE, osc"<> SCALE );\n"
"\t\n";
for (int i=0;iset_max( "<> SCALE;\n"
<< tabtemp << "\t\n"
<< tabtemp << "\tif (sync_phase >= ONE)\n"
<< tabtemp << "\t{\n"
<< tabtemp << "\t\tsync_phase-=ONE;\n"
<< tabtemp << "\t\t\n";
for (int i=0;iwave_len, osc"+IntToStr(i)+".custom_wave->samp_rate)";
else
initstring="ONE * PHASE_INIT";
string full_command="osc"+IntToStr(i)+".phase="+initstring+";\n";
if ( prog.osc[i].sync_const && prog.osc[i].sync )
out << tabtemp << "\t\t" << full_command;
else if ( prog.osc[i].sync_const && (prog.osc[i].sync==false) )
comment << tabtemp << "\t\t//sync is disabled for osc"<>SCALE)*osc"+IntToStr(i)+".factor/samp_rate)>>SCALE";
string phase_inc = "(actual_freq*osc"+IntToStr(i)+".factor/samp_rate)>>SCALE";
if (prog.osc[i].vibrato_depth_const == false)
out << "\tosc"<>SCALE fehlt noch!
for (int j=0;j>SCALE ) )";
else
phase="osc"+IntToStr(i)+".phase";
// generate string for wave
string wavetemp;
if (prog.osc[i].have_custom_wave)
{
string cw="osc"+IntToStr(i)+".custom_wave";
wavetemp=cw+"->wave[ ( "+phase+" * "+cw+"->samp_rate >>(2*SCALE) ) % "+cw+"->wave_len ]";
}
else
{
string waveformtemp;
if (prog.osc[i].waveform_const)
waveformtemp=IntToStr(prog.osc[i].waveform);
else
waveformtemp="osc"+IntToStr(i)+".waveform";
wavetemp="wave["+waveformtemp+"][ ( "+phase+" * WAVE_RES >>SCALE ) % WAVE_RES ]";
}
// finally write "oscval[n]=..."
out << "\toscval["<get_level() >>SCALE;\n";
else if ( (prog.osc[i].ksl!=0) || (prog.osc[i].ksl_const==false) )
// i.e.: if osc[i] has a kslval variable
out<<" * kslval"<>SCALE;\n";
else //no envelope, no kslval
out<<";\n";
// maybe do tremolo
string tremlfo;
if (prog.osc[i].tremolo_lfo_const==false)
tremlfo="osc"+IntToStr(i)+".tremolo_lfo";
else
tremlfo=IntToStr(prog.osc[i].tremolo_lfo);
if (prog.osc[i].tremolo_depth_const==false)
out << "\tif (osc"<>SCALE;\n";
else if (prog.osc[i].tremolo_depth!=0)
out << "\toscval["<>SCALE;\n";
else
comment << "\t//oscillator"<>SCALE )";
if (outstring_nonscaled!="")
outstring+=" "+outstring_nonscaled;
if (outstring=="")
throw string ("this instrument has no output at all!");
out << "\tfixed_t out = "<=filter_update_frames)\n"
<< tabtemp << "\t{\n"
<< tabtemp << "\t\tfilter_update_counter=0;\n"
<< tabtemp << "\t\t\n"
<< tabtemp << "\t\tfloat cutoff= float(actual_freq)/ONE * \n"
<< tabtemp << "\t\t\tfloat(curr_lfo[filter_params.trem_lfo][filter_params.trem_strength])/ONE *\n"
<< tabtemp << "\t\t\t( filter_params.freqfactor_offset + filter_envelope->get_level() * filter_params.env_amount / float(ONE) );\n"
<< tabtemp << "\t\tfilter.set_params( cutoff, filter_params.resonance );\n"
<< tabtemp << "\t}\n"
<< tabtemp << "\t\n"
<< tabtemp << "\tfilter.process_sample(&out);\n";
if (prog.filter.enabled_const==false)
{
out << "\t}\n";
tabtemp="";
}
out << "\t\n";
}
out << "\treturn out;\n";
out << "}\n";
}
void write_set_param()
{
out << "void Note::set_param(const parameter_t &p, fixed_t v)\n"
"{\n"
"\toscillator_t* sel_osc=NULL;\n"
"\toscillator_t* sel_orig_osc=NULL;\n"
"\tEnvelope* sel_env=NULL;\n"
"\t\n"
"\tswitch (p.osc)\n"
"\t{\n";
for (int i=0;i