Version 4.2.0

This commit is contained in:
Gary Scavone
2009-03-24 23:02:14 -04:00
committed by Stephen Sinclair
parent cf06b7598b
commit a6381b9d38
281 changed files with 17152 additions and 12000 deletions

1
projects/demo/Drums Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Drums.tcl | ./demo Drummer -or -ip

View File

@@ -6,14 +6,14 @@ SRC_PATH = ../../src
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
OBJECTS = Stk.o Noise.o SubNoise.o Envelope.o ADSR.o \
OBJECTS = Stk.o Generator.o Noise.o SubNoise.o Envelope.o ADSR.o \
Modulate.o SingWave.o \
WvIn.o WaveLoop.o WvOut.o \
Filter.o OneZero.o OnePole.o PoleZero.o TwoZero.o \
BiQuad.o FormSwep.o Delay.o DelayL.o DelayA.o \
ReedTabl.o JetTabl.o BowTabl.o \
Reverb.o PRCRev.o \
Modulate.o SingWave.o Voicer.o \
Vector3D.o Sphere.o \
Function.o ReedTable.o JetTable.o BowTable.o \
Effect.o PRCRev.o \
Voicer.o Vector3D.o Sphere.o \
\
Instrmnt.o Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
Bowed.o Plucked.o StifKarp.o Sitar.o PluckTwo.o Mandolin.o Mesh2D.o \
@@ -21,7 +21,7 @@ OBJECTS = Stk.o Noise.o SubNoise.o Envelope.o ADSR.o \
Sampler.o Moog.o Simple.o Drummer.o Shakers.o \
Modal.o ModalBar.o BandedWG.o Resonate.o VoicForm.o Phonemes.o Whistle.o \
\
Messager.o SKINI.o utilities.o
Messager.o Skini.o utilities.o
INCLUDE = @include@
ifeq ($(strip $(INCLUDE)), )
@@ -39,9 +39,8 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
OBJECTS += RtMidi.o RtAudio.o RtWvOut.o Thread.o Socket.o
OBJECTS += RtMidi.o RtAudio.o Thread.o Mutex.o Socket.o
DEFS += @audio_apis@
DEFS += @midiator@
endif
RAWWAVES = @rawwaves@
@@ -58,8 +57,14 @@ all : $(PROGRAMS)
demo: demo.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o demo demo.cpp $(OBJECT_PATH)/*.o $(LIBRARY)
Md2Skini: Md2Skini.cpp Stk.o RtMidi.o Thread.o Socket.o
$(CC) $(CFLAGS) $(DEFS) -o Md2Skini Md2Skini.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Socket.o $(LIBRARY)
libdemo: demo.cpp
$(CC) $(CFLAGS) $(DEFS) -o demo utilities.cpp demo.cpp -L../../src $(LIBRARY) -lstk
Md2Skini: Md2Skini.cpp Stk.o RtMidi.o
$(CC) $(CFLAGS) $(DEFS) -o Md2Skini Md2Skini.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
libMd2Skini: Md2Skini.cpp
$(CC) $(CFLAGS) $(DEFS) -o Md2Skini Md2Skini.cpp -L../../src $(LIBRARY) -lstk
$(OBJECTS) : Stk.h

View File

@@ -6,71 +6,171 @@
(via the RtMidi class), parses it, and turns it
into SKINI messages.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "RtMidi.h"
#include "Thread.h"
#include "Socket.h"
#include "SKINI.msg"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Exit thread declaration.
extern "C" THREAD_RETURN THREAD_TYPE stdinMonitor(void * ptr);
#include <iostream>
#include <string>
void usage(void) {
printf("\nuseage: 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");
printf(" With flag = -s <hostname>, the output is sent over a socket\n");
printf(" connection (port 2001) to the optional hostname (default = localhost).\n");
printf(" With flag = -f <filename>, the output stream is simultaneously\n");
printf(" written to the file specified by the optional <filename>\n");
printf(" (default = test.ski).\n\n");
std::cout << "\nuseage: Md2Skini <flag(s)>\n\n";
std::cout << " With no arguments, Md2Skini converts MIDI input to SKINI\n";
std::cout << " format and sends the output directly to stdout.\n";
std::cout << " With flag = -f <filename>, the output stream is simultaneously\n";
std::cout << " written to the file specified by the optional <filename>\n";
std::cout << " (default = test.ski).\n";
std::cout << " A MIDI input port can be specified with flag = -p portNumber.\n" << std::endl;
exit(0);
}
int main(int argc,char *argv[])
void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *userData )
{
bool done = false, firstMessage = true, writeFile = false, useSocket = false;
FILE *file = NULL;
char fileName[256];
char hostName[128];
RtMidi *rtmidi = 0;
Socket *soket = 0;
Thread *thread = 0;
if ( bytes->size() < 2 ) return;
if ( argc>5 ) {
usage();
// Parse the MIDI bytes ... only keep MIDI channel messages.
if ( bytes->at(0) > 239 ) return;
register long type = bytes->at(0) & 0xF0;
register long channel = bytes->at(0) & 0x0F;
register long databyte1 = bytes->at(1);
register long databyte2 = 0;
if ( ( type != 0xC0 ) && ( type != 0xD0 ) ) {
if ( bytes->size() < 3 ) return;
databyte2 = bytes->at(2);
}
std::string typeName;
switch( type ) {
case __SK_NoteOn_:
if ( databyte2 == 0 ) {
typeName = "NoteOff\t\t";
databyte2 = 64;
}
else typeName = "NoteOn\t\t";
break;
case __SK_NoteOff_:
typeName = "NoteOff\t\t";
break;
case __SK_PolyPressure_:
typeName = "PolyPressure\t";
break;
case __SK_ProgramChange_:
typeName = "ProgramChange\t";
break;
case __SK_ChannelPressure_:
typeName = "ChannelPressure\t";
break;
case __SK_PitchBend_:
typeName = "PitchBend\t";
break;
case __SK_ControlChange_:
switch( databyte1 ) {
case __SK_PitchChange_:
typeName = "PitchChange\t";
break;
case __SK_Volume_:
typeName = "Volume\t";
break;
case __SK_ModWheel_:
typeName = "ModWheel\t";
break;
case __SK_Breath_:
typeName = "Breath\t\t";
break;
case __SK_FootControl_:
typeName = "FootControl\t";
break;
case __SK_Portamento_:
typeName = "Portamento\t";
break;
case __SK_Balance_:
typeName = "Balance\t";
break;
case __SK_Pan_:
typeName = "Pan\t\t";
break;
case __SK_Sustain_:
typeName = "Sustain\t";
break;
case __SK_Expression_:
typeName = "Expression\t";
break;
default:
typeName = "ControlChange\t";
break;
}
default:
typeName = "Unknown\t";
}
FILE *file = (FILE *) userData;
if ( type == 0xC0 || type == 0xD0 || type == 0xE0 ) { // program change, channel pressure, or pitchbend
fprintf( stdout, "%s %.3f %d %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1 );
}
else if ( type == 0xB0 ) { // control change
fprintf( stdout, "%s %.3f %d %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte2 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte2 );
}
else { // noteon, noteoff, aftertouch, and unknown
fprintf( stdout, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1, (float)databyte2 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1, (float)databyte2 );
}
}
int main( int argc,char *argv[] )
{
FILE *file = NULL;
std::string fileName;
RtMidiIn *midiin = 0;
unsigned int port = 0;
if ( argc > 5 ) usage();
// Parse the command-line arguments.
int i = 1;
while (i < argc) {
while ( i < argc ) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
case 's':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strncpy(hostName, argv[i], 128);
}
else strcpy(hostName, "localhost");
useSocket = true;
break;
case 'f':
if ((i+1 < argc) && argv[i+1][0] != '-') {
if ( (i+1 < argc) && argv[i+1][0] != '-' ) {
i++;
strncpy(fileName, argv[i], 252);
if ( strstr(fileName,".ski") == NULL ) strcat(fileName, ".ski");
fileName = argv[i];
if ( fileName.find( ".ski" ) == std::string::npos ) fileName.append( ".ski" );
}
else strcpy(fileName, "test.ski");
file = fopen(fileName,"wb");
writeFile = true;
else fileName = "test.ski";
file = fopen( fileName.c_str(), "wb" );
break;
case 'p':
if ( i++ >= argc) usage();
port = (unsigned int) atoi( argv[i] );
break;
default:
@@ -82,234 +182,51 @@ int main(int argc,char *argv[])
i++;
}
MY_FLOAT dt=0.0;
try {
rtmidi = new RtMidi();
midiin = new RtMidiIn();
}
catch (StkError &) {
exit(0);
catch (RtError &error) {
error.printMessage();
if ( file != NULL ) fclose( file );
exit(EXIT_FAILURE);
}
// If using sockets, setup the client socket
if (useSocket) {
try {
soket = new Socket( 2001, hostName );
}
catch (StkError &) {
exit(0);
}
// Check available ports vs. specified.
unsigned int nPorts = midiin->getPortCount();
if ( nPorts == 0 ) {
std::cout << "No MIDI ports available!\n";
goto cleanup;
}
// Start the "exit" thread.
thread = new Thread();
if ( !thread->start( (THREAD_FUNCTION)&stdinMonitor, (void *) &done ) ) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
else if ( port >= nPorts ) {
std::cout << "Invalid port specifier!\n";
goto cleanup;
}
// Write SKINI messages to buffer 's'. This is the easiest way to
// allow this single executable to work for both socketing and
// printf's to stdout.
char s[128];
int channel, j;
MY_FLOAT byte2, byte3;
while ( !done ) {
if (rtmidi->nextMessage() > 0) {
byte3 = rtmidi->getByteThree();
byte2 = rtmidi->getByteTwo();
channel = rtmidi->getChannel();
if (writeFile) dt = rtmidi->getDeltaTime();
if (firstMessage) { // first MIDI message time stamp is meaningless
dt = 0.0;
firstMessage = false;
}
switch(rtmidi->getType()) {
case __SK_NoteOn_:
if (byte3 < 1.0) {
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0);
if (writeFile) {
fprintf(file,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,64.0);
}
} else {
sprintf(s,"NoteOn\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"NoteOn\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
}
break;
case __SK_NoteOff_:
if (byte3 < 2.0) byte3 = 64.0;
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_PolyPressure_:
sprintf(s,"PolyPressure\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"PolyPressure\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_ControlChange_:
j = (int) byte2;
switch(j) {
case __SK_PitchChange_:
sprintf(s,"PitchChange\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"PitchChange\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Volume_:
sprintf(s,"Volume\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Volume\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_ModWheel_:
sprintf(s,"ModWheel\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"ModWheel\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Breath_:
sprintf(s,"Breath\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Breath\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_FootControl_:
sprintf(s,"FootControl\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"FootControl\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Portamento_:
sprintf(s,"Portamento\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Portamento\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Balance_:
sprintf(s,"Balance\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Balance\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Pan_:
sprintf(s,"Pan\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Pan\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Sustain_:
sprintf(s,"Sustain\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Sustain\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Expression_:
sprintf(s,"Expression\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Expression\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
default:
sprintf(s,"ControlChange\t%.3f %d %d %.1f\n",0.0,channel,j,byte3);
if (writeFile) {
fprintf(file,"ControlChange\t%.3f %d %d %.1f\n",dt,channel,j,byte3);
}
break;
}
break;
case __SK_ProgramChange_:
j = (int) byte2;
sprintf(s,"ProgramChange\t%.3f %d %d\n",0.0,channel,j);
if (writeFile) {
fprintf(file,"ProgramChange\t%.3f %d %d\n",dt,channel,j);
}
break;
case __SK_ChannelPressure_:
sprintf(s,"ChannelPressure\t%.3f %d %.1f\n",0.0,channel,byte2);
if (writeFile) {
fprintf(file,"ChannelPressure\t%.3f %d %.1f\n",dt,channel,byte2);
}
break;
case __SK_PitchBend_:
sprintf(s,"PitchBend\t%.3f %d %f\n",0.0,channel,byte2);
if (writeFile) {
fprintf(file,"PitchBend\t%.3f %d %f\n",dt,channel,byte2);
}
break;
default:
sprintf(s,"// Unknown\t%.3f %d %f %f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"// Unknown\t\t%.3f %d %f %f\n",dt,channel,byte2,byte3);
}
break;
}
if (useSocket) {
if ( soket->writeBuffer( s, strlen(s), 0 ) < 0 ) {
fprintf(stderr,"Socket connection failed ... aborting.\n");
goto cleanup;
}
}
else {
printf("%s", s);
fflush(stdout);
}
memset(s, 0, sizeof(s));
} else {
// Sleep for 10 milliseconds
Stk::sleep( 10 );
}
// Open the port.
try {
midiin->openPort( port );
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
sprintf(s, "Exiting Md2Skini process ... bye!\n");
if (useSocket)
soket->writeBuffer( s, strlen(s), 0 );
else {
printf("%s", s);
fflush(stdout);
}
// Set our callback function. This should be done immediately after
// opening the port to avoid having incoming messages written to the
// queue instead of sent to the callback function.
midiin->setCallback( &midiCallback, file );
if (writeFile) {
printf("Wrote SKINI output to file %s.\n", fileName);
fclose(file);
}
// We'll ignore sysex, timing, and active sensing messages.
midiin->ignoreTypes( true, true, true );
std::cout << "\nReading MIDI input ... press <enter> to quit.\n";
char input;
std::cin.get(input);
cleanup:
done = true;
delete rtmidi;
delete soket;
delete thread;
delete midiin;
if ( file != NULL ) fclose( file );
return 0;
}
THREAD_RETURN THREAD_TYPE stdinMonitor(void * ptr)
{
bool *done = (bool *) ptr;
char inputString[128];
printf("Type 'Exit<cr>' to quit.\n");
while ( !*done ) {
fgets(inputString, 128, stdin);
if (inputString[3] == 't' && inputString[1] == 'x'
&& inputString[2] == 'i' && inputString[0] == 'E') {
*done = true;
}
else {
printf(inputString);
fflush(stdout);
}
}
std::cout << "Md2Skini finished ... bye!" << std::endl;
return 0;
}

View File

@@ -42,7 +42,7 @@ RSC=rc.exe
# 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 /Od /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /Od /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__WINDOWS_MM__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -66,7 +66,7 @@ LINK32=link.exe
# 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 /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -99,16 +99,8 @@ SOURCE=..\..\src\SKINI.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Socket.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Thread.cpp
# End Source File
# End Group
# Begin Group "Header Files"
@@ -123,16 +115,8 @@ SOURCE=..\..\include\SKINI.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Socket.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Stk.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Thread.h
# End Source File
# End Group
# Begin Group "Resource Files"

1
projects/demo/Modal Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Modal.tcl | ./demo ModalBar -or -ip

View File

@@ -1 +1 @@
wish < tcl/Modal.tcl | ./demo ModalBar -or -ip
wish < tcl/Modal.tcl | demo ModalBar -or -ip

1
projects/demo/Physical Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Physical.tcl | ./demo Clarinet -or -ip

View File

@@ -1 +1 @@
wish < tcl/Physical.tcl | ./demo Clarinet -or -ip
wish < tcl/Physical.tcl | demo Clarinet -or -ip

1
projects/demo/Shakers Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Shakers.tcl | ./demo Shakers -or -ip

1
projects/demo/StkDemo Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Demo.tcl | ./demo Clarinet -or -ip

View File

@@ -1 +1 @@
wish < tcl/Demo.tcl | ./demo Clarinet -or -ip
wish < tcl/Demo.tcl | demo Clarinet -or -ip

1
projects/demo/Voice Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Voice.tcl | ./demo FMVoices -or -ip

View File

@@ -1 +1 @@
wish < tcl/Voice.tcl | ./demo FMVoices -or -ip
wish < tcl/Voice.tcl | demo FMVoices -or -ip

View File

@@ -1,35 +1,193 @@
// demo.cpp
//
// An example STK program for voice playback and control.
// An example STK program that allows voice playback and control of
// most of the STK instruments.
#include "SKINI.msg"
#include "WvOut.h"
#include "Instrmnt.h"
#include "PRCRev.h"
#include "Voicer.h"
#include "Skini.h"
#if defined(__STK_REALTIME__)
#include "RtAudio.h"
#include "Mutex.h"
#endif
// Miscellaneous command-line parsing and instrument allocation
// functions are defined in utilites.cpp ... specific to this program.
#include "utilities.h"
#include <stdlib.h>
#include <signal.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#if !defined(__OS_WINDOWS__) // Windoze bogosity for VC++ 6.0
using std::min;
#endif
bool done;
static void finish(int ignore){ done = true; }
int main(int argc, char *argv[])
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
WvOut **wvout;
Instrmnt **instrument;
Voicer *voicer;
Effect *reverb;
Messager messager;
Skini::Message message;
StkFloat volume;
StkFloat t60;
unsigned int nWvOuts;
int nVoices;
int currentVoice;
int channels;
int counter;
bool realtime;
bool settling;
bool haveMessage;
// Default constructor.
TickData()
: wvout(0), instrument(0), voicer(0), reverb(0), volume(1.0), t60(1.0),
nWvOuts(0), nVoices(1), currentVoice(0), channels(2), counter(0),
realtime( false ), settling( false ), haveMessage( false ) {}
};
#define DELTA_CONTROL_TICKS 64 // default sample frames between control input checks
// The processMessage() function encapsulates the handling of control
// messages. It can be easily relocated within a program structure
// depending on the desired scheduling scheme.
void processMessage( TickData* data )
{
Instrmnt **instrument = 0;
WvOut **output = 0;
Messager *messager = 0;
Reverb *reverb = 0;
Voicer *voicer = 0;
int i, nVoices = 1;
MY_FLOAT volume = 1.0;
MY_FLOAT t60 = 1.0; // in seconds
register StkFloat value1 = data->message.floatValues[0];
register StkFloat value2 = data->message.floatValues[1];
switch( data->message.type ) {
case __SK_Exit_:
if ( data->settling == false ) goto settle;
done = true;
return;
case __SK_NoteOn_:
if ( value2 == 0.0 ) // velocity is zero ... really a NoteOff
data->voicer->noteOff( value1, 64.0 );
else // a NoteOn
data->voicer->noteOn( value1, value2 );
break;
case __SK_NoteOff_:
data->voicer->noteOff( value1, value2 );
break;
case __SK_ControlChange_:
if (value1 == 44.0)
data->reverb->setEffectMix(value2 * ONE_OVER_128);
else if (value1 == 7.0)
data->volume = value2 * ONE_OVER_128;
else if (value1 == 49.0)
data->voicer->setFrequency( value2 );
else
data->voicer->controlChange( (int) value1, value2 );
break;
case __SK_AfterTouch_:
data->voicer->controlChange( 128, value1 );
break;
case __SK_PitchChange_:
data->voicer->setFrequency( value1 );
break;
case __SK_PitchBend_:
data->voicer->pitchBend( value1 );
break;
case __SK_Volume_:
data->volume = value1 * ONE_OVER_128;
break;
case __SK_ProgramChange_:
if ( data->currentVoice == (int) value1 ) break;
// Two-stage program change process.
if ( data->settling == false ) goto settle;
// Stage 2: delete and reallocate new voice(s)
for ( int i=0; i<data->nVoices; i++ ) {
data->voicer->removeInstrument( data->instrument[i] );
delete data->instrument[i];
data->currentVoice = voiceByNumber( (int)value1, &data->instrument[i] );
if ( data->currentVoice < 0 )
data->currentVoice = voiceByNumber( 0, &data->instrument[i] );
data->voicer->addInstrument( data->instrument[i] );
data->settling = false;
}
} // end of switch
data->haveMessage = false;
return;
settle:
// Exit and program change messages are preceeded with a short settling period.
data->voicer->silence();
data->counter = (int) (0.3 * data->t60 * Stk::sampleRate());
data->settling = true;
}
// The tick() function handles sample computation and scheduling of
// control updates. If doing realtime audio output, it will be called
// automatically when the system needs a new buffer of audio samples.
int tick(char *buffer, int bufferSize, void *dataPointer)
{
TickData *data = (TickData *) dataPointer;
register StkFloat sample, *samples = (StkFloat *) buffer;
int counter, nTicks = bufferSize;
while ( nTicks > 0 && !done ) {
if ( !data->haveMessage ) {
data->messager.popMessage( data->message );
if ( data->message.type > 0 ) {
data->counter = (long) (data->message.time * Stk::sampleRate());
data->haveMessage = true;
}
else
data->counter = DELTA_CONTROL_TICKS;
}
counter = min( nTicks, data->counter );
data->counter -= counter;
for ( int i=0; i<counter; i++ ) {
sample = data->volume * data->reverb->tick( data->voicer->tick() );
for ( unsigned int j=0; j<data->nWvOuts; j++ ) data->wvout[j]->tick(sample);
if ( data->realtime )
for ( int k=0; k<data->channels; k++ ) *samples++ = sample;
nTicks--;
}
if ( nTicks == 0 ) break;
// Process control messages.
if ( data->haveMessage ) processMessage( data );
}
return 0;
}
int main( int argc, char *argv[] )
{
TickData data;
int i;
#if defined(__STK_REALTIME__)
RtAudio *dac = 0;
#endif
// If you want to change the default sample rate (set in Stk.h), do
// it before instantiating any objects! If the sample rate is
@@ -38,151 +196,110 @@ int main(int argc, char *argv[])
// Check the command-line arguments for errors and to determine
// the number of WvOut objects to be instantiated (in utilities.cpp).
int nOutputs = checkArgs(argc, argv);
output = (WvOut **) calloc(nOutputs, sizeof(WvOut *));
data.nWvOuts = checkArgs(argc, argv);
data.wvout = (WvOut **) calloc(data.nWvOuts, sizeof(WvOut *));
// Instantiate the instrument(s) type from the command-line argument
// (in utilities.cpp).
nVoices = countVoices(argc, argv);
instrument = (Instrmnt **) calloc(nVoices, sizeof(Instrmnt *));
int voice = voiceByName(argv[1], &instrument[0]);
if ( voice < 0 ) {
free( output );
free( instrument );
data.nVoices = countVoices(argc, argv);
data.instrument = (Instrmnt **) calloc(data.nVoices, sizeof(Instrmnt *));
data.currentVoice = voiceByName(argv[1], &data.instrument[0]);
if ( data.currentVoice < 0 ) {
free( data.wvout );
free( data.instrument );
usage(argv[0]);
}
// If there was no error allocating the first voice, we should be fine for more.
for ( i=1; i<nVoices; i++ )
voiceByName(argv[1], &instrument[i]);
for ( i=1; i<data.nVoices; i++ )
voiceByName(argv[1], &data.instrument[i]);
voicer = (Voicer *) new Voicer(nVoices);
for ( i=0; i<nVoices; i++ )
voicer->addInstrument( instrument[i] );
data.voicer = (Voicer *) new Voicer( data.nVoices );
for ( i=0; i<data.nVoices; i++ )
data.voicer->addInstrument( data.instrument[i] );
// Parse the command-line flags, instantiate WvOut objects, and
// instantiate the input message controller (in utilities.cpp).
try {
parseArgs(argc, argv, output, &messager);
data.realtime = parseArgs(argc, argv, data.wvout, data.messager);
}
catch (StkError &) {
goto cleanup;
}
// Set the number of ticks between realtime messages (default =
// RT_BUFFER_SIZE).
messager->setRtDelta( 64 );
// If realtime output, allocate the dac here.
#if defined(__STK_REALTIME__)
if ( data.realtime ) {
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
dac = new RtAudio(0, data.channels, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
}
#endif
// Set the reverb parameters.
reverb = new PRCRev( t60 );
reverb->setEffectMix(0.2);
data.reverb = new PRCRev( data.t60 );
data.reverb->setEffectMix(0.2);
// Install an interrupt handler function.
(void) signal(SIGINT, finish);
// The runtime loop begins here:
done = FALSE;
int nTicks, type, j;
MY_FLOAT byte2, byte3, sample;
while (!done) {
// Look for new messages and return a delta time (in samples).
type = messager->nextMessage();
if (type < 0)
done = TRUE;
nTicks = messager->getDelta();
for ( i=0; i<nTicks; i++ ) {
sample = volume * reverb->tick( voicer->tick() );
for ( j=0; j<nOutputs; j++ ) output[j]->tick(sample);
// If realtime output, set our callback function and start the dac.
#if defined(__STK_REALTIME__)
if ( data.realtime ) {
try {
dac->setStreamCallback(&tick, (void *)&data);
dac->startStream();
}
if ( type > 0 ) {
// Process the new control message.
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_NoteOn_:
if (byte3 == 0.0) // velocity is zero ... really a NoteOff
voicer->noteOff( byte2, 64.0 );
else // a NoteOn
voicer->noteOn( byte2, byte3 );
break;
case __SK_NoteOff_:
voicer->noteOff( byte2, byte3 );
break;
case __SK_ControlChange_:
if (byte2 == 44.0)
reverb->setEffectMix(byte3 * ONE_OVER_128);
else if (byte2 == 7.0)
volume = byte3 * ONE_OVER_128;
else if (byte2 == 49.0)
voicer->setFrequency( byte3 );
else
voicer->controlChange( (int) byte2, byte3 );
break;
case __SK_AfterTouch_:
voicer->controlChange( 128, byte2 );
break;
case __SK_PitchChange_:
voicer->setFrequency( byte2 );
break;
case __SK_PitchBend_:
voicer->pitchBend( byte2 );
break;
case __SK_Volume_:
volume = byte2 * ONE_OVER_128;
break;
case __SK_ProgramChange_:
if ( voice != (int) byte2 ) {
voicer->silence();
// Let the instrument(s) settle a bit.
for ( i=0; i<4096; i++ ) {
sample = reverb->tick( voicer->tick() );
for ( j=0; j<nOutputs; j++ ) output[j]->tick(sample);
}
for ( i=0; i<nVoices; i++ ) {
voicer->removeInstrument( instrument[i] );
delete instrument[i];
voice = voiceByNumber( (int)byte2, &instrument[i] );
if ( voice < 0 )
voice = voiceByNumber( 0, &instrument[i] );
voicer->addInstrument( instrument[i] );
}
}
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
}
#endif
// Let the reverb settle a bit.
nTicks = (long) (t60 * Stk::sampleRate());
for ( i=0; i<nTicks; i++) {
sample = reverb->tick( voicer->tick() );
for ( j=0; j<nOutputs; j++ ) output[j]->tick(sample);
// Setup finished.
while ( !done ) {
#if defined(__STK_REALTIME__)
if ( data.realtime )
// Periodically check "done" status.
Stk::sleep( 200 );
else
#endif
// Call the "tick" function to process data.
tick( NULL, 256, (void *)&data );
}
// Shut down the callback and output stream.
#if defined(__STK_REALTIME__)
try {
dac->cancelStreamCallback();
dac->closeStream();
}
catch (RtError& error) {
error.printMessage();
}
#endif
cleanup:
for ( i=0; i<nOutputs; i++ ) delete output[i];
free(output);
for ( i=0; i<(int)data.nWvOuts; i++ ) delete data.wvout[i];
free( data.wvout );
delete messager;
delete reverb;
delete voicer;
#if defined(__STK_REALTIME__)
delete dac;
#endif
delete data.reverb;
delete data.voicer;
for ( i=0; i<nVoices; i++ ) delete instrument[i];
free(instrument);
for ( i=0; i<data.nVoices; i++ ) delete data.instrument[i];
free( data.instrument );
std::cout << "\nStk demo finished ... goodbye.\n" << std::endl;
std::cout << "\nStk demo finished ... goodbye.\n\n";
return 0;
}

View File

@@ -42,7 +42,7 @@ RSC=rc.exe
# 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 /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -66,7 +66,7 @@ LINK32=link.exe
# 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 /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -91,6 +91,10 @@ SOURCE=..\..\src\ADSR.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Asymp.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\BandedWG.cpp
# End Source File
# Begin Source File
@@ -115,7 +119,7 @@ SOURCE=..\..\src\Bowed.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\BowTabl.cpp
SOURCE=..\..\src\BowTable.cpp
# End Source File
# Begin Source File
@@ -147,6 +151,10 @@ SOURCE=..\..\src\Drummer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Effect.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Envelope.cpp
# End Source File
# Begin Source File
@@ -171,6 +179,14 @@ SOURCE=..\..\src\FormSwep.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Function.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Generator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\HevyMetl.cpp
# End Source File
# Begin Source File
@@ -183,7 +199,7 @@ SOURCE=..\..\src\JCRev.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\JetTabl.cpp
SOURCE=..\..\src\JetTable.cpp
# End Source File
# Begin Source File
@@ -215,6 +231,10 @@ SOURCE=..\..\src\Moog.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Noise.cpp
# End Source File
# Begin Source File
@@ -255,7 +275,7 @@ SOURCE=..\..\src\PRCRev.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\ReedTabl.cpp
SOURCE=..\..\src\ReedTable.cpp
# End Source File
# Begin Source File
@@ -263,10 +283,6 @@ SOURCE=..\..\src\Resonate.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Reverb.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Rhodey.cpp
# End Source File
# Begin Source File
@@ -399,6 +415,10 @@ SOURCE=..\..\include\ADSR.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Asymp.h
# End Source File
# Begin Source File
SOURCE=..\..\include\BandedWG.h
# End Source File
# Begin Source File
@@ -423,7 +443,7 @@ SOURCE=..\..\include\Bowed.h
# End Source File
# Begin Source File
SOURCE=..\..\include\BowTabl.h
SOURCE=..\..\include\BowTable.h
# End Source File
# Begin Source File
@@ -451,6 +471,10 @@ SOURCE=..\..\include\Drummer.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Effect.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Envelope.h
# End Source File
# Begin Source File
@@ -475,6 +499,14 @@ SOURCE=..\..\include\FormSwep.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Function.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Generator.h
# End Source File
# Begin Source File
SOURCE=..\..\include\HevyMetl.h
# End Source File
# Begin Source File
@@ -487,7 +519,7 @@ SOURCE=..\..\include\JCRev.h
# End Source File
# Begin Source File
SOURCE=..\..\include\JetTabl.h
SOURCE=..\..\include\JetTable.h
# End Source File
# Begin Source File
@@ -519,6 +551,10 @@ SOURCE=..\..\include\Moog.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Mutex.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Noise.h
# End Source File
# Begin Source File
@@ -559,7 +595,7 @@ SOURCE=..\..\include\PRCRev.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ReedTabl.h
SOURCE=..\..\include\ReedTable.h
# End Source File
# Begin Source File
@@ -567,10 +603,6 @@ SOURCE=..\..\include\Resonate.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Reverb.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Rhodey.h
# End Source File
# Begin Source File

View File

@@ -755,7 +755,7 @@ proc printWhatz {tag value1 value2 } {
proc changePress {value} {
global outID patchnum
if { $patchnum<700 || $patchnum>900 } {
if { $patchnum<700 || ($patchnum>900 && $patchnum<2500) || $patchnum>=2600 } {
puts $outID [format "AfterTouch 0.0 1 %3.2f" $value]
flush $outID
}

View File

@@ -36,10 +36,6 @@
#include "Resonate.h"
#include "Whistle.h"
#if defined(__STK_REALTIME__)
#include "RtWvOut.h"
#endif
#define NUM_INSTS 28
// The order of the following list is important. The location of a particular
@@ -123,12 +119,13 @@ void usage(char *function) {
printf(" -os <file name> for .snd audio output file,\n");
printf(" -om <file name> for .mat audio output file,\n");
printf(" -oa <file name> for .aif audio output file,\n");
printf(" -if <file name> to read control input from SKINI file,\n");
#if defined(__STK_REALTIME__)
printf(" -or for realtime audio output,\n");
printf(" -ip for realtime control input by pipe,\n");
printf(" (won't work under Win95/98),\n");
printf(" -is <port> for realtime control input by socket,\n");
printf(" -im for realtime control input by MIDI,\n");
printf(" -im <port> for realtime control input by MIDI (virtual port = 0, default = 1),\n");
#endif
printf(" and Instrument = one of these:\n");
for (i=0;i<NUM_INSTS;i+=8) {
@@ -150,24 +147,25 @@ void usage(char *function) {
int checkArgs(int numArgs, char *args[])
{
int w, i = 2, j = 0;
int numOutputs = 0;
int nWvOuts = 0;
char flags[2][50] = {""};
bool realtime = false;
if (numArgs < 3 || numArgs > 17) usage(args[0]);
if (numArgs < 3 || numArgs > 22) usage(args[0]);
while (i < numArgs) {
if (args[i][0] == '-') {
if (args[i][1] == 'o') {
if ( (args[i][2] == 'r') || (args[i][2] == 's') ||
(args[i][2] == 'w') || (args[i][2] == 'm')
|| (args[i][2] == 'a') )
numOutputs++;
if ( args[i][2] == 'r' ) realtime = true;
if ( (args[i][2] == 's') || (args[i][2] == 'w') ||
(args[i][2] == 'm') || (args[i][2] == 'a') )
nWvOuts++;
flags[0][j] = 'o';
flags[1][j++] = args[i][2];
}
else if (args[i][1] == 'i') {
if ( (args[i][2] != 's') && (args[i][2] != 'p') &&
(args[i][2] != 'm') ) usage(args[0]);
(args[i][2] != 'm') && (args[i][2] != 'f') ) usage(args[0]);
flags[0][j] = 'i';
flags[1][j++] = args[i][2];
}
@@ -196,9 +194,9 @@ int checkArgs(int numArgs, char *args[])
}
// Make sure we have at least one output type
if (numOutputs < 1) usage(args[0]);
if ( nWvOuts < 1 && !realtime ) usage(args[0]);
return numOutputs;
return nWvOuts;
}
int countVoices(int nArgs, char *args[])
@@ -218,20 +216,24 @@ int countVoices(int nArgs, char *args[])
return nInstruments;
}
void parseArgs(int numArgs, char *args[], WvOut **output, Messager **messager)
bool parseArgs(int numArgs, char *args[], WvOut **output, Messager& messager)
{
int i = 2, j = 0;
int inputMask = 0;
int port = -1;
bool realtime = false;
char fileName[256];
while (i < numArgs) {
if ( (args[i][0] == '-') && (args[i][1] == 'i') ) {
switch(args[i][2]) {
case 'f':
strcpy(fileName,args[++i]);
if ( !messager.setScoreFile( fileName ) ) usage(args[0]);
break;
case 'p':
#if defined(__STK_REALTIME__)
inputMask |= STK_PIPE;
if ( !messager.startStdInput() ) usage(args[0]);
break;
#else
usage(args[0]);
@@ -239,10 +241,12 @@ void parseArgs(int numArgs, char *args[], WvOut **output, Messager **messager)
case 's':
#if defined(__STK_REALTIME__)
inputMask |= STK_SOCKET;
// Check for an optional socket port argument.
if ((i+1 < numArgs) && args[i+1][0] != '-')
port = atoi(args[++i]);
if ((i+1 < numArgs) && args[i+1][0] != '-') {
int port = atoi(args[++i]);
if ( !messager.startSocketInput( port ) ) usage(args[0]);
}
else if ( !messager.startSocketInput() ) usage(args[0]);
break;
#else
usage(args[0]);
@@ -250,7 +254,12 @@ void parseArgs(int numArgs, char *args[], WvOut **output, Messager **messager)
case 'm':
#if defined(__STK_REALTIME__)
inputMask |= STK_MIDI;
// Check for an optional MIDI port argument.
if ((i+1 < numArgs) && args[i+1][0] != '-') {
int port = atoi(args[++i]);
if ( !messager.startMidiInput( port-1 ) ) usage(args[0]);
}
else if ( !messager.startMidiInput() ) usage(args[0]);
break;
#else
usage(args[0]);
@@ -266,8 +275,7 @@ void parseArgs(int numArgs, char *args[], WvOut **output, Messager **messager)
case 'r':
#if defined(__STK_REALTIME__)
output[j] = (WvOut *) new RtWvOut(2);
j++;
realtime = true;
break;
#else
usage(args[0]);
@@ -321,10 +329,5 @@ void parseArgs(int numArgs, char *args[], WvOut **output, Messager **messager)
i++;
}
// Instantiate the messager.
if ( inputMask & STK_SOCKET && port >= 0 )
*messager = new Messager( inputMask, port );
else
*messager = new Messager( inputMask );
return realtime;
}

View File

@@ -16,4 +16,4 @@ int checkArgs(int numArgs, char *args[]);
int countVoices(int nArgs, char *args[]);
void parseArgs(int numArgs, char *args[], WvOut **output, Messager **messager);
bool parseArgs(int numArgs, char *args[], WvOut **output, Messager& messager);