Commit e165625d authored by jhammen's avatar jhammen
Browse files

config level gains

parent e7ca9e96
......@@ -75,6 +75,7 @@ Plugin::~Plugin() {
inactive = inactive->next;
delete done;
}
SampleFile::dtor();
for (int i = 0; i < HD_MAX_PATCHES; i++) {
delete config[i];
}
......@@ -118,9 +119,10 @@ LV2_State_Status Plugin::restore(LV2_State_Retrieve_Function retrieve, LV2_State
}
// launch workers
for (uint i = 0; i < root.size(); i++) {
StringMesg mesg;
LoadMesg mesg;
mesg.index(i);
// TODO: add gain
float gain = root[i].isMember("gain") ? root[i]["gain"].asFloat() : 1.0;
mesg.gain(gain);
try {
const char *path = root[i]["path"].asCString();
if (mesg.name(path, strlen(path))) {
......@@ -133,6 +135,7 @@ LV2_State_Status Plugin::restore(LV2_State_Retrieve_Function retrieve, LV2_State
printf("Handrumr cannot restore, error parsing JSON: %s\n", err.what());
}
}
delete reader; // TODO: use smart pointer
return LV2_STATE_SUCCESS;
}
......@@ -145,15 +148,16 @@ LV2_Worker_Status Plugin::work(LV2_Worker_Respond_Function respond,
mesg.deserialize((const char *)data);
delete mesg.config();
return LV2_WORKER_SUCCESS;
} else if (mesgtype != WKR_STRING_MESG) {
} else if (mesgtype != WKR_LOAD_REQUEST) {
return LV2_WORKER_ERR_UNKNOWN;
}
StringMesg mesg;
LoadMesg mesg;
if (!mesg.deserialize((const char *)data, size)) {
return LV2_WORKER_ERR_NO_SPACE;
}
const char *path = mesg.name();
const uint32_t index = mesg.index();
const float gain = mesg.gain();
std::ifstream ifs;
ifs.open(path);
if (!ifs.is_open()) {
......@@ -229,19 +233,27 @@ LV2_Worker_Status Plugin::work(LV2_Worker_Respond_Function respond,
}
uint16_t bufferCount = 0; // overall channel count for sample
for (uint16_t f = 0; f < fileCount; f++) {
// pre-cache file
const string &filename = jsamples[f]["file"].asString();
const string path = fullpath(sampleBase, filename);
SampleFile *file = filecache[path];
if (!file) {
try {
file = new SampleFile(zip, path);
file = new SampleFile(zip, path, gain);
filecache[path] = file;
} catch (const std::logic_error &e) {
StringMesg mesg(e.what(), index);
respond(handle, mesg.size(), &mesg);
return LV2_WORKER_ERR_UNKNOWN;
}
} else {
// check gain is same on cached file
if (file->gain() != gain) {
StringMesg mesg(
"TBD: sample file adjustgain() when cached gain is different",
index);
respond(handle, mesg.size(), &mesg);
return LV2_WORKER_ERR_UNKNOWN;
}
}
// validate channels
uint16_t filechannels = file->channels();
......@@ -318,11 +330,11 @@ LV2_Worker_Status Plugin::work(LV2_Worker_Respond_Function respond,
respond(handle, errmesg.size(), &errmesg);
return LV2_WORKER_ERR_UNKNOWN;
}
if (zip) {
zip_close(zip);
}
config->filepath = path;
config->gain = gain;
NewConfigMesg response;
response.index(index);
response.config(config);
......@@ -601,7 +613,8 @@ void Plugin::run(uint32_t sampleCount) {
}
json.append("{\"name\" : \"");
json.append(config[i]->patchName.c_str());
json.append("\"", 1);
json.append("\", \"gain\" : ");
json.append(config[i]->gain);
json.append("}", 1);
}
json.append("]", 1);
......
......@@ -36,12 +36,13 @@ namespace handrumr {
struct PluginConfig {
string filepath;
float gain;
Instrument *instruments;
uint16_t instrumentCount;
string patchName;
bool exclusive;
PluginConfig *next;
PluginConfig() : instruments(nullptr), instrumentCount(0), next(nullptr) {}
PluginConfig() : gain(1.0), instruments(nullptr), instrumentCount(0), next(nullptr) {}
~PluginConfig() { delete[] instruments; }
};
......@@ -106,6 +107,11 @@ class StringBuffer {
sprintf(numbuf, "%u", number);
return append(numbuf, ::strlen(numbuf));
}
bool append(float number) {
char numbuf[64];
sprintf(numbuf, "%f", number);
return append(numbuf, ::strlen(numbuf));
}
size_t size() { return mend + 1; }
size_t strlen() { return mend; }
const char *ptr() { return buffer; }
......@@ -113,7 +119,33 @@ class StringBuffer {
};
// worker message types
enum { WKR_STRING_MESG, WKR_DELETE_REQUEST, WKR_CONFIG_RESPONSE };
enum { WKR_LOAD_REQUEST, WKR_STRING_MESG, WKR_DELETE_REQUEST, WKR_CONFIG_RESPONSE };
class LoadMesg {
const int64_t mtype = WKR_LOAD_REQUEST;
uint32_t mindex;
float mgain;
StringBuffer mname;
public:
LoadMesg() {}
LoadMesg(const char *str, uint32_t index) : mindex(index) { name(str, ::strlen(str)); }
int32_t type() { return mtype; }
float gain() { return mgain; }
void gain(float gain) { mgain = gain; }
const char *name() { return mname.ptr(); }
bool name(const char *str, uint32_t size) { return mname.append(str, size); }
void index(uint32_t index) { mindex = index; }
uint32_t index() { return mindex; }
size_t size() { return sizeof(mtype) + sizeof(mindex) + sizeof(mgain) + mname.size(); }
size_t strlen() { return mname.strlen(); }
bool deserialize(const char *buffer, uint32_t size) {
mindex = *((uint32_t *)(buffer + sizeof(mtype)));
mgain = *((float *)(buffer + sizeof(mtype) + sizeof(mindex)));
uint32_t header = sizeof(mtype) + sizeof(mindex) + sizeof(mgain);
return mname.append(buffer + header, size - header);
}
};
class StringMesg {
const int64_t mtype = WKR_STRING_MESG;
......
......@@ -209,10 +209,12 @@ void PluginUi::notify(uint32_t format, const LV2_Atom *atom) {
} else {
gtk_tree_store_clear(treestore);
for (uint i = 0; i < root.size(); i++) {
const char *name = root[i]["name"].asCString();
char gainstr[128];
sprintf(gainstr, "%.2f", root[i]["gain"].asFloat());
GtkTreeIter treeitem;
gtk_tree_store_append(treestore, &treeitem, NULL);
gtk_tree_store_set(treestore, &treeitem, 0, 0, 1,
root[i]["name"].asCString(), 2, "1.0", -1);
gtk_tree_store_set(treestore, &treeitem, 0, 0, 1, name, 2, gainstr, -1);
}
}
}
......
......@@ -39,16 +39,17 @@ sf_count_t hd_zip_write(const void *, sf_count_t, void *) {
sf_count_t hd_zip_tell(void *userdata) { return static_cast<SampleZipEntry *>(userdata)->tell(); }
SampleFile::SampleFile(zip *zip, const std::string &path) {
SampleFile::SampleFile(zip *zip, const std::string &path, float gain) : mgain(gain) {
// open wav file
SF_INFO info;
memset(&info, 0, sizeof(info));
SNDFILE *sndfile = nullptr;
zip_file *zipfile = nullptr;
if (!zip) {
sndfile = sf_open(path.c_str(), SFM_READ, &info);
} else {
// zipfile
zip_file *zipfile = zip_fopen(zip, path.c_str(), 0);
zipfile = zip_fopen(zip, path.c_str(), 0);
if (!zipfile) {
std::string mesg("Failed to open file in zip ");
mesg.append(path);
......@@ -62,7 +63,8 @@ SampleFile::SampleFile(zip *zip, const std::string &path) {
zip_stat_t zipstat;
zip_stat(zip, path.c_str(), 0, &zipstat);
if (zipstat.size > zipbufsize) {
zipbuffer = (char *)realloc(zipbuffer, zipstat.size);
free(zipbuffer);
zipbuffer = (char *)malloc(zipstat.size);
zipbufsize = zipstat.size;
}
uint64_t read = zip_fread(zipfile, zipbuffer, zipstat.size);
......@@ -95,13 +97,16 @@ SampleFile::SampleFile(zip *zip, const std::string &path) {
sf_seek(sndfile, 0ul, SEEK_SET);
sf_readf_float(sndfile, buffer, mframes);
sf_close(sndfile);
if (zipfile) {
zip_fclose(zipfile);
}
// create file buffers
mdata = new float *[mchannels];
for (uint16_t c = 0; c < mchannels; c++) {
mdata[c] = new float[mframes];
for (uint64_t f = 0; f < mframes; f++) {
mdata[c][f] = buffer[f * mchannels + c];
mdata[c][f] = buffer[f * mchannels + c] * gain;
}
}
delete[] buffer;
......
......@@ -47,18 +47,21 @@ class SampleFile {
// buffer for reading zip files
static uint64_t zipbufsize;
static char *zipbuffer;
float mgain;
public:
SampleFile(zip *zip, const string &path);
SampleFile(zip *zip, const string &path, float gain);
~SampleFile() {
for (uint16_t i = 0; i < mchannels; i++) {
delete[] mdata[i];
}
delete[] mdata;
}
static void dtor() { free(zipbuffer); }
float *buffer(uint16_t i) { return mdata[i]; }
uint64_t frames() { return mframes; }
uint16_t channels() { return mchannels; }
float gain() { return mgain; }
};
class SampleZipEntry {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment