WIP Entwurf Verarbeitungsrahmen
This commit is contained in:
parent
f018ca9371
commit
947e27746f
1 changed files with 120 additions and 29 deletions
|
|
@ -13,16 +13,19 @@ GNU PUBLIC LICENCE (GPL) Version 2 and above.
|
|||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
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<Channel> 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 --> "
|
||||
|
|
|
|||
Loading…
Reference in a new issue