Version 3.1

This commit is contained in:
Gary Scavone
2013-09-25 14:44:17 +02:00
committed by Stephen Sinclair
parent 868787a5f9
commit 4b6500d3de
140 changed files with 5171 additions and 632 deletions

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