1 Commits
3.0 ... 3.1

Author SHA1 Message Date
Gary Scavone
4b6500d3de Version 3.1 2013-09-29 22:42:17 +02:00
140 changed files with 5171 additions and 632 deletions

View File

@@ -1,10 +1,10 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
Version 3.1
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
STK Classes, Version 3.0
STK Classes, Version 3.1
Please read README.txt for more information.
<--------Building Blocks---------->|<----------------Instruments------------------>

View File

@@ -1,12 +1,12 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
Version 3.1
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
Please read the file README.txt for more general STK information.
STK for Linux is currently using the OSS sound and MIDI API. The free version of OSS will probably work, though it doesn't work with as many soundcards as the commercial version (which costs about $20).
STK for Linux is currently using the OSS sound and MIDI API. The free version of OSS will probably work, though it doesn't work with as many soundcards as the commercial version (which costs about $20). The Advanced Linux Sound Architecture (ALSA) drivers seem to perform well, though I've done only minimal testing with them. You'll need to install the OSS compatability library. You can read more about ALSA at http://www.alsa-project.org/. ALSA is open source and holds great promise for audio under Linux.
STK should compile without much trouble under Linux. Since all Linux distributions typically include the GNU makefile utilities, you should be able to use the default Makefile. Typing "make" will initiate the compilation process.

View File

@@ -1,11 +1,15 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
Version 3.1
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
Please read the file README.txt for more general STK information.
It seems that SGI systems are not distributed with the GNU Makefile utilities. The default Make utility has very limited functionality, so your safest bet is to download the GNU Makefile utilities from the Internet and use STK's default Makefile. If this is not possible, try using Makefile.sgi (make -f Makefile.sgi).
Aside from the Makefile issues, STK should compile and run on SGI platforms without any problems.
Aside from the Makefile issues, STK should compile and run on SGI platforms without any problems.
NOTE REGARDING PTHREADS:
With release 3.1, STK is now using the pthread API under Irix. It appears that pthread functionality is standard on SGI, so this change shouldn't cause any problems. If I'm wrong, let me know!

View File

@@ -1,15 +1,15 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
Version 3.1
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
Please read the file README.txt for more general STK information.
DirectX and WindowsNT Issues:
-----------------------------
The newly offered STK realtime sound input capabilities under Windoze are only supported using the DirectSoundCapture API. The latency is pretty horrendous, but what do you expect? Also, there is a good chance you don't have DirectSoundCapture support on your computer. You should download the DirectX 6.0 (or higher) runtime libraries from Microsoft's WWW site (http://www.microsoft.com/directx/download.asp) in order to run the pre-compiled STK executables for Windoze. HOWEVER, there is no DirectSoundCapture support for WindowsNT at this time ... you'll have to wait for Windows 2000. If you wish to compile STK under WindowsNT (without realtime audio input support), you'll have to uncomment the __WINMM_API_ flag (and comment out the __WINDS_API flag) in Object.h and recompile the source code.
The newly offered STK realtime sound input capabilities under Windoze are only supported using the DirectSoundCapture API. The latency is pretty horrendous, but what do you expect? Also, there is a good chance you don't have DirectSoundCapture support on your computer. You should download the DirectX 6.0 (or higher) runtime libraries from Microsoft's WWW site (http://www.microsoft.com/directx/download.asp) in order to run the pre-compiled STK executables for Windoze. There is no DirectSoundCapture support for WindowsNT ... you'll have to switch to Windows 2000. If you wish to compile STK under WindowsNT (without realtime audio input support), you'll have to uncomment the __WINMM_API_ flag (and comment out the __WINDS_API flag) in Object.h and recompile the source code.
Realtime sound output under Windoze is supported using either the DirectSound (dsound.lib) API or the old WinMM (winmm.lib) API. The DirectSound version appears to well out-perform the older API. All new versions of Win95/98/NT come with the DirectSound library, but early versions did not. If you have trouble running the distributed executables (compiled for DirectSound API), then you probably don't have DirectSound installed on your system. You can download the necessary DirectSound stuff from Microsoft's WWW pages (http://www.microsoft.com/directx/download.asp). If all else fails, you should be able to compile using the winmm.lib routines ... more latency, but at least it will work.
@@ -63,4 +63,9 @@ USE REALTIME MIDI INPUT FOR CONTROL:
WINDOWS NT ONLY:
Realtime piping seems to work under WindowsNT in much the same way as on Unix platforms. Thus, it is possible to pipe realtime control data to syntmono under WindowsNT as well.
Realtime piping seems to work under WindowsNT in much the same way as on Unix platforms. Thus, it is possible to pipe realtime control data to syntmono under WindowsNT as well.
WINDOWS 2000:
I don't have Windows 2000 and I don't expect to get it anytime soon. Things should work under 2000 at least as well as they do using NT. Since 2000 is supposed to ship with DirectX 7.0, the DirectSoundCapture functionality should work as well.

View File

@@ -1,8 +1,8 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
Version 3.1
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
Please read the Legal and Ethical notes near the bottom of this document.
@@ -23,14 +23,14 @@ WHAT'S NEW:
STK has undergone several key revisions, changes, and additions since its last release in 1998. Despite being available in one form or another since 1996, we still consider STK to be alpha software. Thus, backward compatability has not been a priority. Please read the ReleaseNotes to see what has changed since the last release.
Realtime audio input capabilities have now been added to STK, though the behavior of such is very hardware dependent. Under Linux and Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 15 milliseconds, while input sound latency is on the order of several hundred milliseconds! It is also possible to generate simultaneous .snd, .wav, .raw, and .mat (Matlab MAT-file) output file types, as well as SKINI scorefiles using MD2SKINI. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler.
Realtime audio input capabilities were added to STK with release 3.0, though the behavior of such is very hardware dependent. Under Linux and Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 15 milliseconds, while input sound latency is on the order of several hundred milliseconds! It is also possible to generate simultaneous .snd, .wav, .raw, and .mat (Matlab MAT-file) output file types, as well as SKINI scorefiles using MD2SKINI. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler.
Socketing capabilities have been extended in this release to function under Unix platforms, as well as Windoze platforms. Further, the socket server thread has been updated to accept multiple simultaneous socket connections. Thus, it is now possible to have several different socket clients sending SKINI control messages to the server at the same time. Under Linux and Irix, it is also possible to pipe GUI messages through MD2SKINI, enabling both MIDI and GUI control via piping at the same time.
Socketing capabilities were extended in release 3.0 to function under Unix platforms, as well as Windoze platforms. Further, the socket server thread was updated to accept multiple simultaneous socket connections. Thus, it is now possible to have several different socket clients sending SKINI control messages to the server at the same time. Under Linux and Irix, it is also possible to pipe GUI messages through MD2SKINI, enabling both MIDI and GUI control via piping at the same time.
GETTING STARTED:
A number of example executables are provided with this distribution. The effects directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. The MUS151 directory contains a simple two-oscillator program that can be used to demonstrate psychoacoustic masking effects. The syntmono directory offers a program for monophonic STK instrument playback and manipulation. Syntmono is the primary STK synthesis server and is used to demonstrate all the current STK instruments. MD2SKINI is an executable (currently compiles from the syntmono project) which takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or any socket host and port ID. Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK and can be found in the "scores" directory of the syntmono project.
A number of example executables are provided with this distribution. The effects directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. The MUS151 directory contains a simple two-oscillator program that can be used to demonstrate psychoacoustic masking effects. RagaMatic is a totally cool application for achieving inner piece. The syntmono directory offers a program for monophonic STK instrument playback and manipulation. Syntmono is the primary STK synthesis server and is used to demonstrate all the current STK instruments. MD2SKINI is an executable (currently compiles from the syntmono project) which takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or any socket host and port ID. Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK and can be found in the "scores" directory of the syntmono project.
Unless you downloaded the distribution with precompiled Windoze binaries, it is necessary to first compile the sources. Under Linux or Irix, simply typing "make" in any of the particular project directories will begin the compilation process. If your Unix system does not have the GNU Makefile utilities, you will have to use one of the platform specific Makefiles (eg. make -f Makefile.sgi). To compile the projects under Windoze, you should use the VC++ project files provided with the STK distribution.

View File

@@ -1,10 +1,24 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Release 3.0
Release 3.1
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000
v3.0
v3.1: (13 March 2000)
- new RagaMatic project!!!
- added "microphone position" to Mandolin in STKdemo
- fixed MIDI system message exclusion under Irix
- added a few bitmaps for the Shaker instruments
- made destructors virtual for Reverb.h, WvIn.h and Simple.h
- fixed bug setting delay length in DLineA when value too big
- fixed bug in WinMM realtime code (RTSoundIO)
- added tick() method to BowTabl, JetTabl, and ReedTabl (same as lookup)
- switched to pthread API on SGI platforms
- added some defines to Object.h for random number generation, FPU overflow checking, etc...
- a lot of minor changes, some bug fixes ... can't remember all of them
v3.0: (10 October 1999)
- new #define flags for OS and realtime dependencies (this will probably cause problems for most everyone, but it was necessary to make future ports easier)
- fixed Linux MIDI input bug
- fixed MIDI status masking problem in Windows
@@ -29,8 +43,7 @@ v3.0
- pulled various utility and thread functions out of syntmono.cpp (to aid readability of the code)
v2.02:
- 16 November 1998
v2.02: (16 November 1998)
- created RawWave abstract class, with subclasses of RawLoop (looping rawwave oscillator), RawShot (non-looping, non-interpolating rawwave player ... used to be RawWvIn), and RawInterp (looping or non-looping, interpolating rawwave player ... used to be RawWave).
- modified DrumSynt to correctly handle sample rates different than 22050 Hz.
- modified syntmono parsing vs. tick routine so that some ticking occurs between each message. When multiple messages are waiting to be processed, the time between message updates is inversely proportional to the number of messages in the buffer.
@@ -38,13 +51,11 @@ v2.02:
- fixed bug in MD2SKINI which prevented some NoteOff statements from being output.
v2.01:
- 27 July 1998
v2.01: (27 July 1998)
- Corrected extraneous ^M line return characters that were incompatible with SGI.
v2.0:
- 20 July 1998
v2.0: (20 July 1998)
- The first true release by Gary, with unified capabilities across SGI, Linux, and Win platforms. See WWW pages (http://www-ccrma.stanford.edu/CCRMA/Software/STK/) for more info.

View File

@@ -7,10 +7,11 @@
BowTabl :: BowTabl()
{
offSet = (MY_FLOAT) 0.0; /* offset is a bias, really not needed unless */
/* friction is different in each direction */
slope = (MY_FLOAT) 0.1; /* controls width of friction pulse, */
/* related to bowForce */
/* offset is a bias, really not needed unless */
/* friction is different in each direction */
offSet = (MY_FLOAT) 0.0;
slope = (MY_FLOAT) 0.1; /* controls width of friction pulse, */
/* related to bowForce */
}
BowTabl :: ~BowTabl()
@@ -19,28 +20,33 @@ BowTabl :: ~BowTabl()
void BowTabl :: setOffset(MY_FLOAT aValue)
{
offSet = aValue;
offSet = aValue;
}
void BowTabl :: setSlope(MY_FLOAT aValue)
{
slope = aValue;
slope = aValue;
}
MY_FLOAT BowTabl :: lookup(MY_FLOAT sample) /* Perform Table Lookup */
{ /* sample is differential */
/* string vs. bow velocity */
MY_FLOAT input;
input = sample + offSet; /* add bias to sample */
input *= slope; /* scale it */
lastOutput = (MY_FLOAT) fabs((double) input) + (MY_FLOAT) 0.75; /* below min delta, friction = 1 */
lastOutput = (MY_FLOAT) pow(lastOutput,(MY_FLOAT) -4.0);
// if (lastOutput < 0.0 ) lastOutput = 0.0; /* minimum friction is 0.0 */
if (lastOutput > 1.0 ) lastOutput = (MY_FLOAT) 1.0; /* maximum friction is 1.0 */
return lastOutput;
MY_FLOAT BowTabl :: lookup(MY_FLOAT sample)
{
return this->tick(sample);
}
MY_FLOAT BowTabl :: tick(MY_FLOAT sample) /* Perform Table Lookup */
{ /* sample is differential */
/* string vs. bow velocity */
MY_FLOAT input;
input = sample + offSet; /* add bias to sample */
input *= slope; /* scale it */
lastOutput = (MY_FLOAT) fabs((double) input) + (MY_FLOAT) 0.75; /* below min delta, friction = 1 */
lastOutput = (MY_FLOAT) pow(lastOutput,(MY_FLOAT) -4.0);
// if (lastOutput < 0.0 ) lastOutput = 0.0; /* minimum friction is 0.0 */
if (lastOutput > 1.0 ) lastOutput = (MY_FLOAT) 1.0; /* maximum friction is 1.0 */
return lastOutput;
}
MY_FLOAT BowTabl :: lastOut()
{
return lastOutput;
return lastOutput;
}

View File

@@ -10,17 +10,18 @@
class BowTabl : public Object
{
protected:
MY_FLOAT offSet;
MY_FLOAT slope;
MY_FLOAT lastOutput;
public:
BowTabl();
~BowTabl();
void setOffset(MY_FLOAT aValue);
void setSlope(MY_FLOAT aValue);
MY_FLOAT lookup(MY_FLOAT sample);
MY_FLOAT lastOut();
protected:
MY_FLOAT offSet;
MY_FLOAT slope;
MY_FLOAT lastOutput;
public:
BowTabl();
~BowTabl();
void setOffset(MY_FLOAT aValue);
void setSlope(MY_FLOAT aValue);
MY_FLOAT lookup(MY_FLOAT sample);
MY_FLOAT tick(MY_FLOAT sample);
MY_FLOAT lastOut();
};
#endif

View File

@@ -61,7 +61,7 @@ void DLineA :: setDelay(MY_FLOAT lag)
if (lag > length-1) { // if delay is too big,
printf("DLineA: Delay length too big.\n");
printf("Setting to maximum length of %ld.\n",length-1);
outPointer = inPoint - 18.0; // force delay to max_length
outPointer = inPoint + 1.0; // force delay to max_length
}
else if (lag < 0.1) {
printf("DLineA: Delays < 0.1 not possible with current structure.\n");

View File

View File

@@ -58,8 +58,8 @@ extern char phonemes[32][4];
void FMVoices :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT temp,temp2;
int tempi,tempi2;
MY_FLOAT temp, temp2 = 0.0;
int tempi, tempi2 = 0;
if (currentVowel < 32) {
tempi2 = currentVowel;

View File

@@ -6,7 +6,7 @@
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the the Chowning/Moorer/ */
/* all based on the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */

View File

@@ -6,7 +6,7 @@
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the the Chowning/Moorer/ */
/* all based on the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */

View File

@@ -11,26 +11,33 @@
JetTabl :: JetTabl()
{
lastOutput = (MY_FLOAT) 0.0;
lastOutput = (MY_FLOAT) 0.0;
}
JetTabl :: ~JetTabl()
{
}
MY_FLOAT JetTabl :: lookup(MY_FLOAT sample) /* Perform "Table Lookup" */
{ /* By Polynomial Calculation */
lastOutput = sample *
(sample*sample - (MY_FLOAT) 1.0); /* (x^3 - x) approximates sigmoid of jet */
if (lastOutput > 1.0)
lastOutput = (MY_FLOAT) 1.0; /* Saturation at +/- 1.0 */
if (lastOutput < -1.0)
lastOutput = (MY_FLOAT) -1.0;
return lastOutput;
MY_FLOAT JetTabl :: lookup(MY_FLOAT sample)
{
return this->tick(sample);
}
MY_FLOAT JetTabl :: tick(MY_FLOAT sample)
// Perform "Table Lookup"
// By Polynomial Calculation
{
// (x^3 - x) approximates sigmoid of jet
lastOutput = sample * (sample*sample - (MY_FLOAT) 1.0);
if (lastOutput > 1.0)
lastOutput = (MY_FLOAT) 1.0; // Saturation at +/- 1.0
if (lastOutput < -1.0)
lastOutput = (MY_FLOAT) -1.0;
return lastOutput;
}
MY_FLOAT JetTabl :: lastOut()
{
return lastOutput;
return lastOutput;
}

View File

@@ -14,13 +14,14 @@
class JetTabl : public Object
{
protected:
MY_FLOAT lastOutput;
public:
JetTabl();
~JetTabl();
MY_FLOAT lookup(MY_FLOAT deltaP);
MY_FLOAT lastOut();
protected:
MY_FLOAT lastOutput;
public:
JetTabl();
~JetTabl();
MY_FLOAT lookup(MY_FLOAT deltaP);
MY_FLOAT tick(MY_FLOAT deltaP);
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,67 +1,65 @@
/**********************************************/
/* Lip Filter Object by Perry R. Cook, 1995-96*/
/* The lip of the brass player has dynamics */
/* which are controlled by the mass, spring */
/* constant, and damping of the lip. This */
/* filter simulates that behavior and the */
/* transmission/reflection properties as */
/* well. See Cook TBone and HosePlayer */
/* instruments and articles. */
/**********************************************/
/************************************************/
/* Lip Filter Object by Perry R. Cook, 1995-96 */
/* The lip of the brass player has dynamics */
/* which are controlled by the mass, spring */
/* constant, and damping of the lip. This */
/* filter simulates that behavior and the */
/* transmission/reflection properties as */
/* well. See Cook TBone and HosePlayer */
/* instruments and articles. */
/************************************************/
#include "LipFilt.h"
LipFilt :: LipFilt()
{
MY_FLOAT coeffs[2];
filter = new BiQuad;
coeffs[0] = (MY_FLOAT) 0.0;
coeffs[1] = (MY_FLOAT) 0.0;
filter->setZeroCoeffs(coeffs);
this->clear();
MY_FLOAT coeffs[2];
filter = new BiQuad;
coeffs[0] = (MY_FLOAT) 0.0;
coeffs[1] = (MY_FLOAT) 0.0;
filter->setZeroCoeffs(coeffs);
this->clear();
}
LipFilt :: ~LipFilt()
{
delete filter;
delete filter;
}
void LipFilt :: clear()
{
filter->clear();
lastOutput = (MY_FLOAT) 0.0;
filter->clear();
lastOutput = (MY_FLOAT) 0.0;
}
void LipFilt :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT coeffs[2];
coeffs[0] = (MY_FLOAT) 2.0 * (MY_FLOAT) 0.997 *
MY_FLOAT coeffs[2];
coeffs[0] = (MY_FLOAT) 2.0 * (MY_FLOAT) 0.997 *
(MY_FLOAT) cos(TWO_PI * frequency / SRATE); /* damping should change with */
coeffs[1] = (MY_FLOAT) (-0.997 * 0.997); /* lip parameters, but not yet.*/
filter->setPoleCoeffs(coeffs);
filter->setGain((MY_FLOAT) 0.03);
coeffs[1] = (MY_FLOAT) (-0.997 * 0.997); /* lip parameters, but not yet.*/
filter->setPoleCoeffs(coeffs);
filter->setGain((MY_FLOAT) 0.03);
}
/* NOTE: Here we should add lip tension */
/* settings based on Mass/Spring/Damping */
/* Maybe in TookKit97 */
/* NOTE: Here we should add lip tension */
/* settings based on Mass/Spring/Damping */
MY_FLOAT LipFilt :: tick(MY_FLOAT mouthSample,MY_FLOAT boreSample)
/* Perform "Table Lookup" By Polynomial Calculation */
{
MY_FLOAT temp;
temp = mouthSample - boreSample; /* Differential pressure */
temp = filter->tick(temp); /* Force -> position */
temp = temp*temp; /* Simple position to area mapping */
if (temp > 1.0) temp = (MY_FLOAT) 1.0; /* Saturation at + 1.0 */
lastOutput = temp * mouthSample; /* Assume mouth input = area */
lastOutput += ((MY_FLOAT) 1.0 - temp)
* boreSample; /* and Bore reflection is compliment. */
return lastOutput;
MY_FLOAT temp;
temp = mouthSample - boreSample; /* Differential pressure */
temp = filter->tick(temp); /* Force -> position */
temp = temp*temp; /* Simple position to area mapping */
if (temp > 1.0) temp = (MY_FLOAT) 1.0; /* Saturation at + 1.0 */
lastOutput = temp * mouthSample; /* Assume mouth input = area */
lastOutput += ((MY_FLOAT) 1.0 - temp) * boreSample; /* and Bore reflection is compliment. */
return lastOutput;
}
MY_FLOAT LipFilt :: lastOut()
{
return lastOutput;
return lastOutput;
}

View File

@@ -1,28 +1,28 @@
/**********************************************/
/* Lip Filter Object by Perry R. Cook, 1995-96*/
/* The lip of the brass player has dynamics */
/* which are controlled by the mass, spring */
/* constant, and damping of the lip. This */
/* filter simulates that behavior and the */
/* transmission/reflection properties as */
/* well. See Cook TBone and HosePlayer */
/* instruments and articles. */
/**********************************************/
/************************************************/
/* Lip Filter Object by Perry R. Cook, 1995-96 */
/* The lip of the brass player has dynamics */
/* which are controlled by the mass, spring */
/* constant, and damping of the lip. This */
/* filter simulates that behavior and the */
/* transmission/reflection properties as */
/* well. See Cook TBone and HosePlayer */
/* instruments and articles. */
/************************************************/
#include "Object.h"
#include "BiQuad.h"
class LipFilt : public Object
{
protected:
BiQuad *filter;
MY_FLOAT lastOutput;
public:
LipFilt();
~LipFilt();
void clear();
void setFreq(MY_FLOAT frequency);
MY_FLOAT tick(MY_FLOAT mouthSample,MY_FLOAT boreSample);
MY_FLOAT lastOut();
protected:
BiQuad *filter;
MY_FLOAT lastOutput;
public:
LipFilt();
~LipFilt();
void clear();
void setFreq(MY_FLOAT frequency);
MY_FLOAT tick(MY_FLOAT mouthSample,MY_FLOAT boreSample);
MY_FLOAT lastOut();
};

View File

@@ -18,26 +18,14 @@
int outAHere = 0;
// Do OS dependent declarations and includes
#if defined(__OS_IRIX_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
#include <sys/types.h>
#include <sys/prctl.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
pid_t exit_thread;
#elif defined(__OS_Linux_)
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
pthread_t exit_thread;
@@ -50,13 +38,9 @@ unsigned long exit_thread;
#endif
// The thread function definition protocols are slightly
// different under Irix, Linux, and Windoze.
#if defined(__OS_IRIX_)
void monitorStdin(void *)
#elif defined(__OS_Linux_)
// The thread function protocols are slightly different
// under Windoze ... but of course!
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
void *monitorStdin(void *)
@@ -80,10 +64,17 @@ void monitorStdin(void *)
fflush(stdout);
}
}
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
pthread_exit(NULL);
return NULL;
#elif defined(__OS_Win_)
_endthread();
#endif
}
void errorf(void) {
void usage(void) {
printf("useage: MD2SKINI <flag(s)>\n\n");
printf(" With no arguments, MD2SKINI converts MIDI input to SKINI\n");
printf(" format and sends the output directly to stdout.\n");
@@ -95,23 +86,24 @@ void errorf(void) {
exit(0);
}
void main(int argc,char *argv[])
int main(int argc,char *argv[])
{
long j, i = 1;
MY_FLOAT byte2, byte3;
int channel;
int firstMessage = 1;
int writeFileOut = 0;
FILE *fileOut;
FILE *fileOut = NULL;
MIDIIO *controller;
char hostName[256];
char fileName[256];
int useSocket = 0;
int theSocket;
int theSocket = 0;
struct sockaddr_in saServer;
static struct timeval timeout = {0, 10000}; // ten millisecond
if (argc>5) {
errorf();
usage();
}
// Parse the command-line arguments.
@@ -140,11 +132,11 @@ void main(int argc,char *argv[])
break;
default:
errorf();
usage();
break;
}
}
else errorf();
else usage();
i++;
}
@@ -198,22 +190,14 @@ void main(int argc,char *argv[])
}
// Setup the exit thread.
#if defined(__OS_IRIX_)
exit_thread = sproc(monitorStdin, PR_SALL);
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
int err = 0;
err = pthread_create(&exit_thread, NULL, monitorStdin, NULL);
if (err) {
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
if (pthread_create(&exit_thread, NULL, monitorStdin, NULL)) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Win_)
exit_thread = _beginthread(monitorStdin, 0, NULL);
if (exit_thread == -1) {
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
@@ -380,11 +364,19 @@ void main(int argc,char *argv[])
fflush(stdout);
}
memset(s, 0, sizeof(s));
} else {
// With Irix 5.3, you can no longer use the usleep()
// function. And in Windoze, you can't use the select()
// function to do timings. I love supporting multiple
// platforms!
#if defined(__OS_Win_)
} else Sleep ( (DWORD) 2);
Sleep ( (DWORD) 5);
#else
} else usleep( (unsigned long) 2000);
timeout.tv_sec = 0;
timeout.tv_usec = 10000; // 0.01 seconds
select(0, NULL, NULL, NULL, &timeout);
#endif
}
}
sprintf(s,"Exiting MD2SKINI process ... bye!\n");
@@ -406,6 +398,7 @@ void main(int argc,char *argv[])
fclose(fileOut);
}
delete controller;
return 0;
}
#endif

View File

@@ -33,18 +33,18 @@ int readOffset;
/* SGI MIDI INPUT */
/*************************************/
#include <pthread.h>
#include <dmedia/midi.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <signal.h>
MDport inport;
MDevent *midiBuffer;
pid_t midi_input_pid;
pthread_t midi_input_thread;
void midiInputThread(void *)
void *midiInputThread(void *)
{
MDevent newMessage;
int status;
@@ -53,8 +53,9 @@ void midiInputThread(void *)
mdReceive(inport, &newMessage, 1);
status = (newMessage.msg[0] & MD_STATUSMASK);
// Ignore Active Sensing messages
if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) {
// Ignore all system messages
//if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) {
if (status != 0xf0) {
midiBuffer[writeOffset] = newMessage;
writeOffset++;
@@ -83,16 +84,15 @@ MIDIIO :: MIDIIO()
readOffset = 0;
writeOffset = 0;
midi_input_pid = sproc(midiInputThread, PR_SALL);
if (midi_input_pid == -1) {
fprintf(stderr, "unable to create MIDI input thread...aborting.\n");
if (pthread_create(&midi_input_thread, NULL, midiInputThread, NULL)) {
fprintf(stderr, "unable to create MIDI input thread ... aborting.\n");
exit(0);
}
}
MIDIIO :: ~MIDIIO()
{
kill (midi_input_pid, SIGKILL);
pthread_cancel(midi_input_thread);
mdClosePort(inport);
delete [] midiBuffer;
}

View File

@@ -93,6 +93,8 @@ MY_FLOAT NRev :: lastOutputR()
MY_FLOAT NRev :: tick(MY_FLOAT input)
{
// FPU underflow checks seem to make things much
// worse here, so I won't do them.
MY_FLOAT temp,temp0,temp1,temp2,temp3;
int i;

View File

@@ -9,12 +9,6 @@
#include <libc.h>
#endif
#if defined(__OS_Win_) /* For Windoze */
#define ONE_OVER_RANDLIMIT 0.00006103516
#else /* This is for Linux, NeXT and SGI */
#define ONE_OVER_RANDLIMIT 0.00000000093132258
#endif
Noise :: Noise() : Object()
{
lastOutput = (MY_FLOAT) 0.0;
@@ -27,9 +21,9 @@ Noise :: ~Noise()
MY_FLOAT Noise :: tick()
{
#if defined(__OS_Win_) /* For Windoze */
lastOutput = (MY_FLOAT) (rand() - 16383);
lastOutput = (MY_FLOAT) (rand() - (int)RANDLIMIT_OVER_TWO);
#else /* This is for Linux, NeXT and SGI */
lastOutput = (MY_FLOAT) random() - 1073741823.0;
lastOutput = (MY_FLOAT) (random() - (int)RANDLIMIT_OVER_TWO);
#endif
lastOutput *= (MY_FLOAT) ONE_OVER_RANDLIMIT;
@@ -41,12 +35,3 @@ MY_FLOAT Noise :: lastOut()
return lastOutput;
}
/************ Test Main ************************/
/*
void main()
{
long i;
Noise test;
for (i=0;i<20;i++) printf("%lf\n",test.tick());
}
*/

View File

@@ -26,27 +26,34 @@ class Object
/* The OS type definitions are made in the Makefile */
#if defined(__OS_NeXT_) /* For NeXTStep - Black or White Hardware */
// No special defines at this time
#define RANDLIMIT 2147483647
#elif defined(__OS_IRIX_) /* For SGI */
#define __STK_REALTIME_
#define RANDLIMIT 2147483647
#elif defined(__OS_Linux_) /* For Linux */
#define __STK_REALTIME_
#define __OSS_API_ /* Use OSS API */
#define __LITTLE_ENDIAN__
#define RANDLIMIT 2147483647
#elif defined(__OS_Win_) /* For WindowsXX or NT */
#define __STK_REALTIME_
#define __WINDS_API_ /* For DirectSound API */
// #define __WINMM_API_ /* For Win MM API */
#define __LITTLE_ENDIAN__
#define RANDLIMIT 32767
#endif
/* Real-time output buffer size. If clicks are occuring in the
* output sound stream, a larger buffer size may help. Larger
* buffer sizes, however, produce more latency between input and
* output.
* NOTE FOR WINDOZE USERS: Given inherent delays in the sound
* output mechanism under Windoze, there is a trade-off between
* smoothness of fast SKINI parameter updates and input/output
/* Real-time audio input and output buffer size. The value of
* this buffer should be an integer multiple of the number of
* channels your application plans to support, in order that
* multi-channel data is not split across multiple buffers. If
* clicks are occuring in the input or output sound stream, a
* larger buffer size may help. Larger buffer sizes, however,
* produce more latency between input and output.
*
* NOTE FOR WINDOZE USERS: Given inherent delays in the audio
* input and output mechanism under Windoze, there is a trade-off
* between smoothness of fast SKINI parameter updates and input/output
* latency as discussed above. You can use buffer sizes as low
* as 100 (maybe lower) for delay critical applications, but in
* this case SKINI parameter updates will be clumped together
@@ -93,6 +100,23 @@ class Object
#define ONE_OVER_TWO_PI (MY_FLOAT) 0.15915494309
#define SQRT_TWO 1.414213562
/* Useful random number generator values */
#define ONE_OVER_RANDLIMIT (1.0/RANDLIMIT)
#define RANDLIMIT_OVER_TWO (int)(RANDLIMIT/2)
/* FPU Underflow Limit
* The IEEE specification doesn't call for automatic
* zeroing of floating-point values when they reach
* their numerical limits. Instead, most processors
* switch to a much more computation-intensive mode
* when a FPU underflow occurs. We set a lower limit
* here for our own (not so efficient) checks. Here's
* a useful macro for limiting MY_FLOATs. At this time,
* no FPU underflow checks are being performed.
*/
#define FPU_UFLOW_LIMIT 0.0000000001
#define LIMIT_MY_FLOAT(j) ((((j)<(MY_FLOAT)FPU_UFLOW_LIMIT)&&((j)>(MY_FLOAT)-FPU_UFLOW_LIMIT))?(MY_FLOAT)0.0:(j))
/* States for Envelopes, etc. */
#define ATTACK 0
#define DECAY 1

View File

@@ -49,10 +49,11 @@ void Plucked :: pluck(MY_FLOAT amplitude)
long i;
pickFilt->setPole((MY_FLOAT) 0.999 - (amplitude * (MY_FLOAT) 0.15));
pickFilt->setGain(amplitude * (MY_FLOAT) 0.5);
for (i=0;i<length;i++)
delayLine->tick(delayLine->lastOut() * (MY_FLOAT) 0.6 /* fill delay with noise */
+ pickFilt->tick(noise->tick())); /* additively with current */
/* contents */
for (i=0;i<length;i++)
// fill delay with noise additively with current contents
delayLine->tick(delayLine->lastOut() * (MY_FLOAT) 0.6
+ pickFilt->tick(noise->tick()));
}
void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp)

View File

@@ -21,8 +21,9 @@ class RTDuplex : public Object
{
protected:
RTSoundIO *soundIO;
short indata[RT_BUFFER_SIZE];
short outdata[RT_BUFFER_SIZE];
// Add an extra 10 samples to indata[] and outdata[] just to be safe
short indata[RT_BUFFER_SIZE+10];
short outdata[RT_BUFFER_SIZE+10];
long readCounter;
long writeCounter;
int channels;

View File

@@ -382,6 +382,8 @@ int RTSoundIO :: recordBuffer(short *buf, int bufsize)
* capabilities.
*/
#define DS_WRITE_METHOD 1
#include <stdio.h>
RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels, char *mode)
@@ -414,8 +416,8 @@ RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels, char *mode)
// Define a maximum distance that the write pointer is
// allowed to lead safePos. The size of this zone is
// fairly critical to the behavior of this scheme. The
// value below is set for a 10 millisecond region.
zoneSize = (DWORD) (0.01 * srate * sizeof(short)); // bytes
// value below is set for a 15 millisecond region.
zoneSize = (DWORD) (0.015 * srate * sizeof(short)); // bytes
// Create the DS object
if ((result = DirectSoundCreate(NULL, &lpDirectSound, NULL)) != DS_OK) {
@@ -651,110 +653,110 @@ int RTSoundIO :: playBuffer(short *buf, int bufsize)
hr = lpDSBuffer->GetCurrentPosition(&playPos, &safePos);
if (hr != DS_OK) return -1;
// METHOD 1: Keep write pointer in front of read pointer.
//
// Microsloth says that the safePos is about 15 ms ahead of
// playPos. I think this figure is somewhat hardware related,
// especially if you are writing to the primary buffer. With
// my shit-blaster 16, I found the safePos to be about 10 ms
// ahead of playPos. If you really need to reduce delay, you
// can try moving your "safePos" closer to the play pointer.
// You'll be treading on dangerous ground, but then again,
// you're obviously using Windoze so you're already familiar
// with such uncertainty! I've been able to lop off 2-5 ms
// in some circumstances.
//static DWORD backup = (DWORD) (0.005 * SRATE * sizeof(short));
//safePos = (safePos + dwDSBufSize - backup) % dwDSBufSize;
// METHOD 1: Keep write pointer in front of read pointer.
//
// Microsloth says that the safePos is about 15 ms ahead of
// playPos. I think this figure is somewhat hardware related,
// especially if you are writing to the primary buffer. With
// my shit-blaster 16, I found the safePos to be about 10 ms
// ahead of playPos. If you really need to reduce delay, you
// can try moving your "safePos" closer to the play pointer.
// You'll be treading on dangerous ground, but then again,
// you're obviously using Windoze so you're already familiar
// with such uncertainty! I've been able to lop off 2-5 ms
// in some circumstances.
//static DWORD backup = (DWORD) (0.005 * SRATE * sizeof(short));
//safePos = (safePos + dwDSBufSize - backup) % dwDSBufSize;
// Assume that the next write position is always in front
// of safePos. If not, the write pointer must have wrapped.
// NOTE: If safePos somehow gets ahead of the write pointer,
// then an underrun has occurred and there's not much we can
// do anyway.
DWORD deltaPos;
if( safePos > nextWritePos )
deltaPos = nextWritePos + dwDSBufSize - safePos;
else
deltaPos = nextWritePos - safePos;
// Assume that the next write position is always in front
// of safePos. If not, the write pointer must have wrapped.
// NOTE: If safePos somehow gets ahead of the write pointer,
// then an underrun has occurred and there's not much we can
// do anyway.
DWORD deltaPos;
if( safePos > nextWritePos )
deltaPos = nextWritePos + dwDSBufSize - safePos;
else
deltaPos = nextWritePos - safePos;
// Check whether the write pointer is in the allowed region.
while ( deltaPos > zoneSize ) {
// If we are here, then we must wait until the write pointer
// is in the allowed region. For this, we can either
// continuously check the pointer positions until they are
// OK or we can use the Sleep() function to pause operations
// for a certain amount of time. Use of the Sleep() function
// would seem to be the better choice, however, there are
// reports that Sleep() often "sleeps" for much longer than
// requested. I'll let you choose which method to use.
static int sleep = 1; // 1 = sleep, 0 = don't sleep
// Check whether the write pointer is in the allowed region.
while ( deltaPos > zoneSize ) {
// If we are here, then we must wait until the write pointer
// is in the allowed region. For this, we can either
// continuously check the pointer positions until they are
// OK or we can use the Sleep() function to pause operations
// for a certain amount of time. Use of the Sleep() function
// would seem to be the better choice, however, there are
// reports that Sleep() often "sleeps" for much longer than
// requested. I'll let you choose which method to use.
static int sleep = 1; // 1 = sleep, 0 = don't sleep
if (sleep) {
// Sleep until safePos catches up. Calculate number of
// milliseconds to wait as:
// time = distance * (milliseconds/second) * fudgefactor /
// ((bytes/sample) * (samples/second))
// A "fudgefactor" less than 1 is used because it was found
// that sleeping too long was MUCH worse than sleeping for
// several shorter periods.
DWORD millis = (DWORD) ((deltaPos * 200.0) / ( sizeof(short) * SRATE));
if (sleep) {
// Sleep until safePos catches up. Calculate number of
// milliseconds to wait as:
// time = distance * (milliseconds/second) * fudgefactor /
// ((bytes/sample) * (samples/second))
// A "fudgefactor" less than 1 is used because it was found
// that sleeping too long was MUCH worse than sleeping for
// several shorter periods.
DWORD millis = (DWORD) ((deltaPos * 200.0) / ( sizeof(short) * SRATE));
// Sleep for that long
Sleep( millis );
}
// Sleep for that long
Sleep( millis );
}
// Wake up, find out where we are now
hr = lpDSBuffer->GetCurrentPosition( &playPos, &safePos );
if( hr != DS_OK ) return -1;
// Wake up, find out where we are now
hr = lpDSBuffer->GetCurrentPosition( &playPos, &safePos );
if( hr != DS_OK ) return -1;
// Backup safePos? (See above)
//safePos = (safePos + dwDSBufSize - backup) % dwDSBufSize;
// Backup safePos? (See above)
//safePos = (safePos + dwDSBufSize - backup) % dwDSBufSize;
if( safePos > nextWritePos )
deltaPos = nextWritePos + dwDSBufSize - safePos;
else
deltaPos = nextWritePos - safePos;
}
// End of Method 1
if( safePos > nextWritePos )
deltaPos = nextWritePos + dwDSBufSize - safePos;
else
deltaPos = nextWritePos - safePos;
}
// End of Method 1
/*
// METHOD 2: Keep write region behind of play pointer.
if( playPos < nextWritePos ) playPos += dwDSBufSize; // unwrap offset
DWORD endWrite = nextWritePos + bufsize * sizeof(short);
/*
// METHOD 2: Keep write region behind of play pointer.
if( playPos < nextWritePos ) playPos += dwDSBufSize; // unwrap offset
DWORD endWrite = nextWritePos + bufsize * sizeof(short);
// Check whether the write region is behind the play pointer.
while ( playPos < endWrite ) {
// If we are here, then we must wait until the play pointer
// gets beyond the write region. For this, we can either
// continuously check the pointer positions until they are
// OK or we can use the Sleep() function to pause operations
// for a certain amount of time. Use of the Sleep() function
// would seem to be the better choice, however, there are
// reports that Sleep() often "sleeps" for much longer than
// requested. I'll let you choose which method to use.
static int sleep = 1; // 1 = sleep, 0 = don't sleep
// Check whether the write region is behind the play pointer.
while ( playPos < endWrite ) {
// If we are here, then we must wait until the play pointer
// gets beyond the write region. For this, we can either
// continuously check the pointer positions until they are
// OK or we can use the Sleep() function to pause operations
// for a certain amount of time. Use of the Sleep() function
// would seem to be the better choice, however, there are
// reports that Sleep() often "sleeps" for much longer than
// requested. I'll let you choose which method to use.
static int sleep = 1; // 1 = sleep, 0 = don't sleep
if (sleep) {
// Sleep until safePos catches up. Calculate number of
// milliseconds to wait as:
// time = distance * (milliseconds/second) * fudgefactor /
// ((bytes/sample) * (samples/second))
// A "fudgefactor" less than 1 is used because it was found
// that sleeping too long was MUCH worse than sleeping for
// several shorter periods.
DWORD millis = (DWORD) (((endWrite - playPos) * 200.0) / ( sizeof(short) * SRATE));
if (sleep) {
// Sleep until safePos catches up. Calculate number of
// milliseconds to wait as:
// time = distance * (milliseconds/second) * fudgefactor /
// ((bytes/sample) * (samples/second))
// A "fudgefactor" less than 1 is used because it was found
// that sleeping too long was MUCH worse than sleeping for
// several shorter periods.
DWORD millis = (DWORD) (((endWrite - playPos) * 200.0) / ( sizeof(short) * SRATE));
// Sleep for that long
Sleep( millis );
}
// Sleep for that long
Sleep( millis );
}
// Wake up, find out where we are now
hr = lpDSBuffer->GetCurrentPosition( &playPos, &safePos );
if( hr != DS_OK ) return -1;
if( playPos < nextWritePos ) playPos += dwDSBufSize; // unwrap offset
}
// End of Method 2.
*/
// Wake up, find out where we are now
hr = lpDSBuffer->GetCurrentPosition( &playPos, &safePos );
if( hr != DS_OK ) return -1;
if( playPos < nextWritePos ) playPos += dwDSBufSize; // unwrap offset
}
// End of Method 2.
*/
// Lock free space in the DS
hr = lpDSBuffer->Lock (nextWritePos, bufsize * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);

View File

@@ -22,10 +22,10 @@
RTWvIn :: RTWvIn(MY_FLOAT srate, short chans)
{
soundIO = new RTSoundIO(srate, chans, "record");
length = RT_BUFFER_SIZE;
channels = chans;
length = RT_BUFFER_SIZE/channels;
data = 0;
rtdata = (short *) new short[channels*(RT_BUFFER_SIZE+1)];
rtdata = (short *) new short[RT_BUFFER_SIZE+channels];
this->getMoreData();
@@ -78,8 +78,8 @@ void RTWvIn :: setLooping(int aLoopStatus)
void RTWvIn :: getMoreData()
{
soundIO->recordBuffer(rtdata,(RT_BUFFER_SIZE)*channels);
long temp = channels*(RT_BUFFER_SIZE);
soundIO->recordBuffer(rtdata,RT_BUFFER_SIZE);
long temp = RT_BUFFER_SIZE;
for (int i=0;i<channels;i++) {
rtdata[temp] = rtdata[temp-channels];
temp++;

View File

@@ -19,7 +19,8 @@ class RTWvOut : public WvOut
{
protected:
RTSoundIO *soundIO;
short data[RT_BUFFER_SIZE];
// Add an extra 10 samples to data[] just to be safe
short data[RT_BUFFER_SIZE+10];
long counter;
int channels;
public:

View File

@@ -10,8 +10,8 @@
ReedTabl :: ReedTabl() : Object()
{
offSet = (MY_FLOAT) 0.6; /* Offset is a bias, related to reed rest position */
slope = (MY_FLOAT) -0.8; /* Slope corresponds loosely to reed stiffness */
offSet = (MY_FLOAT) 0.6; /* Offset is a bias, related to reed rest position */
slope = (MY_FLOAT) -0.8; /* Slope corresponds loosely to reed stiffness */
}
ReedTabl :: ~ReedTabl()
@@ -21,22 +21,27 @@ ReedTabl :: ~ReedTabl()
void ReedTabl :: setOffset(MY_FLOAT aValue)
{
offSet = aValue; /* Offset is a bias, related to reed rest position */
offSet = aValue; /* Offset is a bias, related to reed rest position */
}
void ReedTabl :: setSlope(MY_FLOAT aValue)
{
slope = aValue; /* Slope corresponds loosely to reed stiffness */
slope = aValue; /* Slope corresponds loosely to reed stiffness */
}
MY_FLOAT ReedTabl :: lookup(MY_FLOAT deltaP)
{
return this->tick(deltaP);
}
MY_FLOAT ReedTabl :: tick(MY_FLOAT deltaP)
/* Perform "Table Lookup" by direct clipped */
/* linear function calculation */
{ /* deltaP is differential reed pressure */
lastOutput = offSet + (slope * deltaP); /* compute basic non-linearity */
if (lastOutput > 1.0) lastOutput = (MY_FLOAT) 1.0; /* if other way, reed slams shut */
if (lastOutput < -1.0) lastOutput = (MY_FLOAT) -1.0; /* if all the way open, acts like open end */
return lastOutput;
lastOutput = offSet + (slope * deltaP); /* compute basic non-linearity */
if (lastOutput > 1.0) lastOutput = (MY_FLOAT) 1.0; /* if other way, reed slams shut */
if (lastOutput < -1.0) lastOutput = (MY_FLOAT) -1.0; /* if all the way open, acts like open end */
return lastOutput;
}
MY_FLOAT ReedTabl :: lastOut()

View File

@@ -13,17 +13,18 @@
class ReedTabl : public Object
{
protected:
MY_FLOAT offSet;
MY_FLOAT slope;
MY_FLOAT lastOutput;
public:
ReedTabl();
~ReedTabl();
void setOffset(MY_FLOAT aValue);
void setSlope(MY_FLOAT aValue);
MY_FLOAT lookup(MY_FLOAT deltaP);
MY_FLOAT lastOut();
protected:
MY_FLOAT offSet;
MY_FLOAT slope;
MY_FLOAT lastOutput;
public:
ReedTabl();
~ReedTabl();
void setOffset(MY_FLOAT aValue);
void setSlope(MY_FLOAT aValue);
MY_FLOAT lookup(MY_FLOAT deltaP);
MY_FLOAT tick(MY_FLOAT deltaP);
MY_FLOAT lastOut();
};
#endif

View File

@@ -12,6 +12,10 @@ Reverb :: Reverb()
{
}
Reverb :: ~Reverb()
{
}
MY_FLOAT Reverb :: tick(MY_FLOAT sample)
{
printf("Warning: Using virtual function Reverb :: tick()\n");

View File

@@ -14,10 +14,11 @@
class Reverb : public Object
{
public:
Reverb();
Reverb();
virtual ~Reverb();
virtual MY_FLOAT tick(MY_FLOAT sample);
virtual void setEffectMix(MY_FLOAT mix);
int isprime(int val);
int isprime(int val);
};
#endif // defined(__Reverb_h)

View File

@@ -140,7 +140,7 @@ long SKINI11 :: parseThis(char* aString)
int somePointrs[__SK_MAX_FIELDS_];
temp = nextChar(aString);
if (which = ignore(aString[temp])) {
if ((which = ignore(aString[temp]))) {
if (which == 2) printf("// CommentLine: %s\n",aString);
messageType = 0;
return messageType;

View File

@@ -60,34 +60,39 @@ MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0
/************************* MARACA *****************************/
#define MARA_SOUND_DECAY 0.95
#define MARA_SYSTEM_DECAY 0.999
#define MARA_GAIN 25.0
//#define MARA_GAIN 25.0
#define MARA_GAIN 20.0
#define MARA_NUM_BEANS 25
#define MARA_CENTER_FREQ 3200.0
#define MARA_RESON 0.96
/*********************** SEKERE *****************************/
#define SEKE_SOUND_DECAY 0.96
#define SEKE_SYSTEM_DECAY 0.999
#define SEKE_GAIN 30.0
//#define SEKE_GAIN 30.0
#define SEKE_GAIN 20.0
#define SEKE_NUM_BEANS 64
#define SEKE_CENTER_FREQ 5500.0
#define SEKE_RESON 0.6
/*********************** SANDPAPER **************************/
#define SANDPAPR_SOUND_DECAY 0.999
#define SANDPAPR_SYSTEM_DECAY 0.999
#define SANDPAPR_GAIN 1.0
//#define SANDPAPR_GAIN 1.0
#define SANDPAPR_GAIN 0.5
#define SANDPAPR_NUM_GRAINS 128
#define SANDPAPR_CENTER_FREQ 4500.0
#define SANDPAPR_RESON 0.6
/************************ CABASA *****************************/
#define CABA_SOUND_DECAY 0.96
#define CABA_SYSTEM_DECAY 0.997
#define CABA_GAIN 150.0
//#define CABA_GAIN 150.0
#define CABA_GAIN 40.0
#define CABA_NUM_BEADS 512
#define CABA_CENTER_FREQ 3000.0
#define CABA_RESON 0.7
/************************ Bamboo Wind Chimes *****************/
#define BAMB_SOUND_DECAY 0.95
#define BAMB_SYSTEM_DECAY 0.99995
//#define BAMB_SYSTEM_DECAY 0.99995
#define BAMB_SYSTEM_DECAY 0.9999
#define BAMB_GAIN 2.0
#define BAMB_NUM_TUBES 1.25
#define BAMB_CENTER_FREQ0 2800.0
@@ -96,9 +101,11 @@ MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0
#define BAMB_RESON 0.995
/******************* Water Drops ****************************/
#define WUTR_SOUND_DECAY 0.95
#define WUTR_SYSTEM_DECAY 0.999
//#define WUTR_SYSTEM_DECAY 0.999
#define WUTR_SYSTEM_DECAY 0.996
#define WUTR_GAIN 1.0
#define WUTR_NUM_SOURCES 4
//#define WUTR_NUM_SOURCES 4
#define WUTR_NUM_SOURCES 10
#define WUTR_CENTER_FREQ0 450.0
#define WUTR_CENTER_FREQ1 600.0
#define WUTR_CENTER_FREQ2 750.0
@@ -107,7 +114,8 @@ MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0
/****************** TAMBOURINE *****************************/
#define TAMB_SOUND_DECAY 0.95
#define TAMB_SYSTEM_DECAY 0.9985
#define TAMB_GAIN 10.0
//#define TAMB_GAIN 10.0
#define TAMB_GAIN 5.0
#define TAMB_NUM_TIMBRELS 32
#define TAMB_SHELL_FREQ 2300
#define TAMB_SHELL_GAIN 0.1
@@ -118,7 +126,8 @@ MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0
/********************** SLEIGHBELLS *************************/
#define SLEI_SOUND_DECAY 0.97
#define SLEI_SYSTEM_DECAY 0.9994
#define SLEI_GAIN 2.0
//#define SLEI_GAIN 2.0
#define SLEI_GAIN 1.0
#define SLEI_NUM_BELLS 32
#define SLEI_CYMB_FREQ0 2500
#define SLEI_CYMB_FREQ1 5300
@@ -145,7 +154,8 @@ MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0
/************************ COKECAN **************************/
#define COKECAN_SOUND_DECAY 0.97
#define COKECAN_SYSTEM_DECAY 0.999
#define COKECAN_GAIN 1.0
//#define COKECAN_GAIN 1.0
#define COKECAN_GAIN 0.8
#define COKECAN_NUM_PARTS 48
#define COKECAN_HELMFREQ 370
#define COKECAN_HELM_RES 0.99
@@ -169,7 +179,8 @@ MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0
/************************ Crunch1 ***************************/
#define CRUNCH1_SOUND_DECAY 0.95
#define CRUNCH1_SYSTEM_DECAY 0.99806
#define CRUNCH1_GAIN 30.0
//#define CRUNCH1_GAIN 30.0
#define CRUNCH1_GAIN 20.0
#define CRUNCH1_NUM_BEADS 7
#define CRUNCH1_CENTER_FREQ 800.0
#define CRUNCH1_RESON 0.95
@@ -270,12 +281,16 @@ int Shakers :: setFreqAndReson(int which, MY_FLOAT freq, MY_FLOAT reson) {
int Shakers :: setupNum(int inst)
{
int i;
int i, rv = 0;
MY_FLOAT temp;
if (inst==1) { // cabasa_setup();
rv = inst;
num_objects = CABA_NUM_BEADS;
defObjs[inst] = CABA_NUM_BEADS;
setDecays(CABA_SOUND_DECAY, CABA_SYSTEM_DECAY);
defDecays[inst] = CABA_SYSTEM_DECAY;
decayScale[inst] = 0.97;
num_freqs = 1;
baseGain = CABA_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -285,8 +300,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,-1.0,0.0);
}
else if (inst==2) { // sekere_setup();
rv = inst;
num_objects = SEKE_NUM_BEANS;
defObjs[inst] = SEKE_NUM_BEANS;
this->setDecays(SEKE_SOUND_DECAY,SEKE_SYSTEM_DECAY);
defDecays[inst] = SEKE_SYSTEM_DECAY;
decayScale[inst] = 0.94;
num_freqs = 1;
baseGain = SEKE_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -296,8 +315,12 @@ int Shakers :: setupNum(int inst)
this->setFinalZs(1.0, 0.0, -1.0);
}
else if (inst==3) { // guiro_setup();
rv = inst;
num_objects = GUIR_NUM_PARTS;
defObjs[inst] = GUIR_NUM_PARTS;
setDecays(GUIR_SOUND_DECAY,1.0);
defDecays[inst] = 0.9999;
decayScale[inst] = 1.0;
num_freqs = 2;
baseGain = GUIR_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -313,8 +336,12 @@ int Shakers :: setupNum(int inst)
ratchetPos = 10;
}
else if (inst==4) { // wuter_setup();
rv = inst;
num_objects = WUTR_NUM_SOURCES;
defObjs[inst] = WUTR_NUM_SOURCES;
setDecays(WUTR_SOUND_DECAY,WUTR_SYSTEM_DECAY);
defDecays[inst] = WUTR_SYSTEM_DECAY;
decayScale[inst] = 0.8;
num_freqs = 3;
baseGain = WUTR_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -333,8 +360,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,0.0,0.0);
}
else if (inst==5) { // bamboo_setup();
rv = inst;
num_objects = BAMB_NUM_TUBES;
defObjs[inst] = BAMB_NUM_TUBES;
setDecays(BAMB_SOUND_DECAY, BAMB_SYSTEM_DECAY);
defDecays[inst] = BAMB_SYSTEM_DECAY;
decayScale[inst] = 0.7;
num_freqs = 3;
baseGain = BAMB_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -353,8 +384,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,0.0,0.0);
}
else if (inst==6) { // tambourine_setup();
rv = inst;
num_objects = TAMB_NUM_TIMBRELS;
defObjs[inst] = TAMB_NUM_TIMBRELS;
setDecays(TAMB_SOUND_DECAY,TAMB_SYSTEM_DECAY);
defDecays[inst] = TAMB_SYSTEM_DECAY;
decayScale[inst] = 0.95;
num_freqs = 3;
baseGain = TAMB_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -373,8 +408,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,0.0,-1.0);
}
else if (inst==7) { // sleighbell_setup();
rv = inst;
num_objects = SLEI_NUM_BELLS;
defObjs[inst] = SLEI_NUM_BELLS;
setDecays(SLEI_SOUND_DECAY,SLEI_SYSTEM_DECAY);
defDecays[inst] = SLEI_SYSTEM_DECAY;
decayScale[inst] = 0.9;
num_freqs = 5;
baseGain = SLEI_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -395,8 +434,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,0.0,-1.0);
}
else if (inst==8) { // stix1_setup();
rv = inst;
num_objects = STIX1_NUM_BEANS;
defObjs[inst] = STIX1_NUM_BEANS;
setDecays(STIX1_SOUND_DECAY,STIX1_SYSTEM_DECAY);
defDecays[inst] = STIX1_SYSTEM_DECAY;
decayScale[inst] = 0.96;
num_freqs = 1;
baseGain = STIX1_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -406,8 +449,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,0.0,-1.0);
}
else if (inst==9) { // crunch1_setup();
rv = inst;
num_objects = CRUNCH1_NUM_BEADS;
defObjs[inst] = CRUNCH1_NUM_BEADS;
setDecays(CRUNCH1_SOUND_DECAY,CRUNCH1_SYSTEM_DECAY);
defDecays[inst] = CRUNCH1_SYSTEM_DECAY;
decayScale[inst] = 0.96;
num_freqs = 1;
baseGain = CRUNCH1_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -417,8 +464,12 @@ int Shakers :: setupNum(int inst)
setFinalZs(1.0,-1.0,0.0);
}
else if (inst==10) { // wrench_setup();
rv = inst;
num_objects = WRENCH_NUM_PARTS;
defObjs[inst] = WRENCH_NUM_PARTS;
setDecays(WRENCH_SOUND_DECAY,1.0);
defDecays[inst] = 0.9999;
decayScale[inst] = 0.98;
num_freqs = 2;
baseGain = WRENCH_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -434,8 +485,12 @@ int Shakers :: setupNum(int inst)
ratchetPos = 10;
}
else if (inst==11) { // sandpapr_setup();
rv = inst;
num_objects = SANDPAPR_NUM_GRAINS;
defObjs[inst] = SANDPAPR_NUM_GRAINS;
this->setDecays(SANDPAPR_SOUND_DECAY,SANDPAPR_SYSTEM_DECAY);
defDecays[inst] = SANDPAPR_SYSTEM_DECAY;
decayScale[inst] = 0.97;
num_freqs = 1;
baseGain = SANDPAPR_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -445,8 +500,12 @@ int Shakers :: setupNum(int inst)
this->setFinalZs(1.0, 0.0, -1.0);
}
else if (inst==12) { // cokecan_setup();
rv = inst;
num_objects = COKECAN_NUM_PARTS;
defObjs[inst] = COKECAN_NUM_PARTS;
setDecays(COKECAN_SOUND_DECAY,COKECAN_SYSTEM_DECAY);
defDecays[inst] = COKECAN_SYSTEM_DECAY;
decayScale[inst] = 0.95;
num_freqs = 5;
baseGain = COKECAN_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -469,7 +528,10 @@ int Shakers :: setupNum(int inst)
}
else { // maraca_setup(); inst == 0 or other
num_objects = MARA_NUM_BEANS;
defObjs[0] = MARA_NUM_BEANS;
setDecays(MARA_SOUND_DECAY,MARA_SYSTEM_DECAY);
defDecays[0] = MARA_SYSTEM_DECAY;
decayScale[inst] = 0.9;
num_freqs = 1;
baseGain = MARA_GAIN;
temp = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
@@ -478,7 +540,7 @@ int Shakers :: setupNum(int inst)
setFreqAndReson(0,MARA_CENTER_FREQ,MARA_RESON);
setFinalZs(1.0,-1.0,0.0);
}
return inst;
return rv;
}
void Shakers :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
@@ -486,7 +548,8 @@ void Shakers :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
// Yep ... pretty kludgey, but it works!
int noteNum = (int) ((12*log(freq/220)/log(2)) + 57.01) % 32;
if (instType != noteNum) instType = this->setupNum(noteNum);
shakeEnergy = amp * MAX_SHAKE * 0.1;
//shakeEnergy = amp * MAX_SHAKE * 0.1;
shakeEnergy += amp * MAX_SHAKE * 0.1;
if (shakeEnergy > MAX_SHAKE) shakeEnergy = MAX_SHAKE;
if (instType==10 || instType==3) ratchetPos += 1;
#if defined(_debug_)
@@ -497,6 +560,7 @@ void Shakers :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
void Shakers :: noteOff(MY_FLOAT amp)
{
shakeEnergy = 0.0;
if (instType==10 || instType==3) ratchetPos = 0;
}
#define MIN_ENERGY 0.3
@@ -510,6 +574,7 @@ MY_FLOAT Shakers :: tick()
if (instType==4) {
if (shakeEnergy > MIN_ENERGY) {
lastOutput = wuter_tick();
lastOutput *= 0.0001;
}
else {
lastOutput = 0.0;
@@ -524,6 +589,7 @@ MY_FLOAT Shakers :: tick()
}
totalEnergy = ratchet;
lastOutput = ratchet_tick();
lastOutput *= 0.0001;
}
else lastOutput = 0.0;
}
@@ -560,13 +626,11 @@ MY_FLOAT Shakers :: tick()
data += finalZCoeffs[2] * finalZ[2]; // Extra zero(s) for shape
if (data > 10000.0) data = 10000.0;
if (data < -10000.0) data = -10000.0;
lastOutput = data;
lastOutput = data * 0.0001;
}
else lastOutput = 0.0;
}
lastOutput *= 0.0001;
return lastOutput;
}
@@ -593,23 +657,64 @@ void Shakers :: controlChange(int number, MY_FLOAT value)
#if defined(_debug_)
printf("setting decay\n");
#endif
systemDecay = 0.998 + (value * NORM_7 * 0.002);
//systemDecay = 0.998 + (value * NORM_7 * 0.002);
if (instType != 3 && instType != 10) {
systemDecay = defDecays[instType] + ((value - 64.0) * decayScale[instType] * (1.0 - defDecays[instType]) / 64.0 );
gains[0] = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
for (i=1;i<num_freqs;i++) gains[i] = gains[0];
if (instType == 6) { // tambourine
gains[0] *= TAMB_SHELL_GAIN;
gains[1] *= 0.8;
}
else if (instType == 7) { // sleighbell
gains[3] *= 0.5;
gains[4] *= 0.3;
}
else if (instType == 12) { // cokecan
for (i=1;i<num_freqs;i++) gains[i] *= 1.8;
}
for (i=0;i<num_freqs;i++) gains[i] *= ((128-value)/100.0 + 0.36);
}
}
else if (number == __SK_ModFrequency_) { // control_change #11
#if defined(_debug_)
printf("setting number of objects\n");
#endif
if (instType==5) num_objects = (MY_FLOAT) (value/32.0) + 1;
else num_objects = (MY_FLOAT) value + 1;
if (instType == 5) // bamboo
num_objects = (MY_FLOAT) (value * defObjs[instType] / 64.0) + 0.3;
else
num_objects = (MY_FLOAT) (value * defObjs[instType] / 64.0) + 1.1;
gains[0] = log(num_objects) * baseGain / (MY_FLOAT) num_objects;
for (i=1;i<num_freqs;i++) gains[i] = gains[0];
if (instType == 6) { // tambourine
gains[0] *= TAMB_SHELL_GAIN;
gains[1] *= 0.8;
}
else if (instType == 7) { // sleighbell
gains[3] *= 0.5;
gains[4] *= 0.3;
}
else if (instType == 12) { // cokecan
for (i=1;i<num_freqs;i++) gains[i] *= 1.8;
}
if (instType != 3 && instType != 10) {
// reverse calculate decay setting
float temp = 64.0 * (systemDecay-defDecays[instType])/(decayScale[instType]*(1-defDecays[instType])) + 64.0;
// scale gains by decay setting
for (i=0;i<num_freqs;i++) gains[i] *= ((128-temp)/100.0 + 0.36);
}
}
else if (number == __SK_ModWheel_) { // control_change #1
#if defined(_debug_)
printf("setting resonance %i freq. to %f\n",i,temp);
#endif
for (i=0;i<num_freqs;i++) {
temp = center_freqs[i] * pow (1.015,value-64);
if (instType == 6 || instType == 2 || instType == 7) // limit range a bit for tambourine
temp = center_freqs[i] * pow (1.008,value-64);
else
temp = center_freqs[i] * pow (1.015,value-64);
t_center_freqs[i] = temp;
#if defined(_debug_)
printf("setting resonance %i freq. to %f\n",i,temp);
#endif
coeffs[i][0] = -resons[i] * 2.0 * cos(temp * TWO_PI / SRATE);
coeffs[i][1] = resons[i]*resons[i];
}

View File

@@ -27,6 +27,7 @@
#include "Instrmnt.h"
#define MAX_FREQS 8
#define NUM_INSTR 13
class Shakers : public Instrmnt
{
@@ -59,6 +60,9 @@ class Shakers : public Instrmnt
void setFinalZs(MY_FLOAT z0, MY_FLOAT z1, MY_FLOAT z2);
MY_FLOAT wuter_tick();
MY_FLOAT ratchet_tick();
MY_FLOAT defObjs[NUM_INSTR];
MY_FLOAT defDecays[NUM_INSTR];
MY_FLOAT decayScale[NUM_INSTR];
public:
Shakers();
~Shakers();

View File

@@ -30,7 +30,7 @@ class Simple : public Instrmnt
MY_FLOAT loopGain;
public:
Simple();
~Simple();
virtual ~Simple();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void keyOn();

View File

@@ -180,9 +180,6 @@ MY_FLOAT VoicForm :: tick()
void VoicForm :: controlChange(int number, MY_FLOAT value)
{
MY_FLOAT temp;
int tempi;
#if defined(_debug_)
printf("VoicForm : ControlChange: Number=%i Value=%f\n",number,value);
#endif
@@ -191,7 +188,8 @@ void VoicForm :: controlChange(int number, MY_FLOAT value)
this->setUnVoiced((MY_FLOAT) 0.01 * value * (MY_FLOAT) NORM_7);
}
else if (number == __SK_FootControl_) {
tempi = (int) value;
MY_FLOAT temp = 0.0;
int tempi = (int) value;
if (tempi < 32) {
tempi = tempi;
temp = (MY_FLOAT) 0.9;

View File

@@ -28,7 +28,7 @@ class WvIn : public Object
MY_FLOAT *lastOutput;
public:
WvIn();
~WvIn();
virtual ~WvIn();
void reset();
void normalize();
void normalize(MY_FLOAT newPeak);

View File

@@ -15,25 +15,25 @@
class MandPlyr : public Instrmnt
{
protected:
VoicMang *strings;
Noise *noise;
short strumming;
long strumRate;
long strumCount;
MY_FLOAT skill;
short nums[NUM_STRINGS]; // For Now Integer Note Nums
MY_FLOAT amps[NUM_STRINGS];
long tags[NUM_STRINGS];
public:
MandPlyr();
~MandPlyr();
virtual void noteOnN(short num, MY_FLOAT amp);
virtual void noteOffN(short num, MY_FLOAT amp);
virtual MY_FLOAT tick();
MY_FLOAT special_tick();
virtual void controlChange(int number, MY_FLOAT value);
virtual void playChord(MY_FLOAT amp, char* chordString);
protected:
VoicMang *strings;
Noise *noise;
short strumming;
long strumRate;
long strumCount;
MY_FLOAT skill;
short nums[NUM_STRINGS]; // For Now Integer Note Nums
MY_FLOAT amps[NUM_STRINGS];
long tags[NUM_STRINGS];
public:
MandPlyr();
~MandPlyr();
virtual void noteOnN(short num, MY_FLOAT amp);
virtual void noteOffN(short num, MY_FLOAT amp);
virtual MY_FLOAT tick();
MY_FLOAT special_tick();
virtual void controlChange(int number, MY_FLOAT value);
virtual void playChord(MY_FLOAT amp, char* chordString);
};
#endif

View File

@@ -18,12 +18,12 @@ RM = /bin/rm
ifeq ($(OS),IRIX) # These are for SGI
INSTR = effects
CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread
endif
ifeq ($(OS),Linux) # These are for Linux
INSTR = effects
CC = g++ -O3 -D__OS_Linux_ # -g
CC = g++ -O3 -Wall -D__OS_Linux_ # -g
LIBRARY = -lpthread -lm
endif

View File

@@ -19,7 +19,7 @@ int numStrings = 0;
int notDone = 1;
char **inputString;
void errorfun(void) {
void usage(void) {
/* Error function in case of incorrect command-line argument specifications */
printf("\nuseage: effects flag \n");
printf(" where flag = -ip for realtime SKINI input by pipe\n");
@@ -28,7 +28,7 @@ void errorfun(void) {
exit(0);
}
void main(int argc,char *argv[])
int main(int argc,char *argv[])
{
MY_FLOAT inSample = 0.0;
MY_FLOAT lastSample = 0.0;
@@ -36,12 +36,12 @@ void main(int argc,char *argv[])
long i, synlength;
int type, j, outOne = 0, effect = 0, useSocket = 0;
if (argc != 2) errorfun();
if (argc != 2) usage();
if (!strcmp(argv[1],"-is") )
useSocket = 1;
else if (strcmp(argv[1],"-ip")) {
errorfun();
usage();
}
RTDuplex *inout = new RTDuplex(SRATE,1);
@@ -85,21 +85,25 @@ void main(int argc,char *argv[])
score->parseThis(inputString[outOne]);
type = score->getType();
if (type > 0) {
if (type == __SK_NoteOn_ ) {
switch(type) {
case __SK_NoteOn_:
// check to see if velocity is zero ... really a NoteOff
if (( byte3 = score->getByteThree() ) == 0) { // NoteOff
envelope->setRate(0.001);
envelope->setTarget(0.0);
}
else { // Really a NoteOn
else { // really a NoteOn
envelope->setRate(0.001);
envelope->setTarget(1.0);
}
}
else if (type == __SK_NoteOff_) {
break;
case __SK_NoteOff_:
envelope->setRate(0.001);
envelope->setTarget(0.0);
}
else if (type == __SK_ControlChange_) {
break;
case __SK_ControlChange_:
j = (int) score->getByteTwo();
byte3 = score->getByteThree();
if (j == 20) effect = (int) byte3; // effect change
@@ -119,6 +123,7 @@ void main(int argc,char *argv[])
else if (j == 23) { // effect1 parameter change
chorus->setModDepth(byte3*NORM_7*0.2);
}
break;
}
}
outOne += 1;
@@ -156,4 +161,5 @@ void main(int argc,char *argv[])
delete envelope;
printf("effects finished ... goodbye.\n");
return 0;
}

View File

@@ -1,26 +1,28 @@
// Thread functions for use with syntmono.
//
// Gary P. Scavone, 1999.
// No mutexes are currently being used when accessing
// the global variables shared between these threads
// and the main() routine. In a single processor
// environment, no problems have resulted from such data
// sharing. However, if STK is to be run on a true parallel
// processing platform, it is likely that mutexes will be
// necessary. While the mutex calls are simple to code, I
// am trying to keep the code as generic as possible. A
// quick investigation of threads under Windoze indicates
// that mutex functionality is not available, at least with
// the standard libraries.
//
// Gary P. Scavone, 2000.
#include "threads.h"
#if defined(__STK_REALTIME_)
#define SERVICE_PORT 2001 // Socket Port ID number
// Default STK socket port ID number
#define SERVICE_PORT 2001
// Do OS dependent declarations and includes
#if defined(__OS_IRIX_)
#include <signal.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
pid_t string_thread;
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -39,13 +41,10 @@ unsigned long string_thread;
#endif
// The thread function definition protocols are slightly
// different under Irix, Linux, and Windoze.
#if defined(__OS_IRIX_)
// The thread function protocols are slightly different
// under Windoze ... but of course!
void newStringByPipe(void *)
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
void *newStringByPipe(void *)
@@ -86,14 +85,15 @@ void newStringByPipe(void *)
// Free inputString.
for ( i=0;i<MAX_IN_STRINGS;i++ ) free(inputString[i]);
free(inputString);
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
pthread_exit(NULL);
return NULL;
#elif defined(__OS_Win_)
_endthread();
#endif
}
#if defined(__OS_IRIX_)
void newStringBySocket(void *)
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
void *newStringBySocket(void *)
@@ -113,7 +113,7 @@ void newStringBySocket(void *)
fd_set mask, rmask;
struct sockaddr_in sockname;
char socBuf[STRING_LEN];
static struct timeval timeout = {0, 1000}; // one millisecond
static struct timeval timeout = {0, 10000}; // ten millisecond
// Malloc inputString.
inputString = (char **) malloc(MAX_IN_STRINGS * sizeof(char *));
@@ -163,6 +163,9 @@ void newStringBySocket(void *)
while (notDone) {
rmask = mask;
// Need to reset the timeout values because of linux "select" implementation
timeout.tv_sec = 0;
timeout.tv_usec = 10000; // 0.01 seconds
select(maxfd+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout);
if (FD_ISSET(soc_id,&rmask)) { // a new connection is available
// Accept and service the incoming connection request
@@ -232,18 +235,18 @@ void newStringBySocket(void *)
free(inputString);
printf("Socket connection closed.\n");
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
pthread_exit(NULL);
return NULL;
#elif defined(__OS_Win_)
_endthread();
#endif
}
void startPipeThread()
{
#if defined(__OS_IRIX_)
string_thread = sproc(newStringByPipe, PR_SALL);
if (string_thread == -1) {
fprintf(stderr, "unable to create input pipe thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
if (pthread_create(&string_thread, NULL, newStringByPipe, NULL)) {
fprintf(stderr, "unable to create input pipe thread ... aborting.\n");
exit(0);
@@ -259,13 +262,7 @@ void startPipeThread()
void startSocketThread()
{
#if defined(__OS_IRIX_)
string_thread = sproc(newStringBySocket, PR_SALL);
if (string_thread == -1) {
fprintf(stderr, "unable to create input socket thread...aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
if (pthread_create(&string_thread, NULL, newStringBySocket, NULL)) {
fprintf(stderr, "unable to create input socket thread...aborting.\n");
exit(0);

View File

@@ -6,12 +6,15 @@
#define STRING_LEN 60
/*
#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_) )
void newStringByPipe(void *);
void newStringBySocket(void *);
#elif (defined(__STK_REALTIME_) && defined(__OS_Linux_) )
*/
#if (defined(__STK_REALTIME_) && (defined(__OS_IRIX_) || defined(__OS_Linux_)))
void *newStringByPipe(void *);
void *newStringBySocket(void *);

View File

@@ -17,7 +17,7 @@ char **inputString;
#include "threads.h"
/* Error function in case of incorrect command-line argument specifications */
void errorf(char *func) {
void usage(char *func) {
printf("\nuseage: %s Instr flag\n",func);
printf(" where Instr = TwoOsc (only one available for now)\n");
printf(" and flag = -ip for realtime SKINI input by pipe\n");
@@ -26,19 +26,19 @@ void errorf(char *func) {
exit(0);
}
void main(int argc,char *argv[])
int main(int argc,char *argv[])
{
long i, j, synlength, useSocket = 0;
int type, rtInput = 0;
int type;
int outOne = 0;
MY_FLOAT settleTime = 0.5; /* in seconds */
MY_FLOAT temp, byte3, lastPitch;
if (argc == 3) {
if (strcmp(argv[1],"TwoOsc")) errorf(argv[0]);
if (strcmp(argv[1],"TwoOsc")) usage(argv[0]);
if (!strcmp(argv[2],"-is")) useSocket = 1;
else if (strcmp(argv[2],"-ip")) errorf(argv[0]);
} else errorf(argv[0]);
else if (strcmp(argv[2],"-ip")) usage(argv[0]);
} else usage(argv[0]);
TwoOsc *instrument = new TwoOsc;
WvOut *output = new RTWvOut(SRATE,1);
@@ -63,38 +63,40 @@ void main(int argc,char *argv[])
if (numStrings) {
score->parseThis(inputString[outOne]);
type = score->getType();
if (type > 0) {
if (type == __SK_NoteOn_ ) {
if (type > 0) {
switch(type) {
case __SK_NoteOn_:
// check to see if velocity is zero ... really a NoteOff
if (( byte3 = score->getByteThree() ) == 0)
instrument->noteOff(byte3*NORM_7);
else {
instrument->noteOff(0.0);
else { // really a NoteOn
j = (int) score->getByteTwo();
temp = __MIDI_To_Pitch[j];
lastPitch = temp;
instrument->noteOn(temp,byte3*NORM_7);
lastPitch = __MIDI_To_Pitch[j];
instrument->noteOn(lastPitch,byte3*NORM_7);
}
}
else if (type == __SK_NoteOff_) {
byte3 = score->getByteThree();
instrument->noteOff(byte3*NORM_7);
}
else if (type == __SK_ControlChange_) {
j = (int) score->getByteTwo();
byte3 = score->getByteThree();
instrument->controlChange(j,byte3);
}
else if (type == __SK_AfterTouch_) {
j = (int) score->getByteTwo();
instrument->controlChange(128,j);
}
else if (type == __SK_PitchBend_) {
break;
case __SK_NoteOff_:
instrument->noteOff(NORM_7*score->getByteThree());
break;
case __SK_ControlChange_:
instrument->controlChange((int)score->getByteTwo(),
score->getByteThree());
break;
case __SK_AfterTouch_:
instrument->controlChange(128,score->getByteTwo());
break;
case __SK_PitchBend_:
temp = score->getByteTwo();
j = (int) temp;
temp -= j;
temp -= j; // floating-point remainder
lastPitch = __MIDI_To_Pitch[j] * pow(2.0,temp / 12.0) ;
instrument->setFreq(1, lastPitch); /* change osc1 pitch for now */
}
else if (type == __SK_ProgramChange_) {
break;
}
}
outOne += 1;
@@ -102,6 +104,7 @@ void main(int argc,char *argv[])
numStrings--;
}
}
for (i=0;i<settleTime*SRATE;i++) { /* let the sound settle a little */
output->tick(instrument->tick());
}
@@ -111,4 +114,5 @@ void main(int argc,char *argv[])
delete instrument;
printf("MUS151 finished.\n");
return 0;
}

View File

@@ -26,7 +26,7 @@ RM = /bin/rm
ifeq ($(OS),IRIX) # These are for SGI
INSTR = MUS151
CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
LIBRARY = -L/usr/sgitcl/lib -laudio -lm -lpthread
endif
ifeq ($(OS),Linux) # These are for Linux

View File

@@ -102,7 +102,7 @@ bind . <Destroy> +myExit
proc myExit {} {
global outID
puts $outID [format "NoteOff 0.0 1 64 127" ]
puts $outID [format "NoteOff 0.0 1 64.0 127.0" ]
flush $outID
puts $outID [format "ExitProgram"]
flush $outID

View File

@@ -1,26 +1,28 @@
// Thread functions for use with syntmono.
//
// Gary P. Scavone, 1999.
// No mutexes are currently being used when accessing
// the global variables shared between these threads
// and the main() routine. In a single processor
// environment, no problems have resulted from such data
// sharing. However, if STK is to be run on a true parallel
// processing platform, it is likely that mutexes will be
// necessary. While the mutex calls are simple to code, I
// am trying to keep the code as generic as possible. A
// quick investigation of threads under Windoze indicates
// that mutex functionality is not available, at least with
// the standard libraries.
//
// Gary P. Scavone, 2000.
#include "threads.h"
#if defined(__STK_REALTIME_)
#define SERVICE_PORT 2001 // Socket Port ID number
// Default STK socket port ID number
#define SERVICE_PORT 2001
// Do OS dependent declarations and includes
#if defined(__OS_IRIX_)
#include <signal.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
pid_t string_thread;
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -39,13 +41,10 @@ unsigned long string_thread;
#endif
// The thread function definition protocols are slightly
// different under Irix, Linux, and Windoze.
#if defined(__OS_IRIX_)
// The thread function protocols are slightly different
// under Windoze ... but of course!
void newStringByPipe(void *)
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
void *newStringByPipe(void *)
@@ -86,14 +85,15 @@ void newStringByPipe(void *)
// Free inputString.
for ( i=0;i<MAX_IN_STRINGS;i++ ) free(inputString[i]);
free(inputString);
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
pthread_exit(NULL);
return NULL;
#elif defined(__OS_Win_)
_endthread();
#endif
}
#if defined(__OS_IRIX_)
void newStringBySocket(void *)
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
void *newStringBySocket(void *)
@@ -113,7 +113,7 @@ void newStringBySocket(void *)
fd_set mask, rmask;
struct sockaddr_in sockname;
char socBuf[STRING_LEN];
static struct timeval timeout = {0, 1000}; // one millisecond
static struct timeval timeout = {0, 10000}; // ten millisecond
// Malloc inputString.
inputString = (char **) malloc(MAX_IN_STRINGS * sizeof(char *));
@@ -163,6 +163,9 @@ void newStringBySocket(void *)
while (notDone) {
rmask = mask;
// Need to reset the timeout values because of linux "select" implementation
timeout.tv_sec = 0;
timeout.tv_usec = 10000; // 0.01 seconds
select(maxfd+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout);
if (FD_ISSET(soc_id,&rmask)) { // a new connection is available
// Accept and service the incoming connection request
@@ -232,18 +235,18 @@ void newStringBySocket(void *)
free(inputString);
printf("Socket connection closed.\n");
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
pthread_exit(NULL);
return NULL;
#elif defined(__OS_Win_)
_endthread();
#endif
}
void startPipeThread()
{
#if defined(__OS_IRIX_)
string_thread = sproc(newStringByPipe, PR_SALL);
if (string_thread == -1) {
fprintf(stderr, "unable to create input pipe thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
if (pthread_create(&string_thread, NULL, newStringByPipe, NULL)) {
fprintf(stderr, "unable to create input pipe thread ... aborting.\n");
exit(0);
@@ -259,13 +262,7 @@ void startPipeThread()
void startSocketThread()
{
#if defined(__OS_IRIX_)
string_thread = sproc(newStringBySocket, PR_SALL);
if (string_thread == -1) {
fprintf(stderr, "unable to create input socket thread...aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
if (pthread_create(&string_thread, NULL, newStringBySocket, NULL)) {
fprintf(stderr, "unable to create input socket thread...aborting.\n");
exit(0);

View File

@@ -6,12 +6,15 @@
#define STRING_LEN 60
/*
#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_) )
void newStringByPipe(void *);
void newStringBySocket(void *);
#elif (defined(__STK_REALTIME_) && defined(__OS_Linux_) )
*/
#if (defined(__STK_REALTIME_) && (defined(__OS_IRIX_) || defined(__OS_Linux_)))
void *newStringByPipe(void *);
void *newStringBySocket(void *);

1
ragamatic/GUIRaga Executable file
View File

@@ -0,0 +1 @@
wish < tcl/TCLRaga.tcl | ragamat -ip

70
ragamatic/Makefile Normal file
View File

@@ -0,0 +1,70 @@
# STK Makefile - Global version for Unix systems which have GNU
# Makefile utilities installed. If this Makefile does not work on
# your system, try using the platform specific Makefiles (.sgi,
# .next, and .linux).
OS = $(shell uname)
# The following definition indicates the relative location of
# the core STK classes.
STK_PATH = ../STK/
O_FILES = Object.o Envelope.o ADSR.o Noise.o \
Filter.o DLineA.o DLineL.o DLineN.o \
OnePole.o OneZero.o DCBlock.o SKINI11.o \
swapstuf.o Tabla.o Instrmnt.o Sitar1.o \
StrDrone.o VoicDrum.o WvOut.o WvIn.o RawWvIn.o \
RTSoundIO.o RTWvOut.o MIDIIO.o Reverb.o \
NRev.o JCRev.o PRCRev.o threads.o
RM = /bin/rm
ifeq ($(OS),IRIX) # These are for SGI
INSTR = ragamat MD2SKINI
CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread
endif
ifeq ($(OS),Linux) # These are for Linux
INSTR = ragamat MD2SKINI
CC = g++ -O3 -Wall -D__OS_Linux_ # -g
LIBRARY = -lpthread -lm
endif
%.o : $(STK_PATH)%.cpp
$(CC) -c $(<) -o $@
all: $(INSTR)
ragamat: ragamat.cpp $(O_FILES)
$(CC) $(INCLUDE) -o ragamat ragamat.cpp $(O_FILES) $(LIBRARY)
MD2SKINI: $(STK_PATH)MD2SKINI.cpp Object.o MIDIIO.o
$(CC) -o MD2SKINI $(STK_PATH)MD2SKINI.cpp Object.o MIDIIO.o $(LIBRARY)
clean :
rm *.o
rm $(INSTR)
cleanIns :
rm $(INSTR)
strip :
strip $(INSTR)
# $(O_FILES) :
threads.o: threads.cpp
$(CC) -c threads.cpp
Tabla.o: Tabla.cpp
$(CC) -c Tabla.cpp
Sitar1.o: Sitar1.cpp
$(CC) -c Sitar1.cpp
StrDrone.o: StrDrone.cpp
$(CC) -c StrDrone.cpp
VoicDrum.o: VoicDrum.cpp
$(CC) -c VoicDrum.cpp

23
ragamatic/README-raga.txt Normal file
View File

@@ -0,0 +1,23 @@
This is RagaMatic (tm).
by Perry Cook
Written for Ken Steiglitz's birthday, 1999.
Sitar and Drones are physical models.
Vocalize drums and Tabla drums are samples.
In the RagaMatic directory, type:
> make
to compile and then
> GUIRaga
to have fun and achieve inner peace.
If you ask me, I think this band needs a flute player too. If you like, team up and see if you can add the flute model to the project. This requires adding a few files to the Makefile, a few lines to the ragamat.cpp file (including how the flute player should play, etc.), and another slider to the TCL script to control the flute's contributions. This might only run on the fastest machines once you've added the flute.
Since latency isn't much of an issue in raga-land, you might bump up the RT_BUFFER_SIZE in Object.h to something around 1024, depending on the speed of your machine. If you don't have the GNU makefile utilities on your system, take a look at one of the system-specific makefiles (example: Makefile.sgi) in the syntmono directory to see what changes you need to make.
All is Bliss...
All is Bliss...

100
ragamatic/Sitar1.cpp Normal file
View File

@@ -0,0 +1,100 @@
/******************************************/
/* Karplus-Strong Sitar1 string model */
/* by Perry Cook, 1995-96 */
/* */
/* There exist at least two patents, */
/* assigned to Stanford, bearing the */
/* names of Karplus and/or Strong. */
/******************************************/
#include "Sitar1.h"
Sitar1 :: Sitar1(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
loopGain = (MY_FLOAT) 0.999;
loopFilt = new OneZero();
loopFilt->setCoeff(0.01);
delayLine = new DLineA(length);
delay = length/2;
delayTarg = delay;
envelope = new ADSR();
noise = new Noise;
envelope->setAllTimes(0.001,0.04,0.0,0.5);
this->clear();
}
Sitar1 :: ~Sitar1()
{
delete loopFilt;
delete delayLine;
delete envelope;
delete noise;
}
void Sitar1 :: clear()
{
loopFilt->clear();
delayLine->clear();
}
void Sitar1 :: setFreq(MY_FLOAT frequency)
{
delayTarg = (SRATE / frequency);
delay = delayTarg * (1.0 + (0.05 * noise->tick()));
delayLine->setDelay(delay);
loopGain = (MY_FLOAT) 0.995 + (frequency * (MY_FLOAT) 0.000001);
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.9995;
}
void Sitar1 :: pluck(MY_FLOAT amplitude)
{
envelope->keyOn();
}
void Sitar1 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->pluck(amp);
amPluck = 0.05 * amp;
#if defined(_debug_)
printf("Sitar1 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Sitar1 :: noteOff(MY_FLOAT amp)
{
loopGain = (MY_FLOAT) 1.0 - amp;
#if defined(_debug_)
printf("Sitar1 : NoteOff: Amp=%lf\n",amp);
#endif
}
MY_FLOAT Sitar1 :: tick()
{
MY_FLOAT temp;
temp = delayLine->lastOut();
if (fabs(temp) > 1.0) {
loopGain = 0.1;
this->noteOff(0.9);
delay = delayTarg;
delayLine->setDelay(delay);
}
temp *= loopGain;
if (fabs(delayTarg - delay) > 0.001) {
if (delayTarg < delay)
delay *= 0.99999;
else
delay *= 1.00001;
delayLine->setDelay(delay);
}
lastOutput = delayLine->tick(loopFilt->tick(temp)
+ (amPluck * envelope->tick() * noise->tick()));
return lastOutput;
}

43
ragamatic/Sitar1.h Normal file
View File

@@ -0,0 +1,43 @@
/******************************************/
/* Karplus-Strong Sitar1 string model */
/* by Perry Cook, 1995-96 */
/* */
/* There exist at least two patents, */
/* assigned to Stanford, bearing the */
/* names of Karplus and/or Strong. */
/******************************************/
#if !defined(__Sitar1_h)
#define __Sitar1_h
#include "../STK/Instrmnt.h"
#include "../STK/DLineA.h"
#include "../STK/OneZero.h"
#include "../STK/ADSR.h"
#include "../STK/Noise.h"
class Sitar1 : public Instrmnt
{
protected:
DLineA *delayLine;
OneZero *loopFilt;
ADSR *envelope;
Noise *noise;
long length;
MY_FLOAT loopGain;
MY_FLOAT amPluck;
MY_FLOAT delay;
MY_FLOAT delayTarg;
public:
Sitar1(MY_FLOAT lowestFreq);
~Sitar1();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void pluck(MY_FLOAT amplitude);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

77
ragamatic/StrDrone.cpp Normal file
View File

@@ -0,0 +1,77 @@
/******************************************/
/* Karplus-Strong StrDrone string model */
/* by Perry Cook, 1995-96 */
/* */
/* There exist at least two patents, */
/* assigned to Stanford, bearing the */
/* names of Karplus and/or Strong. */
/******************************************/
#include "StrDrone.h"
StrDrone :: StrDrone(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
loopGain = (MY_FLOAT) 0.999;
loopFilt = new OneZero();
delayLine = new DLineA(length);
envelope = new ADSR();
noise = new Noise;
envelope->setAllTimes(2.0,0.5,0.0,0.5);
this->clear();
}
StrDrone :: ~StrDrone()
{
delete loopFilt;
delete delayLine;
delete envelope;
delete noise;
}
void StrDrone :: clear()
{
loopFilt->clear();
delayLine->clear();
}
void StrDrone :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT delay;
delay = (SRATE / frequency);
delayLine->setDelay(delay - 0.5);
loopGain = (MY_FLOAT) 0.997 + (frequency * (MY_FLOAT) 0.000002);
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
}
void StrDrone :: pluck(MY_FLOAT amplitude)
{
envelope->keyOn();
}
void StrDrone :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->pluck(amp);
#if defined(_debug_)
printf("StrDrone : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void StrDrone :: noteOff(MY_FLOAT amp)
{
loopGain = (MY_FLOAT) 1.0 - amp;
#if defined(_debug_)
printf("StrDrone : NoteOff: Amp=%lf\n",amp);
#endif
}
MY_FLOAT StrDrone :: tick()
{
/* check this out */
/* here's the whole inner loop of the instrument!! */
lastOutput = delayLine->tick(loopFilt->tick((delayLine->lastOut() * loopGain))
+ (0.005 * envelope->tick() * noise->tick()));
return lastOutput;
}

40
ragamatic/StrDrone.h Normal file
View File

@@ -0,0 +1,40 @@
/******************************************/
/* Karplus-Strong StrDrone string model */
/* by Perry Cook, 1995-96 */
/* */
/* There exist at least two patents, */
/* assigned to Stanford, bearing the */
/* names of Karplus and/or Strong. */
/******************************************/
#if !defined(__StrDrone_h)
#define __StrDrone_h
#include "../STK/Instrmnt.h"
#include "../STK/DLineA.h"
#include "../STK/OneZero.h"
#include "../STK/ADSR.h"
#include "../STK/Noise.h"
class StrDrone : public Instrmnt
{
protected:
DLineA *delayLine;
ADSR *envelope;
Noise *noise;
OneZero *loopFilt;
long length;
MY_FLOAT loopGain;
public:
StrDrone(MY_FLOAT lowestFreq);
~StrDrone();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void pluck(MY_FLOAT amplitude);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

155
ragamatic/Tabla.cpp Normal file
View File

@@ -0,0 +1,155 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn objects, run through a bunch */
/* of one-pole filters. All the */
/* corresponding rawwave files have been */
/* sampled at 22050 Hz. Thus, if the */
/* compile-time SRATE = 22050, then */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#include "Tabla.h"
#include <string.h>
Tabla :: Tabla() : Instrmnt()
{
int i;
for (i=0;i<TABLA_POLYPHONY;i++) {
filters[i] = new OnePole;
sounding[i] = -1;
}
/* This counts the number of sounding voices */
numSounding = 0;
/* Print warning about aliasing if SRATE < 22050 */
if (SRATE < 22050) {
printf("\nWarning: Tabla is designed for sampling rates of\n");
printf("22050 Hz or greater. You will likely encounter aliasing\n");
printf("at the current sampling rate of %.0f Hz.\n\n", SRATE);
}
}
Tabla :: ~Tabla()
{
int i;
for ( i=0; i<numSounding-1; i++ ) delete waves[i];
for ( i=0; i<TABLA_POLYPHONY; i++ ) delete filters[i];
}
void Tabla :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
int i, notDone;
int noteNum;
int vel;
char tempString[64];
RawWvIn *tempWv;
OnePole *tempFilt;
char waveNames[TABLA_NUMWAVES][16] = {
"Drdak2.raw",
"Drdak3.raw",
"Drdak4.raw",
"Drddak1.raw",
"Drdee1.raw",
"Drdee2.raw",
"Drdoo1.raw",
"Drdoo2.raw",
"Drdoo3.raw",
"Drjun1.raw",
"Drjun2.raw",
"DrDoi1.raw",
"DrDoi2.raw",
"DrTak1.raw",
"DrTak2.raw"
};
noteNum = (int) freq;
vel = (int) (amp * 127);
#if defined(_debug_)
printf("NoteOn: %i vel=%i\n",noteNum,vel);
#endif
notDone = -1;
for (i=0;i<TABLA_POLYPHONY;i++) { /* Check first to see */
if (sounding[i] == noteNum) notDone = i; /* if there's already */
} /* one like this sounding */
if (notDone<0) { /* If not, then */
if (numSounding == TABLA_POLYPHONY) { /* If we're already */
delete waves[0]; /* at max polyphony, */
filters[0]->clear(); /* then */
tempWv = waves[0];
tempFilt = filters[0];
for (i=0;i<TABLA_POLYPHONY-1;i++) { /* preempt oldest */
waves[i] = waves[i+1]; /* voice and */
filters[i] = filters[i+1]; /* ripple all down */
}
waves[TABLA_POLYPHONY-1] = tempWv;
filters[TABLA_POLYPHONY-1] = tempFilt;
} else {
numSounding += 1; /* otherwise just add one */
}
sounding[numSounding-1] = noteNum; /* allocate new wave */
strcpy(tempString,"rawwaves/");
strcat(tempString,waveNames[noteNum]);
waves[numSounding-1] = new RawWvIn(tempString, "oneshot");
if (SRATE != 22050) {
waves[numSounding-1]->setRate((MY_FLOAT) (22050.0/SRATE));
}
waves[numSounding-1]->normalize((MY_FLOAT) 0.4);
filters[numSounding-1]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
filters[numSounding-1]->setGain(vel / (MY_FLOAT) 128.0);
}
else {
waves[notDone]->reset();
filters[notDone]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
filters[notDone]->setGain(vel / (MY_FLOAT) 128.0);
}
#if defined(_debug_)
printf("Number Sounding = %i\n",numSounding);
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
printf("\n");
#endif
}
MY_FLOAT Tabla :: tick()
{
int j, i = 0;
MY_FLOAT output = 0.0;
OnePole *tempFilt;
while (i < numSounding) {
output += filters[i]->tick(waves[i]->lastOut());
if (waves[i]->informTick() == 1) {
delete waves[i];
tempFilt = filters[i];
for (j=i;j<numSounding-1;j++) {
sounding[j] = sounding[j+1];
waves[j] = waves[j+1];
filters[j] = filters[j+1];
}
filters[j] = tempFilt;
filters[j]->clear();
sounding[j] = -1;
numSounding -= 1;
i -= 1;
}
i++;
}
return output;
}

46
ragamatic/Tabla.h Normal file
View File

@@ -0,0 +1,46 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn objects, run through a bunch */
/* of one-pole filters. All the */
/* corresponding rawwave files have been */
/* sampled at 22050 Hz. Thus, if the */
/* compile-time SRATE = 22050, then */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#if !defined(__Tabla_h)
#define __Tabla_h
#include "../STK/Instrmnt.h"
#include "../STK/RawWvIn.h"
#include "../STK/OnePole.h"
#define TABLA_NUMWAVES 15
#define TABLA_POLYPHONY 4
class Tabla : public Instrmnt
{
protected:
RawWvIn *waves[TABLA_POLYPHONY];
OnePole *filters[TABLA_POLYPHONY];
int sounding[TABLA_POLYPHONY];
int numSounding;
public:
Tabla();
~Tabla();
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

152
ragamatic/VoicDrum.cpp Normal file
View File

@@ -0,0 +1,152 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn objects, run through a bunch */
/* of one-pole filters. All the */
/* corresponding rawwave files have been */
/* sampled at 22050 Hz. Thus, if the */
/* compile-time SRATE = 22050, then */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#include "VoicDrum.h"
#include <string.h>
VoicDrum :: VoicDrum() : Instrmnt()
{
int i;
for (i=0;i<DRUM_POLYPHONY;i++) {
filters[i] = new OnePole;
sounding[i] = -1;
}
/* This counts the number of sounding voices */
numSounding = 0;
/* Print warning about aliasing if SRATE < 22050 */
if (SRATE < 22050) {
printf("\nWarning: VoicDrum is designed for sampling rates of\n");
printf("22050 Hz or greater. You will likely encounter aliasing\n");
printf("at the current sampling rate of %.0f Hz.\n\n", SRATE);
}
}
VoicDrum :: ~VoicDrum()
{
int i;
for ( i=0; i<numSounding-1; i++ ) delete waves[i];
for ( i=0; i<DRUM_POLYPHONY; i++ ) delete filters[i];
}
void VoicDrum :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
int i, notDone;
int noteNum;
int vel;
char tempString[64];
RawWvIn *tempWv;
OnePole *tempFilt;
char waveNames[DRUM_NUMWAVES][16] = {
"tak2.raw",
"tak1.raw",
"bee1.raw",
"dee1.raw",
"dee2.raw",
"din1.raw",
"gun1.raw",
"jun1.raw",
"jun2.raw",
"tak3.raw",
"tak4.raw"
};
/* Yes I know, this is tres kludgey */
noteNum = (int)freq;
vel = (int) (amp * 127);
#if defined(_debug_)
printf("NoteOn: %i vel=%i\n",noteNum,vel);
#endif
notDone = -1;
for (i=0;i<DRUM_POLYPHONY;i++) { /* Check first to see */
if (sounding[i] == noteNum) notDone = i; /* if there's already */
} /* one like this sounding */
if (notDone<0) { /* If not, then */
if (numSounding == DRUM_POLYPHONY) { /* If we're already */
delete waves[0]; /* at max polyphony, */
filters[0]->clear(); /* then */
tempWv = waves[0];
tempFilt = filters[0];
for (i=0;i<DRUM_POLYPHONY-1;i++) { /* preempt oldest */
waves[i] = waves[i+1]; /* voice and */
filters[i] = filters[i+1]; /* ripple all down */
}
waves[DRUM_POLYPHONY-1] = tempWv;
filters[DRUM_POLYPHONY-1] = tempFilt;
} else {
numSounding += 1; /* otherwise just add one */
}
sounding[numSounding-1] = noteNum; /* allocate new wave */
strcpy(tempString,"rawwaves/");
strcat(tempString,waveNames[noteNum]);
waves[numSounding-1] = new RawWvIn(tempString, "oneshot");
if (SRATE != 22050) {
waves[numSounding-1]->setRate((MY_FLOAT) (22050.0/SRATE));
}
waves[numSounding-1]->normalize((MY_FLOAT) 0.4);
filters[numSounding-1]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
filters[numSounding-1]->setGain(vel / (MY_FLOAT) 128.0);
}
else {
waves[notDone]->reset();
filters[notDone]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
filters[notDone]->setGain(vel / (MY_FLOAT) 128.0);
}
#if defined(_debug_)
printf("Number Sounding = %i\n",numSounding);
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
printf("\n");
#endif
}
MY_FLOAT VoicDrum :: tick()
{
int j, i = 0;
MY_FLOAT output = 0.0;
OnePole *tempFilt;
while (i < numSounding) {
output += filters[i]->tick(waves[i]->lastOut());
if (waves[i]->informTick() == 1) {
delete waves[i];
tempFilt = filters[i];
for (j=i;j<numSounding-1;j++) {
sounding[j] = sounding[j+1];
waves[j] = waves[j+1];
filters[j] = filters[j+1];
}
filters[j] = tempFilt;
filters[j]->clear();
sounding[j] = -1;
numSounding -= 1;
i -= 1;
}
i++;
}
return output;
}

46
ragamatic/VoicDrum.h Normal file
View File

@@ -0,0 +1,46 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn objects, run through a bunch */
/* of one-pole filters. All the */
/* corresponding rawwave files have been */
/* sampled at 22050 Hz. Thus, if the */
/* compile-time SRATE = 22050, then */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#if !defined(__VoicDrum_h)
#define __VoicDrum_h
#include "../STK/Instrmnt.h"
#include "../STK/RawWvIn.h"
#include "../STK/OnePole.h"
#define DRUM_NUMWAVES 11
#define DRUM_POLYPHONY 4
class VoicDrum : public Instrmnt
{
protected:
RawWvIn *waves[DRUM_POLYPHONY];
OnePole *filters[DRUM_POLYPHONY];
int sounding[DRUM_POLYPHONY];
int numSounding;
public:
VoicDrum();
~VoicDrum();
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

19
ragamatic/miditabl.h Normal file
View File

@@ -0,0 +1,19 @@
#include "../STK/Object.h"
double __MIDI_To_Pitch[128] = {
8.18,8.66,9.18,9.72,10.30,10.91,11.56,12.25,
12.98,13.75,14.57,15.43,16.35,17.32,18.35,19.45,
20.60,21.83,23.12,24.50,25.96,27.50,29.14,30.87,
32.70,34.65,36.71,38.89,41.20,43.65,46.25,49.00,
51.91,55.00,58.27,61.74,65.41,69.30,73.42,77.78,
82.41,87.31,92.50,98.00,103.83,110.00,116.54,123.47,
130.81,138.59,146.83,155.56,164.81,174.61,185.00,196.00,
207.65,220.00,233.08,246.94,261.63,277.18,293.66,311.13,
329.63,349.23,369.99,392.00,415.30,440.00,466.16,493.88,
523.25,554.37,587.33,622.25,659.26,698.46,739.99,783.99,
830.61,880.00,932.33,987.77,1046.50,1108.73,1174.66,1244.51,
1318.51,1396.91,1479.98,1567.98,1661.22,1760.00,1864.66,1975.53,
2093.00,2217.46,2349.32,2489.02,2637.02,2793.83,2959.96,3135.96,
3322.44,3520.00,3729.31,3951.07,4186.01,4434.92,4698.64,4978.03,
5274.04,5587.65,5919.91,6271.93,6644.88,7040.00,7458.62,7902.13,
8372.02,8869.84,9397.27,9956.06,10548.08,11175.30,11839.82,12543.85};

262
ragamatic/ragamat.cpp Normal file
View File

@@ -0,0 +1,262 @@
/************** Test Main Program Individual Voice *********************/
#include "../STK/WvOut.h"
#include "../STK/RTWvOut.h"
#include "../STK/SKINI11.h"
#include "../STK/SKINI11.msg"
#include "../STK/Instrmnt.h"
#include "../STK/Reverb.h"
#include "../STK/NRev.h"
#include "../STK/PRCRev.h"
#include "../STK/JCRev.h"
#include "StrDrone.h"
#include "Sitar1.h"
#include "Tabla.h"
#include "VoicDrum.h"
#include "miditabl.h"
#define RATE_NORM (MY_FLOAT) (22050.0/SRATE)
int numStrings = 0;
int notDone = 1;
char **inputString;
// The input command pipe and socket threads are defined in threads.cpp.
#include "threads.h"
// Return random float between 0.0 and max
MY_FLOAT float_random(MY_FLOAT max) {
MY_FLOAT temp;
#if defined(__OS_Win_) /* For Windoze */
temp = (MY_FLOAT) (rand() * max);
temp *= ONE_OVER_RANDLIMIT;
#else /* This is for unix */
temp = (MY_FLOAT) (random() * max);
temp *= ONE_OVER_RANDLIMIT;
#endif
return temp;
}
void usage(void) {
/* Error function in case of incorrect command-line argument specifications */
printf("\nuseage: ragamat flag \n");
printf(" where flag = -ip for realtime SKINI input by pipe\n");
printf(" (won't work under Win95/98),\n");
printf(" and flag = -is for realtime SKINI input by socket.\n");
exit(0);
}
int main(int argc,char *argv[])
{
long i, j, synlength;
int type, outOne = 0, useSocket = 0;
MY_FLOAT reverbTime = 5.0; /* in seconds */
MY_FLOAT byte3, outSample, temp;
MY_FLOAT drone_prob = 0.01, note_prob = 0.0;
MY_FLOAT drum_prob = 0.0, voic_prob = 0.0;
MY_FLOAT droneFreqs[3] = {55.0,82.5,220.0};
int tempo = 3000;
int counter = 3000;
int key = 0;
int ragaStep, ragaPoint = 6, voicNote;
int ragaUp[2][13] = {{57, 60, 62, 64, 65, 68, 69, 71, 72, 76, 77, 81},
{52, 54, 55, 57, 59, 60, 63, 64, 66, 67, 71, 72}};
int ragaDown[2][13] = {{57, 60, 62, 64, 65, 67, 69, 71, 72, 76, 79, 81},
{48, 52, 53, 55, 57, 59, 60, 64, 66, 68, 70, 72}};
WvOut *output;
Instrmnt *drones[3];
Instrmnt *sitar;
Instrmnt *voicDrums;
Instrmnt *drums;
Reverb *reverbs[2];
SKINI11 *score;
if (argc != 2) usage();
if (!strcmp(argv[1],"-is") )
useSocket = 1;
else if (strcmp(argv[1],"-ip")) {
usage();
}
output = new RTWvOut(SRATE,1);
drones[0] = new StrDrone(50.0);
drones[1] = new StrDrone(50.0);
drones[2] = new StrDrone(50.0);
sitar = new Sitar1(50.0);
voicDrums = new VoicDrum();
drums = new Tabla();
score = new SKINI11();
reverbs[0] = new JCRev(reverbTime);
reverbs[0]->setEffectMix(0.5);
reverbs[1] = new JCRev(2.0);
reverbs[1]->setEffectMix(0.2);
// Start the input thread
if (useSocket)
startSocketThread();
else
startPipeThread();
drones[0]->noteOn(droneFreqs[0],0.1);
drones[1]->noteOn(droneFreqs[1],0.1);
drones[2]->noteOn(droneFreqs[2],0.1);
for (i=0;i<SRATE;i++) { /* warm everybody up a little */
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
output->tick(reverbs[0]->tick(outSample));
}
/* Finally ... the runtime loop begins! */
notDone = 1;
synlength = RT_BUFFER_SIZE;
while(notDone || numStrings) {
if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings;
else synlength = RT_BUFFER_SIZE;
for ( i=0; i<synlength; i++ ) {
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
outSample -= sitar->tick();
output->tick(reverbs[0]->tick(outSample)
+ reverbs[1]->tick(voicDrums->tick() + drums->tick()));
counter -= 1;
if (counter == 0) {
counter = (int) (tempo / RATE_NORM);
if (float_random(1.0) < drone_prob)
drones[0]->noteOn(droneFreqs[0],0.1);
if (float_random(1.0) < drone_prob)
drones[1]->noteOn(droneFreqs[1],0.1);
if (float_random(1.0) < drone_prob)
drones[2]->noteOn(droneFreqs[2],0.1);
if (float_random(1.0) < note_prob) {
if ((temp = float_random(1.0)) < 0.1)
ragaStep = 0;
else if (temp < 0.5)
ragaStep = 1;
else
ragaStep = -1;
ragaPoint += ragaStep;
if (ragaPoint < 0)
ragaPoint -= (2*ragaStep);
if (ragaPoint > 11)
ragaPoint = 11;
if (ragaStep > 0)
sitar->noteOn(__MIDI_To_Pitch[ragaUp[key][ragaPoint]]
,0.05 + float_random(0.3));
else
sitar->noteOn(__MIDI_To_Pitch[ragaDown[key][ragaPoint]]
,0.05 + float_random(0.3));
}
if (float_random(1.0) < voic_prob) {
voicNote = (int) float_random(11);
voicDrums->noteOn(voicNote,0.3 + (0.4 * drum_prob) +
float_random(0.9 * voic_prob));
}
if (float_random(1.0) < drum_prob) {
voicNote = (int) float_random(TABLA_NUMWAVES);
drums->noteOn(voicNote,0.2 + (0.2 * drum_prob) +
float_random(0.7 * drum_prob));
}
}
}
if (numStrings) {
score->parseThis(inputString[outOne]);
type = score->getType();
if (type > 0) {
if (type == __SK_ControlChange_) {
j = (int) score->getByteTwo();
byte3 = score->getByteThree();
if (j == 1) {
drone_prob = byte3 * NORM_7;
}
else if (j == 2) {
note_prob = byte3 * NORM_7;
}
else if (j == 4) {
voic_prob = byte3 * NORM_7;
}
else if (j == 11) {
drum_prob = byte3 * NORM_7;
}
else if (j == 7) {
tempo = (int) (11025 - (byte3 * 70));
}
else if (j == 64) {
if (byte3 == 0) {
key = 1;
droneFreqs[0] = 55.0;
droneFreqs[1] = 82.5;
droneFreqs[2] = 220.0;
}
else {
key = 0;
droneFreqs[0] = 82.5;
droneFreqs[1] = 123.5;
droneFreqs[2] = 330.0;
}
}
}
}
outOne += 1;
if (outOne == MAX_IN_STRINGS) outOne = 0;
numStrings--;
}
}
printf("What Need Have I for This?\n");
drones[1]->noteOn(droneFreqs[1],0.1);
for (i=0;i<reverbTime*SRATE;i++) { // Calm down a little
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
output->tick(reverbs[0]->tick(outSample));
}
printf("What Need Have I for This?\n");
drones[2]->noteOn(droneFreqs[2],0.1);
for (i=0;i<reverbTime*SRATE;i++) { // and a little more
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
output->tick(reverbs[0]->tick(outSample));
}
printf("RagaMatic finished ... \n");
drones[0]->noteOn(droneFreqs[0],0.1);
for (i=0;i<reverbTime*SRATE;i++) { // almost ready to think about ending
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
output->tick(reverbs[0]->tick(outSample));
}
printf("All is Bliss ...\n");
for (i=0;i<reverbTime*SRATE;i++) { // nearly finished now
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
output->tick(reverbs[0]->tick(outSample));
}
printf("All is Bliss ...\n");
for (i=0;i<reverbTime*SRATE;i++) { // all is bliss....
outSample = 0;
for (j=0;j<3;j++)
outSample += drones[j]->tick();
output->tick(reverbs[0]->tick(outSample));
}
delete output;
delete score;
delete drones[0];
delete drones[1];
delete drones[2];
delete sitar;
delete drums;
delete voicDrums;
delete reverbs[0];
delete reverbs[1];
return 0;
}

306
ragamatic/ragamat.dsp Executable file
View File

@@ -0,0 +1,306 @@
# Microsoft Developer Studio Project File - Name="ragamatic" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=ragamatic - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ragamat.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ragamat.mak" CFG="ragamatic - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ragamatic - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ragamatic - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "ragamatic - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib dsound.lib winmm.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "ragamatic - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib dsound.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "ragamatic - Win32 Release"
# Name "ragamatic - Win32 Debug"
# Begin Source File
SOURCE=..\Stk\ADSR.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\ADSR.h
# End Source File
# Begin Source File
SOURCE=..\Stk\DLineA.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\DLineA.h
# End Source File
# Begin Source File
SOURCE=..\Stk\DLineL.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\DLineL.h
# End Source File
# Begin Source File
SOURCE=..\Stk\DLineN.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\DLineN.h
# End Source File
# Begin Source File
SOURCE=..\Stk\Envelope.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\Envelope.h
# End Source File
# Begin Source File
SOURCE=..\Stk\Filter.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\Filter.h
# End Source File
# Begin Source File
SOURCE=..\Stk\Instrmnt.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\Instrmnt.h
# End Source File
# Begin Source File
SOURCE=..\Stk\JCRev.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\JCRev.h
# End Source File
# Begin Source File
SOURCE=..\Stk\Noise.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\Noise.h
# End Source File
# Begin Source File
SOURCE=..\Stk\NRev.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\NRev.h
# End Source File
# Begin Source File
SOURCE=..\Stk\Object.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\Object.h
# End Source File
# Begin Source File
SOURCE=..\Stk\OnePole.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\OnePole.h
# End Source File
# Begin Source File
SOURCE=..\Stk\OneZero.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\OneZero.h
# End Source File
# Begin Source File
SOURCE=..\Stk\PRCRev.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\PRCRev.h
# End Source File
# Begin Source File
SOURCE=.\ragamat.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\RawWvIn.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\RawWvIn.h
# End Source File
# Begin Source File
SOURCE=..\Stk\Reverb.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\Reverb.h
# End Source File
# Begin Source File
SOURCE=..\Stk\RTSoundIO.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\RTSoundIO.h
# End Source File
# Begin Source File
SOURCE=..\Stk\RTWvOut.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\RTWvOut.h
# End Source File
# Begin Source File
SOURCE=.\Sitar1.cpp
# End Source File
# Begin Source File
SOURCE=.\Sitar1.h
# End Source File
# Begin Source File
SOURCE=..\Stk\SKINI11.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\SKINI11.h
# End Source File
# Begin Source File
SOURCE=.\StrDrone.cpp
# End Source File
# Begin Source File
SOURCE=.\StrDrone.h
# End Source File
# Begin Source File
SOURCE=..\Stk\swapstuf.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\swapstuf.h
# End Source File
# Begin Source File
SOURCE=.\Tabla.cpp
# End Source File
# Begin Source File
SOURCE=.\Tabla.h
# End Source File
# Begin Source File
SOURCE=.\threads.cpp
# End Source File
# Begin Source File
SOURCE=.\threads.h
# End Source File
# Begin Source File
SOURCE=.\VoicDrum.cpp
# End Source File
# Begin Source File
SOURCE=.\VoicDrum.h
# End Source File
# Begin Source File
SOURCE=..\Stk\WvIn.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\WvIn.h
# End Source File
# Begin Source File
SOURCE=..\Stk\WvOut.cpp
# End Source File
# Begin Source File
SOURCE=..\Stk\WvOut.h
# End Source File
# End Target
# End Project

53
ragamatic/ragamat.plg Executable file
View File

@@ -0,0 +1,53 @@
--------------------Configuration: ragamatic - Win32 Release--------------------
Begining build with project "C:\gary\STKRelease\ragamatic\ragamat.dsp", at root.
Active configuration is Win32 (x86) Console Application (based on Win32 (x86) Console Application)
Project's tools are:
"32-bit C/C++ Compiler for 80x86" with flags "/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /Fp"Release/ragamat.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c "
"Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" "
"Browser Database Maker" with flags "/nologo /o"ragamat.bsc" "
"COFF Linker for 80x86" with flags "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib dsound.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:"ragamat.pdb" /machine:I386 /out:"ragamat.exe" "
"Custom Build" with flags ""
"<Component 0xa>" with flags ""
Creating temp file "C:\WINDOWS\TEMP\RSP53A0.TMP" with contents </nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /Fp"Release/ragamat.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c
"C:\gary\STKRelease\Stk\RTWvOut.cpp"
>
Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP53A0.TMP"
Creating temp file "C:\WINDOWS\TEMP\RSP53A1.TMP" with contents <kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib dsound.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:"ragamat.pdb" /machine:I386 /out:"ragamat.exe"
.\Release\Sitar1.obj
.\Release\StrDrone.obj
.\Release\Tabla.obj
.\Release\threads.obj
.\Release\VoicDrum.obj
.\Release\ragamat.obj
.\Release\DLineA.obj
.\Release\DLineL.obj
.\Release\DLineN.obj
.\Release\Envelope.obj
.\Release\Filter.obj
.\Release\Instrmnt.obj
.\Release\JCRev.obj
.\Release\Noise.obj
.\Release\NRev.obj
.\Release\Object.obj
.\Release\OnePole.obj
.\Release\OneZero.obj
.\Release\PRCRev.obj
.\Release\RawWvIn.obj
.\Release\Reverb.obj
.\Release\RTSoundIO.obj
.\Release\SKINI11.obj
.\Release\swapstuf.obj
.\Release\WvIn.obj
.\Release\ADSR.obj
.\Release\WvOut.obj
.\Release\RTWvOut.obj>
Creating command line "link.exe @C:\WINDOWS\TEMP\RSP53A1.TMP"
Compiling...
RTWvOut.cpp
Linking...
ragamat.exe - 0 error(s), 0 warning(s)

29
ragamatic/ragamatic.dsw Executable file
View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 5.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "ragamatic"=.\ragamatic.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ragamatic/rawwaves/ahh.raw Normal file

Binary file not shown.

Binary file not shown.

BIN
ragamatic/rawwaves/bee1.raw Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ragamatic/rawwaves/dee1.raw Normal file

Binary file not shown.

BIN
ragamatic/rawwaves/dee2.raw Normal file

Binary file not shown.

BIN
ragamatic/rawwaves/din1.raw Normal file

Binary file not shown.

Binary file not shown.

BIN
ragamatic/rawwaves/gun1.raw Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ragamatic/rawwaves/jun1.raw Normal file

Binary file not shown.

BIN
ragamatic/rawwaves/jun2.raw Normal file

Binary file not shown.

View File

@@ -0,0 +1,55 @@
/**********************************************/
/** Utility to make various functions **/
/** like exponential and log gain curves. **/
/** **/
/** Included here: **/
/** Yamaha TX81Z curves for master gain, **/
/** Envelope Rates (in normalized units), **/
/** envelope sustain level, and more.... **/
/**********************************************/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
int i,j;
double temp;
double data[128];
/*************** TX81Z Master Gain *************/
for (i=0;i<100;i++) {
data[i] = pow(2.0,-(99-i)/10.0);
}
data[0] = 0.0;
printf("double __FM4Op_gains[99] = {");
for (i=0;i<100;i++) {
if (i%8 == 0) printf("\n");
printf("%lf,",data[i]);
}
printf("};\n");
/*************** TX81Z Sustain Level ***********/
for (i=0;i<16;i++) {
data[i] = pow(2.0,-(15-i)/2.0);
}
data[0] = 0.0;
printf("double __FM4Op_susLevels[16] = {");
for (i=0;i<16;i++) {
if (i%8 == 0) printf("\n");
printf("%lf,",data[i]);
}
printf("};\n");
/****************** Attack Rate ***************/
for (i=0;i<32;i++) {
data[i] = 6.0 * pow(5.7,-(i-1)/5.0);
}
printf("double __FM4Op_attTimes[16] = {");
for (i=0;i<32;i++) {
if (i%8 == 0) printf("\n");
printf("%lf,",data[i]);
}
printf("};\n");
exit(1);
}

View File

@@ -0,0 +1,33 @@
/**********************************************/
/** Utility to make various functions **/
/** like exponential and log gain curves. **/
/** Specifically for direct MIDI parameter **/
/** conversions. **/
/** Included here: **/
/** A440 Referenced Equal Tempered Pitches **/
/** as a function of MIDI note number. **/
/** **/
/**********************************************/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
int i,j;
double temp;
double data[128];
/********* Pitch as fn. of MIDI Note **********/
printf("double __MIDI_To_Pitch[128] = {");
for (i=0;i<128;i++) {
if (i%8 == 0) printf("\n");
temp = 220.0 * pow(2.0,((double) i - 57) / 12.0);
printf("%.2lf,",temp);
}
printf("};\n");
exit(1);
}

View File

@@ -0,0 +1,116 @@
/**********************************************/
/** Utility to make various flavors of **/
/** sine wave (rectified, etc), and **/
/** other commonly needed waveforms, like **/
/** triangles, ramps, etc. **/
/** The files generated are all 16 bit **/
/** linear signed integer, of length **/
/** as defined by LENGTH below **/
/**********************************************/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 256
#define PI 3.14159265358979323846
void main()
{
int i,j;
double temp;
short data[LENGTH + 2];
FILE *fd;
/////////// Yer Basic TX81Z Waves, Including Sine ///////////
fd = fopen("halfwave.raw","wb");
for (i=0;i<LENGTH/2;i++)
data[i] = 32767 * sin(i * 2 * PI / (double) LENGTH);
for (i=LENGTH/2;i<LENGTH;i++)
data[i] = 0;
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("sinewave.raw","wb");
for (i=LENGTH/2;i<LENGTH;i++)
data[i] = 32767 * sin(i * 2 * PI / (double) LENGTH);
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("sineblnk.raw","wb");
for (i=0;i<LENGTH/2;i++)
data[i] = data[2*i];
for (i=LENGTH/2;i<LENGTH;i++)
data[i] = 0;
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("fwavblnk.raw","wb");
for (i=0;i<LENGTH/4;i++)
data[i+LENGTH/4] = data[i];
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("snglpeak.raw","wb");
for (i=0;i<=LENGTH/4;i++)
data[i] = 32767 * (1.0 - cos(i * 2 * PI / (double) LENGTH));
for (i=0;i<=LENGTH/4;i++)
data[LENGTH/2-i] = data[i];
for (i=LENGTH/2;i<LENGTH;i++)
data[i] = 0;
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("twopeaks.raw","wb");
for (i=0;i<=LENGTH/2;i++) {
data[LENGTH/2+i] = -data[i];
}
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("peksblnk.raw","wb");
for (i=0;i<=LENGTH/2;i++)
data[i] = data[i*2];
for (i=LENGTH/2;i<LENGTH;i++)
data[i] = 0;
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("ppksblnk.raw","wb");
for (i=0;i<=LENGTH/4;i++)
data[i+LENGTH/4] = data[i];
fwrite(&data,2,LENGTH,fd);
fclose(fd);
/////////// Impulses of various bandwidth ///////////
fd = fopen("impuls10.raw","wb");
for (i=0;i<LENGTH;i++) {
temp = 0.0;
for (j=1;j<=10;j++)
temp += cos(i * j * 2 * PI / (double) LENGTH);
data[i] = 32767 / 10.0 * temp;
}
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("impuls20.raw","wb");
for (i=0;i<LENGTH;i++) {
temp = 0.0;
for (j=1;j<=20;j++)
temp += cos(i * j * 2 * PI / (double) LENGTH);
data[i] = 32767 / 20.0 * temp;
}
fwrite(&data,2,LENGTH,fd);
fclose(fd);
fd = fopen("impuls40.raw","wb");
for (i=0;i<LENGTH;i++) {
temp = 0.0;
for (j=1;j<=40;j++)
temp += cos(i * j * 2 * PI / (double) LENGTH);
data[i] = 32767 / 40.0 * temp;
}
fwrite(&data,2,LENGTH,fd);
fclose(fd);
}

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More