diff --git a/sauSynKlick/SynKlick.cc b/sauSynKlick/SynKlick.cc index 527b170..6a734fd 100644 --- a/sauSynKlick/SynKlick.cc +++ b/sauSynKlick/SynKlick.cc @@ -13,16 +13,19 @@ GNU PUBLIC LICENCE (GPL) Version 2 and above. #include #include +#include #include #include #include using std::string; +using std::vector; using std::cout; using std::cerr; -const size_t BUFF_SIZE = 44100; -const size_t CONTEXT = 1; +const size_t BUFF_SIZE = 44100; +const size_t CONTEXT = 100; +const size_t CHUNK_SIZE = BUFF_SIZE + 2*CONTEXT; /* ==== Helpers ==== */ @@ -48,49 +51,114 @@ name_without_path (string rawName) /* ==== Abstraction: single channel to be processed ==== */ -struct Channel +enum Event { + NO=0, + MAYBE, + YES +}; + +class Channel { - string name; - SNDFILE *in = nullptr, - *out = nullptr; - SF_INFO info_in, - info_out; + string name_; + SNDFILE *in_ = nullptr, + *out_ = nullptr; + SF_INFO info_in_, + info_out_; - float buff[BUFF_SIZE+CONTEXT]; + float buff_[CHUNK_SIZE]; + size_t workPos=0, + loadPos=0; + public: void open (string name, string target) { - this->name = name; + this->name_ = name; target += name_without_path(name); - info_in.format = 0; - in = sf_open (name.c_str(), SFM_READ, &info_in); - if (!in) + info_in_.format = 0; + in_ = sf_open (name.c_str(), SFM_READ, &info_in_); + if (!in_) error ("could not open "+name+" -- " + sf_strerror (NULL)); - info_out.format = info_in.format; - info_out.channels = info_in.channels; - info_out.samplerate = info_in.samplerate; - out = sf_open(target.c_str(), SFM_WRITE, &info_out); - if (!out) + info_out_.format = info_in_.format; + info_out_.channels = info_in_.channels; + info_out_.samplerate = info_in_.samplerate; + out_ = sf_open(target.c_str(), SFM_WRITE, &info_out_); + if (!out_) error ("unable to create target "+target+" -- " + sf_strerror (NULL)); } ~Channel() { - sf_close (in); - if (!sf_close (out)) - cerr << "WARNING: problems while closing target '" << name_without_path(name) - << "' -- " << sf_strerror(out) << "\n"; + sf_close (in_); + if (!sf_close (out_)) + cerr << "WARNING: problems while closing target '" << name_without_path(name_) + << "' -- " << sf_strerror(out_) << "\n"; - in = out = nullptr; + in_ = out_ = nullptr; } + + + void + fillBuffer() + { + error("TODO"); + } + + void + writeBuffer() + { + error("TODO"); + } + + /** + * process a single sample position in the current buffer content. + * The sample is copied to the output and it is investigated for glitches. + * @param i position of current sample + * @param event state of other tracks investigated thus far + * @return the event detection state including the results of investigating this sample. + * If the sample is positively an glitch event, and the state is undecided thus far, + * the event state is confirmed; if a glitch can not be confirmed, the state is + * cleared. Otherwise, the undecided state is passed on. + */ + Event + visit (uint i, Event event) + { + return event; + } + }; +/** + * fix a glitch detected in the corresponding channel. + * When the Patch is applied, internal work buffers are used + * to create two (partially synthetic) copies of the channel's signal + * which are then cross faded. The result is pushed back into the + * output of the underlying channel. + */ +class Patch + { + float workBuff[2*CONTEXT]; + Channel& chan_; + + public: + Patch(Channel& c) + : chan_(c) + { + + } + + void + apply() + { + error("TODO"); + } + }; + @@ -98,28 +166,51 @@ struct Channel /* ==== high-level operation ==== */ int num_sources = 0; -Channel* channel = nullptr; +vector streams(0); +bool hitEnd = false; void openStreams (char* name[], string targetDir) { - assert (!channel); assert (num_sources); - channel = new Channel[num_sources]; + assert (0 == streams.size()); + streams.resize(num_sources); assert (targetDir.length()); if (targetDir.back() != '/') targetDir += '/'; for (uint i=0; i < num_sources; ++i) - channel[i].open (name[i], targetDir); + streams[i].open (name[i], targetDir); } void closeStreams() { - delete[] channel; + streams.clear(); +} + + +void +process() +{ + while (!hitEnd) + { + for (Channel& channel : streams) + channel.fillBuffer(); + for (uint i=0; i < CHUNK_SIZE; ++i) + { + Event event = MAYBE; + for (Channel& channel : streams) + event = channel.visit(i, event); + if (YES == event) + for (Channel& channel : streams) + Patch(channel).apply(); + } + for (Channel& channel : streams) + channel.writeBuffer(); + } } @@ -141,7 +232,7 @@ main (int argc, char* argv[]) { string targetDir = argv[argc-1]; openStreams (&argv[1], targetDir); - + process(); closeStreams(); cout << "\nSUCCESS\n" << num_sources << " files read and processed --> "