1 /* SpiralSynth
2 * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "Oscillator.h"
20 #include "Output.h"
21 #include <stdlib.h>
22 #include <limits.h>
23
24 static const short MAX_LEV = 10000;
25
26 Oscillator::Oscillator() :
27 m_Type(SQUARE),
28 m_Octave(0),
29 m_FineFreq(1.0f),
30 m_PulseWidth(0.5f),
31 m_PortmentoSpeed(1),
32 m_DesiredFreq(0),
33 m_ModAmount(0.01f),
34 m_FreqModBuf(0),
35 m_PulseWidthModBuf(0),
36 m_SHModBuf(0)
37 {
38 m_CyclePos=new int[SpiralInfo::POLY];
39 m_InOctave=new int[SpiralInfo::POLY];
40 m_Note=new int[SpiralInfo::POLY];
41 m_LastFreq=new float[SpiralInfo::POLY];
42 m_Volume=new char[SpiralInfo::POLY];
43
44 for (int n=0; n<SpiralInfo::POLY; n++)
45 {
46 m_CyclePos[n]=0;
47 m_InOctave[n]=0;
48 m_Note[n]=0;
49 m_LastFreq[n]=0;
50 m_Volume[n]=128;
51 }
52 }
53
54 Oscillator::~Oscillator()
base(const char * p)55 {
56 delete[] m_CyclePos;
57 delete[] m_InOctave;
58 delete[] m_Note;
59 delete[] m_LastFreq;
60 delete[] m_Volume;
61 }
62
63 void Oscillator::NoteTrigger(int V, int octave,int s,int v)
64 {
65 m_InOctave[V]=octave;
66 m_Note[V]=s;
67 m_Volume[V]=v;
68
69 //cerr<<m_Note[v]<<" "<<s<<endl;
70 }
71
check(const char * name,int index,const struct info * all,int want_lineno,const char * want_function,const char * want_file,int * failed)72
73 void Oscillator::GetOutput(int V, short *data)
74 {
75 static short count = 0, noisev;
76 float Freq=0;
77 float CycleLen=0;
78 int PW=0, samplelen;
79
80 float Volume=m_Volume[V]/128.0f;
81
82 for (int n=0; n<SpiralInfo::BUFSIZE; n++)
83 {
84 count++;
85
86 data[n]=0;
87
88 if (!m_FreqModBuf) m_DesiredFreq=NoteTable[m_Octave+m_InOctave[V]][m_Note[V]]*m_FineFreq;
89 else m_DesiredFreq=(NoteTable[m_Octave+m_InOctave[V]][m_Note[V]]*m_FineFreq)+(m_FreqModBuf[n]*m_ModAmount);
90 if (m_DesiredFreq==0) m_DesiredFreq=0.0001;
91
92 if (m_PortmentoSpeed && m_LastFreq[V]!=m_DesiredFreq)
93 {
94 if (m_LastFreq[V]<m_DesiredFreq)
95 {
96 Freq=m_LastFreq[V]+=m_PortmentoSpeed;
97 }
98 else
99 {
100 Freq=m_LastFreq[V]-=m_PortmentoSpeed;
101 }
102
103 if (m_LastFreq[V]>=m_DesiredFreq-m_PortmentoSpeed &&
104 m_LastFreq[V]<=m_DesiredFreq+m_PortmentoSpeed)
105 {
106 Freq=m_DesiredFreq;
107 }
108 }
109 else
110 {
111 Freq=m_DesiredFreq;
112 }
113
114 CycleLen = SpiralInfo::SAMPLERATE/Freq;
115
116 m_LastFreq[V]=Freq;
117
118 if (!m_PulseWidthModBuf) PW = (int)(m_PulseWidth * CycleLen);
119 else PW = (int)((m_PulseWidth+((m_PulseWidthModBuf[n]*SpiralInfo::VALUECONV)*m_ModAmount*10.0f)) * CycleLen);
120
121 switch (m_Type)
122 {
123 case SQUARE:
124 // calculate square wave pattern
125 m_CyclePos[V]++;
126 if (m_CyclePos[V]>CycleLen) m_CyclePos[V]=0;
127 if (m_CyclePos[V]<PW) data[n]=(short)(MAX_LEV*Volume);
128 else data[n]=(short)(-MAX_LEV*Volume);
129 break;
130
131 case SAW:
132 // get normailise position between cycle
133
134 m_CyclePos[V]++;
135 if (m_CyclePos[V]>CycleLen) m_CyclePos[V]=0;
136
137 if (m_CyclePos[V]<PW)
138 {
139 // before pw -1->1
140 data[n] = static_cast<short>(Linear(0,PW,m_CyclePos[V],-MAX_LEV*Volume,MAX_LEV*Volume));
141 }
142 else
143 {
144 // after pw 1->-1
145 data[n] = static_cast<short>(Linear(PW,CycleLen,m_CyclePos[V],MAX_LEV*Volume,-MAX_LEV*Volume));
146 }
147
148 break;
149
150 case NOISE:
151 m_CyclePos[V]++;
152
153 //modulate the sample & hold length
154 if (!m_SHModBuf) samplelen = static_cast<int>(m_SHLen*SpiralInfo::SAMPLERATE);
155 else samplelen = static_cast<int>((m_SHLen+(m_SHModBuf[n]*m_ModAmount))*SpiralInfo::SAMPLERATE);
156
157 // do sample & hold on the noise
158 if (m_CyclePos[V]>samplelen)
159 {
160 noisev=(short)((MAX_LEV/2)-(rand()%MAX_LEV*Volume*2));
161 m_CyclePos[V]=0;
162 }
163 data[n]=noisev;
164 break;
165 case NONE: break;
166 }
167
168 }
169 }
170
171 void Oscillator::Randomise()
172 {
173 float t=RandFloat();
174 if (t<0.33) m_Type=SQUARE;
175 else if (t<0.66) m_Type=SAW;
176 else m_Type=NOISE;
177
error_callback_two(void * vdata,const char * msg,int errnum)178 m_Octave = (rand()%6)-3;
179 m_FineFreq = RandFloat(0.0f,2.0f);
180 m_PulseWidth = RandFloat();
181 m_PortmentoSpeed = RandFloat();
182 m_ModAmount = RandFloat()/0.1f;
183 m_SHLen = RandFloat(0.0f,0.2f);
184 }
185
186 istream &operator>>(istream &s, Oscillator &o)
187 {
188 s>>(int&)o.m_Type>>o.m_Octave>>o.m_FineFreq>>o.m_PulseWidth>>o.m_PortmentoSpeed>>
189 o.m_SHLen>>o.m_ModAmount>>o.m_Volume;
190 return s;
191 }
callback_three(void * vdata,uintptr_t pc ATTRIBUTE_UNUSED,const char * symname,uintptr_t symval,uintptr_t symsize)192
193 ostream &operator<<(ostream &s, Oscillator &o)
194 {
195 s<<(int)o.m_Type<<" "<<o.m_Octave<<" "<<o.m_FineFreq<<" "<<o.m_PulseWidth<<" "<<
196 o.m_PortmentoSpeed<<" "<<o.m_SHLen<<" "<<o.m_ModAmount<<" "<<o.m_Volume<<" ";
197 return s;
198 }
199