Version 2.02

This commit is contained in:
Gary Scavone
2013-09-25 11:18:58 +02:00
committed by Stephen Sinclair
parent ea749b71d2
commit 7c0ee03d60
47 changed files with 1888 additions and 696 deletions

View File

1
mus151/GUITwoOsc Executable file
View File

@@ -0,0 +1 @@
wish < tcl/TwoWaves.tcl | MUS151 TwoOsc -r

312
mus151/MUS151.cpp Normal file
View File

@@ -0,0 +1,312 @@
/******** Psychoacoustic Interface Program for MUS151 ************/
/******** Center for Computer Research in Music & Acoustics ******/
/******** Stanford University, by Gary P. Scavone, 1998 **********/
#include "../miditabl.h"
#include "../WvOut.h"
#include "../RTWvOut.h"
#include "../SKINI11.h"
#include "TwoOsc.h"
#include "../SKINI11.msg"
#define INSTR_LEN 60
int numStrings = 0;
int notDone = 1;
#if defined(__SGI_REALTIME_)
#include <sys/types.h>
#include <sys/prctl.h>
#include <signal.h>
char inputString[MAX_IN_STRINGS][INSTR_LEN];
pid_t string_thread;
void newString(void *)
{
int inOne = 0;
while (notDone) {
fgets(inputString[inOne],INSTR_LEN,stdin);
if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') {
notDone = 0;
}
else {
numStrings++;
if (numStrings > MAX_IN_STRINGS) {
fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n");
numStrings--;
}
inOne++;
if (inOne == MAX_IN_STRINGS) inOne = 0;
}
}
}
#elif defined(__USS_REALTIME_)
#include <pthread.h>
//#include <pthread/mit/pthread.h>
char inputString[MAX_IN_STRINGS][INSTR_LEN];
pthread_t string_thread;
void *newString(void *)
{
int inOne = 0;
while (notDone) {
fgets(inputString[inOne],INSTR_LEN,stdin);
if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') {
notDone = 0;
}
else {
numStrings++;
if (numStrings > MAX_IN_STRINGS) {
fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n");
numStrings--;
}
inOne++;
if (inOne == MAX_IN_STRINGS) inOne = 0;
}
}
}
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
#include <process.h>
#include <winsock.h>
char inputString[MAX_IN_STRINGS][INSTR_LEN];
unsigned long string_thread;
#define SERVICE_PORT 2001
void newString(void *)
{
int inOne = 0, i=0, m=0, n;
SOCKET soc_id, accept_id;
WSADATA wsaData;
int nRet;
struct sockaddr_in sockname;
WORD wVersionRequested = MAKEWORD(1,1);
char socBuf[INSTR_LEN];
nRet = WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested)
{
fprintf(stderr,"\n Wrong version\n");
exit(0);
}
/* Create the server-side socket */
soc_id = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(soc_id == INVALID_SOCKET) {
fprintf(stderr,"Couldn't create socket!\n");
exit(0);
}
sockname.sin_family=AF_INET;
sockname.sin_addr.s_addr=INADDR_ANY;
sockname.sin_port=htons(SERVICE_PORT);
/* Bind socket to the appropriate port and interface (INADDR_ANY) */
if (bind(soc_id,(LPSOCKADDR)&sockname,sizeof(sockname))==SOCKET_ERROR) {
fprintf(stderr,"Couldn't bind socket!\n");
exit(0);
}
/* Listen for incoming connections */
printf("Listening for socket on port %d\n", SERVICE_PORT);
if (listen(soc_id,1)==SOCKET_ERROR) {
fprintf(stderr,"Couldn't set up listen on socket!\n");
exit(0);
}
/* Accept and service one incoming connection request */
accept_id=accept(soc_id,NULL,NULL);
if (accept_id==INVALID_SOCKET) {
fprintf(stderr,"Couldn't accept incoming connection on socket!\n");
exit(0);
}
memset(socBuf, 0, sizeof(socBuf));
printf("Socket connection made ... ready to receive SKINI messages.\n");
while (notDone) {
i = recv(accept_id, socBuf, INSTR_LEN, 0);
if (i==0) notDone = 0;
n = 0;
while (n < i) {
inputString[inOne][m++] = socBuf[n];
if (socBuf[n++] == '\n') {
if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') {
notDone = 0;
n = i;
}
else {
m = 0;
numStrings++;
if (numStrings > MAX_IN_STRINGS) {
fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n");
numStrings--;
}
inOne++;
if (inOne == MAX_IN_STRINGS) inOne = 0;
}
memset(inputString[inOne], 0, INSTR_LEN);
}
}
}
closesocket(accept_id);
closesocket(soc_id);
WSACleanup();
printf("Socket connection closed.\n");
}
#else
char inputString[1][INSTR_LEN];
#endif
/* Error function in case of incorrect command-line argument specifications */
void errorf(char *func) {
printf("\nuseage: %s Instr \n",func);
printf(" where Instr = TwoOsc (only one available for now)\n\n");
exit(0);
}
void main(int argc,char *argv[])
{
long i, j, synlength;
int type, rtInput = 0;
int outOne = 0;
char *fin;
MY_FLOAT settleTime = 0.5; /* in seconds */
MY_FLOAT temp, byte3, lastPitch;
WvOut *output;
TwoOsc *instrument;
SKINI11 *score;
if (argc > 1) {
if (!strcmp(argv[1],"TwoOsc")) instrument = new TwoOsc;
else errorf(argv[0]);
} else errorf(argv[0]);
output = new RTWvOut();
score = new SKINI11();
rtInput = 1; /* We're going to always use realtime input */
/* If using realtime input, setup the input thread. */
#if defined(__SGI_REALTIME_)
if (rtInput) {
string_thread = sproc(newString, PR_SALL);
if (string_thread == -1) {
fprintf(stderr, "unable to create input thread...aborting.\n");
exit(-1);
}
instrument->noteOn(200.0, 0.2);
}
#elif defined(__USS_REALTIME_)
if (rtInput) {
if (pthread_create(&string_thread, NULL, newString, NULL))
{
fprintf(stderr, "unable to create input thread...aborting.\n");
exit(-1);
}
instrument->noteOn(200.0,0.2);
}
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
if (rtInput) {
string_thread = _beginthread(newString, 0, NULL);
if (string_thread == -1) {
fprintf(stderr, "Unable to create exit thread.\n");
printf("Exiting MD2SKINI process.\n");
exit(0);
}
instrument->noteOn(200.0,0.2);
}
#endif
/* Finally ... the runtime loop begins! */
notDone = 1;
synlength = RT_BUFFER_SIZE;
while(notDone || numStrings) {
if (rtInput) {
if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings;
else synlength = RT_BUFFER_SIZE;
for ( i=0; i<synlength; i++ ) {
output->tick(instrument->tick());
}
}
else {
fin = fgets(inputString[0],INSTR_LEN,stdin);
if (fin == NULL) notDone = 0;
else {
numStrings++;
}
}
if (numStrings) {
score->parseThis(inputString[outOne]);
type = score->getType();
if (type > 0) {
if (temp = score->getDelta()) { /* SKINI score file */
synlength = (long) (temp * SRATE);
for ( i=0; i<synlength; i++ ) {
output->tick(instrument->tick());
}
synlength = 0;
}
if (type == __SK_NoteOn_ ) {
if (( byte3 = score->getByteThree() ) == 0)
instrument->noteOff(byte3*NORM_7);
else {
j = (int) score->getByteTwo();
temp = __MIDI_To_Pitch[j];
lastPitch = temp;
instrument->noteOn(temp,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_) {
temp = score->getByteTwo();
j = (int) temp;
temp -= j;
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_) {
}
}
if (rtInput) {
outOne += 1;
if (outOne == MAX_IN_STRINGS) outOne = 0;
}
numStrings--;
}
}
for (i=0;i<settleTime*SRATE;i++) { /* let the sound settle a little */
output->tick(instrument->tick());
}
delete output;
delete score;
delete instrument;
#if defined(__SGI_REALTIME_)
if (rtInput) kill(string_thread, SIGKILL);
#endif
printf("MUS151 finished.\n");
}

177
mus151/MUS151.dsp Normal file
View File

@@ -0,0 +1,177 @@
# Microsoft Developer Studio Project File - Name="MUS151" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=MUS151 - 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 "MUS151.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 "MUS151.MAK" CFG="MUS151 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MUS151 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "MUS151 - 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)" == "MUS151 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "MUS151__"
# PROP BASE Intermediate_Dir "MUS151__"
# 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 "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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 winmm.lib dsound.lib Wsock32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "MUS151 - 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 "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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 winmm.lib dsound.lib Wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "MUS151 - Win32 Release"
# Name "MUS151 - Win32 Debug"
# Begin Source File
SOURCE=..\Envelope.cpp
# End Source File
# Begin Source File
SOURCE=..\Envelope.h
# End Source File
# Begin Source File
SOURCE=.\MUS151.cpp
# End Source File
# Begin Source File
SOURCE=..\Object.cpp
# End Source File
# Begin Source File
SOURCE=..\Object.h
# End Source File
# Begin Source File
SOURCE=..\RawLoop.cpp
# End Source File
# Begin Source File
SOURCE=..\RawLoop.h
# End Source File
# Begin Source File
SOURCE=..\RawWave.cpp
# End Source File
# Begin Source File
SOURCE=..\RawWave.h
# End Source File
# Begin Source File
SOURCE=..\RTSoundIO.cpp
# End Source File
# Begin Source File
SOURCE=..\RTSoundIO.h
# End Source File
# Begin Source File
SOURCE=..\RTWvOut.cpp
# End Source File
# Begin Source File
SOURCE=..\RTWvOut.h
# End Source File
# Begin Source File
SOURCE=..\SKINI11.cpp
# End Source File
# Begin Source File
SOURCE=..\SKINI11.h
# End Source File
# Begin Source File
SOURCE=..\SKINI11.msg
# End Source File
# Begin Source File
SOURCE=..\SKINI11.tbl
# End Source File
# Begin Source File
SOURCE=..\swapstuf.cpp
# End Source File
# Begin Source File
SOURCE=..\swapstuf.h
# End Source File
# Begin Source File
SOURCE=.\TwoOsc.cpp
# End Source File
# Begin Source File
SOURCE=.\TwoOsc.h
# End Source File
# Begin Source File
SOURCE=..\WvOut.cpp
# End Source File
# Begin Source File
SOURCE=..\WvOut.h
# End Source File
# End Target
# End Project

29
mus151/MUS151.dsw Normal 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: "MUS151"=.\MUS151.DSP - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

BIN
mus151/MUS151.ncb Normal file

Binary file not shown.

65
mus151/Makefile Normal file
View File

@@ -0,0 +1,65 @@
# MUS151 Makefile - Global version for Unix systems which have GNU
# Makefile utilities installed.
#
# This is an example project Makefile, to demonstrate how one might
# develop an STK project that resides apart from the core STK
# distribution. It is highly recommended that you keep your
# personal STK projects separate from the core distribution, to
# make upgrading to newer releases more simple.
#
# by Gary P. Scavone
# CCRMA, Stanford University, 1998.
OS = $(shell uname)
# You will have to modify this path to correspond to the correct
# location in your system. The following definition corresponds
# to an STK project directory that is a subdirectory of the core
# STK distribution.
STK_PATH = ../
O_FILES = Object.o Envelope.o RawWave.o RawLoop.o \
SKINI11.o swapstuf.o WvOut.o \
RTWvOut.o RTSoundIO.o \
\
TwoOsc.o
RM = /bin/rm
ifeq ($(OS),IRIX) # These are for SGI
INSTR = MUS151
CC = CC -O # -g -fullwarn -D__SGI_CC__
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
endif
ifeq ($(OS),Linux) # These are for Linux
INSTR = MUS151
CC = gcc -O3 # -g -pg -O3
LIBRARY = -lpthread -lm
# LIBRARY = /lib/libpthread.so.0 -lm
endif
%.o : $(STK_PATH)%.cpp
$(CC) -c $(<) -o $@
MUS151: MUS151.cpp $(O_FILES)
$(CC) -o MUS151 MUS151.cpp $(O_FILES) $(LIBRARY)
# Personal $(O_FILES) :
TwoOsc.o : TwoOsc.cpp
$(CC) -c TwoOsc.cpp
all: $(INSTR)
clean :
rm *.o
rm $(INSTR)
cleanIns :
rm $(INSTR)
strip :
strip $(INSTR)

16
mus151/README-mus151.txt Normal file
View File

@@ -0,0 +1,16 @@
MUS151: An example project using STK
By Gary P. Scavone
CCRMA, Stanford University, 1998.
It is highly recommended that you keep your personal STK projects separate from the STK core distribution, to make upgrading to newer releases more simple. The files in this directory demonstrate how one might manage this.
This simple project, named MUS151 for the pyschoacoustics class taught at CCRMA, plays two sine waves and allows independent control of their amplitudes and frequencies. The file MUS151.cpp is essentially the same as syntmono.cpp, though simplified to a great extent because of its more specific use. In particular, only one "instrument" is currently supported (TwoOsc) and only real-time output is used (thus, this project cannot be compiled for NeXTStep). A simple Tcl/Tk GUI has been created to control the instrument. The GUI and STK project can be run under Linux and SGI using the simple GUITwoOsc executable script.
The mus151 project directory has been distributed as a subdirectory of the core STK file directory. In this location, the project should compile without any problems (on Linux, SGI, and Win platforms). Should you choose to relocate this directory, several path variables will need to be updated as described below.
Three "personal" STK files were created for this project: MUS151.cpp and the TwoOsc class files TwoOsc.h and TwoOsc.cpp. A specific Tcl/Tk GUI script was written (TwoOsc.tcl) and is located in the "tcl" subdirectory. Depending on where you choose to locate the mus151 directory, several #include statements may need to be updated to reflect the location of the STK core distribution. For example, mus151/ is currently a subdirectory of the STK core files, so the various core STK header files are referenced in TwoOsc.h as: #include "../Instrmnt.h". You could move the mus151 files to a completely different point on your directory tree, but you would have to update those statements to correctly reference your core files. Likewise, the "sinewave.raw" file must be correctly referenced in TwoOsc.cpp.
The unix Makefile must also be updated to correctly reference the STK core distribution. A variable, STK_PATH, has been created to simplify this procedure. Note that all STK core object files are referenced with a single, general statement. All personal object files need their own dependency definitions.
Finally, it is simple to create a VC++ project directory that is completely separate from the STK core distribution. However, it appears that there is no simple way to redefine the location of the project files should you choose to relocate the project after it is created. You will probably have to manually "Add" all the core STK files to the VC++ project after moving the project directory.

View File

76
mus151/TwoOsc.cpp Normal file
View File

@@ -0,0 +1,76 @@
/********************************************/
/* Two oscillator instrument for use */
/* with MUS151 Psychoacoustics course. */
/* by Gary P. Scavone & Oded Ben-Tal, 1998 */
/* CCRMA, Stanford Unviversity */
/********************************************/
#include "TwoOsc.h"
TwoOsc :: TwoOsc()
{
int i;
envelope = new Envelope; /* Envelope to avoid clicks */
for (i=0; i<2; i++) {
osc[i] = new RawLoop("../rawwaves/sinewave.raw");
osc[i]->normalize();
osc[i]->setFreq((MY_FLOAT) 200.0);
amps[i] = 0.2;
}
lastOutput = 0;
}
TwoOsc :: ~TwoOsc()
{
int i;
for (i=0; i<2; i++) delete osc[i];
delete envelope;
}
void TwoOsc :: setFreq(int oscnum, MY_FLOAT frequency)
{
if (oscnum == 1) osc[0]->setFreq(frequency);
else if (oscnum == 2) osc[1]->setFreq(frequency);
}
void TwoOsc :: setAmp(int oscnum, MY_FLOAT amp)
{
if (oscnum == 1) amps[0] = amp;
else if (oscnum == 2) amps[1] = amp;
}
void TwoOsc :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
envelope->keyOn();
}
void TwoOsc :: noteOff(MY_FLOAT amp)
{
envelope->keyOff();
}
MY_FLOAT TwoOsc :: tick()
{
lastOutput = 0.5 * envelope->tick() * (amps[0]*osc[0]->tick() + amps[1]*osc[1]->tick());
return lastOutput;
}
void TwoOsc :: controlChange(int number, MY_FLOAT value)
{
switch (number) {
case 20:
osc[0]->setFreq(value);
break;
case 21:
osc[1]->setFreq(value);
break;
case 22:
amps[0] = value * NORM_7;
break;
case 23:
amps[1] = value * NORM_7;
break;
}
}

35
mus151/TwoOsc.h Normal file
View File

@@ -0,0 +1,35 @@
/******************************************/
/* Two oscillator instrument for use */
/* with MUS151 Psychoacoustics course. */
/* by Gary P. Scavone, 1998 */
/* CCRMA, Stanford Unviversity */
/******************************************/
#if !defined(__TwoOsc_h)
#define __TwoOsc_h
//#include "../Instrmnt.h"
#include "../Envelope.h"
#include "../RawLoop.h"
class TwoOsc : public Object
{
protected:
Envelope *envelope;
RawLoop *osc[2];
MY_FLOAT lastOutput;
MY_FLOAT amps[2];
public:
TwoOsc();
~TwoOsc();
virtual void setFreq(int oscnum, MY_FLOAT frequency);
virtual void setAmp(int oscnum, MY_FLOAT amp);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

201
mus151/tcl/TwoWaves.tcl Normal file
View File

@@ -0,0 +1,201 @@
set pitch 64.0
set osc1on 1
set osc2on 1
set freq1 200.0
set freq2 200.0
set amp1 20
set amp2 20
set outID "stdout"
set commtype "stdout"
# Configure main window
wm title . "MUS152 Two Oscillator Controller"
wm iconname . "TwoOsc"
. config -bg black
# Configure "communications" menu
menu .menu -tearoff 0
menu .menu.communication -tearoff 0
.menu add cascade -label "Communication" -menu .menu.communication \
-underline 0
.menu.communication add radio -label "Console" -variable commtype \
-value "stdout" -command { setComm }
.menu.communication add radio -label "Socket" -variable commtype \
-value "socket" -command { setComm }
. configure -menu .menu
# Configure title display
label .title -text "MUS151 Two Oscillator Controller" \
-font {Times 14 bold} -background white \
-foreground darkred -relief raised
label .title2 -text "by Gary P. Scavone\n Center for Computer Research in Music & Acoustics (CCRMA) \n Stanford University" \
-font {Times 12 bold} -background white \
-foreground darkred -relief raised
pack .title -padx 5 -pady 10
pack .title2 -padx 5 -pady 10
# Configure "note-on" buttons
frame .noteOn -bg black
button .noteOn.on -text NoteOn -bg grey66 -command { noteOn $pitch 64.0 }
button .noteOn.off -text NoteOff -bg grey66 -command { noteOff $pitch 127.0 }
button .noteOn.exit -text "Exit Program" -bg grey66 -command myExit
pack .noteOn.on -side left -padx 5
pack .noteOn.off -side left -padx 5 -pady 10
pack .noteOn.exit -side left -padx 5 -pady 10
pack .noteOn
# Configure sliders
frame .left -bg black
scale .left.freq1 -from 0 -to 10000 -length 400 \
-command {changeParam 20 } \
-orient horizontal -label "Frequency 1" \
-tickinterval 2000 -showvalue true -bg grey66 \
-variable freq1
scale .left.amp1 -from 0 -to 127 -length 400 \
-command {changeParam 22 } \
-orient horizontal -label "Amp 1" \
-tickinterval 32 -showvalue true -bg grey66 \
-variable amp1
scale .left.freq2 -from 0 -to 10000 -length 400 \
-command {changeParam 21 } \
-orient horizontal -label "Frequency 2" \
-tickinterval 2000 -showvalue true -bg grey66 \
-variable freq2
scale .left.amp2 -from 0 -to 127 -length 400 \
-command {changeParam 23 } \
-orient horizontal -label "Amp 2" \
-tickinterval 32 -showvalue true -bg grey66 \
-variable amp2
pack .left.freq1 -padx 10 -pady 3
pack .left.amp1 -padx 10 -pady 3
pack .left.freq2 -padx 10 -pady 3
pack .left.amp2 -padx 10 -pady 3
pack .left -side left
# Configure more buttons
frame .onOff -bg black
checkbutton .onOff.1 -text "Play Osc 1" -variable osc1on -relief flat \
-command {setPlayStatus 22 $osc1on}
checkbutton .onOff.2 -text "Play Osc 2" -variable osc2on -relief flat \
-command {setPlayStatus 23 $osc2on}
pack .onOff.1 .onOff.2 -padx 5
pack .onOff -side right -padx 5 -pady 10
proc myExit {} {
global outID
puts $outID [format "NoteOff 0.0 1 64 127" ]
flush $outID
puts $outID [format "ExitProgram"]
flush $outID
close $outID
exit
}
proc noteOn {pitchVal pressVal} {
global outID
puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal]
flush $outID
}
proc noteOff {pitchVal pressVal} {
global outID
puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal]
flush $outID
}
proc changeParam {controlNum value } {
global outID freq1 freq2 amp1 amp2 osc1on osc2on
if {$controlNum==20 || $controlNum==22} {
if {$osc1on==1} {
puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $value ]
}
} elseif {$controlNum==21 || $controlNum==23} {
if {$osc2on==1} {
puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $value ]
}
}
flush $outID
}
proc setPlayStatus {controlNum value } {
global outID amp1 amp2 freq1 freq2
if {$value==1} {
if {$controlNum==22} {
puts $outID [format "ControlChange 0.0 1 %d %f" 20 $freq1 ]
puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $amp1 ]
} elseif {$controlNum==23} {
puts $outID [format "ControlChange 0.0 1 %d %f" 21 $freq2 ]
puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $amp2 ]
}
} elseif {$value==0} {
puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum 0.0 ]
}
flush $outID
}
# Socket connection procedure
set d .socketdialog
proc setComm {} {
global outID commtype d
if {$commtype == "stdout"} {
if { [string compare "stdout" $outID] } {
set i [tk_dialog .dialog "Break Socket Connection?" {You are about to break an existing socket connection ... is this what you want to do?} "" 0 Cancel OK]
switch $i {
0 {set commtype "socket"}
1 {close $outID
set outID "stdout"}
}
}
} elseif { ![string compare "stdout" $outID] } {
set sockport 2001
toplevel $d
wm title $d "STK Client Socket Connection"
wm resizable $d 0 0
grab $d
label $d.message -text "Specify a socket port number below (if different than the STK default of 2001) and then click the \"Connect\" button to invoke a socket-client connection attempt to the STK socket server." \
-background white -font {Helvetica 10 bold} \
-wraplength 3i -justify left
frame $d.sockport
entry $d.sockport.entry -width 6
label $d.sockport.text -text "Socket Port Number:" \
-font {Helvetica 10 bold}
pack $d.message -side top -padx 5 -pady 10
pack $d.sockport.text -side left -padx 1 -pady 10
pack $d.sockport.entry -side right -padx 5 -pady 10
pack $d.sockport -side top -padx 5 -pady 10
$d.sockport.entry insert 0 $sockport
frame $d.buttons
button $d.buttons.cancel -text "Cancel" -bg grey66 \
-command { set commtype "stdout"
set outID "stdout"
destroy $d }
button $d.buttons.connect -text "Connect" -bg grey66 \
-command {
set sockport [$d.sockport.entry get]
set err [catch {socket localhost $sockport} outID]
if {$err == 0} {
destroy $d
} else {
tk_dialog $d.error "Socket Error" {Error: Unable to make socket connection. Make sure the STK socket server is first running and that the port number is correct.} "" 0 OK
} }
pack $d.buttons.cancel -side left -padx 5 -pady 10
pack $d.buttons.connect -side right -padx 5 -pady 10
pack $d.buttons -side bottom -padx 5 -pady 10
}
}