]> git.treefish.org Git - seamulator.git/blob - src/synthesizer.cpp
Distribute dots in space
[seamulator.git] / src / synthesizer.cpp
1 /**
2  * Copyright (C) 2021  Alexander Schmidt
3  *
4  * This file is part of Seamulator.
5  *
6  * Seamulator is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Seamulator is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Seamulator.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "synthesizer.h"
21
22 #include <cmath>
23 #include <functional>
24 #include <iostream>
25
26 #include <Stk.h>
27 #include <Echo.h>
28 #include <Chorus.h>
29 #include <FreeVerb.h>
30 #include <PitShift.h>
31 #include <PRCRev.h>
32 #include <NRev.h>
33
34 #include <Eigen/Dense>
35
36 #include "watersurface.h"
37
38 using namespace Eigen;
39
40 Synthesizer::Synthesizer(ConstWaterSurfacePtr surface) :
41     m_surface{std::move(surface)},
42     m_startTime{std::chrono::system_clock::now()},
43     m_lastRuntime{getRuntime()}
44 {
45     stk::Stk::setSampleRate( 44100.0 );
46     stk::Stk::showWarnings( true );
47
48     m_dac = std::make_unique<stk::RtWvOut>(2);
49
50     //m_sine1.setFrequency( 441.0 );
51     //m_sine2.setFrequency( 520.0 );
52
53     //m_sine1.noteOn(40.0, 1.0);
54     // m_sine2.noteOn(74.0, 1.0);
55
56     //for (int i = 0; i < 10; ++i) {
57 //        m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(i, 0), 440.0) );
58         //}
59
60     srand (time(NULL));
61     
62     const std::vector<double> frequencies = {939.85, 704.09, 469.92, 352.04, 279.42, 1054.94, 704.09, 527.47, 418.65, 313.64};
63
64     for (const auto& frequency : frequencies) {
65         const std::array<int, 2> pos =
66             { rand() % m_surface->size(), rand() %  m_surface->size() };
67         m_posDots.emplace_back(
68             PosDot{pos, std::make_unique<Dot>(m_surface->at(pos[0], pos[1]), frequency)} );
69     }
70
71     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(10, 50), 939.85) );
72     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(20, 40), 704.09) );
73     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(30, 30), 469.92) );
74     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(40, 20), 352.04) );
75     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(50, 10), 279.42) );
76
77     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(50, 10), 1054.94) );
78     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(40, 20), 704.09) );
79     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(30, 30), 527.47) );
80     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(20, 40), 418.65) );
81     // m_dots.emplace_back( std::make_unique<Dot>(m_surface->at(10, 50), 313.64) );
82
83     m_audioThread = std::thread( [this]{audioLoop();} );
84
85     // std::cout << "NoteOn 0.0 1 64.000000 64.0" << std::endl;
86     // std::cout << std::flush;
87
88     // Figure out how many bytes in an StkFloat and setup the RtAudio stream.
89 //     RtAudio::StreamParameters parameters;
90 //     parameters.deviceId = m_dac.getDefaultOutputDevice();
91 //     parameters.nChannels = 1;
92 //     RtAudioFormat format = ( sizeof(stk::StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
93 //     unsigned int bufferFrames = stk::RT_BUFFER_SIZE;
94 //     try {
95 // //        auto aTick = std::bind(&Synthesizer::audioTick, this, _1, _2, _3, _4, _5, _6);
96 //         std::function<int (void*, void*, unsigned int, double, unsigned int, void*)> bla = [this](void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
97 //                                                                                                              double streamTime, RtAudioStreamStatus status, void *dataPointer) -> int {
98 //             return 0;
99 //         };
100 //         m_dac.openStream( &parameters, NULL, format, (unsigned int)stk::Stk::sampleRate(), &bufferFrames, bla,
101 //                           (void *)&m_sine );
102 //     }
103 //     catch ( RtAudioError &error ) {
104 //         // error.printMessage();
105 //         // goto cleanup;
106 //         throw;
107 //     }
108
109 //     m_sine.setFrequency(440.0);
110 //     try {
111 //         m_dac.startStream();
112 //     }
113 //     catch ( RtAudioError &error ) {
114 //         // error.printMessage();
115 //         // goto cleanup;
116 //         throw;
117 //     }
118 }
119
120 Synthesizer::~Synthesizer()
121 {
122     m_stop = true;
123     m_audioThread.join();
124 }
125
126 void Synthesizer::tick()
127 {
128     const auto runtime = getRuntime();
129     const auto deltaT = runtime - m_lastRuntime;
130
131     for (auto& posDot : m_posDots) {
132         posDot.dot->advance(deltaT);
133     }
134     
135 //     const auto posBefore = m_pos;
136 //     const auto posBefore2 = m_pos2;
137
138 //     m_vel += -1.0 * ( m_pos - m_surface->at(0, 0).getHeight() ) * deltaT - deltaT * m_vel * 0.1;
139 //     m_pos += m_vel * deltaT;
140
141 //     //std::cout << m_vel << std::endl;
142
143 //     std::cout << m_pos2 << std::endl;
144
145 //     m_vel2 += -10.0 * ( m_pos2 - m_surface->at(10, 10).getHeight() ) * deltaT - deltaT * m_vel2 * 0.1;
146 //     m_pos2 += m_vel2 * deltaT;
147
148 //     m_velMax1 = std::max(m_velMax1, m_vel);
149 //     m_velMax2 = std::max(m_velMax2, m_vel2);
150     
151 //     if (posBefore * m_pos < 0.0) {
152 //         //      std::cout << "ControlChange 0.0 2 7 " << 100 * std::fabs(m_vel) << std::endl;
153 //         //m_sine1.noteOn(
154 //         // std::cout << "NoteOn 0.0 2 75 64" << std::endl;
155 //         // std::cout << std::flush;
156 //         m_sine1.noteOn(m_pos >= 0 ? 440.0 : 329.628, m_vel / m_velMax1);
157 //     }
158
159 //     if (posBefore2 * m_pos2 < 0.0) {
160 // //        std::cout << "ControlChange 0.0 1 7 " << 100 * std::fabs(m_vel) << std::endl;
161 //         // std::cout << "NoteOn 0.0 1 44 64" << std::endl;
162 // //        std::cout << "NoteOff 0.1 1 44 64" << std::endl;
163 //         // std::cout << std::flush;
164 //         m_sine2.noteOn(m_pos2 >= 0 ? 440.0 : 329.628, m_vel2 / m_velMax2);
165 //     }
166
167 //     // std::cout << std::fabs(m_vel) * 10000 << std::endl;
168
169 //     // m_sine1.controlChange(128, std::fabs(m_vel) * 10000);
170     
171 //     // std::cout << "ControlChange 0.0 1 7 " << 100 * std::fabs(m_vel) << std::endl;
172 //     // std::cout << "PitchChange 0.0 1 " << 42 + 0.1*m_pos << std::endl;
173
174 // //     std::cout << "ControlChange 0.0 1 7 " << 64 + 100 * m_vel << std::endl;
175 //     //std::cout << "AfterTouch 0.0 1 " << 64 + 10 * m_vel << std::endl;
176 //     //std::cout << "PitchChange 0.0 1 " << 64 + 10*m_vel << std::endl;
177
178 //     std::cout << std::flush;
179
180     
181     
182     m_lastRuntime = runtime;
183 }
184
185 void Synthesizer::audioLoop()
186 {
187     stk::PRCRev effect0(0.5);
188     stk::Echo echo1;
189     stk::Echo echo2{4000};
190     stk::Echo echo3{7000};
191     stk::Chorus chorus{6000};
192     stk::StkFrames frames(88200, 2);
193
194
195     const Vector2d leftPos{0.0, -1.0};
196     const Vector2d rightPos{1.0, -1.0};
197
198     std::vector<double> dotDist;
199
200     for (std::size_t dotIdx = 0; dotIdx < m_posDots.size(); ++dotIdx) {
201         auto& posDot = m_posDots[dotIdx];
202         const Vector2d pos( static_cast<double>(posDot.pos[0]) / m_surface->size(),
203                             static_cast<double>(posDot.pos[1]) / m_surface->size() );
204         dotDist.emplace_back( (leftPos - pos).squaredNorm() );
205         dotDist.emplace_back( (rightPos - pos).squaredNorm() );
206     }
207
208     while (!m_stop) {
209         for (int i = 0; i < 88200; i++) {
210             frames(i, 0) *= 0;
211             frames(i, 1) *= 0;
212             for (std::size_t dotIdx = 0; dotIdx < m_posDots.size(); ++dotIdx) {
213                 const auto tick = m_posDots[dotIdx].dot->tick();
214                 frames(i, 0) += tick / dotDist[dotIdx*2];
215                 frames(i, 1) += tick / dotDist[dotIdx*2+1];
216                 // frames(i, 1) += (1.0 - normPosX) * tick;
217             }
218             //frames(i,1) = frames(i,0);
219         }
220         //       frames = effect0.tick(frames);
221         frames = echo1.tick(frames);
222         // frames = echo2.tick(frames);
223         // frames = echo3.tick(frames);
224
225         frames = chorus.tick(frames);
226
227         m_dac->tick(frames);
228     }
229 }
230
231 double Synthesizer::getRuntime() const
232 {
233   auto timeNow = std::chrono::system_clock::now();
234   auto durationMs =
235     std::chrono::duration_cast<std::chrono::milliseconds>(timeNow - m_startTime);
236   return durationMs.count() / 1000.0;
237 }