@@ -0,0 +1,116 @@ | |||
/* | |||
Copyright (C) 2008-2011 Nasca Octavian Paul | |||
Author: Nasca Octavian Paul | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of version 2 of the GNU General Public License | |||
as published by the Free Software Foundation. | |||
This program 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 (version 2) for more details. | |||
You should have received a copy of the GNU General Public License (version 2) | |||
along with this program; if not, write to the Free Software Foundation, | |||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#include <math.h> | |||
#include <stdio.h> | |||
#include "BinauralBeats.h" | |||
void BinauralBeatsParameters::add2XML(XMLwrapper *xml){ | |||
xml->addpar("stereo_mode",(int) stereo_mode); | |||
xml->addparreal("mono",mono); | |||
xml->beginbranch("FREE_EDIT"); | |||
free_edit.add2XML(xml); | |||
xml->endbranch(); | |||
}; | |||
void BinauralBeatsParameters::getfromXML(XMLwrapper *xml){ | |||
stereo_mode=(BB_STEREO_MODE)xml->getpar("stereo_mode",(int) stereo_mode,0,2); | |||
mono=xml->getparreal("mono",mono); | |||
if (xml->enterbranch("FREE_EDIT")){ | |||
free_edit.getfromXML(xml); | |||
xml->exitbranch(); | |||
}; | |||
}; | |||
//coefficients of allpass filters are found by Olli Niemitalo | |||
const REALTYPE Hilbert::coefl[]={0.6923877778065, 0.9360654322959, 0.9882295226860, 0.9987488452737}; | |||
const REALTYPE Hilbert::coefr[]={0.4021921162426, 0.8561710882420, 0.9722909545651, 0.9952884791278}; | |||
BinauralBeats::BinauralBeats(int samplerate_){ | |||
samplerate=samplerate_; | |||
hilbert_t=0.0; | |||
}; | |||
void BinauralBeats::process(REALTYPE *smpsl,REALTYPE *smpsr,int nsmps,REALTYPE pos_percents){ | |||
// for (int i=0;i<nsmps;i++) smpsl[i]=smpsr[i]=sin(30.0*M_PI*i*2.0/nsmps)*0.4; | |||
//printf(" enabled %d\n",pars.free_edit.get_enabled()); | |||
if (pars.free_edit.get_enabled()){ | |||
float mono=pars.mono*0.5; | |||
for (int i=0;i<nsmps;i++){ | |||
REALTYPE inl=smpsl[i]; | |||
REALTYPE inr=smpsr[i]; | |||
REALTYPE outl=inl*(1.0-mono)+inr*mono; | |||
REALTYPE outr=inr*(1.0-mono)+inl*mono; | |||
smpsl[i]=outl; | |||
smpsr[i]=outr; | |||
}; | |||
REALTYPE freq=pars.free_edit.get_value(pos_percents); | |||
// freq=300;//test | |||
freq*=0.5;//half down for left, half up for right | |||
for (int i=0;i<nsmps;i++){ | |||
hilbert_t=fmod(hilbert_t+freq/samplerate,1.0); | |||
REALTYPE h1=0,h2=0; | |||
hl.process(smpsl[i],h1,h2); | |||
REALTYPE x=hilbert_t*2.0*M_PI; | |||
REALTYPE m1=h1*cos(x); | |||
REALTYPE m2=h2*sin(x); | |||
REALTYPE outl1=m1+m2; | |||
REALTYPE outl2=m1-m2; | |||
h1=0,h2=0; | |||
hr.process(smpsr[i],h1,h2); | |||
m1=h1*cos(x); | |||
m2=h2*sin(x); | |||
REALTYPE outr1=m1-m2; | |||
REALTYPE outr2=m1+m2; | |||
switch(pars.stereo_mode){ | |||
case SM_LEFT_RIGHT: | |||
smpsl[i]=outl2; | |||
smpsr[i]=outr2; | |||
break; | |||
case SM_RIGHT_LEFT: | |||
smpsl[i]=outl1; | |||
smpsr[i]=outr1; | |||
break; | |||
case SM_SYMMETRIC: | |||
smpsl[i]=(outl1+outr1)*0.5; | |||
smpsr[i]=(outl2+outr2)*0.5; | |||
break; | |||
}; | |||
}; | |||
}; | |||
}; | |||
@@ -0,0 +1,109 @@ | |||
/* | |||
Copyright (C) 2011 Nasca Octavian Paul | |||
Author: Nasca Octavian Paul | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of version 2 of the GNU General Public License | |||
as published by the Free Software Foundation. | |||
This program 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 (version 2) for more details. | |||
You should have received a copy of the GNU General Public License (version 2) | |||
along with this program; if not, write to the Free Software Foundation, | |||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#ifndef BINAURAL_BEATS | |||
#define BINAURAL_BEATS | |||
#include "FreeEdit.h" | |||
#include "globals.h" | |||
class AP{//allpass | |||
public: | |||
AP(REALTYPE a_=0.5){ | |||
in1=in2=out1=out2=0.0; | |||
set(a_); | |||
}; | |||
REALTYPE process(REALTYPE in){ | |||
REALTYPE out=a*(in+out2)-in2; | |||
in2=in1;in1=in; | |||
out2=out1;out1=out; | |||
return out; | |||
}; | |||
REALTYPE set(REALTYPE a_){ | |||
a=a_*a_; | |||
}; | |||
private: | |||
REALTYPE in1,in2,out1,out2; | |||
REALTYPE a; | |||
}; | |||
class Hilbert{ | |||
public: | |||
Hilbert(){ | |||
for (int i=0;i<N;i++){ | |||
apl[i].set(coefl[i]); | |||
apr[i].set(coefr[i]); | |||
}; | |||
oldl=0.0; | |||
}; | |||
void process(REALTYPE in, REALTYPE &out1, REALTYPE &out2){ | |||
out1=oldl; | |||
out2=in; | |||
for (int i=0;i<N;i++){ | |||
out1=apl[i].process(out1); | |||
out2=apr[i].process(out2); | |||
}; | |||
oldl=in; | |||
}; | |||
private: | |||
static const int N=4; | |||
static const REALTYPE coefl[]; | |||
static const REALTYPE coefr[]; | |||
AP apl[N],apr[N]; | |||
REALTYPE oldl; | |||
}; | |||
enum BB_STEREO_MODE{ | |||
SM_LEFT_RIGHT=0, | |||
SM_RIGHT_LEFT=1, | |||
SM_SYMMETRIC=2 | |||
}; | |||
struct BinauralBeatsParameters{ | |||
BinauralBeatsParameters(){ | |||
stereo_mode=SM_LEFT_RIGHT; | |||
mono=0.5; | |||
}; | |||
BB_STEREO_MODE stereo_mode; | |||
float mono; | |||
FreeEdit free_edit; | |||
void add2XML(XMLwrapper *xml); | |||
void getfromXML(XMLwrapper *xml); | |||
}; | |||
class BinauralBeats{ | |||
public: | |||
BinauralBeats(int samplerate_); | |||
void process(REALTYPE *smpsl,REALTYPE *smpsr,int nsmps,REALTYPE pos_percents); | |||
BinauralBeatsParameters pars; | |||
private: | |||
int samplerate; | |||
REALTYPE hilbert_t; | |||
Hilbert hl,hr; | |||
}; | |||
#endif |
@@ -0,0 +1,340 @@ | |||
GNU GENERAL PUBLIC LICENSE | |||
Version 2, June 1991 | |||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
Everyone is permitted to copy and distribute verbatim copies | |||
of this license document, but changing it is not allowed. | |||
Preamble | |||
The licenses for most software are designed to take away your | |||
freedom to share and change it. By contrast, the GNU General Public | |||
License is intended to guarantee your freedom to share and change free | |||
software--to make sure the software is free for all its users. This | |||
General Public License applies to most of the Free Software | |||
Foundation's software and to any other program whose authors commit to | |||
using it. (Some other Free Software Foundation software is covered by | |||
the GNU Library General Public License instead.) You can apply it to | |||
your programs, too. | |||
When we speak of free software, we are referring to freedom, not | |||
price. Our General Public Licenses are designed to make sure that you | |||
have the freedom to distribute copies of free software (and charge for | |||
this service if you wish), that you receive source code or can get it | |||
if you want it, that you can change the software or use pieces of it | |||
in new free programs; and that you know you can do these things. | |||
To protect your rights, we need to make restrictions that forbid | |||
anyone to deny you these rights or to ask you to surrender the rights. | |||
These restrictions translate to certain responsibilities for you if you | |||
distribute copies of the software, or if you modify it. | |||
For example, if you distribute copies of such a program, whether | |||
gratis or for a fee, you must give the recipients all the rights that | |||
you have. You must make sure that they, too, receive or can get the | |||
source code. And you must show them these terms so they know their | |||
rights. | |||
We protect your rights with two steps: (1) copyright the software, and | |||
(2) offer you this license which gives you legal permission to copy, | |||
distribute and/or modify the software. | |||
Also, for each author's protection and ours, we want to make certain | |||
that everyone understands that there is no warranty for this free | |||
software. If the software is modified by someone else and passed on, we | |||
want its recipients to know that what they have is not the original, so | |||
that any problems introduced by others will not reflect on the original | |||
authors' reputations. | |||
Finally, any free program is threatened constantly by software | |||
patents. We wish to avoid the danger that redistributors of a free | |||
program will individually obtain patent licenses, in effect making the | |||
program proprietary. To prevent this, we have made it clear that any | |||
patent must be licensed for everyone's free use or not licensed at all. | |||
The precise terms and conditions for copying, distribution and | |||
modification follow. | |||
GNU GENERAL PUBLIC LICENSE | |||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |||
0. This License applies to any program or other work which contains | |||
a notice placed by the copyright holder saying it may be distributed | |||
under the terms of this General Public License. The "Program", below, | |||
refers to any such program or work, and a "work based on the Program" | |||
means either the Program or any derivative work under copyright law: | |||
that is to say, a work containing the Program or a portion of it, | |||
either verbatim or with modifications and/or translated into another | |||
language. (Hereinafter, translation is included without limitation in | |||
the term "modification".) Each licensee is addressed as "you". | |||
Activities other than copying, distribution and modification are not | |||
covered by this License; they are outside its scope. The act of | |||
running the Program is not restricted, and the output from the Program | |||
is covered only if its contents constitute a work based on the | |||
Program (independent of having been made by running the Program). | |||
Whether that is true depends on what the Program does. | |||
1. You may copy and distribute verbatim copies of the Program's | |||
source code as you receive it, in any medium, provided that you | |||
conspicuously and appropriately publish on each copy an appropriate | |||
copyright notice and disclaimer of warranty; keep intact all the | |||
notices that refer to this License and to the absence of any warranty; | |||
and give any other recipients of the Program a copy of this License | |||
along with the Program. | |||
You may charge a fee for the physical act of transferring a copy, and | |||
you may at your option offer warranty protection in exchange for a fee. | |||
2. You may modify your copy or copies of the Program or any portion | |||
of it, thus forming a work based on the Program, and copy and | |||
distribute such modifications or work under the terms of Section 1 | |||
above, provided that you also meet all of these conditions: | |||
a) You must cause the modified files to carry prominent notices | |||
stating that you changed the files and the date of any change. | |||
b) You must cause any work that you distribute or publish, that in | |||
whole or in part contains or is derived from the Program or any | |||
part thereof, to be licensed as a whole at no charge to all third | |||
parties under the terms of this License. | |||
c) If the modified program normally reads commands interactively | |||
when run, you must cause it, when started running for such | |||
interactive use in the most ordinary way, to print or display an | |||
announcement including an appropriate copyright notice and a | |||
notice that there is no warranty (or else, saying that you provide | |||
a warranty) and that users may redistribute the program under | |||
these conditions, and telling the user how to view a copy of this | |||
License. (Exception: if the Program itself is interactive but | |||
does not normally print such an announcement, your work based on | |||
the Program is not required to print an announcement.) | |||
These requirements apply to the modified work as a whole. If | |||
identifiable sections of that work are not derived from the Program, | |||
and can be reasonably considered independent and separate works in | |||
themselves, then this License, and its terms, do not apply to those | |||
sections when you distribute them as separate works. But when you | |||
distribute the same sections as part of a whole which is a work based | |||
on the Program, the distribution of the whole must be on the terms of | |||
this License, whose permissions for other licensees extend to the | |||
entire whole, and thus to each and every part regardless of who wrote it. | |||
Thus, it is not the intent of this section to claim rights or contest | |||
your rights to work written entirely by you; rather, the intent is to | |||
exercise the right to control the distribution of derivative or | |||
collective works based on the Program. | |||
In addition, mere aggregation of another work not based on the Program | |||
with the Program (or with a work based on the Program) on a volume of | |||
a storage or distribution medium does not bring the other work under | |||
the scope of this License. | |||
3. You may copy and distribute the Program (or a work based on it, | |||
under Section 2) in object code or executable form under the terms of | |||
Sections 1 and 2 above provided that you also do one of the following: | |||
a) Accompany it with the complete corresponding machine-readable | |||
source code, which must be distributed under the terms of Sections | |||
1 and 2 above on a medium customarily used for software interchange; or, | |||
b) Accompany it with a written offer, valid for at least three | |||
years, to give any third party, for a charge no more than your | |||
cost of physically performing source distribution, a complete | |||
machine-readable copy of the corresponding source code, to be | |||
distributed under the terms of Sections 1 and 2 above on a medium | |||
customarily used for software interchange; or, | |||
c) Accompany it with the information you received as to the offer | |||
to distribute corresponding source code. (This alternative is | |||
allowed only for noncommercial distribution and only if you | |||
received the program in object code or executable form with such | |||
an offer, in accord with Subsection b above.) | |||
The source code for a work means the preferred form of the work for | |||
making modifications to it. For an executable work, complete source | |||
code means all the source code for all modules it contains, plus any | |||
associated interface definition files, plus the scripts used to | |||
control compilation and installation of the executable. However, as a | |||
special exception, the source code distributed need not include | |||
anything that is normally distributed (in either source or binary | |||
form) with the major components (compiler, kernel, and so on) of the | |||
operating system on which the executable runs, unless that component | |||
itself accompanies the executable. | |||
If distribution of executable or object code is made by offering | |||
access to copy from a designated place, then offering equivalent | |||
access to copy the source code from the same place counts as | |||
distribution of the source code, even though third parties are not | |||
compelled to copy the source along with the object code. | |||
4. You may not copy, modify, sublicense, or distribute the Program | |||
except as expressly provided under this License. Any attempt | |||
otherwise to copy, modify, sublicense or distribute the Program is | |||
void, and will automatically terminate your rights under this License. | |||
However, parties who have received copies, or rights, from you under | |||
this License will not have their licenses terminated so long as such | |||
parties remain in full compliance. | |||
5. You are not required to accept this License, since you have not | |||
signed it. However, nothing else grants you permission to modify or | |||
distribute the Program or its derivative works. These actions are | |||
prohibited by law if you do not accept this License. Therefore, by | |||
modifying or distributing the Program (or any work based on the | |||
Program), you indicate your acceptance of this License to do so, and | |||
all its terms and conditions for copying, distributing or modifying | |||
the Program or works based on it. | |||
6. Each time you redistribute the Program (or any work based on the | |||
Program), the recipient automatically receives a license from the | |||
original licensor to copy, distribute or modify the Program subject to | |||
these terms and conditions. You may not impose any further | |||
restrictions on the recipients' exercise of the rights granted herein. | |||
You are not responsible for enforcing compliance by third parties to | |||
this License. | |||
7. If, as a consequence of a court judgment or allegation of patent | |||
infringement or for any other reason (not limited to patent issues), | |||
conditions are imposed on you (whether by court order, agreement or | |||
otherwise) that contradict the conditions of this License, they do not | |||
excuse you from the conditions of this License. If you cannot | |||
distribute so as to satisfy simultaneously your obligations under this | |||
License and any other pertinent obligations, then as a consequence you | |||
may not distribute the Program at all. For example, if a patent | |||
license would not permit royalty-free redistribution of the Program by | |||
all those who receive copies directly or indirectly through you, then | |||
the only way you could satisfy both it and this License would be to | |||
refrain entirely from distribution of the Program. | |||
If any portion of this section is held invalid or unenforceable under | |||
any particular circumstance, the balance of the section is intended to | |||
apply and the section as a whole is intended to apply in other | |||
circumstances. | |||
It is not the purpose of this section to induce you to infringe any | |||
patents or other property right claims or to contest validity of any | |||
such claims; this section has the sole purpose of protecting the | |||
integrity of the free software distribution system, which is | |||
implemented by public license practices. Many people have made | |||
generous contributions to the wide range of software distributed | |||
through that system in reliance on consistent application of that | |||
system; it is up to the author/donor to decide if he or she is willing | |||
to distribute software through any other system and a licensee cannot | |||
impose that choice. | |||
This section is intended to make thoroughly clear what is believed to | |||
be a consequence of the rest of this License. | |||
8. If the distribution and/or use of the Program is restricted in | |||
certain countries either by patents or by copyrighted interfaces, the | |||
original copyright holder who places the Program under this License | |||
may add an explicit geographical distribution limitation excluding | |||
those countries, so that distribution is permitted only in or among | |||
countries not thus excluded. In such case, this License incorporates | |||
the limitation as if written in the body of this License. | |||
9. The Free Software Foundation may publish revised and/or new versions | |||
of the General Public License from time to time. Such new versions will | |||
be similar in spirit to the present version, but may differ in detail to | |||
address new problems or concerns. | |||
Each version is given a distinguishing version number. If the Program | |||
specifies a version number of this License which applies to it and "any | |||
later version", you have the option of following the terms and conditions | |||
either of that version or of any later version published by the Free | |||
Software Foundation. If the Program does not specify a version number of | |||
this License, you may choose any version ever published by the Free Software | |||
Foundation. | |||
10. If you wish to incorporate parts of the Program into other free | |||
programs whose distribution conditions are different, write to the author | |||
to ask for permission. For software which is copyrighted by the Free | |||
Software Foundation, write to the Free Software Foundation; we sometimes | |||
make exceptions for this. Our decision will be guided by the two goals | |||
of preserving the free status of all derivatives of our free software and | |||
of promoting the sharing and reuse of software generally. | |||
NO WARRANTY | |||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |||
REPAIR OR CORRECTION. | |||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |||
POSSIBILITY OF SUCH DAMAGES. | |||
END OF TERMS AND CONDITIONS | |||
How to Apply These Terms to Your New Programs | |||
If you develop a new program, and you want it to be of the greatest | |||
possible use to the public, the best way to achieve this is to make it | |||
free software which everyone can redistribute and change under these terms. | |||
To do so, attach the following notices to the program. It is safest | |||
to attach them to the start of each source file to most effectively | |||
convey the exclusion of warranty; and each file should have at least | |||
the "copyright" line and a pointer to where the full notice is found. | |||
<one line to give the program's name and a brief idea of what it does.> | |||
Copyright (C) <year> <name of author> | |||
This program 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. | |||
This program 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 this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
Also add information on how to contact you by electronic and paper mail. | |||
If the program is interactive, make it output a short notice like this | |||
when it starts in an interactive mode: | |||
Gnomovision version 69, Copyright (C) year name of author | |||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
This is free software, and you are welcome to redistribute it | |||
under certain conditions; type `show c' for details. | |||
The hypothetical commands `show w' and `show c' should show the appropriate | |||
parts of the General Public License. Of course, the commands you use may | |||
be called something other than `show w' and `show c'; they could even be | |||
mouse-clicks or menu items--whatever suits your program. | |||
You should also get your employer (if you work as a programmer) or your | |||
school, if any, to sign a "copyright disclaimer" for the program, if | |||
necessary. Here is a sample; alter the names: | |||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |||
`Gnomovision' (which makes passes at compilers) written by James Hacker. | |||
<signature of Ty Coon>, 1 April 1989 | |||
Ty Coon, President of Vice | |||
This General Public License does not permit incorporating your program into | |||
proprietary programs. If your program is a subroutine library, you may | |||
consider it more useful to permit linking proprietary applications with the | |||
library. If this is what you want to do, use the GNU Library General | |||
Public License instead of this License. |
@@ -0,0 +1,650 @@ | |||
/* | |||
Copyright (C) 2006-2011 Nasca Octavian Paul | |||
Author: Nasca Octavian Paul | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of version 2 of the GNU General Public License | |||
as published by the Free Software Foundation. | |||
This program 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 (version 2) for more details. | |||
You should have received a copy of the GNU General Public License (version 2) | |||
along with this program; if not, write to the Free Software Foundation, | |||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#include <math.h> | |||
#include <stdlib.h> | |||
#include <FL/Fl.H> | |||
#include "globals.h" | |||
#include "Control.h" | |||
#include "XMLwrapper.h" | |||
using namespace std; | |||
Control::Control(){ | |||
player=new Player(); | |||
player->start(); | |||
wavinfo.samplerate=44100; | |||
wavinfo.nsamples=0; | |||
wavinfo.intype=FILE_WAV; | |||
wav32bit=false; | |||
process.bufsize=16384; | |||
process.stretch=4.0; | |||
/// process.transient.enable=false; | |||
/// process.transient.amount=0.5; | |||
seek_pos=0.0; | |||
window_type=W_HANN; | |||
info.render_percent=-1.0; | |||
info.cancel_render=false; | |||
volume=1.0; | |||
gui_sliders.fftsize_s=0.5; | |||
gui_sliders.stretch_s=0.5; | |||
gui_sliders.mode_s=0; | |||
///#warning test | |||
/// process.transient.enable=true; | |||
}; | |||
Control::~Control(){ | |||
// delete player; face crash daca il las | |||
}; | |||
///void Control::pre_analyse_whole_audio(InputS *ai){ | |||
/// int inbufsize=1024; | |||
/// int readsize=inbufsize/2; | |||
/// | |||
/// short int *inbuf_i=new short int[readsize*2]; | |||
/// | |||
///// REALTYPE *inbuf_f=new REALTYPE[readsize]; | |||
///// for (int i=0;i<readsize;i++) inbuf_f[i]=0.0; | |||
/// | |||
/// REALTYPE *processbuf=new REALTYPE[inbufsize]; | |||
/// for (int i=0;i<inbufsize;i++) processbuf[i]=0.0; | |||
/// | |||
/// FFT *infft=new FFT(inbufsize); | |||
/// | |||
/// int k=0; | |||
/// int fftsize=inbufsize/2; | |||
/// REALTYPE *oldfreq=new REALTYPE[fftsize]; | |||
/// for (int i=0;i<fftsize;i++) oldfreq[i]=0.0; | |||
/// REALTYPE oldsumstart=0.0; | |||
/// int transient_data_n=0; | |||
/// int transient_data_max_n=10000; | |||
/// REALTYPE *transient_data=new REALTYPE [transient_data_max_n]; | |||
/// while(!ai->eof){ | |||
/// float in_pos=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples; | |||
/// | |||
/// int readed=ai->read(readsize,inbuf_i); | |||
/// if (readed!=readsize) break;//do not process the last buffer from the audiofile | |||
/// const float inv_32768=1.0/32768.0; | |||
/// | |||
/// for (int i=0;i<inbufsize-readed;i++){ | |||
/// processbuf[i]=processbuf[i+readed]; | |||
/// }; | |||
/// for (int i=0;i<readed;i++) { | |||
/// processbuf[i+inbufsize-readed]=(inbuf_i[i*2]*inv_32768+inbuf_i[i*2+1]*inv_32768); | |||
/// }; | |||
/// | |||
/// | |||
/// for (int i=0;i<inbufsize;i++) infft->smp[i]=processbuf[i]; | |||
/// | |||
/// | |||
/// infft->applywindow(W_HAMMING); | |||
/// infft->smp2freq(); | |||
/// infft->freq[0]=0; | |||
/// REALTYPE *freq=infft->freq; | |||
/// | |||
/// REALTYPE sumstart=0.0; | |||
/// for (int i=0;i<fftsize;i++){ | |||
/// REALTYPE x=freq[i]-oldfreq[i]; | |||
/// if (x>0) sumstart+=x; | |||
/// }; | |||
/// sumstart/=fftsize; | |||
/// const REALTYPE a=0.1; | |||
/// oldsumstart=oldsumstart*(1.0-a)+sumstart*a; | |||
/// sumstart-=1.5*oldsumstart; | |||
/// if (sumstart<0.0) sumstart=0.0; | |||
/// | |||
/// transient_data[transient_data_n]=sumstart; | |||
/// transient_data_n++; | |||
/// if (transient_data_n>=transient_data_max_n){ | |||
/// transient_data_max_n+=100000; | |||
/// REALTYPE *new_transient_data=new REALTYPE[transient_data_max_n]; | |||
/// for (int i=0;i<transient_data_n;i++) new_transient_data[i]=transient_data[i]; | |||
/// delete [] transient_data; | |||
/// transient_data=new_transient_data; | |||
/// }; | |||
/// | |||
/// for (int i=0;i<fftsize;i++) oldfreq[i]=freq[i]; | |||
/// }; | |||
/// ppar.set_transient_data(transient_data_n,transient_data); | |||
/// delete infft; | |||
/// delete []transient_data; | |||
/// | |||
/// delete []oldfreq; | |||
/// delete [] inbuf_i; | |||
/// //delete [] inbuf_f; | |||
/// delete [] processbuf; | |||
///}; | |||
bool Control::set_input_filename(string filename,FILE_TYPE intype){ | |||
InputS *ai=NULL; | |||
if (intype==FILE_VORBIS) ai=new VorbisInputS; | |||
if (intype==FILE_MP3) ai=new MP3InputS; | |||
if (intype==FILE_WAV) ai=new AInputS; | |||
if (!ai) return false; | |||
wavinfo.filename=filename; | |||
wavinfo.intype=intype; | |||
bool result=ai->open(wavinfo.filename); | |||
if (result) { | |||
wavinfo.samplerate=ai->info.samplerate; | |||
wavinfo.nsamples=ai->info.nsamples; | |||
/// if (process.transient.enable) { | |||
/// pre_analyse_whole_audio(ai); | |||
/// }; | |||
delete ai; | |||
}else{ | |||
wavinfo.filename=""; | |||
wavinfo.samplerate=0; | |||
wavinfo.nsamples=0; | |||
delete ai; | |||
}; | |||
return result; | |||
}; | |||
string Control::get_input_filename(){ | |||
return wavinfo.filename; | |||
}; | |||
string Control::get_input_filename_and_info(){ | |||
int seconds=wavinfo.nsamples/wavinfo.samplerate; | |||
const int size=200; | |||
char tmp[size];tmp[size-1]=0; | |||
snprintf(tmp,size-1," ( samplerate=%d; duration=%02d:%02d:%02d )",wavinfo.samplerate,seconds/3600,(seconds/60)%60,seconds%60); | |||
string filename=wavinfo.filename; | |||
int len=filename.length(); | |||
if (len>70)filename=filename.substr(0,25)+"..."+filename.substr(len-35); | |||
return filename+tmp; | |||
}; | |||
/*string Control::get_recommanded_output_filename(){ | |||
return "none"; | |||
}; | |||
*/ | |||
std::string Control::get_stretch_info(){ | |||
const int size=200; | |||
char tmp[size];tmp[size-1]=0; | |||
if (wavinfo.nsamples==0) return "Stretch: "; | |||
double realduration=wavinfo.nsamples/wavinfo.samplerate*process.stretch; | |||
if (realduration>(365.25*86400.0*1.0e12)){//more than 1 trillion years | |||
double duration=(realduration/(365.25*86400.0*1.0e12));//my | |||
snprintf(tmp,size,"Stretch: %.7gx (%g trillion years)",process.stretch,duration); | |||
return tmp; | |||
}; | |||
if (realduration>(365.25*86400.0*1.0e9)){//more than 1 billion years | |||
double duration=(realduration/(365.25*86400.0*1.0e9));//my | |||
snprintf(tmp,size,"Stretch: %.7gx (%g billion years)",process.stretch,duration); | |||
return tmp; | |||
}; | |||
if (realduration>(365.25*86400.0*1.0e6)){//more than 1 million years | |||
double duration=(realduration/(365.25*86400.0*1.0e6));//my | |||
snprintf(tmp,size,"Stretch: %.7gx (%g million years)",process.stretch,duration); | |||
return tmp; | |||
}; | |||
if (realduration>(365.25*86400.0*2000.0)){//more than two millenniums | |||
int duration=(int)(realduration/(365.25*86400.0));//years | |||
int years=duration%1000; | |||
int milleniums=duration/1000; | |||
char stryears[size];stryears[0]=0; | |||
if (years!=0){ | |||
if (years==1) snprintf(stryears,size," 1 year"); | |||
else snprintf(stryears,size," %d years",years); | |||
}; | |||
snprintf(tmp,size,"Stretch: %.7gx (%d milleniums%s)",process.stretch,milleniums,stryears); | |||
return tmp; | |||
}; | |||
if (realduration>(365.25*86400.0)){//more than 1 year | |||
int duration=(int) (realduration/3600.0);//hours | |||
int hours=duration%24; | |||
int days=(duration/24)%365; | |||
int years=duration/(365*24); | |||
char stryears[size];stryears[0]=0; | |||
if (years==1) snprintf(stryears,size,"1 year "); | |||
else snprintf(stryears,size,"%d years ",years); | |||
char strdays[size];strdays[0]=0; | |||
if (days>0){ | |||
if (days==1) snprintf(strdays,size,"1 day"); | |||
else snprintf(strdays,size,"%d days",days); | |||
}; | |||
if (years>=10) hours=0; | |||
char strhours[size];strhours[0]=0; | |||
if (hours>0){ | |||
snprintf(strhours,size," %d h",hours); | |||
}; | |||
snprintf(tmp,size,"Stretch: %.7gx (%s%s%s)",process.stretch,stryears,strdays,strhours); | |||
return tmp; | |||
}else{//less than 1 year | |||
int duration=(int)(realduration);//seconds | |||
char strdays[size];strdays[0]=0; | |||
int days=duration/86400; | |||
if (days>0){ | |||
if (days==1) snprintf(strdays,size,"1 day "); | |||
else snprintf(strdays,size,"%d days ",duration/86400); | |||
}; | |||
REALTYPE stretch=process.stretch; | |||
if (stretch>=1.0){ | |||
stretch=((int) (stretch*100.0))*0.01; | |||
}; | |||
snprintf(tmp,size,"Stretch: %.7gx (%s%.2d:%.2d:%.2d)", | |||
stretch,strdays,(duration/3600)%24,(duration/60)%60,duration%60); | |||
return tmp; | |||
}; | |||
return ""; | |||
}; | |||
string Control::get_fftsize_info(){ | |||
const int size=200; | |||
char tmp[size];tmp[size-1]=0; | |||
string fftsizelabel; | |||
fftsizelabel+="Window size (samples): "; | |||
if (wavinfo.nsamples==0) return fftsizelabel; | |||
fftsizelabel+=getfftsizestr(process.bufsize); | |||
return fftsizelabel; | |||
}; | |||
string Control::get_fftresolution_info(){ | |||
string resolution="Resolution: "; | |||
if (wavinfo.nsamples==0) return resolution; | |||
//todo: unctime and uncfreq are correct computed? Need to check later. | |||
REALTYPE unctime=process.bufsize/(REALTYPE)wavinfo.samplerate*sqrt(2.0); | |||
REALTYPE uncfreq=1.0/unctime*sqrt(2.0); | |||
char tmp[100]; | |||
snprintf(tmp,100,"%.5g seconds",unctime);resolution+=tmp; | |||
snprintf(tmp,100," (%.5g Hz)",uncfreq);resolution+=tmp; | |||
return resolution; | |||
}; | |||
void Control::startplay(bool bypass){ | |||
if ((!player->info.playing)||(player->info.samplerate!=wavinfo.samplerate)){ | |||
stopplay(); | |||
sleep(200); | |||
#ifdef HAVE_JACK | |||
JACKaudiooutputinit(player,wavinfo.samplerate); | |||
#else | |||
PAaudiooutputinit(player,wavinfo.samplerate); | |||
#endif | |||
}; | |||
if (wavinfo.filename!="") player->startplay(wavinfo.filename,seek_pos,process.stretch,process.bufsize,wavinfo.intype,bypass,&ppar,&bbpar); | |||
// sleep(100); | |||
// update_process_parameters(); | |||
}; | |||
void Control::stopplay(){ | |||
player->stop(); | |||
player->seek(0.0); | |||
seek_pos=0; | |||
#ifdef HAVE_JACK | |||
JACKclose(); | |||
#else | |||
PAfinish(); | |||
#endif | |||
}; | |||
void Control::pauseplay(){ | |||
player->pause(); | |||
}; | |||
void Control::freezeplay(){ | |||
player->freeze(); | |||
}; | |||
void Control::set_volume(REALTYPE vol){ | |||
volume=vol; | |||
player->set_volume(vol); | |||
}; | |||
void Control::set_seek_pos(REALTYPE x){ | |||
seek_pos=x; | |||
player->seek(x); | |||
}; | |||
REALTYPE Control::get_seek_pos(){ | |||
if (player->getmode()==Player::MODE_PLAY) seek_pos=player->info.position; | |||
return seek_pos; | |||
}; | |||
void Control::set_stretch_controls(double stretch_s,int mode,double fftsize_s){ | |||
gui_sliders.stretch_s=stretch_s; | |||
gui_sliders.mode_s=mode; | |||
gui_sliders.fftsize_s=fftsize_s; | |||
double stretch=1.0; | |||
switch(mode){ | |||
case 0: | |||
stretch_s=pow(stretch_s,1.2); | |||
stretch=pow(10.0,stretch_s*4.0); | |||
break; | |||
case 1: | |||
stretch_s=pow(stretch_s,1.5); | |||
stretch=pow(10.0,stretch_s*18.0); | |||
break; | |||
case 2: | |||
stretch=1.0/pow(10.0,stretch_s*3.0); | |||
if (stretch<0.1) stretch=0.1; | |||
break; | |||
}; | |||
fftsize_s=pow(fftsize_s,1.5); | |||
double tmp=1.0; | |||
if (mode==2) tmp=1.0/stretch; | |||
int bufsize=(int)(pow(2.0,fftsize_s*12.0)*512.0*tmp); | |||
bufsize=optimizebufsize(bufsize); | |||
process.stretch=stretch; | |||
process.bufsize=bufsize; | |||
}; | |||
double Control::get_stretch_control(double stretch,int mode){ | |||
double result=1.0; | |||
switch(mode){ | |||
case 0: | |||
if (stretch<1.0) return -1; | |||
stretch=(log(stretch)/log(10))*0.25; | |||
result=pow(stretch,1.0/1.2); | |||
break; | |||
case 1: | |||
if (stretch<1.0) return -1; | |||
stretch=(log(stretch)/log(10))/18.0; | |||
result=pow(stretch,1.0/1.5); | |||
break; | |||
case 2: | |||
if (stretch>1.0) return -1; | |||
result=3.0/(log(stretch)/log(10)); | |||
break; | |||
}; | |||
return result; | |||
}; | |||
void Control::update_player_stretch(){ | |||
player->setrap(process.stretch); | |||
}; | |||
int abs_val(int x){ | |||
if (x<0) return -x; | |||
else return x; | |||
}; | |||
int Control::get_optimized_updown(int n,bool up){ | |||
int orig_n=n; | |||
while(true){ | |||
n=orig_n; | |||
#ifndef KISSFFT | |||
while (!(n%11)) n/=11; | |||
while (!(n%7)) n/=7; | |||
#endif | |||
while (!(n%5)) n/=5; | |||
while (!(n%3)) n/=3; | |||
while (!(n%2)) n/=2; | |||
if (n<2) break; | |||
if (up) orig_n++; | |||
else orig_n--; | |||
if (orig_n<4) return 4; | |||
}; | |||
return orig_n; | |||
}; | |||
int Control::optimizebufsize(int n){ | |||
int n1=get_optimized_updown(n,false); | |||
int n2=get_optimized_updown(n,true); | |||
if ((n-n1)<(n2-n)) return n1; | |||
else return n2; | |||
}; | |||
void Control::set_window_type(FFTWindow window){ | |||
window_type=window; | |||
if (player) player->set_window_type(window); | |||
}; | |||
string Control::Render(string inaudio,string outaudio,FILE_TYPE outtype,FILE_TYPE intype,REALTYPE pos1,REALTYPE pos2){ | |||
if (pos2<pos1){ | |||
REALTYPE tmp=pos2; | |||
pos2=pos1; | |||
pos1=tmp; | |||
}; | |||
InputS *ai=NULL; | |||
switch(intype){ | |||
case FILE_VORBIS:ai=new VorbisInputS; | |||
break; | |||
case FILE_MP3:ai=new MP3InputS; | |||
break; | |||
default:ai=new AInputS; | |||
}; | |||
AOutputS ao; | |||
VorbisOutputS vorbisout; | |||
info.cancel_render=false; | |||
if (!ai->open(inaudio)){ | |||
return "Error: Could not open audio file (or file format not recognized) :"+inaudio; | |||
}; | |||
BinauralBeats bb(ai->info.samplerate); | |||
bb.pars=bbpar; | |||
if (outtype==FILE_WAV) ao.newfile(outaudio,ai->info.samplerate,wav32bit); | |||
if (outtype==FILE_VORBIS) vorbisout.newfile(outaudio,ai->info.samplerate); | |||
ai->seek(pos1); | |||
int inbufsize=process.bufsize; | |||
if (inbufsize<32) inbufsize=32; | |||
short int *inbuf_i=new short int[inbufsize*4]; | |||
int outbufsize; | |||
struct{ | |||
REALTYPE *l,*r; | |||
}inbuf; | |||
ProcessedStretch *stretchl=new ProcessedStretch(process.stretch,inbufsize,window_type,false,ai->info.samplerate,1); | |||
ProcessedStretch *stretchr=new ProcessedStretch(process.stretch,inbufsize,window_type,false,ai->info.samplerate,2); | |||
stretchl->set_parameters(&ppar); | |||
stretchr->set_parameters(&ppar); | |||
outbufsize=stretchl->out_bufsize; | |||
int *outbuf=new int[outbufsize*2]; | |||
int poolsize=stretchl->poolsize; | |||
inbuf.l=new REALTYPE[poolsize]; | |||
inbuf.r=new REALTYPE[poolsize]; | |||
for (int i=0;i<poolsize;i++) inbuf.l[i]=inbuf.r[i]=0.0; | |||
int readsize=0; | |||
const int pause_max_write=65536; | |||
int pause_write=0; | |||
bool firstbuf=true; | |||
while(!ai->eof){ | |||
float in_pos=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples; | |||
if (firstbuf){ | |||
readsize=stretchl->get_nsamples_for_fill(); | |||
firstbuf=false; | |||
}else{ | |||
readsize=stretchl->get_nsamples(in_pos*100.0); | |||
}; | |||
int readed=0; | |||
if (readsize!=0) readed=ai->read(readsize,inbuf_i); | |||
for (int i=0;i<readed;i++) { | |||
inbuf.l[i]=inbuf_i[i*2]/32768.0; | |||
inbuf.r[i]=inbuf_i[i*2+1]/32768.0; | |||
}; | |||
stretchl->process(inbuf.l,readed); | |||
stretchr->process(inbuf.r,readed); | |||
bb.process(stretchl->out_buf,stretchr->out_buf,outbufsize,in_pos*100.0); | |||
for (int i=0;i<outbufsize;i++) { | |||
stretchl->out_buf[i]*=volume; | |||
stretchr->out_buf[i]*=volume; | |||
}; | |||
if (outtype==FILE_WAV){ | |||
for (int i=0;i<outbufsize;i++) { | |||
REALTYPE l=stretchl->out_buf[i],r=stretchr->out_buf[i]; | |||
if (l<-1.0) l=-1.0; | |||
else if (l>1.0) l=1.0; | |||
if (r<-1.0) r=-1.0; | |||
else if (r>1.0) r=1.0; | |||
outbuf[i*2]=(int)(l*32767.0*65536.0); | |||
outbuf[i*2+1]=(int)(r*32767.0*65536.0); | |||
}; | |||
ao.write(outbufsize,outbuf); | |||
}; | |||
if (outtype==FILE_VORBIS) vorbisout.write(outbufsize,stretchl->out_buf,stretchr->out_buf); | |||
REALTYPE totalf=ai->info.currentsample/(REALTYPE)ai->info.nsamples-pos1; | |||
if (totalf>(pos2-pos1)) break; | |||
info.render_percent=(totalf*100.0/(pos2-pos1+0.001)); | |||
pause_write+=outbufsize; | |||
if (pause_write>pause_max_write){ | |||
float tmp=outbufsize/1000000.0; | |||
if (tmp>0.1) tmp=0.1; | |||
Fl::wait(0.01+tmp); | |||
pause_write=0; | |||
if (info.cancel_render) break; | |||
}; | |||
}; | |||
delete stretchl; | |||
delete stretchr; | |||
delete []outbuf; | |||
delete []inbuf_i; | |||
delete []inbuf.l; | |||
delete []inbuf.r; | |||
info.render_percent=-1.0; | |||
return ""; | |||
}; | |||
string Control::getfftsizestr(int fftsize){ | |||
int size=100; | |||
char tmp[size];tmp[size-1]=0; | |||
if (fftsize<1024.0) snprintf(tmp,size-1,"%d",fftsize); | |||
else if (fftsize<(1024.0*1024.0)) snprintf(tmp,size-1,"%.4gK",fftsize/1024.0); | |||
else if (fftsize<(1024.0*1024.0*1024.0)) snprintf(tmp,size-1,"%.4gM",fftsize/(1024.0*1024.0)); | |||
else snprintf(tmp,size-1,"%.7gG",fftsize/(1024.0*1024.0*1024.0)); | |||
return tmp; | |||
}; | |||
void Control::update_process_parameters(){ | |||
if (player) player->set_process_parameters(&ppar,&bbpar); | |||
}; | |||
bool Control::save_parameters(const char *filename){ | |||
XMLwrapper *xml=new XMLwrapper(); | |||
xml->beginbranch("PAULSTRETCH"); | |||
xml->beginbranch("STRETCH_PARAMETERS"); | |||
xml->beginbranch("BASE"); | |||
xml->addpar("bufsize",process.bufsize); | |||
xml->addparreal("stretch",process.stretch); | |||
xml->addparreal("fftsize_s",gui_sliders.fftsize_s); | |||
xml->addparreal("stretch_s",gui_sliders.stretch_s); | |||
xml->addpar("mode_s",gui_sliders.mode_s); | |||
xml->addpar("window_type",window_type); | |||
xml->addparreal("volume",volume); | |||
xml->endbranch(); | |||
xml->beginbranch("PROCESS"); | |||
ppar.add2XML(xml); | |||
xml->endbranch(); | |||
xml->beginbranch("BINAURAL_BEATS"); | |||
bbpar.add2XML(xml); | |||
xml->endbranch(); | |||
xml->endbranch(); | |||
xml->endbranch(); | |||
int result=xml->saveXMLfile(filename); | |||
delete xml; | |||
return true; | |||
}; | |||
bool Control::load_parameters(const char *filename){ | |||
XMLwrapper *xml=new XMLwrapper(); | |||
if (xml->loadXMLfile(filename)<0) { | |||
delete xml; | |||
return false; | |||
}; | |||
if (xml->enterbranch("PAULSTRETCH")==0) { | |||
delete xml; | |||
return false; | |||
}; | |||
if (xml->enterbranch("STRETCH_PARAMETERS")){ | |||
if (xml->enterbranch("BASE")){ | |||
process.bufsize=xml->getpar("bufsize",process.bufsize,16,2e9); | |||
process.stretch=xml->getparreal("stretch",process.stretch); | |||
gui_sliders.fftsize_s=xml->getparreal("fftsize_s",gui_sliders.fftsize_s); | |||
gui_sliders.stretch_s=xml->getparreal("stretch_s",gui_sliders.stretch_s); | |||
gui_sliders.mode_s=xml->getpar("mode_s",gui_sliders.mode_s,0,2); | |||
window_type=(FFTWindow)xml->getpar("window_type",window_type,0,4); | |||
volume=xml->getparreal("volume",1.0); | |||
xml->exitbranch(); | |||
}; | |||
if (xml->enterbranch("PROCESS")){ | |||
ppar.getfromXML(xml); | |||
xml->exitbranch(); | |||
}; | |||
if (xml->enterbranch("BINAURAL_BEATS")){ | |||
bbpar.getfromXML(xml); | |||
xml->exitbranch(); | |||
}; | |||
xml->exitbranch(); | |||
}; | |||
delete xml; | |||
set_stretch_controls(gui_sliders.stretch_s,gui_sliders.mode_s,gui_sliders.fftsize_s); | |||
set_window_type(window_type); | |||
set_volume(volume); | |||
update_process_parameters(); | |||
return true; | |||
}; | |||
@@ -0,0 +1,127 @@ | |||
/* | |||
Copyright (C) 2006-2011 Nasca Octavian Paul | |||
Author: Nasca Octavian Paul | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of version 2 of the GNU General Public License | |||
as published by the Free Software Foundation. | |||
This program 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 (version 2) for more details. | |||
You should have received a copy of the GNU General Public License (version 2) | |||
along with this program; if not, write to the Free Software Foundation, | |||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#ifndef CONTROL_H | |||
#define CONTROL_H | |||
#include "globals.h" | |||
#include "Input/AInputS.h" | |||
#include "Input/VorbisInputS.h" | |||
#include "Input/MP3InputS.h" | |||
#include "Output/AOutputS.h" | |||
#include "Output/VorbisOutputS.h" | |||
#include "ProcessedStretch.h" | |||
#include "Player.h" | |||
#include "JAaudiooutput.h" | |||
#include "PAaudiooutput.h" | |||
#include "BinauralBeats.h" | |||
class Control{ | |||
public: | |||
Control(); | |||
~Control(); | |||
void UpdateControlInfo(); | |||
void startplay(bool bypass); | |||
void stopplay(); | |||
void pauseplay(); | |||
void freezeplay(); | |||
void set_volume(REALTYPE vol); | |||
void set_seek_pos(REALTYPE x); | |||
REALTYPE get_seek_pos(); | |||
bool save_parameters(const char *filename); | |||
bool load_parameters(const char *filename); | |||
bool playing(){ | |||
return player->info.playing; | |||
}; | |||
bool playing_eof(){ | |||
return player->info.eof; | |||
}; | |||
bool set_input_filename(std::string filename,FILE_TYPE intype);//return false if the file cannot be opened | |||
std::string get_input_filename(); | |||
std::string get_input_filename_and_info(); | |||
std::string get_stretch_info(); | |||
std::string get_fftsize_info(); | |||
std::string get_fftresolution_info(); | |||
double get_stretch(){ | |||
return process.stretch; | |||
}; | |||
bool is_freeze(){ | |||
return player->is_freeze(); | |||
}; | |||
void set_stretch_controls(double stretch_s,int mode,double fftsize_s);//*_s sunt de la 0.0 la 1.0 | |||
double get_stretch_control(double stretch,int mode); | |||
void update_player_stretch(); | |||
void set_window_type(FFTWindow window); | |||
/// void pre_analyse_whole_audio(InputS *ai); | |||
std::string Render(std::string inaudio,std::string outaudio,FILE_TYPE outtype,FILE_TYPE intype, | |||
REALTYPE pos1,REALTYPE pos2);//returneaza o eroare sau un string gol (pos1,pos2 are from 0.0 to 1.0) | |||
struct { | |||
REALTYPE render_percent; | |||
bool cancel_render; | |||
}info; | |||
ProcessParameters ppar; | |||
BinauralBeatsParameters bbpar; | |||
bool wav32bit; | |||
void update_process_parameters();//pt. player | |||
struct{ | |||
double fftsize_s,stretch_s; | |||
int mode_s; | |||
}gui_sliders; | |||
FFTWindow window_type; | |||
private: | |||
REALTYPE volume; | |||
int get_optimized_updown(int n,bool up); | |||
int optimizebufsize(int bufsize); | |||
std::string getfftsizestr(int fftsize); | |||
struct { | |||
int bufsize; | |||
double stretch; | |||
/// struct{ | |||
/// bool enable; | |||
/// double amount; | |||
/// } transient; | |||
}process; | |||
struct { | |||
int samplerate; | |||
int nsamples; | |||
std::string filename; | |||
FILE_TYPE intype; | |||
}wavinfo;//input | |||
REALTYPE seek_pos; | |||
Player *player; | |||
}; | |||
#endif | |||
@@ -0,0 +1,233 @@ | |||
/* | |||
Copyright (C) 2009 Nasca Octavian Paul | |||
Author: Nasca Octavian Paul | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of version 2 of the GNU General Public License | |||
as published by the Free Software Foundation. | |||
This program 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 (version 2) for more details. | |||
You should have received a copy of the GNU General Public License (version 2) | |||
along with this program; if not, write to the Free Software Foundation, | |||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "FreeEdit.h" | |||
FreeEdit::FreeEdit(){ | |||
enabled=false; | |||
smooth=0.0; | |||
interp_mode=LINEAR; | |||
npos=FREE_EDIT_MAX_POINTS; | |||
pos=new FreeEditPos[npos]; | |||
for (int i=0;i<npos;i++){ | |||
pos[i].x=pos[i].y=0; | |||
pos[i].enabled=false; | |||
}; | |||
pos[0].x=0; | |||
pos[0].y=0.5; | |||
pos[0].enabled=true; | |||
pos[1].x=1; | |||
pos[1].y=0.5; | |||
pos[1].enabled=true; | |||
curve.data=NULL; | |||
curve.size=0; | |||
}; | |||
void FreeEdit::deep_copy_from(const FreeEdit &other){ | |||
enabled=other.enabled; | |||
smooth=other.smooth; | |||
interp_mode=other.interp_mode; | |||
npos=other.npos; | |||
pos=new FreeEditPos[npos]; | |||
for (int i=0;i<npos;i++){ | |||
pos[i].x=other.pos[i].x; | |||
pos[i].y=other.pos[i].y; | |||
pos[i].enabled=other.pos[i].enabled; | |||
}; | |||
curve.size=other.curve.size; | |||
if (other.curve.data&&other.curve.size){ | |||
curve.data=new REALTYPE[curve.size]; | |||
for (int i=0;i<curve.size;i++) curve.data[i]=other.curve.data[i]; | |||
}else curve.data=NULL; | |||
extreme_x=other.extreme_x; | |||
extreme_y=other.extreme_y; | |||
}; | |||
FreeEdit::FreeEdit (const FreeEdit &other){ | |||
deep_copy_from(other); | |||
}; | |||
const FreeEdit &FreeEdit::operator=(const FreeEdit &other){ | |||
if (this == &other) return *this; | |||
deep_copy_from(other); | |||
return *this; | |||
}; | |||
void FreeEdit::get_curve(int datasize,REALTYPE *data,bool real_values){ | |||
int npos_used=0; | |||
for (int i=0;i<npos;i++) if (is_enabled(i)) npos_used++; | |||
if (!npos_used){ | |||
for (int i=0;i<datasize;i++) data[i]=(real_values?extreme_y.get_min():0.0); | |||
return; | |||
}; | |||
//get the enabled points | |||
REALTYPE posx[npos_used],posy[npos_used]; | |||
int k=0; | |||
for (int i=0;i<npos;i++){ | |||
if (is_enabled(i)){ | |||
posx[k]=get_posx(i); | |||
posy[k]=get_posy(i); | |||
k++; | |||
}; | |||
}; | |||
//sort the points | |||
for (int j=0;j<npos_used-1;j++){ | |||
for (int i=j+1;i<npos_used;i++){ | |||
if (posx[i]<posx[j]){ | |||
swap(posx[i],posx[j]); | |||
swap(posy[i],posy[j]); | |||
}; | |||
}; | |||
}; | |||
//generate the curve | |||
int p1=0,p2=1; | |||
for (int i=0;i<datasize;i++){ | |||
REALTYPE x=(REALTYPE)i/(REALTYPE)datasize; | |||
while ((x>posx[p2])&&(p2<npos_used)){ | |||
p1=p2; | |||
p2++; | |||
}; | |||
REALTYPE px1=posx[p1]; | |||
REALTYPE px2=posx[p2]; | |||
REALTYPE diffx=px2-px1; | |||
REALTYPE x0=0; | |||
if (diffx>1e-5) x0=(x-px1)/diffx; | |||
if (interp_mode==COSINE) x0=(1.0-cos(x0*M_PI))*0.5; | |||
REALTYPE y=y=posy[p1]*(1.0-x0)+posy[p2]*x0; | |||
data[i]=y; | |||
}; | |||
//smooth the curve | |||
if (smooth>0.01){ | |||
const int max_times=4; | |||
REALTYPE a=exp(log(0.25)/(smooth*smooth*datasize*0.25)); | |||
if ((a<=0.0)||(a>=1.0)) return; | |||
a=pow(a,max_times); | |||
for (k=0;k<max_times;k++){ | |||
for (int i=1;i<datasize;i++) data[i]=data[i]*(1.0-a)+data[i-1]*a; | |||
for (int i=datasize-2;i>=0;i--) data[i]=data[i]*(1.0-a)+data[i+1]*a; | |||
}; | |||
}; | |||
if (real_values){ | |||
for (int i=0;i<datasize;i++) data[i]=extreme_y.coord_to_real_value(data[i]); | |||
if (extreme_y.get_scale()==FE_DB){ | |||
for (int i=0;i<datasize;i++) data[i]=dB2rap(data[i]); | |||
}; | |||
}; | |||
}; | |||
void FreeEdit::update_curve(int size){ | |||
if (curve.data) delete []curve.data; | |||
if (size<2) size=2; | |||
curve.size=size; | |||
curve.data=new REALTYPE[size]; | |||
get_curve(curve.size,curve.data,true); | |||
// for(int i=0;i<size;i++) printf("_%d %g\n",i,curve.data[i]); | |||
}; | |||
REALTYPE FreeEdit::get_value(REALTYPE x){ | |||
if (!curve.data) { | |||
return 0.0;// update_curve(); | |||
}; | |||
if (extreme_x.get_scale()==FE_LOG){ | |||
if (x<=0.0) x=1e-9; | |||
}; | |||
// printf("%g\n",curve.data[1]); | |||
x=extreme_x.real_value_to_coord(x); | |||
if (x<0) x=0.0; | |||
else if (x>1.0) x=1.0; | |||
REALTYPE rx=x*curve.size; | |||
REALTYPE rxh=floor(rx); | |||
int k=(int)rxh; | |||
REALTYPE rxl=rx-rxh; | |||
if (k<0) k=0; | |||
if (k>(curve.size-1)) k=curve.size-1; | |||
int k1=k+1; if (k1>(curve.size-1)) k1=curve.size-1; | |||
return curve.data[k]*(1.0-rxl)+curve.data[k1]*rxl; | |||
}; | |||
void FreeEdit::add2XML(XMLwrapper *xml){ | |||
xml->addparbool("enabled",enabled); | |||
xml->addparreal("smooth",smooth); | |||
xml->addpar("interp_mode",interp_mode); | |||
xml->beginbranch("POINTS"); | |||
for (int i=0;i<FREE_EDIT_MAX_POINTS;i++){ | |||
if (!pos[i].enabled) continue; | |||
xml->beginbranch("POINT",i); | |||
xml->addparbool("enabled",pos[i].enabled); | |||
xml->addparreal("x",pos[i].x); | |||
xml->addparreal("y",pos[i].y); | |||
xml->endbranch(); | |||
}; | |||
xml->endbranch(); | |||
xml->beginbranch("EXTREME_X"); | |||
extreme_x.add2XML(xml); | |||
xml->endbranch(); | |||
xml->beginbranch("EXTREME_Y"); | |||
extreme_y.add2XML(xml); | |||
xml->endbranch(); | |||
}; | |||
void FreeEdit::getfromXML(XMLwrapper *xml){ | |||
enabled=xml->getparbool("enabled",enabled); | |||
smooth=xml->getparreal("smooth",smooth); | |||
interp_mode=(INTERP_MODE)xml->getpar("interp_mode",interp_mode,0,1); | |||
if (xml->enterbranch("POINTS")){ | |||
for (int i=0;i<FREE_EDIT_MAX_POINTS;i++){ | |||
if (xml->enterbranch("POINT",i)){ | |||
pos[i].enabled=xml->getparbool("enabled",pos[i].enabled); | |||
pos[i].x=xml->getparreal("x",pos[i].x); | |||
pos[i].y=xml->getparreal("y",pos[i].y); | |||
xml->exitbranch(); | |||
}; | |||
}; | |||
xml->exitbranch(); | |||
}; | |||
if (xml->enterbranch("EXTREME_X")){ | |||
extreme_x.getfromXML(xml); | |||
xml->exitbranch(); | |||
}; | |||
if (xml->enterbranch("EXTREME_Y")){ | |||
extreme_y.getfromXML(xml); | |||
xml->exitbranch(); | |||
}; | |||
update_curve(); | |||
}; | |||
@@ -0,0 +1,252 @@ | |||
/* | |||
Copyright (C) 2011 Nasca Octavian Paul | |||
Author: Nasca Octavian Paul | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of version 2 of the GNU General Public License | |||
as published by the Free Software Foundation. | |||
This program 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 (version 2) for more details. | |||
You should have received a copy of the GNU General Public License (version 2) | |||
along with this program; if not, write to the Free Software Foundation, | |||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
*/ | |||
#ifndef FREEEDIT_H | |||
#define FREEEDIT_H | |||
#define FREE_EDIT_MAX_POINTS 50 | |||
#include <math.h> | |||
#include <stdio.h> | |||
#include "globals.h" | |||
#include "XMLwrapper.h" | |||
#define LOG_2 0.693147181 | |||
#define LOG_10 2.302585093 | |||
#define dB2rap(dB) ((exp((dB)*LOG_10/20.0))) | |||
#define rap2dB(rap) ((20*log(rap)/LOG_10)) | |||
struct FreeEditPos{ | |||
REALTYPE x,y; | |||
bool enabled; | |||
}; | |||
enum FREE_EDIT_EXTREME_SCALE{ | |||
FE_LINEAR=0, | |||
FE_LOG=1, | |||
FE_DB=2 | |||
}; | |||
class FreeEditExtremes{ | |||
public: | |||
FreeEditExtremes(){ | |||
init(); | |||
}; | |||
void init(REALTYPE min_=0.0,REALTYPE max_=1.0,FREE_EDIT_EXTREME_SCALE scale_=FE_LINEAR,bool lock_min_max_=false,bool lock_scale_=false){ | |||
min=min_; | |||
max=max_; | |||
scale=scale_; | |||
lock_min_max=lock_min_max_; | |||
lock_scale=lock_scale_; | |||
correct_values(); | |||
}; | |||
//converting functions | |||
inline REALTYPE coord_to_real_value(REALTYPE coord){//coord = 0.0 .. 1.0 | |||
REALTYPE result; | |||
switch(scale){ | |||
case FE_LOG://log | |||
result=exp(log(min)+coord*(log(max)-log(min))); | |||
return result; | |||
default://linear or dB | |||
result=min+coord*(max-min); | |||
return result; | |||
}; | |||
}; | |||
inline REALTYPE real_value_to_coord(REALTYPE val){//coord = 0.0 .. 1.0 | |||
switch(scale){ | |||
case FE_LOG://log | |||
{ | |||
REALTYPE coord=log(val/min)/log(max/min); | |||
clamp1(coord); | |||
return coord; | |||
}; | |||
default://linear | |||
{ | |||
REALTYPE diff=max-min; | |||
REALTYPE coord; | |||
if (fabs(diff)>0.0001) coord=(val-min)/diff; | |||
else coord=min; | |||
clamp1(coord); | |||
return coord; | |||
}; | |||
}; | |||
}; | |||
//max and min functions | |||
void set_min(REALTYPE val){ | |||
if (lock_min_max) return; | |||
min=val; | |||
correct_values(); | |||
}; | |||
REALTYPE get_min(){ | |||
return min; | |||
}; | |||
void set_max(REALTYPE val){ | |||
if (lock_min_max) return; | |||
max=val; | |||
correct_values(); | |||
}; | |||
REALTYPE get_max(){ | |||
return max; | |||
}; | |||
//scale functions | |||
FREE_EDIT_EXTREME_SCALE get_scale(){ | |||
return scale; | |||
}; | |||
void set_scale(FREE_EDIT_EXTREME_SCALE val){ | |||
if (lock_scale) return; | |||
scale=val; | |||
}; | |||
void add2XML(XMLwrapper *xml){ | |||
xml->addparreal("min",min); | |||
xml->addparreal("max",max); | |||
}; | |||
void getfromXML(XMLwrapper *xml){ | |||
set_min(xml->getparreal("min",min)); | |||
set_max(xml->getparreal("max",max)); | |||
}; | |||
private: | |||
inline REALTYPE clamp1(REALTYPE m){ | |||
if (m<0.0) return 0.0; | |||
if (m>1.0) return 1.0; | |||
return m; | |||
}; | |||
void correct_values(){ | |||
if (scale!=FE_LOG) return; | |||
if (min<1e-8) min=1e-8; | |||
if (max<1e-8) max=1e-8; | |||
}; | |||
bool lock_min_max,lock_scale; | |||
REALTYPE min,max; | |||
FREE_EDIT_EXTREME_SCALE scale; | |||
}; | |||
class FreeEdit{ | |||
public: | |||
enum INTERP_MODE{ | |||
LINEAR=0, | |||
COSINE=1 | |||
}; | |||
FreeEdit(); | |||
FreeEdit (const FreeEdit &other); | |||
const FreeEdit &operator=(const FreeEdit &other); | |||
void deep_copy_from(const FreeEdit &other); | |||
void add2XML(XMLwrapper *xml); | |||
void getfromXML(XMLwrapper *xml); | |||
//Enabled functions | |||
bool get_enabled(){ | |||
return enabled; | |||
}; | |||
void set_enabled(bool val){ | |||
enabled=val; | |||
}; | |||
inline int get_npoints(){ | |||
return npos; | |||
}; | |||
//manipulation functions | |||
inline bool is_enabled(int n){ | |||
if ((n<0)||(n>=npos)) return false; | |||
return pos[n].enabled; | |||
}; | |||
inline void set_enabled(int n,bool enabled){ | |||
if ((n<0)||(n>=npos)) return; | |||
pos[n].enabled=enabled; | |||
}; | |||
inline REALTYPE get_posx(int n){ | |||
if ((n<0)||(n>=npos)) return 0.0; | |||
return pos[n].x; | |||
}; | |||
inline REALTYPE get_posy(int n){ | |||
if ((n<0)||(n>=npos)) return 0.0; | |||
return pos[n].y; | |||
}; | |||
inline void set_posx(int n,REALTYPE x){ | |||
if ((n<2)||(n>=npos)) return;//don't allow to set the x position of the first two positions | |||
pos[n].x=clamp1(x); | |||
}; | |||
inline void set_posy(int n,REALTYPE y){ | |||
if ((n<0)||(n>=npos)) return; | |||
pos[n].y=clamp1(y); | |||
}; | |||
void set_all_values(REALTYPE val){ | |||
for (int i=0;i<npos;i++){ | |||
if (pos[i].enabled) pos[i].y=extreme_y.real_value_to_coord(val); | |||
} | |||
}; | |||
//interpolation mode | |||
INTERP_MODE get_interp_mode(){ | |||
return interp_mode; | |||
}; | |||
void set_interp_mode(INTERP_MODE interp_mode_){ | |||
interp_mode=interp_mode_; | |||
}; | |||
//smooth | |||
REALTYPE get_smooth(){ | |||
return smooth; | |||
}; | |||
void set_smooth(REALTYPE smooth_){ | |||
smooth=clamp1(smooth_);; | |||
}; | |||
//getting the curve | |||
void get_curve(int datasize,REALTYPE *data,bool real_values); | |||
~FreeEdit(){ | |||
delete []pos; | |||
}; | |||
//making/updating the curve | |||
void update_curve(int size=16384); | |||
REALTYPE get_value(REALTYPE x); | |||
//extremes | |||
FreeEditExtremes extreme_x,extreme_y; | |||
struct{ | |||
REALTYPE *data; | |||
int size; | |||
}curve; | |||
private: | |||
inline REALTYPE clamp1(REALTYPE m){ | |||
if (m<0.0) return 0.0; | |||
if (m>1.0) return 1.0; | |||
return m; | |||
}; | |||
inline void swap(REALTYPE &m1,REALTYPE &m2){ | |||
REALTYPE tmp=m1; | |||
m1=m2; | |||
m2=tmp; | |||
}; | |||
FreeEditPos *pos; | |||
int npos; | |||
REALTYPE smooth; | |||
INTERP_MODE interp_mode; | |||
bool enabled; | |||
}; | |||
#endif | |||
@@ -0,0 +1,595 @@ | |||
# data file for the Fltk User Interface Designer (fluid) | |||
version 1.0110 | |||
header_name {.h} | |||
code_name {.cxx} | |||
decl {\#include <FL/Fl_File_Chooser.H>} {} | |||
decl {\#include <FL/Fl_Box.H>} {public | |||
} | |||
decl {\#include <FL/Fl_Group.H>} {public | |||
} | |||
decl {\#include <FL/Fl_Box.H>} {public | |||
} | |||
decl {\#include <FL/fl_draw.H>} {public | |||
} | |||
decl {\#include <FL/Fl_Value_Input.H>} {public | |||
} | |||
decl {\#include <FL/fl_ask.H>} {public | |||
} | |||
decl {\#include<sys/stat.h>} {} | |||
decl {\#include <stdio.h>} {} | |||
decl {\#include <string>} {} | |||
decl {\#include "Control.h"} {public | |||
} | |||
decl {\#include <math.h>} {} | |||
decl {\#include "FreeEdit.h"} {public | |||
} | |||
decl {\#include <FL/Fl_Group.H>} {public | |||
} | |||
class FreeEditUI {open : {public Fl_Box} | |||
} { | |||
Function {FreeEditUI(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { | |||
code {max_value_fl=min_value_fl=value_fl=position_fl=NULL; | |||
free_edit=NULL; | |||
control=NULL; | |||
current_point=-1; | |||
selected_point=-1; | |||
default_value=1.0;} {} | |||
} | |||
Function {~FreeEditUI()} {} { | |||
code {} {} | |||
} | |||
Function {init(FreeEdit *free_edit_,Control *control_)} {open | |||
} { | |||
code {free_edit=free_edit_; | |||
control=control_; | |||
free_edit->update_curve();} {} | |||
} | |||
Function {init_value_io(Fl_Value_Input *value_fl_,Fl_Value_Input *position_fl_,Fl_Value_Input *min_value_fl_,Fl_Value_Input *max_value_fl_)} {} { | |||
code {value_fl=value_fl_; | |||
position_fl=position_fl_; | |||
min_value_fl=min_value_fl_; | |||
max_value_fl=max_value_fl_; | |||
if (free_edit){ | |||
free_edit->extreme_y.set_min(min_value_fl->value()); | |||
free_edit->extreme_y.set_max(max_value_fl->value()); | |||
};} {} | |||
} | |||
Function {get_color(Fl_Color c)} {return_type Fl_Color | |||
} { | |||
code {if (free_edit->get_enabled()) return c; | |||
return fl_color_average(c,fl_rgb_color(178,178,178),0.1);} {} | |||
} | |||
Function {draw()} {open | |||
} { | |||
code {int ox=x(),oy=y(),lx=w(),ly=h(); | |||
//fl_color(FL_WHITE); | |||
fl_color(get_color(color())); | |||
fl_rectf(ox,oy,lx,ly); | |||
//fl_color(FL_GRAY); | |||
fl_color(get_color(labelcolor())); | |||
//draw grid | |||
fl_line_style(FL_SOLID); | |||
for (int ncoord=0;ncoord<2;ncoord++){ | |||
FreeEditExtremes *extreme=(ncoord==0)?&free_edit->extreme_x:&free_edit->extreme_y; | |||
if (extreme->get_scale()==FE_LOG){//logarithmic scale | |||
float p10=pow(10,floor(log10(extreme->get_min()))); | |||
int psteps=(int)(floor(log10(extreme->get_max()/extreme->get_min())))+1; | |||
for (int k=1;k<=psteps;k++){ | |||
for (int i=1;i<10;i++){ | |||
if (i==1) fl_line_style(FL_SOLID); | |||
else if(i==5) fl_line_style(FL_DASH); | |||
else fl_line_style(FL_DOT); | |||
float fpos=extreme->real_value_to_coord(p10*i); | |||
if ((fpos>0.0)&&(fpos<1.0)){ | |||
if (ncoord==0){ | |||
int pos=(int)(fpos*lx); | |||
fl_line(ox+pos,oy,ox+pos,oy+ly); | |||
}else{ | |||
int pos=(int)(ly-1-fpos*ly); | |||
fl_line(ox,oy+pos,ox+lx,oy+pos); | |||
}; | |||
}; | |||
}; | |||
p10*=10.0; | |||
}; | |||
}else{//linear scale | |||
float diff=extreme->get_max()-extreme->get_min(); | |||
float stepsize=pow(10,floor(log10( fabs(diff))))*0.1; | |||
if (stepsize>=1e-6){ | |||
int nsteps=(int)(fabs(diff)/stepsize)+1; | |||
if (nsteps>25) { | |||
nsteps/=5; | |||
stepsize*=5.0; | |||
}; | |||
float min=extreme->get_min(); | |||
float max=extreme->get_max(); | |||
float min1=(min<max)?min:max; | |||
int kstep=(int)(floor(min1/stepsize)); | |||
min1=kstep*stepsize; | |||
for (int i=0;i<nsteps;i++){ | |||
float fpos=extreme->real_value_to_coord(min1+i*stepsize); | |||
int ks=(i+kstep)%10; if (ks<0) ks+=10; | |||
if (ks==0) fl_line_style(FL_SOLID); | |||
else if (ks==5) fl_line_style(FL_DASH); | |||
else fl_line_style(FL_DOT); | |||
if ((fpos>0.0)&&(fpos<1.0)){ | |||
if (ncoord==0){ | |||
int pos=(int)(fpos*lx); | |||
fl_line(ox+pos,oy,ox+pos,oy+ly); | |||
}else{ | |||
int pos=(int)(ly-1-fpos*ly); | |||
fl_line(ox,oy+pos,ox+lx,oy+pos); | |||
}; | |||
}; | |||
}; | |||
}; | |||
}; | |||
}; | |||
//draw the line | |||
fl_line_style(FL_SOLID,2); | |||
fl_color(get_color(labelcolor())); | |||
float *data=new float[lx]; | |||
free_edit->get_curve(lx,data,false); | |||
int oldy=0; | |||
for (int i=0;i<lx;i++){ | |||
int newy=(int)((1.0-data[i])*ly); | |||
if (i) fl_line(ox+i-1,oy+oldy,ox+i,oy+newy); | |||
oldy=newy; | |||
}; | |||
delete[]data; | |||
//draw points | |||
fl_line_style(FL_SOLID,3); | |||
for (int i=0;i<free_edit->get_npoints();i++){ | |||
if (!free_edit->is_enabled(i)) continue; | |||
fl_color(FL_BLACK); | |||
int x=(int)(free_edit->get_posx(i)*lx); | |||
int y=(int)((1.0-free_edit->get_posy(i))*ly); | |||
fl_circle(ox+x,oy+y,3); | |||
if (i==selected_point){ | |||
fl_color(get_color(FL_RED)); | |||
fl_circle(ox+x,oy+y,4); | |||
fl_circle(ox+x,oy+y,5); | |||
}; | |||
}; | |||
/* | |||
//test | |||
{ | |||
fl_color(FL_RED); | |||
fl_line_style(FL_SOLID); | |||
free_edit->update_curve(); | |||
int oldy=0; | |||
//printf("draw %g\\n",free_edit->get_value(8000.0)); | |||
//printf("d %g\\n",free_edit->curve.data[1000]); | |||
for (int i=0;i<lx;i++){ | |||
//int m=(int)(((float)i/(float)lx)*(free_edit->curve.size-1)); | |||
//REALTYPE y=free_edit->curve.data[m]; | |||
REALTYPE freq=i/(float)lx*25000.0; | |||
REALTYPE y=free_edit->get_value(freq); | |||
//if (i<20) printf("%d %g\\n",i,y); | |||
//printf("%g %g\\n",freq,y); | |||
int newy=(int)((1.0-y)*ly); | |||
if (i) fl_line(ox+i-1,oy+oldy,ox+i,oy+newy); | |||
oldy=newy; | |||
}; | |||
}; | |||
*/ | |||
/* | |||
fl_color(FL_RED); | |||
fl_line_style(FL_SOLID); | |||
int samplerate=44100; | |||
int nfreq=lx; | |||
float *freq1=new float [nfreq]; | |||
float *freq2=new float [nfreq]; | |||
float *tmpfreq1=new float [nfreq*2]; | |||
for (int i=0;i<nfreq;i++) tmpfreq1[i]=0.0; | |||
for (int i=0;i<nfreq;i++) freq1[i]=data[i]; | |||
//convert to log spectrum | |||
float minfreq=20.0; | |||
float maxfreq=0.5*samplerate; | |||
for (int i=0;i<nfreq;i++){ | |||
float freqx=i/(float) nfreq; | |||
float x=exp(log(minfreq)+freqx*(log(maxfreq)-log(minfreq)))/maxfreq*nfreq; | |||
float y=0.0; | |||
int x0=(int)floor(x); if (x0>=nfreq) x0=nfreq-1; | |||
int x1=x0+1; if (x1>=nfreq) x1=nfreq-1; | |||
float xp=x-x0; | |||
if (x<nfreq){ | |||
y=freq1[x0]*(1.0-xp)+freq1[x1]*xp; | |||
}; | |||
tmpfreq1[i]=y; | |||
}; | |||
//increase bandwidth of each harmonic | |||
int n=2; | |||
float bandwidth=free_edit->get_posy(0); | |||
float a=1.0-exp(-bandwidth*bandwidth*nfreq*0.002); | |||
a=pow(a,n); | |||
printf("%g\\n",a); | |||
for (int k=0;k<n;k++){ | |||
tmpfreq1[0]=0.0; | |||
for (int i=1;i<nfreq;i++){ | |||
tmpfreq1[i]=tmpfreq1[i-1]*a+tmpfreq1[i]*(1.0-a); | |||
}; | |||
tmpfreq1[nfreq-1]=0.0; | |||
for (int i=nfreq-2;i>0;i--){ | |||
tmpfreq1[i]=tmpfreq1[i+1]*a+tmpfreq1[i]*(1.0-a); | |||
}; | |||
}; | |||
//convert back to linear spectrum | |||
// for (int i=0;i<nfreq;i++) freq2[i]=0.0; | |||
// for (int i=0;i<nfreq;i++) freq2[i]=tmpfreq1[i]; | |||
freq2[0]=0; | |||
for (int i=1;i<nfreq;i++){ | |||
float freqx=i/(float) nfreq; | |||
float x=log((freqx*maxfreq)/minfreq)/log(maxfreq/minfreq)*nfreq; | |||
// printf("%g\\n",x); | |||
float y=0.0; | |||
int x0=(int)floor(x); if (x0>=nfreq) x0=nfreq-1; | |||
int x1=x0+1; if (x1>=nfreq) x1=nfreq-1; | |||
float xp=x-x0; | |||
if (x<nfreq){ | |||
y=tmpfreq1[x0]*(1.0-xp)+tmpfreq1[x1]*xp; | |||
}; | |||
freq2[i]=y; | |||
}; | |||
for (int i=0;i<lx;i++){ | |||
REALTYPE y=freq2[i]; | |||
int newy=(int)((1.0-y)*ly); | |||