commit 21e395b14cf8d08e63e144222e10ca1a172ece10
parent e85dd19254df52b18d4d53554d4a60c8d61a16a4
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sat, 22 May 2010 07:36:01 -0400
Merge branch 'nio'
Diffstat:
55 files changed, 1168 insertions(+), 1119 deletions(-)
diff --git a/doc/gen/Makefile b/doc/gen/Makefile
@@ -1,4 +1,11 @@
+all:echo.png ad-note.png
+
ad-note.png: ad-note.tex
pslatex ad-note.tex
convert ad-note.dvi -trim ad-note.png
rm ad-note.dvi ad-note.log ad-note.aux
+
+echo.png: echo.tex
+ pslatex echo.tex
+ convert echo.dvi -trim echo.png
+ rm echo.dvi echo.log echo.aux
diff --git a/doc/gen/echo.tex b/doc/gen/echo.tex
@@ -0,0 +1,48 @@
+\documentclass[11pt]{report}
+\pagestyle{empty}
+\usepackage{pst-sigsys}
+\begin{document}
+\begin{pspicture}[showgrid=true](0,0)(10,10)
+ %Style
+ \psset{framesize=1 .65}
+ \psset{style=Arrow}
+
+ %In/Out
+ \rput(0,7){\rnode{in}{$x[n]$}}
+ \rput(10,5){\rnode{out}{$y[n]$}}
+
+ %Panning
+ \psfblock[framesize=1.3 .65](1.5,7){pan}{Panning}
+ \ncline{in}{pan}
+
+ %Crossover
+ \psfblock[framesize=1.8 .65](5,5){cross}{Crossover}
+
+ %Gain
+ \psfblock(7,5){gain}{Gain}
+
+ %Feedback
+ \psfblock[framesize=1.6 .65](5,7){fb}{Feedback}
+ \ncline{cross}{fb}
+ \pscircleop(3,7){combine}
+ \ncline{pan}{combine}
+ \ncline{fb}{combine}
+
+ %Dampining
+ \psfblock[framesize=1.6 .65](3,6){hidamp}{Dampening}
+ \ncline{combine}{hidamp}
+
+ %Delay
+ \psfblock(3,5){delay}{$z^{-n}$}
+ \pscircleop(1,5){delayp}
+
+ \nclist{ncline}{delayp,delay,cross,gain,out}
+ %\ncline{in}{delayp}
+
+ %Filter Unit
+ \psfblock(1,6){fildelay}{$z^{-1}$}
+ \ncline[arrows=<->]{fildelay}{hidamp}
+ \ncline{fildelay}{delayp}
+
+\end{pspicture}
+\end{document}
diff --git a/src/DSP/FFTwrapper.cpp b/src/DSP/FFTwrapper.cpp
@@ -134,3 +134,8 @@ void deleteFFTFREQS(FFTFREQS *f)
f->c = f->s = NULL;
}
+void FFT_cleanup()
+{
+ fftw_cleanup();
+}
+
diff --git a/src/DSP/FFTwrapper.h b/src/DSP/FFTwrapper.h
@@ -66,5 +66,6 @@ class FFTwrapper
void newFFTFREQS(FFTFREQS *f, int size);
void deleteFFTFREQS(FFTFREQS *f);
+void FFT_cleanup();
#endif
diff --git a/src/Misc/Bank.cpp b/src/Misc/Bank.cpp
@@ -1,9 +1,11 @@
/*
ZynAddSubFX - a software synthesizer
- Bank.h - Instrument Bank
+ Bank.cpp - Instrument Bank
Copyright (C) 2002-2005 Nasca Octavian Paul
+ Copyright (C) 2010-2010 Mark McCurry
Author: Nasca Octavian Paul
+ Mark McCurry
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License
@@ -26,6 +28,8 @@
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
+#include <algorithm>
+#include <iostream>
#include <sys/types.h>
#include <fcntl.h>
@@ -39,47 +43,25 @@
//if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file
#define FORCE_BANK_DIR_FILE ".bankdir"
+using namespace std;
+
Bank::Bank()
+ :defaultinsname(" ")
{
- ZERO(defaultinsname, PART_MAX_NAME_LEN);
- snprintf(defaultinsname, PART_MAX_NAME_LEN, "%s", " ");
-
- for(int i = 0; i < BANK_SIZE; i++) {
- ins[i].used = false;
- ins[i].filename = NULL;
- ins[i].info.PADsynth_used = false;
- }
- dirname = NULL;
clearbank();
-
-
-
- for(int i = 0; i < MAX_NUM_BANKS; i++) {
- banks[i].dir = NULL;
- banks[i].name = NULL;
- }
-
bankfiletitle = dirname;
-
loadbank(config.cfg.currentBankDir);
}
Bank::~Bank()
{
- for(int i = 0; i < MAX_NUM_BANKS; i++) {
- if(banks[i].dir != NULL)
- delete [] banks[i].dir;
- if(banks[i].name != NULL)
- delete [] banks[i].name;
- }
-
clearbank();
}
/*
* Get the name of an instrument from the bank
*/
-char *Bank::getname(unsigned int ninstrument)
+string Bank::getname(unsigned int ninstrument)
{
if(emptyslot(ninstrument))
return defaultinsname;
@@ -89,82 +71,57 @@ char *Bank::getname(unsigned int ninstrument)
/*
* Get the numbered name of an instrument from the bank
*/
-char *Bank::getnamenumbered(unsigned int ninstrument)
+string Bank::getnamenumbered(unsigned int ninstrument)
{
if(emptyslot(ninstrument))
return defaultinsname;
- snprintf(tmpinsname[ninstrument],
- PART_MAX_NAME_LEN + 15,
- "%d. %s",
- ninstrument + 1,
- getname(ninstrument));
- return tmpinsname[ninstrument];
+
+ return stringFrom(ninstrument + 1) + ". " + getname(ninstrument);
}
/*
* Changes the name of an instrument (and the filename)
*/
-void Bank::setname(unsigned int ninstrument, const char *newname, int newslot)
+void Bank::setname(unsigned int ninstrument, string newname, int newslot)
{
if(emptyslot(ninstrument))
return;
- char newfilename[1000 + 1], tmpfilename[100 + 1];
+ string newfilename;
+ char tmpfilename[100 + 1];
- ZERO(newfilename, 1001);
- ZERO(tmpfilename, 101);
if(newslot >= 0)
- snprintf(tmpfilename, 100, "%4d-%s", newslot + 1, newname);
+ snprintf(tmpfilename, 100, "%4d-%s", newslot + 1, newname.c_str());
else
- snprintf(tmpfilename, 100, "%4d-%s", ninstrument + 1, newname);
+ snprintf(tmpfilename, 100, "%4d-%s", ninstrument + 1, newname.c_str());
//add the zeroes at the start of filename
for(int i = 0; i < 4; i++)
if(tmpfilename[i] == ' ')
tmpfilename[i] = '0';
- //make the filenames legal
- for(int i = 0; i < (int) strlen(tmpfilename); i++) {
- char c = tmpfilename[i];
- if((c >= '0') && (c <= '9'))
- continue;
- if((c >= 'A') && (c <= 'Z'))
- continue;
- if((c >= 'a') && (c <= 'z'))
- continue;
- if((c == '-') || (c == ' '))
- continue;
+ newfilename = dirname + '/' + legalizeFilename(tmpfilename) + ".xiz";
- tmpfilename[i] = '_';
- }
+ rename(ins[ninstrument].filename.c_str(), newfilename.c_str());
- snprintf(newfilename, 1000, "%s/%s.xiz", dirname, tmpfilename);
-
-// printf("rename %s -> %s\n",ins[ninstrument].filename,newfilename);//////////////
-
- rename(ins[ninstrument].filename, newfilename);
- if(ins[ninstrument].filename)
- delete [] ins[ninstrument].filename;
- ins[ninstrument].filename = new char[strlen(newfilename) + 5];
- snprintf(ins[ninstrument].filename, strlen(
- newfilename) + 1, "%s", newfilename);
- snprintf(ins[ninstrument].name, PART_MAX_NAME_LEN, "%s", &tmpfilename[5]);
+ ins[ninstrument].filename = newfilename;
+ ins[ninstrument].name = legalizeFilename(tmpfilename); //TODO limit name to PART_MAX_NAME_LEN
}
/*
* Check if there is no instrument on a slot from the bank
*/
-int Bank::emptyslot(unsigned int ninstrument)
+bool Bank::emptyslot(unsigned int ninstrument)
{
if(ninstrument >= BANK_SIZE)
- return 1;
- if(ins[ninstrument].filename == NULL)
- return 1;
+ return true;
+ if(ins[ninstrument].filename.empty())
+ return true;
if(ins[ninstrument].used)
- return 0;
+ return false;
else
- return 1;
+ return true;
}
/*
@@ -175,10 +132,7 @@ void Bank::clearslot(unsigned int ninstrument)
if(emptyslot(ninstrument))
return;
-// printf("remove %s \n",ins[ninstrument].filename);////////////////////////
-
-
- remove(ins[ninstrument].filename);
+ remove(ins[ninstrument].filename.c_str());
deletefrombank(ninstrument);
}
@@ -204,34 +158,11 @@ void Bank::savetoslot(unsigned int ninstrument, Part *part)
if(tmpfilename[i] == ' ')
tmpfilename[i] = '0';
- //make the filenames legal
- for(int i = 0; i < (int)strlen(tmpfilename); i++) {
- char c = tmpfilename[i];
- if((c >= '0') && (c <= '9'))
- continue;
- if((c >= 'A') && (c <= 'Z'))
- continue;
- if((c >= 'a') && (c <= 'z'))
- continue;
- if((c == '-') || (c == ' '))
- continue;
+ string filename = dirname + '/' + legalizeFilename(tmpfilename) + ".xiz";
- tmpfilename[i] = '_';
- }
-
- strncat(tmpfilename, ".xiz", maxfilename + 10);
-
- int fnsize = strlen(dirname) + strlen(tmpfilename) + 10;
- char *filename = new char[fnsize + 4];
- ZERO(filename, fnsize + 2);
-
- snprintf(filename, fnsize, "%s/%s", dirname, tmpfilename);
-
- remove(filename);
- part->saveXML(filename);
- addtobank(ninstrument, tmpfilename, (char *) part->Pname);
-
- delete[] filename;
+ remove(filename.c_str());
+ part->saveXML(filename.c_str());
+ addtobank(ninstrument, legalizeFilename(tmpfilename), (char *) part->Pname);
}
/*
@@ -244,37 +175,30 @@ void Bank::loadfromslot(unsigned int ninstrument, Part *part)
part->defaultsinstrument();
-// printf("load: %s\n",ins[ninstrument].filename);
-
- part->loadXMLinstrument(ins[ninstrument].filename);
+ part->loadXMLinstrument(ins[ninstrument].filename.c_str());
}
-
/*
* Makes current a bank directory
*/
-int Bank::loadbank(const char *bankdirname)
+int Bank::loadbank(string bankdirname)
{
- DIR *dir = opendir(bankdirname);
+ DIR *dir = opendir(bankdirname.c_str());
clearbank();
if(dir == NULL)
return -1;
- if(dirname != NULL)
- delete[] dirname;
- dirname = new char[strlen(bankdirname) + 1];
- snprintf(dirname, strlen(bankdirname) + 1, "%s", bankdirname);
+ dirname = bankdirname;
bankfiletitle = dirname;
- // printf("loadbank %s/\n",bankdirname);
struct dirent *fn;
while((fn = readdir(dir))) {
const char *filename = fn->d_name;
- //sa verific daca e si extensia dorita
+ //check for extension
if(strstr(filename, INSTRUMENT_EXTENSION) == NULL)
continue;
@@ -292,35 +216,29 @@ int Bank::loadbank(const char *bankdirname)
}
}
-
if((startname + 1) < strlen(filename))
- startname++; //to take out the "-"
+ startname++; //to take out the "-"
- char name[PART_MAX_NAME_LEN + 1];
- ZERO(name, PART_MAX_NAME_LEN + 1);
- snprintf(name, PART_MAX_NAME_LEN, "%s", filename);
+ string name = filename;
//remove the file extension
- for(int i = strlen(name) - 1; i >= 2; i--) {
+ for(int i = name.size() - 1; i >= 2; i--) {
if(name[i] == '.') {
- name[i] = '\0';
+ name = name.substr(0,i);
break;
}
}
if(no != 0) //the instrument position in the bank is found
- addtobank(no - 1, filename, &name[startname]);
+ addtobank(no - 1, filename, name.substr(startname));
else
addtobank(-1, filename, name);
- ;
}
-
closedir(dir);
- if(dirname != NULL)
- sprintf(config.cfg.currentBankDir, "%s", dirname);
- ;
+ if(!dirname.empty())
+ config.cfg.currentBankDir = dirname;
return 0;
}
@@ -328,35 +246,30 @@ int Bank::loadbank(const char *bankdirname)
/*
* Makes a new bank, put it on a file and makes it current bank
*/
-int Bank::newbank(const char *newbankdirname)
+int Bank::newbank(string newbankdirname)
{
int result;
- char tmpfilename[MAX_STRING_SIZE];
- char bankdir[MAX_STRING_SIZE];
- snprintf(bankdir, MAX_STRING_SIZE, "%s", config.cfg.bankRootDirList[0]);
-
- if(((bankdir[strlen(bankdir) - 1]) != '/')
- && ((bankdir[strlen(bankdir) - 1]) != '\\'))
- strncat(bankdir, "/", MAX_STRING_SIZE);
- ;
- strncat(bankdir, newbankdirname, MAX_STRING_SIZE);
+ string bankdir;
+ bankdir = config.cfg.bankRootDirList[0];
+
+ if(((bankdir[bankdir.size() - 1]) != '/')
+ && ((bankdir[bankdir.size() - 1]) != '\\'))
+ bankdir += "/";
+
+ bankdir += newbankdirname;
#if OS_WINDOWS
- result = mkdir(bankdir);
+ result = mkdir(bankdir.c_str());
#elif OS_LINUX || OS_CYGWIN
- result = mkdir(bankdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ result = mkdir(bankdir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#else
#warning Undefined OS
#endif
if(result < 0)
return -1;
- snprintf(tmpfilename,
- MAX_STRING_SIZE,
- "%s/%s",
- bankdir,
- FORCE_BANK_DIR_FILE);
-// printf("%s\n",tmpfilename);
- FILE *tmpfile = fopen(tmpfilename, "w+");
+ string tmpfilename = bankdir + '/' + FORCE_BANK_DIR_FILE;
+
+ FILE *tmpfile = fopen(tmpfilename.c_str(), "w+");
fclose(tmpfile);
return loadbank(bankdir);
@@ -367,7 +280,7 @@ int Bank::newbank(const char *newbankdirname)
*/
int Bank::locked()
{
- return dirname == NULL;
+ return dirname.empty();
}
/*
@@ -379,106 +292,55 @@ void Bank::swapslot(unsigned int n1, unsigned int n2)
return;
if(emptyslot(n1) && (emptyslot(n2)))
return;
- if(emptyslot(n1)) { //change n1 to n2 in order to make
- int tmp = n2;
- n2 = n1;
- n1 = tmp;
- }
+ if(emptyslot(n1)) //change n1 to n2 in order to make
+ swap(n1, n2);
if(emptyslot(n2)) { //this is just a movement from slot1 to slot2
setname(n1, getname(n1), n2);
ins[n2] = ins[n1];
- ins[n1].used = false;
- ins[n1].name[0] = '\0';
- ins[n1].filename = NULL;
- ins[n1].info.PADsynth_used = 0;
+ ins[n1] = ins_t();
}
else { //if both slots are used
- if(strcmp(ins[n1].name, ins[n2].name) == 0) //change the name of the second instrument if the name are equal
- strncat(ins[n2].name, "2", PART_MAX_NAME_LEN);
- ;
+ if(ins[n1].name == ins[n2].name) //change the name of the second instrument if the name are equal
+ ins[n2].name += "2";
+
setname(n1, getname(n1), n2);
setname(n2, getname(n2), n1);
- ins_t tmp;
- tmp.used = true;
- strcpy(tmp.name, ins[n2].name);
- char *tmpfilename = ins[n2].filename;
- bool padsynth_used = ins[n2].info.PADsynth_used;
-
- ins[n2] = ins[n1];
- strcpy(ins[n1].name, tmp.name);
- ins[n1].filename = tmpfilename;
- ins[n1].info.PADsynth_used = padsynth_used;
+ swap(ins[n2],ins[n1]);
}
}
-//a helper function that compares 2 banks[] arrays
-int Bank_compar(const void *a, const void *b)
+bool Bank::bankstruct::operator<(const bankstruct &b) const
{
- struct Bank::bankstruct *bank1 = (Bank::bankstruct *)a;
- struct Bank::bankstruct *bank2 = (Bank::bankstruct *)b;
- if(((bank1->name) == NULL) || ((bank2->name) == NULL))
- return 0;
-
- int result = strcasecmp(bank1->name, bank2->name);
- return result < 0;
+ return name < b.name;
}
-
/*
* Re-scan for directories containing instrument banks
*/
void Bank::rescanforbanks()
{
- for(int i = 0; i < MAX_NUM_BANKS; i++) {
- if(banks[i].dir != NULL)
- delete [] banks[i].dir;
- if(banks[i].name != NULL)
- delete [] banks[i].name;
- banks[i].dir = NULL;
- banks[i].name = NULL;
- }
+ //remove old banks
+ banks.clear();
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
- if(config.cfg.bankRootDirList[i] != NULL)
+ if(!config.cfg.bankRootDirList[i].empty())
scanrootdir(config.cfg.bankRootDirList[i]);
//sort the banks
- for(int j = 0; j < MAX_NUM_BANKS - 1; j++) {
- for(int i = j + 1; i < MAX_NUM_BANKS; i++) {
- if(Bank_compar(&banks[i], &banks[j])) {
- char *tmpname = banks[i].name;
- char *tmpdir = banks[i].dir;
-
- banks[i].name = banks[j].name;
- banks[i].dir = banks[j].dir;
-
- banks[j].name = tmpname;
- banks[j].dir = tmpdir;
- }
- }
- }
+ sort(banks.begin(), banks.end());
//remove duplicate bank names
int dupl = 0;
- for(int j = 0; j < MAX_NUM_BANKS - 1; j++) {
- for(int i = j + 1; i < MAX_NUM_BANKS; i++) {
- if((banks[i].name == NULL) || (banks[j].name == NULL))
- continue;
- if(strcmp(banks[i].name, banks[j].name) == 0) { //add a [1] to the first bankname and [n] to others
- char *tmpname = banks[i].name;
- banks[i].name = new char[strlen(tmpname) + 100];
- sprintf(banks[i].name, "%s[%d]", tmpname, dupl + 2);
- delete[] tmpname;
-
- if(dupl == 0) {
- char *tmpname = banks[j].name;
- banks[j].name = new char[strlen(tmpname) + 100];
- sprintf(banks[j].name, "%s[1]", tmpname);
- delete[] tmpname;
- }
+ for(unsigned int j = 0; j < banks.size() - 1; j++) {
+ for(unsigned int i = j + 1; i < banks.size(); i++) {
+ if(banks[i].name == banks[j].name) {
+ //add a [1] to the first bankname and [n] to others
+ banks[i].name = banks[i].name + '[' + stringFrom(dupl +2) + ']';
+ if(dupl == 0)
+ banks[j].name += "[1]";
dupl++;
}
@@ -489,25 +351,19 @@ void Bank::rescanforbanks()
}
-
// private stuff
-void Bank::scanrootdir(char *rootdir)
+void Bank::scanrootdir(string rootdir)
{
-// printf("Scanning root dir:%s\n",rootdir);
- DIR *dir = opendir(rootdir);
+ DIR *dir = opendir(rootdir.c_str());
if(dir == NULL)
return;
- const int maxdirsize = 1000;
- struct {
- char dir[maxdirsize];
- char name[maxdirsize];
- } bank;
+ bankstruct bank;
const char *separator = "/";
- if(strlen(rootdir)) {
- char tmp = rootdir[strlen(rootdir) - 1];
+ if(rootdir.size()) {
+ char tmp = rootdir[rootdir.size() - 1];
if((tmp == '/') || (tmp == '\\'))
separator = "";
}
@@ -518,12 +374,12 @@ void Bank::scanrootdir(char *rootdir)
if(dirname[0] == '.')
continue;
- snprintf(bank.dir, maxdirsize, "%s%s%s/", rootdir, separator, dirname);
- snprintf(bank.name, maxdirsize, "%s", dirname);
+ bank.dir = rootdir + separator + dirname + '/';
+ bank.name = dirname;
//find out if the directory contains at least 1 instrument
bool isbank = false;
- DIR *d = opendir(bank.dir);
+ DIR *d = opendir(bank.dir.c_str());
if(d == NULL)
continue;
@@ -533,28 +389,14 @@ void Bank::scanrootdir(char *rootdir)
if((strstr(fname->d_name, INSTRUMENT_EXTENSION) != NULL)
|| (strstr(fname->d_name, FORCE_BANK_DIR_FILE) != NULL)) {
isbank = true;
- break; //aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank
+ break; //could put a #instrument counter here instead
}
}
- closedir(d);
+ if(isbank)
+ banks.push_back(bank);
- if(isbank) {
- int pos = -1;
- for(int i = 1; i < MAX_NUM_BANKS; i++) { //banks[0] e liber intotdeauna
- if(banks[i].name == NULL) {
- pos = i;
- break;
- }
- }
-
- if(pos >= 0) {
- banks[pos].name = new char[maxdirsize];
- banks[pos].dir = new char[maxdirsize];
- snprintf(banks[pos].name, maxdirsize, "%s", bank.name);
- snprintf(banks[pos].dir, maxdirsize, "%s", bank.dir);
- }
- }
+ closedir(d);
}
closedir(dir);
@@ -562,58 +404,48 @@ void Bank::scanrootdir(char *rootdir)
void Bank::clearbank()
{
- for(int i = 0; i < BANK_SIZE; i++)
- deletefrombank(i);
- if(dirname != NULL)
- delete[] dirname;
- bankfiletitle = NULL;
- dirname = NULL;
+ for(int i = 0; i < BANK_SIZE; ++i)
+ ins[i] = ins_t();
+
+ bankfiletitle.clear();
+ dirname.clear();
}
-int Bank::addtobank(int pos, const char *filename, const char *name)
+int Bank::addtobank(int pos, string filename, string name)
{
if((pos >= 0) && (pos < BANK_SIZE)) {
if(ins[pos].used)
- pos = -1; //force it to find a new free position
+ pos = -1; //force it to find a new free position
}
else
- if(pos >= BANK_SIZE)
- pos = -1;
+ if(pos >= BANK_SIZE)
+ pos = -1;
if(pos < 0) { //find a free position
- for(int i = BANK_SIZE - 1; i >= 0; i--)
+ for(int i = BANK_SIZE - 1; i >= 0; i--) {
if(!ins[i].used) {
pos = i;
break;
}
- ;
+ }
}
if(pos < 0)
- return -1; //the bank is full
-
- // printf("%s %d\n",filename,pos);
+ return -1;//the bank is full
deletefrombank(pos);
ins[pos].used = true;
- snprintf(ins[pos].name, PART_MAX_NAME_LEN, "%s", name);
-
- snprintf(tmpinsname[pos], PART_MAX_NAME_LEN + 10, " ");
-
- int len = strlen(filename) + 1 + strlen(dirname);
- ins[pos].filename = new char[len + 2];
- ins[pos].filename[len + 1] = 0;
- snprintf(ins[pos].filename, len + 1, "%s/%s", dirname, filename);
+ ins[pos].name = name;
+ ins[pos].filename = dirname + '/' + filename;
//see if PADsynth is used
if(config.cfg.CheckPADsynth) {
- XMLwrapper *xml = new XMLwrapper();
- xml->loadXMLfile(ins[pos].filename);
+ XMLwrapper xml;
+ xml.loadXMLfile(ins[pos].filename);
- ins[pos].info.PADsynth_used = xml->hasPadSynth();
- delete xml;
+ ins[pos].info.PADsynth_used = xml.hasPadSynth();
}
else
ins[pos].info.PADsynth_used = false;
@@ -632,15 +464,14 @@ bool Bank::isPADsynth_used(unsigned int ninstrument)
void Bank::deletefrombank(int pos)
{
- if((pos < 0) || (pos >= BANK_SIZE))
+ if((pos < 0) || (pos >= (int) banks.size()))
return;
- ins[pos].used = false;
- ZERO(ins[pos].name, PART_MAX_NAME_LEN + 1);
- if(ins[pos].filename != NULL) {
- delete [] ins[pos].filename;
- ins[pos].filename = NULL;
- }
+ ins[pos] = ins_t();
+}
- ZERO(tmpinsname[pos], PART_MAX_NAME_LEN + 20);
+Bank::ins_t::ins_t()
+ :used(false), name(""), filename("")
+{
+ info.PADsynth_used = false;
}
diff --git a/src/Misc/Bank.h b/src/Misc/Bank.h
@@ -23,34 +23,30 @@
#ifndef BANK_H
#define BANK_H
+#include <string>
+#include <vector>
#include "../globals.h"
#include "Util.h"
#include "XMLwrapper.h"
#include "Part.h"
+//entries in a bank
#define BANK_SIZE 160
-/**
- * The max. number of banks that are used
- */
-#define MAX_NUM_BANKS 400
-
-/**The instrument Bank
- * \todo add in strings to replace char* */
+/**The instrument Bank*/
class Bank
{
public:
/**Constructor*/
Bank();
~Bank();
- char *getname(unsigned int ninstrument);
- char *getnamenumbered(unsigned int ninstrument);
- void setname(unsigned int ninstrument, const char *newname, int newslot); //if newslot==-1 then this is ignored, else it will be put on that slot
+ std::string getname(unsigned int ninstrument);
+ std::string getnamenumbered(unsigned int ninstrument);
+ void setname(unsigned int ninstrument, const std::string newname, int newslot); //if newslot==-1 then this is ignored, else it will be put on that slot
bool isPADsynth_used(unsigned int ninstrument);
- /**returns 0 if the slot is not empty or 1 if the slot is empty
- * \todo start using bool before facepalm*/
- int emptyslot(unsigned int ninstrument);
+ /**returns true when slot is empty*/
+ bool emptyslot(unsigned int ninstrument);
/**Empties out the selected slot*/
void clearslot(unsigned int ninstrument);
@@ -62,47 +58,48 @@ class Bank
/**Swaps Slots*/
void swapslot(unsigned int n1, unsigned int n2);
- int loadbank(const char *bankdirname);
- int newbank(const char *newbankdirname);
+ int loadbank(std::string bankdirname);
+ int newbank(std::string newbankdirname);
- char *bankfiletitle; //this is shown on the UI of the bank (the title of the window)
+ std::string bankfiletitle; //this is shown on the UI of the bank (the title of the window)
int locked();
void rescanforbanks();
struct bankstruct {
- char *dir;
- char *name;
+ bool operator<(const bankstruct &b) const;
+ std::string dir;
+ std::string name;
};
- bankstruct banks[MAX_NUM_BANKS];
+ std::vector<bankstruct> banks;
private:
//it adds a filename to the bank
//if pos is -1 it try to find a position
//returns -1 if the bank is full, or 0 if the instrument was added
- int addtobank(int pos, const char *filename, const char *name);
+ int addtobank(int pos, std::string filename, std::string name);
void deletefrombank(int pos);
void clearbank();
- char defaultinsname[PART_MAX_NAME_LEN];
- char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN + 20]; //this keeps the numbered names
+ std::string defaultinsname;
struct ins_t {
+ ins_t();
bool used;
- char name[PART_MAX_NAME_LEN + 1];
- char *filename;
+ std::string name;
+ std::string filename;
struct {
bool PADsynth_used;
} info;
} ins[BANK_SIZE];
- char *dirname;
+ std::string dirname;
- void scanrootdir(char *rootdir); //scans a root dir for banks
+ void scanrootdir(std::string rootdir); //scans a root dir for banks
};
#endif
diff --git a/src/Misc/Config.cpp b/src/Misc/Config.cpp
@@ -50,8 +50,7 @@ void Config::init()
cfg.LinuxOSSSeqInDev = new char[MAX_STRING_SIZE];
snprintf(cfg.LinuxOSSSeqInDev, MAX_STRING_SIZE, "/dev/sequencer");
- cfg.DumpFile = new char[MAX_STRING_SIZE];
- snprintf(cfg.DumpFile, MAX_STRING_SIZE, "zynaddsubfx_dump.txt");
+ cfg.DumpFile = "zynaddsubfx_dump.txt";
cfg.WindowsWaveOutId = 0;
cfg.WindowsMidiInId = 0;
@@ -94,90 +93,56 @@ void Config::init()
midiincaps.szPname);
;
#endif
- for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
- cfg.bankRootDirList[i] = NULL;
- cfg.currentBankDir = new char[MAX_STRING_SIZE];
- sprintf(cfg.currentBankDir, "./testbnk");
-
- for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
- cfg.presetsDirList[i] = NULL;
+ cfg.currentBankDir = "./testbnk";
char filename[MAX_STRING_SIZE];
getConfigFileName(filename, MAX_STRING_SIZE);
readConfig(filename);
- if(cfg.bankRootDirList[0] == NULL) {
+ if(cfg.bankRootDirList[0].empty()) {
#if OS_LINUX
//banks
- cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[0], "~/banks");
-
- cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[1], "./");
-
- cfg.bankRootDirList[2] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[2], "/usr/share/zynaddsubfx/banks");
-
- cfg.bankRootDirList[3] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[3], "/usr/local/share/zynaddsubfx/banks");
-
- cfg.bankRootDirList[4] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[4], "../banks");
-
- cfg.bankRootDirList[5] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[5], "banks");
+ cfg.bankRootDirList[0] = "~/banks";
+ cfg.bankRootDirList[1] = "./";
+ cfg.bankRootDirList[2] = "/usr/share/zynaddsubfx/banks";
+ cfg.bankRootDirList[3] = "/usr/local/share/zynaddsubfx/banks";
+ cfg.bankRootDirList[4] = "../banks";
+ cfg.bankRootDirList[5] = "banks";
#else
//banks
- cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[0], "./");
+ cfg.bankRootDirList[0] = "./";
#ifdef VSTAUDIOOUT
- cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[1], "c:/Program Files/ZynAddSubFX/banks");
+ cfg.bankRootDirList[1] = "c:/Program Files/ZynAddSubFX/banks";
#else
- cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[1], "../banks");
+ cfg.bankRootDirList[1] = "../banks";
#endif
- cfg.bankRootDirList[2] = new char[MAX_STRING_SIZE];
- sprintf(cfg.bankRootDirList[2], "banks");
+ cfg.bankRootDirList[2] = "banks";
#endif
}
- if(cfg.presetsDirList[0] == NULL) {
+ if(cfg.presetsDirList[0].empty()) {
#if OS_LINUX || OS_CYGWIN
//presets
- cfg.presetsDirList[0] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[0], "./");
-
- cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[1], "../presets");
-
- cfg.presetsDirList[2] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[2], "presets");
-
- cfg.presetsDirList[3] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[3], "/usr/share/zynaddsubfx/presets");
-
- cfg.presetsDirList[4] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[4], "/usr/local/share/zynaddsubfx/presets");
+ cfg.presetsDirList[0] = "./";
+ cfg.presetsDirList[1] = "../presets";
+ cfg.presetsDirList[2] = "presets";
+ cfg.presetsDirList[3] = "/usr/share/zynaddsubfx/presets";
+ cfg.presetsDirList[4] = "/usr/local/share/zynaddsubfx/presets";
#elif OS_WINDOWS
//presets
- cfg.presetsDirList[0] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[0], "./");
+ cfg.presetsDirList[0] = "./";
#ifdef VSTAUDIOOUT
- cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[1], "c:/Program Files/ZynAddSubFX/presets");
+ cfg.presetsDirList[1] = "c:/Program Files/ZynAddSubFX/presets";
#else
- cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[1], "../presets");
+ cfg.presetsDirList[1] = "../presets";
#endif //end vst
- cfg.presetsDirList[2] = new char[MAX_STRING_SIZE];
- sprintf(cfg.presetsDirList[2], "presets");
+ cfg.presetsDirList[2] = "presets";
#else
#error Undefined OS
#endif //end OS
@@ -190,7 +155,6 @@ Config::~Config()
{
delete [] cfg.LinuxOSSWaveOutDev;
delete [] cfg.LinuxOSSSeqInDev;
- delete [] cfg.DumpFile;
for(int i = 0; i < winmidimax; i++)
delete [] winmididevices[i].name;
@@ -207,128 +171,115 @@ void Config::save()
void Config::clearbankrootdirlist()
{
- for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
- if(cfg.bankRootDirList[i] == NULL)
- delete (cfg.bankRootDirList[i]);
- cfg.bankRootDirList[i] = NULL;
- }
+ for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
+ cfg.bankRootDirList[i].clear();
}
void Config::clearpresetsdirlist()
{
- for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
- if(cfg.presetsDirList[i] == NULL)
- delete (cfg.presetsDirList[i]);
- cfg.presetsDirList[i] = NULL;
- }
+ for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
+ cfg.presetsDirList[i].clear();
}
void Config::readConfig(const char *filename)
{
- XMLwrapper *xmlcfg = new XMLwrapper();
- if(xmlcfg->loadXMLfile(filename) < 0)
+ XMLwrapper xmlcfg;
+ if(xmlcfg.loadXMLfile(filename) < 0)
return;
- if(xmlcfg->enterbranch("CONFIGURATION")) {
- cfg.SampleRate = xmlcfg->getpar("sample_rate",
+ if(xmlcfg.enterbranch("CONFIGURATION")) {
+ cfg.SampleRate = xmlcfg.getpar("sample_rate",
cfg.SampleRate,
4000,
1024000);
- cfg.SoundBufferSize = xmlcfg->getpar("sound_buffer_size",
+ cfg.SoundBufferSize = xmlcfg.getpar("sound_buffer_size",
cfg.SoundBufferSize,
16,
8192);
- cfg.OscilSize = xmlcfg->getpar("oscil_size",
+ cfg.OscilSize = xmlcfg.getpar("oscil_size",
cfg.OscilSize,
MAX_AD_HARMONICS * 2,
131072);
- cfg.SwapStereo = xmlcfg->getpar("swap_stereo",
+ cfg.SwapStereo = xmlcfg.getpar("swap_stereo",
cfg.SwapStereo,
0,
1);
- cfg.BankUIAutoClose = xmlcfg->getpar("bank_window_auto_close",
+ cfg.BankUIAutoClose = xmlcfg.getpar("bank_window_auto_close",
cfg.BankUIAutoClose,
0,
1);
- cfg.DumpNotesToFile = xmlcfg->getpar("dump_notes_to_file",
+ cfg.DumpNotesToFile = xmlcfg.getpar("dump_notes_to_file",
cfg.DumpNotesToFile,
0,
1);
- cfg.DumpAppend = xmlcfg->getpar("dump_append",
+ cfg.DumpAppend = xmlcfg.getpar("dump_append",
cfg.DumpAppend,
0,
1);
- xmlcfg->getparstr("dump_file", cfg.DumpFile, MAX_STRING_SIZE);
+ cfg.DumpFile = xmlcfg.getparstr("dump_file", "");
- cfg.GzipCompression = xmlcfg->getpar("gzip_compression",
+ cfg.GzipCompression = xmlcfg.getpar("gzip_compression",
cfg.GzipCompression,
0,
9);
- xmlcfg->getparstr("bank_current", cfg.currentBankDir, MAX_STRING_SIZE);
- cfg.Interpolation = xmlcfg->getpar("interpolation",
+ cfg.currentBankDir = xmlcfg.getparstr("bank_current", "");
+ cfg.Interpolation = xmlcfg.getpar("interpolation",
cfg.Interpolation,
0,
1);
- cfg.CheckPADsynth = xmlcfg->getpar("check_pad_synth",
+ cfg.CheckPADsynth = xmlcfg.getpar("check_pad_synth",
cfg.CheckPADsynth,
0,
1);
- cfg.UserInterfaceMode = xmlcfg->getpar("user_interface_mode",
+ cfg.UserInterfaceMode = xmlcfg.getpar("user_interface_mode",
cfg.UserInterfaceMode,
0,
2);
- cfg.VirKeybLayout = xmlcfg->getpar("virtual_keyboard_layout",
+ cfg.VirKeybLayout = xmlcfg.getpar("virtual_keyboard_layout",
cfg.VirKeybLayout,
0,
10);
//get bankroot dirs
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
- if(xmlcfg->enterbranch("BANKROOT", i)) {
- cfg.bankRootDirList[i] = new char[MAX_STRING_SIZE];
- xmlcfg->getparstr("bank_root",
- cfg.bankRootDirList[i],
- MAX_STRING_SIZE);
- xmlcfg->exitbranch();
+ if(xmlcfg.enterbranch("BANKROOT", i)) {
+ cfg.bankRootDirList[i] = xmlcfg.getparstr("bank_root", "");
+ xmlcfg.exitbranch();
}
}
//get preset root dirs
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
- if(xmlcfg->enterbranch("PRESETSROOT", i)) {
- cfg.presetsDirList[i] = new char[MAX_STRING_SIZE];
- xmlcfg->getparstr("presets_root",
- cfg.presetsDirList[i],
- MAX_STRING_SIZE);
- xmlcfg->exitbranch();
+ if(xmlcfg.enterbranch("PRESETSROOT", i)) {
+ cfg.presetsDirList[i] = xmlcfg.getparstr("presets_root", "");
+ xmlcfg.exitbranch();
}
}
//linux stuff
- xmlcfg->getparstr("linux_oss_wave_out_dev",
+ xmlcfg.getparstr("linux_oss_wave_out_dev",
cfg.LinuxOSSWaveOutDev,
MAX_STRING_SIZE);
- xmlcfg->getparstr("linux_oss_seq_in_dev",
+ xmlcfg.getparstr("linux_oss_seq_in_dev",
cfg.LinuxOSSSeqInDev,
MAX_STRING_SIZE);
//windows stuff
- cfg.WindowsWaveOutId = xmlcfg->getpar("windows_wave_out_id",
+ cfg.WindowsWaveOutId = xmlcfg.getpar("windows_wave_out_id",
cfg.WindowsWaveOutId,
0,
winwavemax);
- cfg.WindowsMidiInId = xmlcfg->getpar("windows_midi_in_id",
+ cfg.WindowsMidiInId = xmlcfg.getpar("windows_midi_in_id",
cfg.WindowsMidiInId,
0,
winmidimax);
- xmlcfg->exitbranch();
+ xmlcfg.exitbranch();
}
- delete (xmlcfg);
cfg.OscilSize = (int) pow(2, ceil(log(cfg.OscilSize - 1.0) / log(2.0)));
}
@@ -360,20 +311,18 @@ void Config::saveConfig(const char *filename)
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
- if(cfg.bankRootDirList[i] != NULL) {
+ if(!cfg.bankRootDirList[i].empty()) {
xmlcfg->beginbranch("BANKROOT", i);
xmlcfg->addparstr("bank_root", cfg.bankRootDirList[i]);
xmlcfg->endbranch();
}
- ;
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
- if(cfg.presetsDirList[i] != NULL) {
+ if(!cfg.presetsDirList[i].empty()) {
xmlcfg->beginbranch("PRESETSROOT", i);
xmlcfg->addparstr("presets_root", cfg.presetsDirList[i]);
xmlcfg->endbranch();
}
- ;
xmlcfg->addpar("interpolation", cfg.Interpolation);
diff --git a/src/Misc/Config.h b/src/Misc/Config.h
@@ -43,9 +43,9 @@ class Config
int DumpNotesToFile, DumpAppend;
int GzipCompression;
int Interpolation;
- char *DumpFile;
- char *bankRootDirList[MAX_BANK_ROOT_DIRS], *currentBankDir;
- char *presetsDirList[MAX_BANK_ROOT_DIRS];
+ std::string DumpFile;
+ std::string bankRootDirList[MAX_BANK_ROOT_DIRS], currentBankDir;
+ std::string presetsDirList[MAX_BANK_ROOT_DIRS];
int CheckPADsynth;
int UserInterfaceMode;
int VirKeybLayout;
diff --git a/src/Misc/Dump.cpp b/src/Misc/Dump.cpp
@@ -55,9 +55,9 @@ void Dump::startnow()
if(config.cfg.DumpNotesToFile != 0) {
if(config.cfg.DumpAppend != 0)
- file = fopen(config.cfg.DumpFile, "a");
+ file = fopen(config.cfg.DumpFile.c_str(), "a");
else
- file = fopen(config.cfg.DumpFile, "w");
+ file = fopen(config.cfg.DumpFile.c_str(), "w");
if(file == NULL)
return;
if(config.cfg.DumpAppend != 0)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -64,7 +64,6 @@ Master::Master()
//System Effects init
for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++)
sysefx[nefx] = new EffectMgr(0, &mutex);
- ;
defaults();
@@ -119,6 +118,11 @@ bool Master::mutexLock(lockset request)
return false;
}
+Master &Master::getInstance()
+{
+ static Master instance;
+ return instance;
+}
/*
* Note On Messages (velocity=0 for NoteOff)
@@ -468,7 +472,8 @@ Master::~Master()
delete [] tmpmixl;
delete [] tmpmixr;
- delete (fft);
+ delete fft;
+ FFT_cleanup();
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&vumutex);
@@ -551,11 +556,10 @@ vuData Master::getVuData()
return tmp;
}
-void Master::applyparameters()
+void Master::applyparameters(bool lockmutex)
{
for(int npart = 0; npart < NUM_MIDI_PARTS; npart++)
- part[npart]->applyparameters();
- ;
+ part[npart]->applyparameters(lockmutex);
}
void Master::add2XML(XMLwrapper *xml)
diff --git a/src/Misc/Master.h b/src/Misc/Master.h
@@ -50,11 +50,13 @@ typedef struct vuData_t {
class Master
{
public:
- /** Constructor*/
+ /** Constructor TODO make private*/
Master();
/** Destructor*/
~Master();
+ static Master &getInstance();
+
/**Saves all settings to a XML file
* @return 0 for ok or <0 if there is an error*/
int saveXML(const char *filename);
@@ -68,7 +70,7 @@ class Master
/**loads all settings from a XML file
* @return 0 for ok or -1 if there is an error*/
int loadXML(const char *filename);
- void applyparameters();
+ void applyparameters(bool lockmutex = true);
void getfromXML(XMLwrapper *xml);
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -155,13 +155,13 @@ void Part::defaultsinstrument()
/*
* Cleanup the part
*/
-void Part::cleanup()
+void Part::cleanup(bool final)
{
for(int k = 0; k < POLIPHONY; k++)
KillNotePos(k);
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
- partoutl[i] = denormalkillbuf[i];
- partoutr[i] = denormalkillbuf[i];
+ partoutl[i] = final ? 0.0 : denormalkillbuf[i];
+ partoutr[i] = final ? 0.0 : denormalkillbuf[i];
tmpoutl[i] = 0.0;
tmpoutr[i] = 0.0;
}
@@ -170,15 +170,15 @@ void Part::cleanup()
partefx[nefx]->cleanup();
for(int n = 0; n < NUM_PART_EFX + 1; n++) {
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
- partfxinputl[n][i] = denormalkillbuf[i];
- partfxinputr[n][i] = denormalkillbuf[i];
+ partfxinputl[n][i] = final ? 0.0 : denormalkillbuf[i];
+ partfxinputr[n][i] = final ? 0.0 : denormalkillbuf[i];
}
}
}
Part::~Part()
{
- cleanup();
+ cleanup(true);
for(int n = 0; n < NUM_KIT_ITEMS; n++) {
if(kit[n].adpars != NULL)
delete (kit[n].adpars);
@@ -1217,7 +1217,7 @@ void Part::add2XML(XMLwrapper *xml)
xml->endbranch();
}
-int Part::saveXML(char *filename)
+int Part::saveXML(const char *filename)
{
XMLwrapper *xml;
xml = new XMLwrapper();
@@ -1249,12 +1249,11 @@ int Part::loadXMLinstrument(const char *filename)
}
-void Part::applyparameters()
+void Part::applyparameters(bool lockmutex)
{
for(int n = 0; n < NUM_KIT_ITEMS; n++)
if((kit[n].padpars != NULL) && (kit[n].Ppadenabled != 0))
- kit[n].padpars->applyparameters(true);
- ;
+ kit[n].padpars->applyparameters(lockmutex);
}
void Part::getfromXMLinstrument(XMLwrapper *xml)
diff --git a/src/Misc/Part.h b/src/Misc/Part.h
@@ -71,7 +71,7 @@ class Part
//saves the instrument settings to a XML file
//returns 0 for ok or <0 if there is an error
- int saveXML(char *filename);
+ int saveXML(const char *filename);
int loadXMLinstrument(const char *filename);
void add2XML(XMLwrapper *xml);
@@ -80,12 +80,12 @@ class Part
void defaults();
void defaultsinstrument();
- void applyparameters();
+ void applyparameters(bool lockmutex = true);
void getfromXML(XMLwrapper *xml);
void getfromXMLinstrument(XMLwrapper *xml);
- void cleanup();
+ void cleanup(bool final = false);
// ADnoteParameters *ADPartParameters;
// SUBnoteParameters *SUBPartParameters;
diff --git a/src/Misc/Recorder.cpp b/src/Misc/Recorder.cpp
@@ -46,7 +46,7 @@ int Recorder::preparefile(std::string filename_, int overwrite)
return 1;
}
- sysOut->wave->newFile(new WavFile(filename_, SAMPLE_RATE, 2));
+ OutMgr::getInstance().wave->newFile(new WavFile(filename_, SAMPLE_RATE, 2));
status = 1; //ready
@@ -61,15 +61,15 @@ void Recorder::start()
void Recorder::stop()
{
- sysOut->wave->Stop();
- sysOut->wave->destroyFile();
+ OutMgr::getInstance().wave->Stop();
+ OutMgr::getInstance().wave->destroyFile();
status = 0;
}
void Recorder::pause()
{
status = 0;
- sysOut->wave->Stop();
+ OutMgr::getInstance().wave->Stop();
}
int Recorder::recording()
@@ -84,9 +84,10 @@ void Recorder::triggernow()
{
if(status == 2) {
if(notetrigger!=1) {
- sysOut->wave->Start();
+ OutMgr::getInstance().wave->Start();
}
notetrigger = 1;
}
}
+#warning todo move recorder inside nio system
diff --git a/src/Misc/Util.cpp b/src/Misc/Util.cpp
@@ -142,4 +142,14 @@ void os_sleep(long length)
Sleep((long)length/1000);
#endif
}
-
+
+std::string legalizeFilename(std::string filename)
+{
+ for(int i = 0; i < (int) filename.size(); i++) {
+ char c = filename[i];
+ if(!(isdigit(c) || isalpha(c) || (c == '-') || (c == ' ')))
+ filename[i] = '_';
+ }
+ return filename;
+}
+
diff --git a/src/Misc/Util.h b/src/Misc/Util.h
@@ -47,6 +47,8 @@ void set_realtime();
/**Os independent sleep in microsecond*/
void os_sleep(long length);
+std::string legalizeFilename(std::string filename);
+
extern REALTYPE *denormalkillbuf; /**<the buffer to add noise in order to avoid denormalisation*/
extern Config config;
diff --git a/src/Misc/WavFile.cpp b/src/Misc/WavFile.cpp
@@ -20,6 +20,7 @@
#include <cstdio>
#include <cstring>
#include <cstdlib>
+#include <iostream>
#include "WavFile.h"
using namespace std;
@@ -29,6 +30,7 @@ WavFile::WavFile(string filename, int samplerate, int channels)
{
if(file) {
+ cout << "INFO: Making space for wave file header" << endl;
//making space for the header written at destruction
char tmp[44];
memset(tmp, 0, 44*sizeof(char));
@@ -39,6 +41,8 @@ WavFile::WavFile(string filename, int samplerate, int channels)
WavFile::~WavFile()
{
if(file) {
+ cout << "INFO: Writing wave file header" << endl;
+
unsigned int chunksize;
rewind(file);
@@ -73,7 +77,7 @@ WavFile::~WavFile()
bool WavFile::good() const
{
- return NULL != file;
+ return file;
}
void WavFile::writeStereoSamples(int nsmps, short int *smps)
diff --git a/src/Misc/XMLwrapper.cpp b/src/Misc/XMLwrapper.cpp
@@ -140,7 +140,7 @@ XMLwrapper::XMLwrapper()
XMLwrapper::~XMLwrapper()
{
- if(tree != NULL)
+ if(tree)
mxmlDelete(tree);
}
@@ -295,6 +295,13 @@ void XMLwrapper::endbranch()
}
+//workaround for memory leak
+const char *trimLeadingWhite(const char *c)
+{
+ while(isspace(*c))
+ ++c;
+ return c;
+}
/* LOAD XML members */
@@ -306,15 +313,14 @@ int XMLwrapper::loadXMLfile(const string &filename)
const char *xmldata = doloadfile(filename.c_str());
if(xmldata == NULL)
- return -1; //the file could not be loaded or uncompressed
+ return -1; //the file could not be loaded or uncompressed
- root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK);
+ root = tree = mxmlLoadString(NULL, trimLeadingWhite(xmldata), MXML_OPAQUE_CALLBACK);
- delete [] xmldata;
+ delete[] xmldata;
if(tree == NULL)
- return -2; //this is not XML
-
+ return -2; //this is not XML
node = root = mxmlFindElement(tree,
tree,
@@ -323,7 +329,7 @@ int XMLwrapper::loadXMLfile(const string &filename)
NULL,
MXML_DESCEND);
if(root == NULL)
- return -3; //the XML doesnt embbed zynaddsubfx data
+ return -3; //the XML doesnt embbed zynaddsubfx data
//fetch version information
version.Major = stringTo<int>(mxmlElementGetAttr(root, "version-major"));
@@ -335,7 +341,6 @@ int XMLwrapper::loadXMLfile(const string &filename)
cout << "loadXMLfile() version: " << version.Major << '.'
<< version.Minor << '.' << version.Revision << endl;
-
return 0;
}
@@ -379,7 +384,7 @@ bool XMLwrapper::putXMLdata(const char *xmldata)
if(xmldata == NULL)
return false;
- root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK);
+ root = tree = mxmlLoadString(NULL, trimLeadingWhite(xmldata), MXML_OPAQUE_CALLBACK);
if(tree == NULL)
return false;
diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp
@@ -28,8 +28,8 @@ using namespace std;
#include "InMgr.h"
#include "AlsaEngine.h"
-AlsaEngine::AlsaEngine(OutMgr *out)
- :AudioOut(out)
+AlsaEngine::AlsaEngine()
+ :AudioOut()
{
name = "ALSA";
audio.handle = NULL;
@@ -53,8 +53,7 @@ void *AlsaEngine::_AudioThread(void *arg)
void *AlsaEngine::AudioThread()
{
set_realtime();
- processAudio();
- return NULL;
+ return processAudio();
}
bool AlsaEngine::Start()
@@ -68,6 +67,7 @@ void AlsaEngine::Stop()
setMidiEn(false);
if(getAudioEn())
setAudioEn(false);
+ snd_config_update_free_global();
}
void AlsaEngine::setMidiEn(bool nval)
@@ -107,7 +107,7 @@ void *AlsaEngine::MidiThread(void)
snd_seq_event_t *event;
MidiEvent ev;
set_realtime();
- while (snd_seq_event_input(midi.handle, &event) > 0)
+ while(snd_seq_event_input(midi.handle, &event) > 0)
{
//ensure ev is empty
ev.channel = 0;
@@ -126,7 +126,7 @@ void *AlsaEngine::MidiThread(void)
ev.channel = event->data.note.channel;
ev.num = event->data.note.note;
ev.value = event->data.note.velocity;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
}
break;
@@ -135,7 +135,7 @@ void *AlsaEngine::MidiThread(void)
ev.channel = event->data.note.channel;
ev.num = event->data.note.note;
ev.value = 0;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case SND_SEQ_EVENT_PITCHBEND:
@@ -143,7 +143,7 @@ void *AlsaEngine::MidiThread(void)
ev.channel = event->data.control.channel;
ev.num = C_pitchwheel;
ev.value = event->data.control.value;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case SND_SEQ_EVENT_CONTROLLER:
@@ -151,7 +151,7 @@ void *AlsaEngine::MidiThread(void)
ev.channel = event->data.control.channel;
ev.num = event->data.control.param;
ev.value = event->data.control.value;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case SND_SEQ_EVENT_RESET: // reset to power-on state
@@ -159,7 +159,7 @@ void *AlsaEngine::MidiThread(void)
ev.channel = event->data.control.channel;
ev.num = C_resetallcontrollers;
ev.value = 0;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case SND_SEQ_EVENT_PORT_SUBSCRIBED: // ports connected
@@ -311,6 +311,7 @@ bool AlsaEngine::openAudio()
//snd_pcm_hw_params_get_period_size(audio.params, &audio.frames, NULL);
//snd_pcm_hw_params_get_period_time(audio.params, &val, NULL);
+
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -327,10 +328,11 @@ void AlsaEngine::stopAudio()
audio.handle = NULL;
pthread_join(audio.pThread, NULL);
snd_pcm_drain(handle);
- snd_pcm_close(handle);
+ if(snd_pcm_close(handle))
+ cout << "Error: in snd_pcm_close " << __LINE__ << ' ' << __FILE__ << endl;
}
-void AlsaEngine::processAudio()
+void *AlsaEngine::processAudio()
{
int rc;
while (audio.handle) {
@@ -347,5 +349,5 @@ void AlsaEngine::processAudio()
else if (rc < 0)
cerr << "error from writei: " << snd_strerror(rc) << endl;
}
- pthread_exit(NULL);
+ return NULL;
}
diff --git a/src/Nio/AlsaEngine.h b/src/Nio/AlsaEngine.h
@@ -34,7 +34,7 @@
class AlsaEngine : public AudioOut, MidiIn
{
public:
- AlsaEngine(OutMgr *out);
+ AlsaEngine();
~AlsaEngine();
bool Start();
@@ -76,7 +76,7 @@ class AlsaEngine : public AudioOut, MidiIn
pthread_t pThread;
} audio;
- void processAudio();
+ void *processAudio();
};
#endif
diff --git a/src/Nio/AudioOut.cpp b/src/Nio/AudioOut.cpp
@@ -30,63 +30,45 @@ using namespace std;
#include "../Misc/Master.h"
#include "AudioOut.h"
-struct AudioOut::Data
-{
- Data(OutMgr *out);
-
- int samplerate;
- int bufferSize;
-
- Stereo<Sample> current;/**<used for xrun defence*/
-
- OutMgr *manager;
-};
-
-AudioOut::Data::Data(OutMgr *out)
- :samplerate(SAMPLE_RATE),bufferSize(SOUND_BUFFER_SIZE),
- current(Sample(SOUND_BUFFER_SIZE,0.0)),manager(out)
-{}
-
-AudioOut::AudioOut(OutMgr *out)
- :dat(new Data(out))
+AudioOut::AudioOut()
+ :samplerate(SAMPLE_RATE),bufferSize(SOUND_BUFFER_SIZE)
{}
AudioOut::~AudioOut()
{
- delete dat;
}
void AudioOut::setSamplerate(int _samplerate)
{
- dat->samplerate = _samplerate;
+ samplerate = _samplerate;
}
int AudioOut::getSampleRate()
{
- return dat->samplerate;
+ return samplerate;
}
void AudioOut::setBufferSize(int _bufferSize)
{
- dat->bufferSize = _bufferSize;
+ bufferSize = _bufferSize;
}
//delete me
void AudioOut::bufferingSize(int nBuffering)
{
- //dat->buffering = nBuffering;
+ //buffering = nBuffering;
}
//delete me
int AudioOut::bufferingSize()
{
- //return dat->buffering;
+ //return buffering;
}
const Stereo<Sample> AudioOut::getNext(bool wait)
{
- Stereo<REALTYPE *> tmp = sysOut->tick(dat->bufferSize);
+ Stereo<REALTYPE *> tmp = OutMgr::getInstance().tick(bufferSize);
//stop the samples
- return Stereo<Sample>(Sample(dat->bufferSize, tmp.l()), Sample(dat->bufferSize, tmp.r()));
+ return Stereo<Sample>(Sample(bufferSize, tmp.l()), Sample(bufferSize, tmp.r()));
}
diff --git a/src/Nio/AudioOut.h b/src/Nio/AudioOut.h
@@ -30,7 +30,7 @@
class AudioOut : public virtual Engine
{
public:
- AudioOut(class OutMgr *out);
+ AudioOut();
virtual ~AudioOut();
/**Sets the Sample Rate of this Output
@@ -54,9 +54,8 @@ class AudioOut : public virtual Engine
* (has nsamples sampled at a rate of samplerate)*/
const Stereo<Sample> getNext(bool wait = false);
- //using opaque pointer to reduce compile times
- struct Data;
- Data *dat;
+ int samplerate;
+ int bufferSize;
};
#endif
diff --git a/src/Nio/CMakeLists.txt b/src/Nio/CMakeLists.txt
@@ -12,6 +12,7 @@ set(zynaddsubfx_nio_SRCS
InMgr.cpp
Engine.cpp
EngineMgr.cpp
+ Nio.cpp
)
set(zynaddsubfx_nio_lib )
diff --git a/src/Nio/EngineMgr.cpp b/src/Nio/EngineMgr.cpp
@@ -21,46 +21,50 @@
using namespace std;
-EngineMgr *sysEngine;
+EngineMgr &EngineMgr::getInstance()
+{
+ static EngineMgr instance;
+ return instance;
+}
EngineMgr::EngineMgr()
{
Engine *defaultEng = NULL;
//conditional compiling mess (but contained)
- engines.push_back(defaultEng = new NulEngine(sysOut));
+ engines.push_back(defaultEng = new NulEngine());
#if OSS
#if OSS_DEFAULT
- engines.push_back(defaultEng = new OssEngine(sysOut));
+ engines.push_back(defaultEng = new OssEngine());
#else
- engines.push_back(new OssEngine(sysOut));
+ engines.push_back(new OssEngine());
#endif
#endif
#if ALSA
#if ALSA_DEFAULT
- engines.push_back(defaultEng = new AlsaEngine(sysOut));
+ engines.push_back(defaultEng = new AlsaEngine());
#else
- engines.push_back(new AlsaEngine(sysOut));
+ engines.push_back(new AlsaEngine());
#endif
#endif
#if JACK
#if JACK_DEFAULT
- engines.push_back(defaultEng = new JackEngine(sysOut));
+ engines.push_back(defaultEng = new JackEngine());
#else
- engines.push_back(new JackEngine(sysOut));
+ engines.push_back(new JackEngine());
#endif
#endif
#if PORTAUDIO
#if PORTAUDIO_DEFAULT
- engines.push_back(defaultEng = new PaEngine(sysOut));
+ engines.push_back(defaultEng = new PaEngine());
#else
- engines.push_back(new PaEngine(sysOut));
+ engines.push_back(new PaEngine());
#endif
#endif
defaultOut = dynamic_cast<AudioOut *>(defaultEng);
- defaultIn = dynamic_cast<MidiIn *>(defaultEng);
+ defaultIn = dynamic_cast<MidiIn *>(defaultEng);
};
EngineMgr::~EngineMgr()
@@ -93,8 +97,8 @@ void EngineMgr::start()
defaultIn = dynamic_cast<MidiIn *>(getEng("NULL"));
}
- sysOut->currentOut = defaultOut;
- sysIn->current = defaultIn;
+ OutMgr::getInstance().currentOut = defaultOut;
+ InMgr::getInstance().current = defaultIn;
//open up the default output(s)
cout << "Starting Audio: " << defaultOut->name << endl;
@@ -104,8 +108,8 @@ void EngineMgr::start()
}
else {
cerr << "ERROR: The default audio output failed to open!" << endl;
- sysOut->currentOut = dynamic_cast<AudioOut *>(sysEngine->getEng("NULL"));
- sysOut->currentOut->setAudioEn(true);
+ OutMgr::getInstance().currentOut = dynamic_cast<AudioOut *>(getEng("NULL"));
+ OutMgr::getInstance().currentOut->setAudioEn(true);
}
cout << "Starting MIDI: " << defaultIn->name << endl;
@@ -115,8 +119,8 @@ void EngineMgr::start()
}
else { //recover
cerr << "ERROR: The default MIDI input failed to open!" << endl;
- sysIn->current = dynamic_cast<MidiIn *>(sysEngine->getEng("NULL"));
- sysIn->current->setMidiEn(true);
+ InMgr::getInstance().current = dynamic_cast<MidiIn *>(getEng("NULL"));
+ InMgr::getInstance().current->setMidiEn(true);
}
}
diff --git a/src/Nio/EngineMgr.h b/src/Nio/EngineMgr.h
@@ -12,7 +12,7 @@ class OutMgr;
/**Container/Owner of the long lived Engines*/
struct EngineMgr
{
- EngineMgr();
+ static EngineMgr &getInstance();
~EngineMgr();
/**Gets requested engine
@@ -36,8 +36,8 @@ struct EngineMgr
//default I/O
AudioOut *defaultOut;
MidiIn *defaultIn;
+ private:
+ EngineMgr();
};
-
-extern EngineMgr *sysEngine;
#endif
diff --git a/src/Nio/InMgr.cpp b/src/Nio/InMgr.cpp
@@ -6,8 +6,6 @@
using namespace std;
-InMgr *sysIn;
-
ostream &operator<<(ostream &out, const MidiEvent& ev)
{
if(ev.type == M_NOTE)
@@ -25,8 +23,14 @@ MidiEvent::MidiEvent()
:channel(0),type(0),num(0),value(0)
{}
-InMgr::InMgr(Master *_master)
- :queue(100), master(_master)
+InMgr &InMgr::getInstance()
+{
+ static InMgr instance;
+ return instance;
+}
+
+InMgr::InMgr()
+ :queue(100), master(Master::getInstance())
{
current = NULL;
sem_init(&work, PTHREAD_PROCESS_PRIVATE, 0);
@@ -57,28 +61,20 @@ void InMgr::flush()
dump.dumpnote(ev.channel, ev.num, ev.value);
if(ev.value)
- master->noteOn(ev.channel, ev.num, ev.value);
+ master.noteOn(ev.channel, ev.num, ev.value);
else
- master->noteOff(ev.channel, ev.num);
+ master.noteOff(ev.channel, ev.num);
}
else {
dump.dumpcontroller(ev.channel, ev.num, ev.value);
- master->setController(ev.channel, ev.num, ev.value);
+ master.setController(ev.channel, ev.num, ev.value);
}
}
}
bool InMgr::setSource(string name)
{
- MidiIn *src = NULL;
- for(list<Engine*>::iterator itr = sysEngine->engines.begin();
- itr != sysEngine->engines.end(); ++itr) {
- MidiIn *in = dynamic_cast<MidiIn *>(*itr);
- if(in && in->name == name) {
- src = in;
- break;
- }
- }
+ MidiIn *src = getIn(name);
if(!src)
return false;
@@ -88,7 +84,13 @@ bool InMgr::setSource(string name)
current = src;
current->setMidiEn(true);
- return current->getMidiEn();
+ bool success = current->getMidiEn();
+
+ //Keep system in a valid state (aka with a running driver)
+ if(!success)
+ (current = getIn("NULL"))->setMidiEn(true);
+
+ return success;
}
string InMgr::getSource() const
@@ -99,3 +101,9 @@ string InMgr::getSource() const
return "ERROR";
}
+MidiIn *InMgr::getIn(string name)
+{
+ EngineMgr &eng = EngineMgr::getInstance();
+ return dynamic_cast<MidiIn *>(eng.getEng(name));
+}
+
diff --git a/src/Nio/InMgr.h b/src/Nio/InMgr.h
@@ -19,13 +19,11 @@ struct MidiEvent
int value; //velocity or controller value
};
-class Master;
-class MidiIn;
//super simple class to manage the inputs
class InMgr
{
public:
- InMgr(Master *nmaster);
+ static InMgr &getInstance();
~InMgr();
void putEvent(MidiEvent ev);
@@ -39,14 +37,15 @@ class InMgr
friend class EngineMgr;
private:
+ InMgr();
+ class MidiIn *getIn(std::string name);
SafeQueue<MidiEvent> queue;
sem_t work;
- MidiIn *current;
+ class MidiIn *current;
/**the link to the rest of zyn*/
- Master *master;
+ class Master &master;
};
-extern InMgr *sysIn;
#endif
diff --git a/src/Nio/JackEngine.cpp b/src/Nio/JackEngine.cpp
@@ -30,8 +30,8 @@
using namespace std;
-JackEngine::JackEngine(OutMgr *out)
- :AudioOut(out), jackClient(NULL)
+JackEngine::JackEngine()
+ :AudioOut(), jackClient(NULL)
{
name = "JACK";
audio.jackSamplerate = 0;
@@ -41,6 +41,7 @@ JackEngine::JackEngine(OutMgr *out)
audio.ports[i] = NULL;
audio.portBuffs[i] = NULL;
}
+ midi.inport = NULL;
}
bool JackEngine::connectServer(string server)
@@ -318,28 +319,28 @@ void JackEngine::handleMidi(unsigned long frames)
ev.type = M_NOTE;
ev.num = midi_data[1];
ev.value = 0;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case 0x90: /* note-on */
ev.type = M_NOTE;
ev.num = midi_data[1];
ev.value = midi_data[2];
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case 0xB0: /* controller */
ev.type = M_CONTROLLER;
ev.num = midi_data[1];
ev.value = midi_data[2];
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case 0xE0: /* pitch bend */
ev.type = M_CONTROLLER;
ev.num = C_pitchwheel;
ev.value = ((midi_data[2] << 7) | midi_data[1]);
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
/* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */
diff --git a/src/Nio/JackEngine.h b/src/Nio/JackEngine.h
@@ -34,7 +34,7 @@ typedef jack_default_audio_sample_t jsample_t;
class JackEngine : public AudioOut, MidiIn
{
public:
- JackEngine(OutMgr *out);
+ JackEngine();
~JackEngine() { };
bool Start();
diff --git a/src/Nio/MidiIn.cpp b/src/Nio/MidiIn.cpp
@@ -35,28 +35,28 @@ void MidiIn::midiProcess(unsigned char head, unsigned char num, unsigned char va
ev.channel = chan;
ev.num = num;
ev.value = 0;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case 0x90: //Note On
ev.type = M_NOTE;
ev.channel = chan;
ev.num = num;
ev.value = value;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case 0xb0: //Controller
ev.type = M_CONTROLLER;
ev.channel = chan;
ev.num = num;
ev.value = value;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
case 0xe0: //Pitch Wheel
ev.type = M_CONTROLLER;
ev.channel = chan;
ev.num = C_pitchwheel;
ev.value = (num + value * (int) 128) - 8192;
- sysIn->putEvent(ev);
+ InMgr::getInstance().putEvent(ev);
break;
}
}
diff --git a/src/Nio/Nio.cpp b/src/Nio/Nio.cpp
@@ -0,0 +1,100 @@
+#include "Nio.h"
+#include "OutMgr.h"
+#include "InMgr.h"
+#include "EngineMgr.h"
+#include "MidiIn.h"
+#include "AudioOut.h"
+#include <iostream>
+using namespace std;
+
+Nio &Nio::getInstance()
+{
+ static Nio instance;
+ return instance;
+}
+
+Nio::Nio()
+:in(InMgr::getInstance()),//Enable input wrapper
+ out(OutMgr::getInstance()),//Initialize the Output Systems
+ eng(EngineMgr::getInstance())//Initialize The Engines
+{}
+
+Nio::~Nio()
+{
+ stop();
+}
+
+void Nio::start()
+{
+ eng.start();//Drivers start your engines!
+}
+
+void Nio::stop()
+{
+ eng.stop();
+}
+
+int Nio::setDefaultSource(string name)
+{
+ if(name.empty())
+ return 0;
+
+ if(!eng.setInDefault(name)) {
+ cerr << "There is no input for " << name << endl;
+ return false;
+ }
+ return 0;
+}
+
+
+int Nio::setDefaultSink(string name)
+{
+ if(name.empty())
+ return 0;
+
+ if(!eng.setOutDefault(name)) {
+ cerr << "There is no output for " << name << endl;
+ }
+ return 0;
+}
+
+bool Nio::setSource(string name)
+{
+ return in.setSource(name);
+}
+
+bool Nio::setSink(string name)
+{
+ return out.setSink(name);
+}
+
+set<string> Nio::getSources() const
+{
+ set<string> sources;
+ for(list<Engine *>::iterator itr = eng.engines.begin();
+ itr != eng.engines.end(); ++itr)
+ if(dynamic_cast<MidiIn *>(*itr))
+ sources.insert((*itr)->name);
+ return sources;
+}
+
+set<string> Nio::getSinks() const
+{
+ set<string> sinks;
+ for(list<Engine *>::iterator itr = eng.engines.begin();
+ itr != eng.engines.end(); ++itr)
+ if(dynamic_cast<AudioOut *>(*itr))
+ sinks.insert((*itr)->name);
+ return sinks;
+}
+
+string Nio::getSource() const
+{
+ return in.getSource();
+}
+
+string Nio::getSink() const
+{
+ return out.getSink();
+}
+
diff --git a/src/Nio/Nio.h b/src/Nio/Nio.h
@@ -0,0 +1,39 @@
+#ifndef NIO_H
+#define NIO_H
+#include <string>
+#include <set>
+
+/**Interface to Nio Subsystem
+ *
+ * Should be only externally included header */
+class Nio
+{
+ public:
+ static Nio &getInstance();
+ ~Nio();
+
+ void start();
+ void stop();
+
+ int setDefaultSource(std::string name);
+ int setDefaultSink(std::string name);
+
+ bool setSource(std::string name);
+ bool setSink(std::string name);
+
+ std::set<std::string> getSources() const;
+ std::set<std::string> getSinks() const;
+
+ std::string getSource() const;
+ std::string getSink() const;
+
+ private:
+ Nio();
+
+ class InMgr ∈
+ class OutMgr &out;
+ class EngineMgr ŋ
+};
+
+#endif
+
diff --git a/src/Nio/NulEngine.cpp b/src/Nio/NulEngine.cpp
@@ -27,8 +27,8 @@
using namespace std;
-NulEngine::NulEngine(OutMgr *out)
- :AudioOut(out), pThread(NULL)
+NulEngine::NulEngine()
+ :AudioOut(), pThread(NULL)
{
name = "NULL";
playing_until.tv_sec = 0;
@@ -68,7 +68,7 @@ void *NulEngine::AudioThread()
playing_until.tv_sec += playing_until.tv_usec / 1000000;
playing_until.tv_usec %= 1000000;
}
- pthread_exit(NULL);
+ return NULL;
}
NulEngine::~NulEngine()
diff --git a/src/Nio/NulEngine.h b/src/Nio/NulEngine.h
@@ -32,7 +32,7 @@
class NulEngine: public AudioOut, MidiIn
{
public:
- NulEngine(OutMgr *out);
+ NulEngine();
~NulEngine();
bool Start();
diff --git a/src/Nio/OssEngine.cpp b/src/Nio/OssEngine.cpp
@@ -38,8 +38,8 @@
using namespace std;
-OssEngine::OssEngine(OutMgr *out)
- :AudioOut(out), engThread(NULL)
+OssEngine::OssEngine()
+ :AudioOut(), engThread(NULL)
{
name = "OSS";
diff --git a/src/Nio/OssEngine.h b/src/Nio/OssEngine.h
@@ -31,7 +31,7 @@
class OssEngine: public AudioOut, MidiIn
{
public:
- OssEngine(OutMgr *out);
+ OssEngine();
~OssEngine();
bool Start();
diff --git a/src/Nio/OutMgr.cpp b/src/Nio/OutMgr.cpp
@@ -11,15 +11,19 @@
using namespace std;
-OutMgr *sysOut;
+OutMgr &OutMgr::getInstance()
+{
+ static OutMgr instance;
+ return instance;
+}
-OutMgr::OutMgr(Master *nmaster)
- :wave(new WavEngine(this)),
- priBuf(new REALTYPE[4096],new REALTYPE[4096]),priBuffCurrent(priBuf)
+OutMgr::OutMgr()
+ :wave(new WavEngine()),
+ priBuf(new REALTYPE[4096],new REALTYPE[4096]),priBuffCurrent(priBuf),master(Master::getInstance())
{
currentOut = NULL;
stales = 0;
- master = nmaster;
+ master = Master::getInstance();
//init samples
outr = new REALTYPE[SOUND_BUFFER_SIZE];
@@ -28,6 +32,9 @@ OutMgr::OutMgr(Master *nmaster)
OutMgr::~OutMgr()
{
+ delete wave;
+ delete [] priBuf.l();
+ delete [] priBuf.r();
delete [] outr;
delete [] outl;
}
@@ -45,15 +52,15 @@ OutMgr::~OutMgr()
*/
const Stereo<REALTYPE *> OutMgr::tick(unsigned int frameSize)
{
- pthread_mutex_lock(&(master->mutex));
- sysIn->flush();
- pthread_mutex_unlock(&(master->mutex));
+ pthread_mutex_lock(&(master.mutex));
+ InMgr::getInstance().flush();
+ pthread_mutex_unlock(&(master.mutex));
//SysEv->execute();
removeStaleSmps();
while(frameSize > storedSmps()) {
- pthread_mutex_lock(&(master->mutex));
- master->AudioOut(outl, outr);
- pthread_mutex_unlock(&(master->mutex));
+ pthread_mutex_lock(&(master.mutex));
+ master.AudioOut(outl, outr);
+ pthread_mutex_unlock(&(master.mutex));
addSmps(outl,outr);
}
Stereo<REALTYPE *> ans = priBuffCurrent;
@@ -65,7 +72,7 @@ const Stereo<REALTYPE *> OutMgr::tick(unsigned int frameSize)
AudioOut *OutMgr::getOut(string name)
{
- return dynamic_cast<AudioOut *>(sysEngine->getEng(name));
+ return dynamic_cast<AudioOut *>(EngineMgr::getInstance().getEng(name));
}
string OutMgr::getDriver() const
@@ -85,7 +92,14 @@ bool OutMgr::setSink(string name)
currentOut = sink;
currentOut->setAudioEn(true);
- return currentOut->getAudioEn();
+
+ bool success = currentOut->getAudioEn();
+
+ //Keep system in a valid state (aka with a running driver)
+ if(!success)
+ (currentOut = getOut("NULL"))->setAudioEn(true);
+
+ return success;
}
string OutMgr::getSink() const
@@ -122,7 +136,6 @@ void OutMgr::addSmps(REALTYPE *l, REALTYPE *r)
void OutMgr::removeStaleSmps()
{
int toShift = storedSmps() - stales;
- //cout << "toShift: " << toShift << endl << "stales: " << stales << endl << priBuf.l() << ' ' << priBuffCurrent.l() << endl;
if(!stales)
return;
diff --git a/src/Nio/OutMgr.h b/src/Nio/OutMgr.h
@@ -10,12 +10,10 @@
class AudioOut;
-class WavEngine;
-class Master;
class OutMgr
{
public:
- OutMgr(Master *nmaster);
+ static OutMgr &getInstance();
~OutMgr();
/**Execute a tick*/
@@ -42,9 +40,10 @@ class OutMgr
std::string getSink() const;
- WavEngine *wave; /**<The Wave Recorder*/
+ class WavEngine *wave; /**<The Wave Recorder*/
friend class EngineMgr;
private:
+ OutMgr();
void addSmps(REALTYPE *l, REALTYPE *r);
int storedSmps() const {return priBuffCurrent.l() - priBuf.l();};
void removeStaleSmps();
@@ -60,11 +59,10 @@ class OutMgr
REALTYPE *outl;
REALTYPE *outr;
- Master *master;
+ class Master &master;
int stales;
};
-extern OutMgr *sysOut;
#endif
diff --git a/src/Nio/PaEngine.h b/src/Nio/PaEngine.h
@@ -47,7 +47,6 @@ class PaEngine: public AudioOut
};
-void PAaudiooutputinit(Master *master_);
void PAfinish();
#endif
diff --git a/src/Nio/SafeQueue.cpp b/src/Nio/SafeQueue.cpp
@@ -3,13 +3,17 @@ template<class T>
SafeQueue<T>::SafeQueue(size_t maxlen)
:writePtr(0),readPtr(0),bufSize(maxlen)
{
+ sem_init(&w_space, PTHREAD_PROCESS_PRIVATE, maxlen-1);
+ sem_init(&r_space, PTHREAD_PROCESS_PRIVATE, 0);
buffer = new T[maxlen];
}
template<class T>
SafeQueue<T>::~SafeQueue()
{
- delete[] buffer;
+ sem_destroy(&w_space);
+ sem_destroy(&r_space);
+ delete [] buffer;
}
template<class T>
@@ -21,33 +25,17 @@ unsigned int SafeQueue<T>::size() const
template<class T>
unsigned int SafeQueue<T>::rSpace() const
{
- size_t w, r;
-
- w = writePtr;
- r = readPtr;
-
- if (w > r) {
- return w - r;
- }
- else {
- return (w - r + bufSize) % bufSize;
- }
+ int space = 0;
+ sem_getvalue(&r_space, &space);
+ return space;
}
template<class T>
unsigned int SafeQueue<T>::wSpace() const
{
- size_t w, r;
-
- w = writePtr;
- r = readPtr - 1;
-
- if (r > w) {
- return r - w;
- }
- else {
- return (r - w + bufSize) % bufSize;
- }
+ int space = 0;
+ sem_getvalue(&w_space, &space);
+ return space;
}
template<class T>
@@ -60,6 +48,10 @@ int SafeQueue<T>::push(const T &in)
size_t w = (writePtr + 1) % bufSize;
buffer[w] = in;
writePtr = w;
+
+ //adjust ranges
+ sem_wait(&w_space);//guaranteed not to wait
+ sem_post(&r_space);
return 0;
}
@@ -73,11 +65,18 @@ int SafeQueue<T>::pop(T &out)
size_t r = (readPtr + 1) % bufSize;
out = buffer[r];
readPtr = r;
+
+ //adjust ranges
+ sem_wait(&r_space);//guaranteed not to wait
+ sem_post(&w_space);
return 0;
}
template<class T>
void SafeQueue<T>::clear()
{
+ //thread unsafe
+ while(!sem_trywait(&r_space))
+ sem_post(&w_space);
readPtr = writePtr;
}
diff --git a/src/Nio/SafeQueue.h b/src/Nio/SafeQueue.h
@@ -2,6 +2,7 @@
#ifndef SAFEQUEUE_H
#define SAFEQUEUE_H
#include <cstdlib>
+#include <semaphore.h>
/**
* C++ thread safe lockless queue
@@ -28,10 +29,15 @@ class SafeQueue
unsigned int wSpace() const;
unsigned int rSpace() const;
- //next writting spot
- volatile size_t writePtr;
+ //write space
+ mutable sem_t w_space;
+ //read space
+ mutable sem_t r_space;
+
+ //next writing spot
+ size_t writePtr;
//next reading spot
- volatile size_t readPtr;
+ size_t readPtr;
const size_t bufSize;
T *buffer;
};
diff --git a/src/Nio/WavEngine.cpp b/src/Nio/WavEngine.cpp
@@ -25,8 +25,8 @@
using namespace std;
-WavEngine::WavEngine(OutMgr *out)
- :AudioOut(out), file(NULL), buffer(SAMPLE_RATE*2), pThread(NULL)
+WavEngine::WavEngine()
+ :AudioOut(), file(NULL), buffer(SAMPLE_RATE*4), pThread(NULL)
{
sem_init(&work, PTHREAD_PROCESS_PRIVATE, 0);
}
@@ -80,8 +80,8 @@ void WavEngine::push(Stereo<REALTYPE *> smps, size_t len)
for(size_t i = 0; i < len; ++i) {
buffer.push(*smps.l()++);
buffer.push(*smps.r()++);
- sem_post(&work);
}
+ sem_post(&work);
}
void WavEngine::newFile(WavFile *_file)
@@ -89,12 +89,17 @@ void WavEngine::newFile(WavFile *_file)
//ensure system is clean
destroyFile();
file = _file;
+
+ //check state
+ if(!file->good())
+ cerr << "ERROR: WavEngine handed bad file output WavEngine::newFile()" << endl;
}
void WavEngine::destroyFile()
{
if(file)
delete file;
+ file = NULL;
}
void *WavEngine::_AudioThread(void *arg)
@@ -104,17 +109,22 @@ void *WavEngine::_AudioThread(void *arg)
void *WavEngine::AudioThread()
{
- short int recordbuf_16bit[2];
+ short *recordbuf_16bit = new short[2*SOUND_BUFFER_SIZE];
while(!sem_wait(&work) && pThread)
{
- float left=0.0f, right=0.0f;
- buffer.pop(left);
- buffer.pop(right);
- recordbuf_16bit[0] = limit((int)(left * 32767.0), -32768, 32767);
- recordbuf_16bit[1] = limit((int)(right * 32767.0), -32768, 32767);
- file->writeStereoSamples(1, recordbuf_16bit);
+ for(int i = 0; i < SOUND_BUFFER_SIZE; ++i) {
+ float left=0.0f, right=0.0f;
+ buffer.pop(left);
+ buffer.pop(right);
+ recordbuf_16bit[2*i] = limit((int)(left * 32767.0), -32768, 32767);
+ recordbuf_16bit[2*i+1] = limit((int)(right * 32767.0), -32768, 32767);
+ }
+ file->writeStereoSamples(SOUND_BUFFER_SIZE, recordbuf_16bit);
}
- pthread_exit(NULL);
+
+ delete[] recordbuf_16bit;
+
+ return NULL;
}
diff --git a/src/Nio/WavEngine.h b/src/Nio/WavEngine.h
@@ -32,7 +32,7 @@ class WavFile;
class WavEngine: public AudioOut
{
public:
- WavEngine(OutMgr *out);
+ WavEngine();
~WavEngine();
bool openAudio();
diff --git a/src/Params/PresetsStore.cpp b/src/Params/PresetsStore.cpp
@@ -97,7 +97,7 @@ void PresetsStore::rescanforpresets(string type)
string ftype = "." + type + ".xpz";
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
- if(config.cfg.presetsDirList[i] == NULL)
+ if(config.cfg.presetsDirList[i].empty())
continue;
//open directory
@@ -140,15 +140,11 @@ void PresetsStore::rescanforpresets(string type)
void PresetsStore::copypreset(XMLwrapper *xml, char *type, string name)
{
- if(config.cfg.presetsDirList[0] == NULL)
+ if(config.cfg.presetsDirList[0].empty())
return;
//make the filenames legal
- for(int i = 0; i < (int) name.size(); i++) {
- char c = name[i];
- if(!(isdigit(c) || isalpha(c) || (c == '-') || (c == ' ')))
- name[i] = '_';
- }
+ name = legalizeFilename(name);
//make path legal
const string dirname = config.cfg.presetsDirList[0];
diff --git a/src/Synth/Envelope.cpp b/src/Synth/Envelope.cpp
@@ -79,9 +79,9 @@ Envelope::Envelope(EnvelopeParams *envpars, REALTYPE basefreq)
envdt[0] = 1.0;
currentpoint = 1; //the envelope starts from 1
- keyreleased = 0;
+ keyreleased = false;
t = 0.0;
- envfinish = 0;
+ envfinish = false;
inct = envdt[1];
envoutval = 0.0;
}
@@ -95,9 +95,9 @@ Envelope::~Envelope()
*/
void Envelope::relasekey()
{
- if(keyreleased == 1)
+ if(keyreleased)
return;
- keyreleased = 1;
+ keyreleased = true;
if(forcedrelase != 0)
t = 0.0;
}
@@ -109,16 +109,16 @@ REALTYPE Envelope::envout()
{
REALTYPE out;
- if(envfinish != 0) { //if the envelope is finished
+ if(envfinish) { //if the envelope is finished
envoutval = envval[envpoints - 1];
return envoutval;
}
- if((currentpoint == envsustain + 1) && (keyreleased == 0)) { //if it is sustaining now
+ if((currentpoint == envsustain + 1) && !keyreleased) { //if it is sustaining now
envoutval = envval[envsustain];
return envoutval;
}
- if((keyreleased != 0) && (forcedrelase != 0)) { //do the forced release
+ if(keyreleased && (forcedrelase != 0)) { //do the forced release
int tmp = (envsustain < 0) ? (envpoints - 1) : (envsustain + 1); //if there is no sustain point, use the last point for release
if(envdt[tmp] < 0.00000001)
@@ -133,21 +133,20 @@ REALTYPE Envelope::envout()
t = 0.0;
inct = envdt[currentpoint];
if((currentpoint >= envpoints) || (envsustain < 0))
- envfinish = 1;
+ envfinish = true;
}
return out;
}
if(inct >= 1.0)
out = envval[currentpoint];
else
- out =
- envval[currentpoint
- - 1] + (envval[currentpoint] - envval[currentpoint - 1]) * t;
+ out = envval[currentpoint - 1] +
+ (envval[currentpoint] - envval[currentpoint - 1]) * t;
t += inct;
if(t >= 1.0) {
if(currentpoint >= envpoints - 1)
- envfinish = 1;
+ envfinish = true;
else
currentpoint++;
t = 0.0;
@@ -167,7 +166,7 @@ REALTYPE Envelope::envout_dB()
if(linearenvelope != 0)
return envout();
- if((currentpoint == 1) && ((keyreleased == 0) || (forcedrelase == 0))) { //first point is always lineary interpolated
+ if((currentpoint == 1) && (!keyreleased || (forcedrelase == 0))) { //first point is always lineary interpolated
REALTYPE v1 = dB2rap(envval[0]);
REALTYPE v2 = dB2rap(envval[1]);
out = v1 + (v2 - v1) * t;
@@ -191,7 +190,7 @@ REALTYPE Envelope::envout_dB()
return out;
}
-int Envelope::finished()
+bool Envelope::finished() const
{
return envfinish;
}
diff --git a/src/Synth/Envelope.h b/src/Synth/Envelope.h
@@ -40,10 +40,8 @@ class Envelope
REALTYPE envout();
REALTYPE envout_dB();
/**Determines the status of the Envelope
- *
- *\todo see if this can be changed to use a boolean
* @return returns 1 if the envelope is finished*/
- int finished();
+ bool finished() const;
private:
int envpoints;
int envsustain; //"-1" means disabled
@@ -54,8 +52,8 @@ class Envelope
int currentpoint; //current envelope point (starts from 1)
int forcedrelase;
- char keyreleased; //if the key was released /** \todo figure out WHY IS THIS A CHAR*/
- char envfinish; /** \todo figure out WHY IS THIS A CHAR*/
+ bool keyreleased; //if the key was released
+ bool envfinish;
REALTYPE t; // the time from the last point
REALTYPE inct; // the time increment
REALTYPE envoutval; //used to do the forced release
diff --git a/src/Synth/OscilGen.cpp b/src/Synth/OscilGen.cpp
@@ -20,6 +20,7 @@
*/
+#include <cassert>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
@@ -27,6 +28,7 @@
#include "OscilGen.h"
#include "../Effects/Distorsion.h"
+
OscilGen::OscilGen(FFTwrapper *fft_, Resonance *res_):Presets()
{
setpresettype("Poscilgen");
@@ -173,154 +175,6 @@ void OscilGen::convert2sine(int magtype)
}
/*
- * Base Functions - START
- */
-REALTYPE OscilGen::basefunc_pulse(REALTYPE x, REALTYPE a)
-{
- return (fmod(x, 1.0) < a) ? -1.0 : 1.0;
-}
-
-REALTYPE OscilGen::basefunc_saw(REALTYPE x, REALTYPE a)
-{
- if(a < 0.00001)
- a = 0.00001;
- else
- if(a > 0.99999)
- a = 0.99999;
- x = fmod(x, 1);
- if(x < a)
- return x / a * 2.0 - 1.0;
- else
- return (1.0 - x) / (1.0 - a) * 2.0 - 1.0;
-}
-
-REALTYPE OscilGen::basefunc_triangle(REALTYPE x, REALTYPE a)
-{
- x = fmod(x + 0.25, 1);
- a = 1 - a;
- if(a < 0.00001)
- a = 0.00001;
- if(x < 0.5)
- x = x * 4 - 1.0;
- else
- x = (1.0 - x) * 4 - 1.0;
- x /= -a;
- if(x < -1.0)
- x = -1.0;
- if(x > 1.0)
- x = 1.0;
- return x;
-}
-
-REALTYPE OscilGen::basefunc_power(REALTYPE x, REALTYPE a)
-{
- x = fmod(x, 1);
- if(a < 0.00001)
- a = 0.00001;
- else
- if(a > 0.99999)
- a = 0.99999;
- return pow(x, exp((a - 0.5) * 10.0)) * 2.0 - 1.0;
-}
-
-REALTYPE OscilGen::basefunc_gauss(REALTYPE x, REALTYPE a)
-{
- x = fmod(x, 1) * 2.0 - 1.0;
- if(a < 0.00001)
- a = 0.00001;
- return exp(-x * x * (exp(a * 8) + 5.0)) * 2.0 - 1.0;
-}
-
-REALTYPE OscilGen::basefunc_diode(REALTYPE x, REALTYPE a)
-{
- if(a < 0.00001)
- a = 0.00001;
- else
- if(a > 0.99999)
- a = 0.99999;
- a = a * 2.0 - 1.0;
- x = cos((x + 0.5) * 2.0 * PI) - a;
- if(x < 0.0)
- x = 0.0;
- return x / (1.0 - a) * 2 - 1.0;
-}
-
-REALTYPE OscilGen::basefunc_abssine(REALTYPE x, REALTYPE a)
-{
- x = fmod(x, 1);
- if(a < 0.00001)
- a = 0.00001;
- else
- if(a > 0.99999)
- a = 0.99999;
- return sin(pow(x, exp((a - 0.5) * 5.0)) * PI) * 2.0 - 1.0;
-}
-
-REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x, REALTYPE a)
-{
- if(a < 0.00001)
- a = 0.00001;
- x = (fmod(x, 1) - 0.5) * exp((a - 0.5) * log(128));
- if(x < -0.5)
- x = -0.5;
- else
- if(x > 0.5)
- x = 0.5;
- x = sin(x * PI * 2.0);
- return x;
-}
-
-REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x, REALTYPE a)
-{
- x = fmod(x + 0.5, 1) * 2.0 - 1.0;
- a = (a - 0.5) * 4;
- if(a > 0.0)
- a *= 2;
- a = pow(3.0, a);
- REALTYPE b = pow(fabs(x), a);
- if(x < 0)
- b = -b;
- return -sin(b * PI);
-}
-
-REALTYPE OscilGen::basefunc_chirp(REALTYPE x, REALTYPE a)
-{
- x = fmod(x, 1.0) * 2.0 * PI;
- a = (a - 0.5) * 4;
- if(a < 0.0)
- a *= 2.0;
- a = pow(3.0, a);
- return sin(x / 2.0) * sin(a * x * x);
-}
-
-REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x, REALTYPE a)
-{
- x = fmod(x + 0.5, 1) * 2.0 - 1.0;
- a = (a - 0.5) * 9;
- a = pow(3.0, a);
- REALTYPE b = pow(fabs(x), a);
- if(x < 0)
- b = -b;
- return -pow(sin(b * PI), 2);
-}
-
-REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x, REALTYPE a)
-{
- a = a * a * a * 30.0 + 1.0;
- return cos(acos(x * 2.0 - 1.0) * a);
-}
-
-REALTYPE OscilGen::basefunc_sqr(REALTYPE x, REALTYPE a)
-{
- a = a * a * a * a * 160.0 + 0.001;
- return -atan(sin(x * 2.0 * PI) * a);
-}
-/*
- * Base Functions - END
- */
-
-
-/*
* Get the base function
*/
void OscilGen::getbasefunction(REALTYPE *smps)
@@ -359,7 +213,7 @@ void OscilGen::getbasefunction(REALTYPE *smps)
break;
}
-// printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3);
+ base_func func = getBaseFunction(Pcurrentbasefunc);
for(i = 0; i < OSCIL_SIZE; i++) {
REALTYPE t = i * 1.0 / OSCIL_SIZE;
@@ -368,65 +222,26 @@ void OscilGen::getbasefunction(REALTYPE *smps)
case 1:
t = t * basefuncmodulationpar3 + sin(
(t
- + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1; //rev
+ + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1;//rev
break;
case 2:
t = t + sin(
(t * basefuncmodulationpar3
- + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1; //sine
+ + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1;//sine
break;
case 3:
t = t + pow((1.0 - cos(
(t + basefuncmodulationpar2) * 2.0 * PI)) * 0.5,
- basefuncmodulationpar3) * basefuncmodulationpar1; //power
+ basefuncmodulationpar3) * basefuncmodulationpar1;//power
break;
}
t = t - floor(t);
- switch(Pcurrentbasefunc) {
- case 1:
- smps[i] = basefunc_triangle(t, par);
- break;
- case 2:
- smps[i] = basefunc_pulse(t, par);
- break;
- case 3:
- smps[i] = basefunc_saw(t, par);
- break;
- case 4:
- smps[i] = basefunc_power(t, par);
- break;
- case 5:
- smps[i] = basefunc_gauss(t, par);
- break;
- case 6:
- smps[i] = basefunc_diode(t, par);
- break;
- case 7:
- smps[i] = basefunc_abssine(t, par);
- break;
- case 8:
- smps[i] = basefunc_pulsesine(t, par);
- break;
- case 9:
- smps[i] = basefunc_stretchsine(t, par);
- break;
- case 10:
- smps[i] = basefunc_chirp(t, par);
- break;
- case 11:
- smps[i] = basefunc_absstretchsine(t, par);
- break;
- case 12:
- smps[i] = basefunc_chebyshev(t, par);
- break;
- case 13:
- smps[i] = basefunc_sqr(t, par);
- break;
- default:
+ if(func)
+ smps[i] = func(t, par);
+ else
smps[i] = -sin(2.0 * PI * i / OSCIL_SIZE);
- }
}
}
@@ -437,129 +252,37 @@ void OscilGen::oscilfilter()
{
if(Pfiltertype == 0)
return;
- REALTYPE par = 1.0 - Pfilterpar1 / 128.0;
- REALTYPE par2 = Pfilterpar2 / 127.0;
- REALTYPE max = 0.0, tmp = 0.0, p2, x;
- for(int i = 1; i < OSCIL_SIZE / 2; i++) {
- REALTYPE gain = 1.0;
- switch(Pfiltertype) {
- case 1:
- gain = pow(1.0 - par * par * par * 0.99, i); //lp
- tmp = par2 * par2 * par2 * par2 * 0.5 + 0.0001;
- if(gain < tmp)
- gain = pow(gain, 10.0) / pow(tmp, 9.0);
- break;
- case 2:
- gain = 1.0 - pow(1.0 - par * par, i + 1); //hp1
- gain = pow(gain, par2 * 2.0 + 0.1);
- break;
- case 3:
- if(par < 0.2)
- par = par * 0.25 + 0.15;
- gain = 1.0 - pow(1.0 - par * par * 0.999 + 0.001,
- i * 0.05 * i + 1.0); //hp1b
- tmp = pow(5.0, par2 * 2.0);
- gain = pow(gain, tmp);
- break;
- case 4:
- gain = i + 1 - pow(2, (1.0 - par) * 7.5); //bp1
- gain = 1.0 / (1.0 + gain * gain / (i + 1.0));
- tmp = pow(5.0, par2 * 2.0);
- gain = pow(gain, tmp);
- if(gain < 1e-5)
- gain = 1e-5;
- break;
- case 5:
- gain = i + 1 - pow(2, (1.0 - par) * 7.5); //bs1
- gain = pow(atan(gain / (i / 10.0 + 1)) / 1.57, 6);
- gain = pow(gain, par2 * par2 * 3.9 + 0.1);
- break;
- case 6:
- tmp = pow(par2, 0.33);
- gain =
- (i + 1 >
- pow(2, (1.0 - par) * 10) ? 0.0 : 1.0) * par2 + (1.0 - par2); //lp2
- break;
- case 7:
- tmp = pow(par2, 0.33);
- //tmp=1.0-(1.0-par2)*(1.0-par2);
- gain =
- (i + 1 >
- pow(2, (1.0 - par) * 7) ? 1.0 : 0.0) * par2 + (1.0 - par2); //hp2
- if(Pfilterpar1 == 0)
- gain = 1.0;
- break;
- case 8:
- tmp = pow(par2, 0.33);
- //tmp=1.0-(1.0-par2)*(1.0-par2);
- gain =
- (fabs(pow(2,
- (1.0
- - par)
- * 7) - i) > i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2); //bp2
- break;
- case 9:
- tmp = pow(par2, 0.33);
- gain =
- (fabs(pow(2,
- (1.0
- - par)
- * 7) - i) < i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2); //bs2
- break;
- case 10:
- tmp = pow(5.0, par2 * 2.0 - 1.0);
- tmp = pow(i / 32.0, tmp) * 32.0;
- if(Pfilterpar2 == 64)
- tmp = i;
- gain = cos(par * par * PI / 2.0 * tmp); //cos
- gain *= gain;
- break;
- case 11:
- tmp = pow(5.0, par2 * 2.0 - 1.0);
- tmp = pow(i / 32.0, tmp) * 32.0;
- if(Pfilterpar2 == 64)
- tmp = i;
- gain = sin(par * par * PI / 2.0 * tmp); //sin
- gain *= gain;
- break;
- case 12:
- p2 = 1.0 - par + 0.2;
- x = i / (64.0 * p2 * p2);
- if(x < 0.0)
- x = 0.0;
- else
- if(x > 1.0)
- x = 1.0;
- tmp = pow(1.0 - par2, 2.0);
- gain = cos(x * PI) * (1.0 - tmp) + 1.01 + tmp; //low shelf
- break;
- case 13:
- tmp = (int) (pow(2.0, (1.0 - par) * 7.2));
- gain = 1.0;
- if(i == (int) (tmp))
- gain = pow(2.0, par2 * par2 * 8.0);
- break;
- }
+ const REALTYPE par = 1.0 - Pfilterpar1 / 128.0;
+ const REALTYPE par2 = Pfilterpar2 / 127.0;
+ REALTYPE max = 0.0;
+ filter_func filter = getFilter(Pfiltertype);
+
+ for(int i = 1; i < OSCIL_SIZE / 2; i++) {
+ REALTYPE gain = filter(i,par,par2);
oscilFFTfreqs.s[i] *= gain;
oscilFFTfreqs.c[i] *= gain;
- REALTYPE tmp = oscilFFTfreqs.s[i] * oscilFFTfreqs.s[i]
- + oscilFFTfreqs.c[i] * oscilFFTfreqs.c[i];
- if(max < tmp)
- max = tmp;
+ REALTYPE magnitude = oscilFFTfreqs.s[i] * oscilFFTfreqs.s[i]
+ + oscilFFTfreqs.c[i] * oscilFFTfreqs.c[i];
+ if(max < magnitude)
+ max = magnitude;
}
+ //Finish RMS calculation
max = sqrt(max);
if(max < 1e-10)
max = 1.0;
REALTYPE imax = 1.0 / max;
+
+ //Normalize signal
for(int i = 1; i < OSCIL_SIZE / 2; i++) {
oscilFFTfreqs.s[i] *= imax;
oscilFFTfreqs.c[i] *= imax;
}
}
+
/*
* Change the base function
*/
@@ -692,17 +415,17 @@ void OscilGen::modulation()
switch(Pmodulation) {
case 1:
t = t * modulationpar3
- + sin((t + modulationpar2) * 2.0 * PI) * modulationpar1; //rev
+ + sin((t + modulationpar2) * 2.0 * PI) * modulationpar1; //rev
break;
case 2:
t = t
+ sin((t * modulationpar3
- + modulationpar2) * 2.0 * PI) * modulationpar1; //sine
+ + modulationpar2) * 2.0 * PI) * modulationpar1; //sine
break;
case 3:
t = t + pow((1.0 - cos(
(t + modulationpar2) * 2.0 * PI)) * 0.5,
- modulationpar3) * modulationpar1; //power
+ modulationpar3) * modulationpar1; //power
break;
}
@@ -907,8 +630,6 @@ void OscilGen::prepare()
if(Pharmonicshiftfirst != 0)
shiftharmonics();
-
-
if(Pfilterbeforews == 0) {
waveshape();
oscilfilter();
@@ -1021,7 +742,7 @@ void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f, int size)
if(Padaptiveharmonics == 2) { //2n+1
for(int i = 0; i < size; i++)
if((i % 2) == 0)
- f[i] += inf[i]; //i=0 pt prima armonica,etc.
+ f[i] += inf[i]; //i=0 pt prima armonica,etc.
}
else { //celelalte moduri
int nh = (Padaptiveharmonics - 3) / 2 + 2;
@@ -1043,16 +764,6 @@ void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f, int size)
delete (inf);
}
-
-
-/*
- * Get the oscillator function
- */
-short int OscilGen::get(REALTYPE *smps, REALTYPE freqHz)
-{
- return this->get(smps, freqHz, 0);
-}
-
void OscilGen::newrandseed(unsigned int randseed)
{
this->randseed = randseed;
@@ -1473,3 +1184,315 @@ void OscilGen::getfromXML(XMLwrapper *xml)
}
}
+//Define basic functions
+#define FUNC(b) REALTYPE basefunc_##b(REALTYPE x, REALTYPE a)
+
+FUNC(pulse)
+{
+ return (fmod(x, 1.0) < a) ? -1.0 : 1.0;
+}
+
+FUNC(saw)
+{
+ if(a < 0.00001)
+ a = 0.00001;
+ else
+ if(a > 0.99999)
+ a = 0.99999;
+ x = fmod(x, 1);
+ if(x < a)
+ return x / a * 2.0 - 1.0;
+ else
+ return (1.0 - x) / (1.0 - a) * 2.0 - 1.0;
+}
+
+FUNC(triangle)
+{
+ x = fmod(x + 0.25, 1);
+ a = 1 - a;
+ if(a < 0.00001)
+ a = 0.00001;
+ if(x < 0.5)
+ x = x * 4 - 1.0;
+ else
+ x = (1.0 - x) * 4 - 1.0;
+ x /= -a;
+ if(x < -1.0)
+ x = -1.0;
+ if(x > 1.0)
+ x = 1.0;
+ return x;
+}
+
+FUNC(power)
+{
+ x = fmod(x, 1);
+ if(a < 0.00001)
+ a = 0.00001;
+ else
+ if(a > 0.99999)
+ a = 0.99999;
+ return pow(x, exp((a - 0.5) * 10.0)) * 2.0 - 1.0;
+}
+
+FUNC(gauss)
+{
+ x = fmod(x, 1) * 2.0 - 1.0;
+ if(a < 0.00001)
+ a = 0.00001;
+ return exp(-x * x * (exp(a * 8) + 5.0)) * 2.0 - 1.0;
+}
+
+FUNC(diode)
+{
+ if(a < 0.00001)
+ a = 0.00001;
+ else
+ if(a > 0.99999)
+ a = 0.99999;
+ a = a * 2.0 - 1.0;
+ x = cos((x + 0.5) * 2.0 * PI) - a;
+ if(x < 0.0)
+ x = 0.0;
+ return x / (1.0 - a) * 2 - 1.0;
+}
+
+FUNC(abssine)
+{
+ x = fmod(x, 1);
+ if(a < 0.00001)
+ a = 0.00001;
+ else
+ if(a > 0.99999)
+ a = 0.99999;
+ return sin(pow(x, exp((a - 0.5) * 5.0)) * PI) * 2.0 - 1.0;
+}
+
+FUNC(pulsesine)
+{
+ if(a < 0.00001)
+ a = 0.00001;
+ x = (fmod(x, 1) - 0.5) * exp((a - 0.5) * log(128));
+ if(x < -0.5)
+ x = -0.5;
+ else
+ if(x > 0.5)
+ x = 0.5;
+ x = sin(x * PI * 2.0);
+ return x;
+}
+
+FUNC(stretchsine)
+{
+ x = fmod(x + 0.5, 1) * 2.0 - 1.0;
+ a = (a - 0.5) * 4;
+ if(a > 0.0)
+ a *= 2;
+ a = pow(3.0, a);
+ REALTYPE b = pow(fabs(x), a);
+ if(x < 0)
+ b = -b;
+ return -sin(b * PI);
+}
+
+FUNC(chirp)
+{
+ x = fmod(x, 1.0) * 2.0 * PI;
+ a = (a - 0.5) * 4;
+ if(a < 0.0)
+ a *= 2.0;
+ a = pow(3.0, a);
+ return sin(x / 2.0) * sin(a * x * x);
+}
+
+FUNC(absstretchsine)
+{
+ x = fmod(x + 0.5, 1) * 2.0 - 1.0;
+ a = (a - 0.5) * 9;
+ a = pow(3.0, a);
+ REALTYPE b = pow(fabs(x), a);
+ if(x < 0)
+ b = -b;
+ return -pow(sin(b * PI), 2);
+}
+
+FUNC(chebyshev)
+{
+ a = a * a * a * 30.0 + 1.0;
+ return cos(acos(x * 2.0 - 1.0) * a);
+}
+
+FUNC(sqr)
+{
+ a = a * a * a * a * 160.0 + 0.001;
+ return -atan(sin(x * 2.0 * PI) * a);
+}
+
+typedef REALTYPE(*base_func)(REALTYPE,REALTYPE);
+base_func getBaseFunction(unsigned char func)
+{
+ if(!func)
+ return NULL;
+
+ func--;
+ assert(func < 13);
+ base_func functions[] = {
+ basefunc_triangle,
+ basefunc_pulse,
+ basefunc_saw,
+ basefunc_power,
+ basefunc_gauss,
+ basefunc_diode,
+ basefunc_abssine,
+ basefunc_pulsesine,
+ basefunc_stretchsine,
+ basefunc_chirp,
+ basefunc_absstretchsine,
+ basefunc_chebyshev,
+ basefunc_sqr,};
+ return functions[func];
+}
+
+//And filters
+
+#define FILTER(x) REALTYPE osc_##x(unsigned int i, REALTYPE par, REALTYPE par2)
+FILTER(lp)
+{
+ REALTYPE gain = pow(1.0 - par * par * par * 0.99, i);
+ REALTYPE tmp = par2 * par2 * par2 * par2 * 0.5 + 0.0001;
+ if(gain < tmp)
+ gain = pow(gain, 10.0) / pow(tmp, 9.0);
+ return gain;
+}
+
+FILTER(hp1)
+{
+ REALTYPE gain = 1.0 - pow(1.0 - par * par, i + 1);
+ return pow(gain, par2 * 2.0 + 0.1);
+}
+
+FILTER(hp1b)
+{
+ if(par < 0.2)
+ par = par * 0.25 + 0.15;
+ REALTYPE gain = 1.0 - pow(1.0 - par * par * 0.999 + 0.001, i * 0.05 * i + 1.0);
+ REALTYPE tmp = pow(5.0, par2 * 2.0);
+ return pow(gain, tmp);
+}
+
+FILTER(bp1)
+{
+ REALTYPE gain = i + 1 - pow(2, (1.0 - par) * 7.5);
+ gain = 1.0 / (1.0 + gain * gain / (i + 1.0));
+ REALTYPE tmp = pow(5.0, par2 * 2.0);
+ gain = pow(gain, tmp);
+ if(gain < 1e-5)
+ gain = 1e-5;
+ return gain;
+}
+
+FILTER(bs1)
+{
+ REALTYPE gain = i + 1 - pow(2, (1.0 - par) * 7.5);
+ gain = pow(atan(gain / (i / 10.0 + 1)) / 1.57, 6);
+ return pow(gain, par2 * par2 * 3.9 + 0.1);
+}
+
+FILTER(lp2)
+{
+ return (i + 1 > pow(2, (1.0 - par) * 10) ? 0.0 : 1.0) * par2 + (1.0 - par2);
+}
+
+FILTER(hp2)
+{
+ if(par == 1)
+ return 1.0;
+ return (i + 1 > pow(2, (1.0 - par) * 7) ? 1.0 : 0.0) * par2 + (1.0 - par2);
+}
+
+FILTER(bp2)
+{
+ return (fabs(pow(2, (1.0 - par) * 7) - i) > i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2);
+}
+
+FILTER(bs2)
+{
+ return (fabs(pow(2, (1.0 - par) * 7) - i) < i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2);
+}
+
+bool floatEq(float a, float b)
+{
+ const float fudge = .01;
+ return a + fudge > b && a - fudge < b;
+}
+
+FILTER(cos)
+{
+ REALTYPE tmp = pow(5.0, par2 * 2.0 - 1.0);
+ tmp = pow(i / 32.0, tmp) * 32.0;
+ if(floatEq(par2 * 127.0, 64.0))
+ tmp = i;
+ REALTYPE gain = cos(par * par * PI / 2.0 * tmp);
+ gain *= gain;
+ return gain;
+}
+
+FILTER(sin)
+{
+ REALTYPE tmp = pow(5.0, par2 * 2.0 - 1.0);
+ tmp = pow(i / 32.0, tmp) * 32.0;
+ if(floatEq(par2 * 127.0, 64.0))
+ tmp = i;
+ REALTYPE gain = sin(par * par * PI / 2.0 * tmp);
+ gain *= gain;
+ return gain;
+}
+
+FILTER(low_shelf)
+{
+ REALTYPE p2 = 1.0 - par + 0.2;
+ REALTYPE x = i / (64.0 * p2 * p2);
+ if(x < 0.0)
+ x = 0.0;
+ else
+ if(x > 1.0)
+ x = 1.0;
+ REALTYPE tmp = pow(1.0 - par2, 2.0);
+ return cos(x * PI) * (1.0 - tmp) + 1.01 + tmp;
+}
+
+FILTER(s)
+{
+ unsigned int tmp = (int) (pow(2.0, (1.0 - par) * 7.2));
+ REALTYPE gain = 1.0;
+ if(i == tmp)
+ gain = pow(2.0, par2 * par2 * 8.0);
+ return gain;
+}
+#undef FILTER
+
+typedef REALTYPE(*filter_func)(unsigned int, REALTYPE, REALTYPE);
+filter_func getFilter(unsigned char func)
+{
+ if(!func)
+ return NULL;
+
+ func--;
+ assert(func < 13);
+ filter_func functions[] = {
+ osc_lp,
+ osc_hp1,
+ osc_hp1b,
+ osc_bp1,
+ osc_bs1,
+ osc_lp2,
+ osc_hp2,
+ osc_bp2,
+ osc_bs2,
+ osc_cos,
+ osc_sin,
+ osc_low_shelf,
+ osc_s};
+ return functions[func];
+}
+
diff --git a/src/Synth/OscilGen.h b/src/Synth/OscilGen.h
@@ -39,8 +39,8 @@ class OscilGen:public Presets
void prepare();
/**do the antialiasing(cut off higher freqs.),apply randomness and do a IFFT*/
- short get(REALTYPE *smps, REALTYPE freqHz); //returns where should I start getting samples, used in block type randomness
- short get(REALTYPE *smps, REALTYPE freqHz, int resonance);
+ //returns where should I start getting samples, used in block type randomness
+ short get(REALTYPE *smps, REALTYPE freqHz, int resonance=0);
//if freqHz is smaller than 0, return the "un-randomized" sample for UI
void getbasefunction(REALTYPE *smps);
@@ -79,7 +79,7 @@ class OscilGen:public Presets
unsigned char Pbasefuncmodulation; //what modulation is applied to the basefunc
unsigned char Pbasefuncmodulationpar1, Pbasefuncmodulationpar2,
- Pbasefuncmodulationpar3; //the parameter of the base function modulation
+ Pbasefuncmodulationpar3;//the parameter of the base function modulation
/*the Randomness:
64=no randomness
@@ -144,21 +144,6 @@ class OscilGen:public Presets
//(that's why the sine and cosine components should be processed with a separate call)
void adaptiveharmonicpostprocess(REALTYPE *f, int size);
- //Basic/base functions (Functiile De Baza)
- REALTYPE basefunc_pulse(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_saw(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_triangle(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_power(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_gauss(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_diode(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_abssine(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_pulsesine(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_stretchsine(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_chirp(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_absstretchsine(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_chebyshev(REALTYPE x, REALTYPE a);
- REALTYPE basefunc_sqr(REALTYPE x, REALTYPE a);
-
//Internal Data
unsigned char oldbasefunc, oldbasepar, oldhmagtype,
oldwaveshapingfunction, oldwaveshaping;
@@ -178,6 +163,11 @@ class OscilGen:public Presets
unsigned int randseed;
};
+typedef REALTYPE(*filter_func)(unsigned int, REALTYPE, REALTYPE);
+filter_func getFilter(unsigned char func);
+typedef REALTYPE(*base_func)(REALTYPE,REALTYPE);
+base_func getBaseFunction(unsigned char func);
+
#endif
diff --git a/src/Tests/XMLwrapperTest.h b/src/Tests/XMLwrapperTest.h
@@ -21,6 +21,8 @@
*/
#include <cxxtest/TestSuite.h>
#include "../Misc/XMLwrapper.h"
+#include <string>
+using namespace std;
class XMLwrapperTest:public CxxTest::TestSuite
{
@@ -36,6 +38,24 @@ class XMLwrapperTest:public CxxTest::TestSuite
TS_ASSERT_EQUALS(xmla->getpar("my Pa*_ramet@er", 0, -200, 200), 75);
}
+ //here to verify that no leaks occur
+ void testLoad() {
+ string location = string(SOURCE_DIR) + string("/Tests/guitar-adnote.xmz");
+ xmla->loadXMLfile(location);
+ }
+
+ void testAnotherLoad()
+ {
+ string dat = "\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<!DOCTYPE ZynAddSubFX-data>\n\
+<ZynAddSubFX-data version-major=\"2\" version-minor=\"4\"\n\
+version-revision=\"1\" ZynAddSubFX-author=\"Nasca Octavian Paul\">\n\
+</ZynAddSubFX-data>\n";
+ xmlb->putXMLdata(dat.c_str());
+#warning todo contact mxml people about possible memoryleak when
+#warning mxmlLoadString is giving something starting with a newline
+ }
+
void tearDown() {
delete xmla;
delete xmlb;
diff --git a/src/UI/BankUI.fl b/src/UI/BankUI.fl
@@ -37,7 +37,7 @@ class BankProcess_ {} {
}
}
-class BankSlot {open : {public Fl_Button,BankProcess_}
+class BankSlot {: {public Fl_Button,BankProcess_}
} {
Function {BankSlot(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label)} {} {
code {what=NULL;
@@ -59,8 +59,7 @@ int tmp=Fl_Button::handle(event);
if ((*what!=0) && Fl::event_inside(this)) (bp->*fnc)();
return(tmp);} {}
}
- Function {init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_)} {open
- } {
+ Function {init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_)} {} {
code {nslot=nslot_;
what=what_;
whatslot=whatslot_;
@@ -74,21 +73,23 @@ labelsize(13);
align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
highlight=0;
-refresh();} {selected
- }
+refresh();} {}
}
Function {refresh()} {} {
- code {if (bank->emptyslot(nslot)) {
- color(46);
-} else {
- if (bank->isPADsynth_used(nslot)) color(26);
- else color(51);
-};
+ code {if (bank->emptyslot(nslot))
+ color(46);
+else if (bank->isPADsynth_used(nslot))
+ color(26);
+else
+ color(51);
-if (*nselected==nslot) color(6);
+if (*nselected==nslot)
+ color(6);
-label(bank->getnamenumbered(nslot));} {}
+
+copy_label(bank->getnamenumbered(nslot).c_str());} {selected
+ }
}
decl {int *what,*whatslot,nslot,highlight, *nselected;} {}
decl {void (BankProcess_:: *fnc)(void);} {}
@@ -100,9 +101,9 @@ class BankUI {: {public BankProcess_}
Function {make_window()} {} {
Fl_Window bankuiwindow {
label Bank
- xywh {4 64 785 575} type Double hide
- code0 {o->label(bank->bankfiletitle);}
- code1 {if (bank->bankfiletitle==NULL) o->label ("Choose a bank from the bank list on the left (or go to settings if to configure the bank location) or choose 'New Bank...' to make a new bank.");}
+ xywh {5 64 785 575} type Double hide
+ code0 {o->label(bank->bankfiletitle.c_str());}
+ code1 {if (bank->bankfiletitle.empty()) o->label ("Choose a bank from the bank list on the left (or go to settings if to configure the bank location) or choose 'New Bank...' to make a new bank.");}
} {
Fl_Button {} {
label Close
@@ -193,13 +194,13 @@ refreshmainwindow();}
}
Fl_Choice banklist {
callback {int n=o->value();
-char *dirname=bank->banks[n].dir;
-if (dirname==NULL) return;
+std::string dirname=bank->banks[n].dir;
+if (dirname.empty()) return;
if (bank->loadbank(dirname)==2)
- fl_alert("Error: Could not load the bank from the directory\\n%s.",dirname);
+ fl_alert("Error: Could not load the bank from the directory\\n%s.",dirname.c_str());
for (int i=0;i<BANK_SIZE;i++) bs[i]->refresh();
-refreshmainwindow();} open
+refreshmainwindow();}
xywh {5 8 220 20} down_box BORDER_BOX labelfont 1 align 0 textfont 1 textsize 11
} {}
Fl_Button {} {
@@ -248,7 +249,7 @@ rescan_for_banks();} {}
code {int slot=this->slot;
if ((what==2)&&(bank->emptyslot(slot)==0)&&(mode!=4)) {//Rename slot
- const char *tmp=fl_input("Slot (instrument) name:",(const char *)bank->getname(slot));
+ const char *tmp=fl_input("Slot (instrument) name:",bank->getname(slot).c_str());
if (tmp!=NULL) bank->setname(slot,tmp,-1);
bs[slot]->refresh();
};
@@ -258,7 +259,7 @@ if ((what==1)&&(mode==1)&&(!bank->emptyslot(slot))){//Reads from slot
bank->loadfromslot(slot,master->part[*npart]);
pthread_mutex_unlock(&master->mutex);
master->part[*npart]->applyparameters();
- snprintf((char *)master->part[*npart]->Pname,PART_MAX_NAME_LEN,"%s",bank->getname(slot));
+ snprintf((char *)master->part[*npart]->Pname,PART_MAX_NAME_LEN,"%s",bank->getname(slot).c_str());
cbwig->do_callback();
if (config.cfg.BankUIAutoClose!=0)
@@ -308,7 +309,7 @@ if (mode==4){//swap
if (mode!=4) refreshmainwindow();} {}
}
Function {refreshmainwindow()} {} {
- code {bankuiwindow->label(bank->bankfiletitle);
+ code {bankuiwindow->label(bank->bankfiletitle.c_str());
mode=1;readbutton->value(1);writebutton->value(0);clearbutton->value(0);swapbutton->value(0);
nselected=-1;
if (bank->locked()){
@@ -320,7 +321,8 @@ if (bank->locked()){
clearbutton->activate();
swapbutton->activate();
};
-for (int i=0;i<BANK_SIZE;i++) bs[i]->refresh();} {}
+for (int i=0;i<BANK_SIZE;i++)
+ bs[i]->refresh();} {}
}
Function {removeselection()} {} {
code {if (nselected>=0) {
@@ -334,8 +336,8 @@ for (int i=0;i<BANK_SIZE;i++) bs[i]->refresh();} {}
banklist->add(" ");
bank->rescanforbanks();
-for (int i=1;i<MAX_NUM_BANKS;i++) {
- if (bank->banks[i].name!=NULL) banklist->add(bank->banks[i].name);
+for (unsigned int i=1;i<bank->banks.size();i++) {
+ banklist->add(bank->banks[i].name.c_str());
};} {}
}
Function {simplesetmode(bool beginnerui)} {} {
diff --git a/src/UI/ConfigUI.fl b/src/UI/ConfigUI.fl
@@ -1,5 +1,5 @@
# data file for the Fltk User Interface Designer (fluid)
-version 1.0106
+version 1.0107
header_name {.h}
code_name {.cc}
decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {}
@@ -60,35 +60,35 @@ setsamplerateinput();}
xywh {20 50 85 20} down_box BORDER_BOX textsize 10
code0 {o->value(getsamplerateorder());}
} {
- menuitem {} {
+ MenuItem {} {
label Custom
xywh {10 10 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 16000Hz
xywh {30 30 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 22050Hz
xywh {20 20 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 32000Hz
xywh {30 30 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 44100Hz
xywh {40 40 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 48000Hz
xywh {50 50 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 88200Hz
xywh {60 60 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 96000Hz
xywh {70 70 100 20} labelfont 1
}
@@ -122,35 +122,35 @@ config.cfg.SoundBufferSize=strtoul(o->value(),&tmp,10);}
tooltip {ADSynth Oscillator Size (samples)} xywh {175 80 75 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 10
code0 {o->value( (int) (log(config.cfg.OscilSize/128.0-1.0)/log(2)) +1);}
} {
- menuitem {} {
+ MenuItem {} {
label 128
xywh {25 25 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 256
xywh {35 35 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 512
xywh {45 45 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 1024
xywh {45 45 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 2048
xywh {55 55 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 4096
xywh {55 55 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 8192
xywh {65 65 100 20} labelfont 1
}
- menuitem {} {
+ MenuItem {} {
label 16384
xywh {75 75 100 20} labelfont 1
}
@@ -168,9 +168,9 @@ config.cfg.SoundBufferSize=strtoul(o->value(),&tmp,10);}
} {
Fl_File_Input {} {
label {Dump File}
- callback {snprintf(config.cfg.DumpFile,config.maxstringsize,"%s",o->value());}
+ callback {config.cfg.DumpFile = o->value();} selected
xywh {20 170 220 35} align 5
- code0 {o->insert(config.cfg.DumpFile);}
+ code0 {o->insert(config.cfg.DumpFile.c_str());}
}
Fl_Check_Button {} {
label {Dump notes}
@@ -241,38 +241,38 @@ midiinputnamebox->label(config.winmididevices[config.cfg.WindowsMidiInId].name);
xywh {175 105 75 15} down_box BORDER_BOX labelsize 10 textsize 11
code0 {o->value(config.cfg.Interpolation);}
} {
- menuitem {} {
+ MenuItem {} {
label {Linear(fast)}
xywh {0 0 100 20} labelfont 1 labelsize 10
}
- menuitem {} {
+ MenuItem {} {
label {Cubic(slow)}
xywh {10 10 100 20} labelfont 1 labelsize 10
}
}
Fl_Choice {} {
label {Virtual Keyboard Layout}
- callback {config.cfg.VirKeybLayout=(int) o->value();;} open selected
+ callback {config.cfg.VirKeybLayout=(int) o->value();;}
xywh {155 235 85 20} down_box BORDER_BOX labelsize 12 textfont 1 textsize 11
code0 {o->value(config.cfg.VirKeybLayout);}
} {
- menuitem {} {
+ MenuItem {} {
label { }
xywh {5 5 100 20} labelfont 1 labelsize 11 deactivate
}
- menuitem {} {
+ MenuItem {} {
label QWERTY
xywh {15 15 100 20} labelfont 1 labelsize 11
}
- menuitem {} {
+ MenuItem {} {
label Dvorak
xywh {25 25 100 20} labelfont 1 labelsize 11
}
- menuitem {} {
+ MenuItem {} {
label QWERTZ
xywh {35 35 100 20} labelfont 1 labelsize 11
}
- menuitem {} {
+ MenuItem {} {
label AZERTY
xywh {45 45 100 20} labelfont 1 labelsize 11
}
@@ -395,31 +395,30 @@ readpresetcfg();} {}
code {rootsbrowse->clear();
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){
- if (config.cfg.bankRootDirList[i]!=NULL) rootsbrowse->add(config.cfg.bankRootDirList[i]);
+ if (!config.cfg.bankRootDirList[i].empty())
+ rootsbrowse->add(config.cfg.bankRootDirList[i].c_str());
};} {}
}
Function {writebankcfg()} {} {
code {config.clearbankrootdirlist();
for (int n=0;n<rootsbrowse->size();n++){
- config.cfg.bankRootDirList[n]=new char [MAX_STRING_SIZE];
- strncpy(config.cfg.bankRootDirList[n],rootsbrowse->text(n+1),MAX_STRING_SIZE);
+ config.cfg.bankRootDirList[n] = rootsbrowse->text(n+1);
};} {}
}
Function {readpresetcfg()} {} {
code {presetbrowse->clear();
-for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){
- if (config.cfg.presetsDirList[i]!=NULL) presetbrowse->add(config.cfg.presetsDirList[i]);
+for(int i=0;i<MAX_BANK_ROOT_DIRS;i++){
+ if(!config.cfg.presetsDirList[i].empty())
+ presetbrowse->add(config.cfg.presetsDirList[i].c_str());
};} {}
}
Function {writepresetcfg()} {} {
code {config.clearpresetsdirlist();
-for (int n=0;n<presetbrowse->size();n++){
- config.cfg.presetsDirList[n]=new char [MAX_STRING_SIZE];
- strncpy(config.cfg.presetsDirList[n],presetbrowse->text(n+1),MAX_STRING_SIZE);
-};} {}
+for (int n=0;n<presetbrowse->size();n++)
+ config.cfg.presetsDirList[n] = presetbrowse->text(n+1);} {}
}
Function {getsamplerateorder()} {return_type int
} {
diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl
@@ -1750,7 +1750,7 @@ pthread_mutex_lock(&master->mutex);
//load the data
int result=master->loadXML(filename);
-master->applyparameters();
+master->applyparameters(false);
pthread_mutex_unlock(&master->mutex);
npartcounter->value(1);
diff --git a/src/UI/NioUI.cpp b/src/UI/NioUI.cpp
@@ -1,9 +1,5 @@
#include "NioUI.h"
-#include "../Nio/EngineMgr.h"
-#include "../Nio/OutMgr.h"
-#include "../Nio/InMgr.h"
-#include "../Nio/AudioOut.h"
-#include "../Nio/MidiIn.h"
+#include "../Nio/Nio.h"
#include <cstdio>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Group.H>
@@ -40,23 +36,36 @@ NioUI::NioUI()
midi->callback(midiCallback);
}
settings->end();
-
- int audioval = 0;
- int midival = 0;
- for(list<Engine *>::iterator itr = sysEngine->engines.begin();
- itr != sysEngine->engines.end(); ++itr) {
- Engine *eng = *itr;
- if(dynamic_cast<MidiIn *>(eng))
- midi->add(eng->name.c_str());
- if(dynamic_cast<AudioOut *>(eng))
- audio->add(eng->name.c_str());
- if(eng->name == sysOut->getSink())
- audioval = audio->size() - 2;
- if(eng->name == sysIn->getSource())
- midival = midi->size() - 2;
+
+ Nio &nio = Nio::getInstance();
+
+ //initialize midi list
+ {
+ set<string> midiList = nio.getSources();
+ string source = nio.getSource();
+ int midival = 0;
+ for(set<string>::iterator itr = midiList.begin();
+ itr != midiList.end(); ++itr) {
+ midi->add(itr->c_str());
+ if(*itr == source)
+ midival = midi->size() - 2;
+ }
+ midi->value(midival);
+ }
+
+ //initialize audio list
+ {
+ set<string> audioList = nio.getSinks();
+ string sink = nio.getInstance().getSink();
+ int audioval = 0;
+ for(set<string>::iterator itr = audioList.begin();
+ itr != audioList.end(); ++itr) {
+ audio->add(itr->c_str());
+ if(*itr == sink)
+ audioval = audio->size() - 2;
+ }
+ audio->value(audioval);
}
- audio->value(audioval);
- midi->value(midival);
}
wintabs->end();
@@ -70,13 +79,13 @@ void NioUI::refresh()
void NioUI::midiCallback(Fl_Widget *c)
{
- bool good = sysIn->setSource(static_cast<Fl_Choice *>(c)->text());
+ bool good = Nio::getInstance().setSource(static_cast<Fl_Choice *>(c)->text());
static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255*!good,0,0));
}
void NioUI::audioCallback(Fl_Widget *c)
{
- bool good = sysOut->setSink(static_cast<Fl_Choice *>(c)->text());
+ bool good = Nio::getInstance().setSink(static_cast<Fl_Choice *>(c)->text());
static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255*!good,0,0));
}
diff --git a/src/UI/NioUI.h b/src/UI/NioUI.h
@@ -17,8 +17,6 @@ class NioUI : public Fl_Window
NioUI();
void refresh();
private:
- //std::list<NioTab *> tabs;
-
Fl_Choice *midi;
Fl_Choice *audio;
static void midiCallback(Fl_Widget *c);
diff --git a/src/main.cpp b/src/main.cpp
@@ -24,6 +24,7 @@
#include <cmath>
#include <cctype>
#include <algorithm>
+#include <signal.h>
#include <unistd.h>
#include <pthread.h>
@@ -41,11 +42,7 @@
extern Dump dump;
//Nio System
-#include "Nio/MidiIn.h"
-#include "Nio/AudioOut.h"
-#include "Nio/OutMgr.h"
-#include "Nio/InMgr.h"
-#include "Nio/EngineMgr.h"
+#include "Nio/Nio.h"
#ifndef DISABLE_GUI
#ifdef QT_GUI
@@ -167,6 +164,18 @@ void *thread4(void *arg)
}
#endif
+void exitprogram();
+
+//cleanup on signaled exit
+void sigterm_exit(int sig)
+{
+ Pexitprogram = 1;
+ sleep(1);
+ exitprogram();
+ exit(0);
+}
+
+
/*
* Program initialisation
*/
@@ -180,24 +189,12 @@ void initprogram()
/ SAMPLE_RATE << " ms" << endl;
cerr << "ADsynth Oscil.Size = \t" << OSCIL_SIZE << " samples" << endl;
- srand(time(NULL));
- denormalkillbuf = new REALTYPE [SOUND_BUFFER_SIZE];
- for(int i = 0; i < SOUND_BUFFER_SIZE; i++)
- denormalkillbuf[i] = (RND - 0.5) * 1e-16;
- master = new Master();
+ master = &Master::getInstance();
master->swaplr = swaplr;
- //Nio Initialization
-
- //Enable input wrapper
- sysIn = new InMgr(master);
-
- //Initialize the Output Systems
- sysOut = new OutMgr(master);
-
- //Initialize The Engines
- sysEngine = new EngineMgr();
+ signal(SIGINT, sigterm_exit);
+ signal(SIGTERM, sigterm_exit);
}
/*
@@ -205,17 +202,15 @@ void initprogram()
*/
void exitprogram()
{
+ //ensure that everything has stopped with the mutex wait
pthread_mutex_lock(&master->mutex);
pthread_mutex_unlock(&master->mutex);
- sysEngine->stop();
- delete sysOut;
- delete sysIn;
- delete sysEngine;
+
+ Nio::getInstance().stop();
#ifndef DISABLE_GUI
delete ui;
#endif
- delete master;
#ifdef USE_LASH
delete lash;
@@ -278,6 +273,11 @@ int main(int argc, char *argv[])
OSCIL_SIZE = config.cfg.OscilSize;
swaplr = config.cfg.SwapStereo;
+ srand(time(NULL));
+ //produce denormal buf
+ denormalkillbuf = new REALTYPE [SOUND_BUFFER_SIZE];
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++)
+ denormalkillbuf[i] = (RND - 0.5) * 1e-16;
/* Parse command-line options */
#if OS_LINUX || OS_CYGWIN
@@ -300,7 +300,7 @@ int main(int argc, char *argv[])
opterr = 0;
int option_index = 0, opt, exitwithhelp = 0;
- string loadfile, loadinstrument, input, output;
+ string loadfile, loadinstrument;
while(1) {
/**\todo check this process for a small memory leak*/
@@ -374,10 +374,16 @@ int main(int argc, char *argv[])
dump.startnow();
break;
case 'I':
- GETOP(input);
+ if(optarguments) {
+ if(Nio::getInstance().setDefaultSource(optarguments))
+ exit(1);
+ }
break;
case 'O':
- GETOP(output);
+ if(optarguments) {
+ if(Nio::getInstance().setDefaultSink(optarguments))
+ exit(1);
+ }
break;
case '?':
cerr << "ERROR:Bad option or parameter.\n" << endl;
@@ -450,24 +456,8 @@ int main(int argc, char *argv[])
}
}
-
- if(!input.empty()) {
- if(!sysEngine->setInDefault(input)) {
- cerr << "There is no input for " << input << endl;
- exit(1);
- }
- cout << input << " selected." << endl;
- }
- if(!output.empty()) {
- if(!sysEngine->setOutDefault(output)) {
- cerr << "There is no output for " << output << endl;
- exit(1);
- }
- cout << output << " selected." << endl;
- }
-
//Run the Nio system
- sysEngine->start(); //Drivers start your engines!
+ Nio::getInstance().start();
#warning remove welcome message when system is out of beta
cout << "\nThanks for using the Nio system :)" << endl;