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);

1
projects/effects/Effects Executable file
View File

@@ -0,0 +1 @@
wish < tcl/Effects.tcl | ./effects -ip

View File

@@ -1 +1 @@
wish < tcl/Effects.tcl | ./effects -ip
wish < tcl/Effects.tcl | effects -ip

View File

@@ -6,11 +6,11 @@ SRC_PATH = ../../src
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
OBJECTS = Stk.o Reverb.o PRCRev.o JCRev.o \
NRev.o Delay.o Filter.o \
SKINI.o Envelope.o Echo.o \
PitShift.o DelayL.o Chorus.o \
WvIn.o WaveLoop.o Messager.o
OBJECTS = Stk.o Generator.o Envelope.o \
Filter.o Delay.o DelayL.o \
Effect.o Echo.o PitShift.o Chorus.o \
PRCRev.o JCRev.o NRev.o \
WvIn.o WaveLoop.o Skini.o Messager.o
INCLUDE = @include@
ifeq ($(strip $(INCLUDE)), )
@@ -28,9 +28,8 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
OBJECTS += RtMidi.o RtAudio.o RtDuplex.o Thread.o Socket.o
OBJECTS += RtMidi.o RtAudio.o Thread.o Mutex.o Socket.o
DEFS += @audio_apis@
DEFS += @midiator@
endif
RAWWAVES = @rawwaves@
@@ -47,6 +46,9 @@ all : $(PROGRAMS)
effects: effects.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o effects effects.cpp $(OBJECT_PATH)/*.o $(LIBRARY)
libeffects: effects.cpp
$(CC) $(CFLAGS) $(DEFS) -o effects effects.cpp -L../../src $(LIBRARY) -lstk
$(OBJECTS) : Stk.h
clean :

View File

@@ -1,7 +1,6 @@
/************** Effects Program *********************/
#include "RtDuplex.h"
#include "SKINI.h"
#include "Skini.h"
#include "SKINI.msg"
#include "Envelope.h"
#include "PRCRev.h"
@@ -10,183 +9,256 @@
#include "Echo.h"
#include "PitShift.h"
#include "Chorus.h"
// The input control handler.
#include "Messager.h"
#include "RtAudio.h"
#include <signal.h>
#include <iostream>
#include <algorithm>
#if !defined(__OS_WINDOWS__) // Windoze bogosity for VC++ 6.0
using std::min;
#endif
void usage(void) {
/* Error function in case of incorrect command-line argument specifications */
printf("\nuseage: effects flags \n");
printf(" where flag = -s RATE to specify a sample rate,\n");
printf(" flag = -ip for realtime SKINI input by pipe\n");
printf(" (won't work under Win95/98),\n");
printf(" and flag = -is <port> for realtime SKINI input by socket.\n");
// Error function in case of incorrect command-line argument specifications
std::cout << "\nuseage: effects flags \n";
std::cout << " where flag = -s RATE to specify a sample rate,\n";
std::cout << " flag = -ip for realtime SKINI input by pipe\n";
std::cout << " (won't work under Win95/98),\n";
std::cout << " and flag = -is <port> for realtime SKINI input by socket.\n";
exit(0);
}
int main(int argc,char *argv[])
bool done;
static void finish(int ignore){ done = true; }
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
Effect *effect;
PRCRev prcrev;
JCRev jcrev;
NRev nrev;
Echo echo;
PitShift shifter;
Chorus chorus;
Envelope envelope;
Messager messager;
Skini::Message message;
StkFloat lastSample;
StkFloat t60;
int counter;
bool settling;
bool haveMessage;
// Default constructor.
TickData()
: effect(0), t60(1.0), counter(0),
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 )
{
register unsigned int value1 = data->message.intValues[0];
register StkFloat value2 = data->message.floatValues[1];
register StkFloat temp = value2 * ONE_OVER_128;
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->envelope.setTarget( 0.0 );
else // a NoteOn
data->envelope.setTarget( 1.0 );
break;
case __SK_NoteOff_:
data->envelope.setTarget( 0.0 );
break;
case __SK_ControlChange_:
// Change all effect values so they are "synched" to the interface.
switch ( value1 ) {
case 20: { // effect type change
int type = data->message.intValues[1];
if ( type == 0 )
data->effect = &(data->echo);
else if ( type == 1 )
data->effect = &(data->shifter);
else if ( type == 2 )
data->effect = &(data->chorus);
else if ( type == 3 )
data->effect = &(data->prcrev);
else if ( type == 4 )
data->effect = &(data->jcrev);
else if ( type == 5 )
data->effect = &(data->nrev);
break;
}
case 22: // effect parameter change 1
data->echo.setDelay( (unsigned long) (temp * Stk::sampleRate() * 0.95) );
// data->shifter.setShift( temp * 3 + 0.25);
data->shifter.setShift( 1.4 * temp + 0.3);
data->chorus.setModFrequency( temp );
data->prcrev.setT60( temp * 10.0 );
data->jcrev.setT60( temp * 10.0 );
data->nrev.setT60( temp * 10.0 );
break;
case 23: // effect parameter change 2
data->chorus.setModDepth( temp * 0.2 );
break;
case 44: // effect mix
data->echo.setEffectMix( temp );
data->shifter.setEffectMix( temp );
data->chorus.setEffectMix( temp );
data->prcrev.setEffectMix( temp );
data->jcrev.setEffectMix( temp );
data->nrev.setEffectMix( temp );
break;
default:
break;
}
} // end of type switch
data->haveMessage = false;
return;
settle:
// Exit and program change messages are preceeded with a short settling period.
data->envelope.setTarget( 0.0 );
data->counter = (int) (0.3 * data->t60 * Stk::sampleRate());
data->settling = true;
}
// The tick() function handles sample computation and scheduling of
// control updates. It will be called automatically by RtAudio 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 i, 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 ( i=0; i<counter; i++ ) {
sample = data->envelope.tick() * data->effect->tick( *samples );
*samples++ = sample; // two channels interleaved
*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;
RtAudio *adac = 0;
int i;
if (argc < 2 || argc > 6) usage();
// If you want to change the default sample rate (set in Stk.h), do
// it before instantiating any objects! If the sample rate is
// specified in the command line, it will override this setting.
Stk::setSampleRate(22050.0);
Stk::setSampleRate( 44100.0 );
int port = -1;
int controlMask = 0;
for (int k=1; k<argc; k++ ) {
if (!strcmp(argv[k],"-is") ) {
controlMask |= STK_SOCKET;
if (k+1 < argc && argv[k+1][0] != '-' ) port = atoi(argv[++k]);
// Parse the command-line arguments.
unsigned int port = 2001;
for ( i=1; i<argc; i++ ) {
if ( !strcmp( argv[i], "-is" ) ) {
if ( i+1 < argc && argv[i+1][0] != '-' ) port = atoi(argv[++i]);
data.messager.startSocketInput( port );
}
else if (!strcmp(argv[k],"-ip") )
controlMask |= STK_PIPE;
else if (!strcmp(argv[k],"-s") && (k+1 < argc) && argv[k+1][0] != '-')
Stk::setSampleRate( atoi(argv[++k]) );
else if (!strcmp( argv[i], "-ip" ) )
data.messager.startStdInput();
else if ( !strcmp( argv[i], "-s" ) && ( i+1 < argc ) && argv[i+1][0] != '-')
Stk::setSampleRate( atoi(argv[++i]) );
else
usage();
}
bool done;
int effect = 0;
MY_FLOAT lastSample, inSample;
Envelope *envelope = new Envelope;
PRCRev *prcrev = new PRCRev(2.0);
JCRev *jcrev = new JCRev(2.0);
NRev *nrev = new NRev(2.0);
Echo *echo = new Echo( (long) Stk::sampleRate() ); // one second delay
PitShift *shifter = new PitShift();
Chorus *chorus = new Chorus(5000.0);
SKINI *score = new SKINI();
Messager *messager = 0;
RtDuplex *inout = 0;
// Allocate the adac here.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
// Change the nBuffers parameter to a smaller number to get better input/output latency.
inout = new RtDuplex(1, Stk::sampleRate(), 0, RT_BUFFER_SIZE, 10);
// Instantiate the input message controller.
if ( controlMask & STK_SOCKET && port >= 0 )
messager = new Messager( controlMask, port );
else
messager = new Messager( controlMask );
adac = new RtAudio(0, 2, 0, 2, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (StkError &) {
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
// The runtime loop begins here:
long i, nTicks;
int type;
lastSample = 0.0;
inSample = 0.0;
MY_FLOAT byte2, byte3;
done = FALSE;
while (!done) {
data.envelope.setRate( 0.001 );
data.effect = &(data.echo);
// Look for new messages and return a delta time (in samples).
type = messager->nextMessage();
if (type < 0)
done = TRUE;
// Install an interrupt handler function.
(void) signal( SIGINT, finish );
nTicks = messager->getDelta();
for (i=0; i<nTicks; i++) {
if (effect == 0)
inSample = inout->tick(envelope->tick() * echo->tick(lastSample));
else if (effect == 1)
inSample = inout->tick(envelope->tick() * shifter->tick(lastSample));
else if (effect == 2)
inSample = inout->tick(envelope->tick() * chorus->tick(lastSample));
else if (effect == 3)
inSample = inout->tick(envelope->tick() * prcrev->tick(lastSample));
else if (effect == 4)
inSample = inout->tick(envelope->tick() * jcrev->tick(lastSample));
else if (effect == 5)
inSample = inout->tick(envelope->tick() * nrev->tick(lastSample));
lastSample = inSample;
}
if (type > 0) {
// parse the input control message
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_NoteOn_:
if (byte3 == 0) { // velocity is zero ... really a NoteOff
envelope->setRate(0.001);
envelope->setTarget(0.0);
}
else { // really a NoteOn
envelope->setRate(0.001);
envelope->setTarget(1.0);
}
break;
case __SK_NoteOff_:
envelope->setRate(0.001);
envelope->setTarget(0.0);
break;
case __SK_ControlChange_:
if (byte2 == 20) effect = (int) byte3; // effect change
else if (byte2 == 44) { // effects mix
echo->setEffectMix(byte3*ONE_OVER_128);
shifter->setEffectMix(byte3*ONE_OVER_128);
chorus->setEffectMix(byte3*ONE_OVER_128);
prcrev->setEffectMix(byte3*ONE_OVER_128);
jcrev->setEffectMix(byte3*ONE_OVER_128);
nrev->setEffectMix(byte3*ONE_OVER_128);
}
else if (byte2 == 22) { // effect1 parameter change
echo->setDelay(byte3*ONE_OVER_128*Stk::sampleRate()*0.95);
shifter->setShift(byte3*ONE_OVER_128*3 + 0.25);
chorus->setModFrequency(byte3*ONE_OVER_128);
}
else if (byte2 == 23) { // effect1 parameter change
chorus->setModDepth(byte3*ONE_OVER_128*0.2);
}
break;
}
}
// If realtime output, set our callback function and start the dac.
try {
adac->setStreamCallback( &tick, (void *)&data );
adac->startStream();
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
envelope->setRate(0.001);
envelope->setTarget(0.0);
nTicks = (long) Stk::sampleRate();
for (i=0; i<nTicks; i++) { // let the sound settle a bit
if (effect == 0)
inSample = inout->tick(envelope->tick() * echo->tick(lastSample));
else if (effect == 1)
inSample = inout->tick(envelope->tick() * shifter->tick(lastSample));
else if (effect == 2)
inSample = inout->tick(envelope->tick() * chorus->tick(lastSample));
else if (effect == 3)
inSample = inout->tick(envelope->tick() * prcrev->tick(lastSample));
else if (effect == 4)
inSample = inout->tick(envelope->tick() * jcrev->tick(lastSample));
else if (effect == 5)
inSample = inout->tick(envelope->tick() * nrev->tick(lastSample));
lastSample = inSample;
// Setup finished.
while ( !done ) {
// Periodically check "done" status.
Stk::sleep( 50 );
}
delete echo;
delete shifter;
delete chorus;
delete prcrev;
delete jcrev;
delete nrev;
delete score;
delete envelope;
// Shut down the callback and output stream.
try {
adac->cancelStreamCallback();
adac->closeStream();
}
catch (RtError& error) {
error.printMessage();
}
cleanup:
delete messager;
delete inout;
printf("effects finished ... goodbye.\n");
delete adac;
std::cout << "\neffects 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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -67,7 +67,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 /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -118,6 +118,14 @@ SOURCE=..\..\include\Echo.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Effect.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Effect.h
# End Source File
# Begin Source File
SOURCE=.\effects.cpp
# End Source File
# Begin Source File
@@ -138,6 +146,14 @@ SOURCE=..\..\include\Filter.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Generator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Generator.h
# End Source File
# Begin Source File
SOURCE=..\..\src\JCRev.cpp
# End Source File
# Begin Source File
@@ -154,6 +170,14 @@ SOURCE=..\..\include\Messager.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Mutex.h
# End Source File
# Begin Source File
SOURCE=..\..\src\NRev.cpp
# End Source File
# Begin Source File
@@ -178,14 +202,6 @@ SOURCE=..\..\include\PRCRev.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Reverb.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Reverb.h
# End Source File
# Begin Source File
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -194,14 +210,6 @@ SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File
SOURCE=..\..\src\RtDuplex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\RtDuplex.h
# End Source File
# Begin Source File
SOURCE=..\..\src\RtMidi.cpp
# End Source File
# Begin Source File

View File

@@ -26,7 +26,7 @@ label .title -text "STK Effects 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" \
label .title2 -text "by Gary P. Scavone\n Music Technology, McGill University" \
-font {Times 12 bold} -background white \
-foreground darkred -relief raised
@@ -50,7 +50,7 @@ frame .left -bg black
scale .left.effectsmix -from 0 -to 127 -length 400 \
-command {printWhatz "ControlChange 0.0 1 " 44} \
-orient horizontal -label "Effects Mix" \
-orient horizontal -label "Effects Mix (0% effect - 100% effect)" \
-tickinterval 32 -showvalue true -bg grey66 \
-variable mixlevel
@@ -132,7 +132,7 @@ proc changeEffect {tag value1 value2 } {
.left.effect2 config -state disabled -label "Disabled"
}
if ($value2==1) {
.left.effect1 config -state normal -label "Pitch Shift Amount"
.left.effect1 config -state normal -label "Pitch Shift Amount (center = no shift)"
.left.effect2 config -state disabled -label "Disabled"
}
if ($value2==2) {
@@ -140,7 +140,7 @@ proc changeEffect {tag value1 value2 } {
.left.effect2 config -state normal -label "Chorus Modulation Depth"
}
if {$value2>=3 && $value2<=5} {
.left.effect1 config -state disabled -label "Disabled"
.left.effect1 config -state normal -label "T60 Decay Time ( 0 - 10 seconds)"
.left.effect2 config -state disabled -label "Disabled"
}
puts $outID [format "%s %i %f" $tag $value1 $value2]

View File

@@ -1,6 +1,6 @@
### STK examples Makefile - for various flavors of unix
PROGRAMS = sine play record io tcpIn tcpOut sineosc rtsine bethree controlbee foursine threebees
PROGRAMS = sine play record io tcpIn tcpOut sineosc rtsine crtsine bethree controlbee foursine threebees playsmf
RM = /bin/rm
SRC_PATH = ../../src
OBJECT_PATH = @object_path@
@@ -23,7 +23,6 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
DEFS += @audio_apis@
DEFS += @midiator@
endif
RAWWAVES = @rawwaves@
@@ -46,8 +45,8 @@ clean :
strip :
strip $(PROGRAMS)
play: play.cpp Stk.o WvIn.o WvOut.o RtWvOut.o RtAudio.o
$(CC) $(CFLAGS) $(DEFS) -o play play.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
play: play.cpp Stk.o WvIn.o RtAudio.o
$(CC) $(CFLAGS) $(DEFS) -o play play.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
record: record.cpp Stk.o WvIn.o WvOut.o RtWvIn.o RtAudio.o
$(CC) $(CFLAGS) $(DEFS) -o record record.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvIn.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
@@ -58,11 +57,11 @@ sine: sine.cpp Stk.o WvIn.o WvOut.o WaveLoop.o
io: io.cpp Stk.o RtAudio.o RtDuplex.o
$(CC) $(CFLAGS) $(DEFS) -o io io.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/RtDuplex.o $(LIBRARY)
tcpIn: tcpIn.cpp Stk.o WvIn.o TcpWvIn.o WvOut.o RtWvOut.o RtAudio.o Socket.o Thread.o
$(CC) $(CFLAGS) $(DEFS) -o tcpIn tcpIn.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/TcpWvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
tcpIn: tcpIn.cpp Stk.o WvIn.o TcpWvIn.o WvOut.o RtWvOut.o RtAudio.o Socket.o Thread.o Mutex.o
$(CC) $(CFLAGS) $(DEFS) -o tcpIn tcpIn.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/TcpWvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
tcpOut: tcpOut.cpp Stk.o WvIn.o WvOut.o TcpWvOut.o Socket.o Thread.o
$(CC) $(CFLAGS) $(DEFS) -o tcpOut tcpOut.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/TcpWvOut.o $(LIBRARY)
tcpOut: tcpOut.cpp Stk.o WvIn.o WvOut.o TcpWvOut.o Socket.o Thread.o Mutex.o
$(CC) $(CFLAGS) $(DEFS) -o tcpOut tcpOut.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/TcpWvOut.o $(LIBRARY)
sineosc: sineosc.cpp Stk.o WvIn.o WvOut.o WaveLoop.o
$(CC) $(CFLAGS) $(DEFS) -o sineosc sineosc.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/WaveLoop.o $(LIBRARY)
@@ -70,14 +69,20 @@ sineosc: sineosc.cpp Stk.o WvIn.o WvOut.o WaveLoop.o
rtsine: rtsine.cpp Stk.o WvIn.o WaveLoop.o WvOut.o RtWvOut.o RtAudio.o
$(CC) $(CFLAGS) $(DEFS) -o rtsine rtsine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
bethree: bethree.cpp Stk.o WvIn.o WaveLoop.o FM.o WvOut.o RtWvOut.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Envelope.o ADSR.o BeeThree.o
$(CC) $(CFLAGS) $(DEFS) -o bethree bethree.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(LIBRARY)
crtsine: crtsine.cpp Stk.o WvIn.o WaveLoop.o RtAudio.o
$(CC) $(CFLAGS) $(DEFS) -o crtsine crtsine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
controlbee: controlbee.cpp Stk.o WvIn.o WaveLoop.o FM.o WvOut.o RtWvOut.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Envelope.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o Thread.o SKINI.o
$(CC) $(CFLAGS) $(DEFS) -o controlbee controlbee.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/SKINI.o $(LIBRARY)
bethree: bethree.cpp Stk.o WvIn.o WaveLoop.o FM.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Generator.o Envelope.o ADSR.o BeeThree.o
$(CC) $(CFLAGS) $(DEFS) -o bethree bethree.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(LIBRARY)
controlbee: controlbee.cpp Stk.o WvIn.o WaveLoop.o FM.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Generator.o Envelope.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o Thread.o Mutex.o Skini.o
$(CC) $(CFLAGS) $(DEFS) -o controlbee controlbee.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/Skini.o $(LIBRARY)
foursine: foursine.cpp Stk.o WvIn.o WvOut.o WaveLoop.o
$(CC) $(CFLAGS) $(DEFS) -o foursine foursine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/WaveLoop.o $(LIBRARY)
threebees: threebees.cpp Stk.o WvIn.o WaveLoop.o FM.o WvOut.o RtWvOut.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Envelope.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o Thread.o SKINI.o Voicer.o
$(CC) $(CFLAGS) $(DEFS) -o threebees threebees.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/SKINI.o $(OBJECT_PATH)/Voicer.o $(LIBRARY)
threebees: threebees.cpp Stk.o WvIn.o WaveLoop.o FM.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Generator.o Envelope.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o Thread.o Mutex.o Skini.o Voicer.o
$(CC) $(CFLAGS) $(DEFS) -o threebees threebees.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/Skini.o $(OBJECT_PATH)/Voicer.o $(LIBRARY)
playsmf: playsmf.cpp Stk.o MidiFileIn.o RtMidi.o
$(CC) $(CFLAGS) $(DEFS) -o playsmf playsmf.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/MidiFileIn.o $(OBJECT_PATH)/RtMidi.o $(LIBRARY)

View File

@@ -1,7 +1,43 @@
// bethree.cpp STK tutorial program
#include "BeeThree.h"
#include "RtWvOut.h"
#include "RtAudio.h"
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
Instrmnt *instrument;
StkFloat frequency;
StkFloat scaler;
long counter;
bool done;
// Default constructor.
TickData()
: instrument(0), scaler(1.0), counter(0), done( false ) {}
};
// This tick() function handles sample computation only. 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 *samples = (StkFloat *) buffer;
for ( int i=0; i<bufferSize; i++ ) {
*samples++ = data->instrument->tick();
if ( ++data->counter % 2000 == 0 ) {
data->scaler += 0.025;
data->instrument->setFrequency( data->frequency * data->scaler );
}
}
if ( data->counter > 80000 )
data->done = true;
return 0;
}
int main()
{
@@ -9,50 +45,56 @@ int main()
Stk::setSampleRate( 44100.0 );
Stk::setRawwavePath( "../../rawwaves/" );
Instrmnt *instrument = 0;
RtWvOut *output = 0;
MY_FLOAT frequency, amplitude, scaler;
long counter, i;
TickData data;
RtAudio *dac = 0;
// Figure out how many bytes in an StkFloat and setup the RtAudio object.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
dac = new RtAudio(0, 1, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
try {
// Define and load the BeeThree instrument
instrument = new BeeThree();
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
data.instrument = new BeeThree();
}
catch (StkError &) {
goto cleanup;
}
scaler = 1.0;
frequency = 220.0;
amplitude = 0.5;
instrument->noteOn( frequency, amplitude );
data.frequency = 220.0;
data.instrument->noteOn( data.frequency, 0.5 );
// Play the instrument for 80000 samples, changing the frequency every 2000 samples
counter = 0;
while ( counter < 80000 ) {
for ( i=0; i<2000; i++ ) {
try {
output->tick( instrument->tick() );
}
catch (StkError &) {
goto cleanup;
}
}
counter += 2000;
scaler += 0.025;
instrument->setFrequency( frequency * scaler );
try {
dac->setStreamCallback(&tick, (void *)&data);
dac->startStream();
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// Turn the instrument off with maximum decay envelope.
instrument->noteOff( 1.0 );
// Block waiting until callback signals done.
while ( !data.done )
Stk::sleep( 100 );
// Shut down the callback and output stream.
try {
dac->cancelStreamCallback();
dac->closeStream();
}
catch (RtError &error) {
error.printMessage();
}
cleanup:
delete instrument;
delete output;
delete data.instrument;
delete dac;
return 0;
}

View File

@@ -42,14 +42,14 @@ 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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /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__" /D "__WINDOWS_MM__" /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 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 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 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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "bethree - Win32 Debug"
@@ -65,15 +65,15 @@ LINK32=link.exe
# 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 /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 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 "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /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 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 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 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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
@@ -111,6 +111,10 @@ SOURCE=..\..\src\FM.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Generator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Instrmnt.cpp
# End Source File
# Begin Source File
@@ -167,6 +171,10 @@ SOURCE=..\..\include\FM.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Generator.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Instrmnt.h
# End Source File
# Begin Source File

View File

@@ -1,91 +1,175 @@
// controlbee.cpp STK tutorial program
#include "BeeThree.h"
#include "RtWvOut.h"
#include "RtAudio.h"
#include "Messager.h"
#include "SKINI.msg"
#include <math.h>
#include <algorithm>
#if !defined(__OS_WINDOWS__) // Windoze bogosity for VC++ 6.0
using std::min;
#endif
int main()
void usage(void) {
// Error function in case of incorrect command-line
// argument specifications.
std::cout << "\nuseage: controlbee file\n";
std::cout << " where file = a SKINI scorefile.\n\n";
exit(0);
}
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
Instrmnt *instrument;
Messager messager;
Skini::Message message;
int counter;
bool haveMessage;
bool done;
// Default constructor.
TickData()
: instrument(0), counter(0), haveMessage(false), done( 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 )
{
register StkFloat value1 = data->message.floatValues[0];
register StkFloat value2 = data->message.floatValues[1];
switch( data->message.type ) {
case __SK_Exit_:
data->done = true;
return;
case __SK_NoteOn_:
if ( value2 == 0.0 ) // velocity is zero ... really a NoteOff
data->instrument->noteOff( 0.5 );
else { // a NoteOn
StkFloat frequency = 220.0 * pow( 2.0, (value1 - 57.0) / 12.0 );
data->instrument->noteOn( frequency, value2 * ONE_OVER_128 );
}
break;
case __SK_NoteOff_:
data->instrument->noteOff( value2 * ONE_OVER_128 );
break;
case __SK_ControlChange_:
data->instrument->controlChange( (int) value1, value2 );
break;
case __SK_AfterTouch_:
data->instrument->controlChange( 128, value1 );
} // end of switch
data->haveMessage = false;
return;
}
// This tick() function handles sample computation and scheduling of
// control updates. 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 *samples = (StkFloat *) buffer;
int counter, nTicks = bufferSize;
while ( nTicks > 0 && !data->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++ ) {
*samples++ = data->instrument->tick();
nTicks--;
}
if ( nTicks == 0 ) break;
// Process control messages.
if ( data->haveMessage ) processMessage( data );
}
return 0;
}
int main( int argc, char *argv[] )
{
if ( argc != 2 ) usage();
// Set the global sample rate and rawwave path before creating class instances.
Stk::setSampleRate( 44100.0 );
Stk::setRawwavePath( "../../rawwaves/" );
Instrmnt *instrument = 0;
RtWvOut *output = 0;
Messager *messager = 0;
bool done = FALSE;
TickData data;
RtAudio *dac = 0;
// Figure out how many bytes in an StkFloat and setup the RtAudio object.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
dac = new RtAudio(0, 1, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
try {
// Define and load the BeeThree instrument
instrument = new BeeThree();
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
data.instrument = new BeeThree();
}
catch (StkError &) {
goto cleanup;
}
if ( data.messager.setScoreFile( argv[1] ) == false )
goto cleanup;
try {
// Create a Messager instance to read from a redirected SKINI scorefile.
messager = new Messager();
dac->setStreamCallback(&tick, (void *)&data);
dac->startStream();
}
catch (StkError &) {
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// Play the instrument until the end of the scorefile.
int i, nTicks, type;
MY_FLOAT byte2, byte3, frequency;
while (!done) {
// Look for new messages and return a delta time (in samples).
type = messager->nextMessage();
if (type < 0)
done = TRUE;
nTicks = messager->getDelta();
try {
for ( i=0; i<nTicks; i++ )
output->tick( instrument->tick() );
}
catch (StkError &) {
goto cleanup;
}
if ( type > 0 ) {
// Process the new control message.
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_NoteOn_:
frequency = (MY_FLOAT) 220.0 * pow( 2.0, (byte2 - 57.0) / 12.0 );
instrument->noteOn( frequency, byte3 * ONE_OVER_128 );
break;
case __SK_NoteOff_:
instrument->noteOff( byte3 * ONE_OVER_128 );
break;
case __SK_ControlChange_:
instrument->controlChange( (int) byte2, byte3 );
break;
case __SK_AfterTouch_:
instrument->controlChange( 128, byte2 );
break;
}
}
// Block waiting until callback signals done.
while ( !data.done )
Stk::sleep( 100 );
// Shut down the callback and output stream.
try {
dac->cancelStreamCallback();
dac->closeStream();
}
catch (RtError &error) {
error.printMessage();
}
cleanup:
delete instrument;
delete output;
delete messager;
delete data.instrument;
delete dac;
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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /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__" /D "__WINDOWS_MM__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -67,7 +67,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 "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -112,6 +112,10 @@ SOURCE=..\..\src\FM.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Generator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Instrmnt.cpp
# End Source File
# Begin Source File
@@ -120,6 +124,10 @@ SOURCE=..\..\src\Messager.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -196,6 +204,10 @@ SOURCE=..\..\include\Messager.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Mutex.h
# End Source File
# Begin Source File
SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File

View File

@@ -0,0 +1,78 @@
// crtsine.cpp STK tutorial program
#include "WaveLoop.h"
#include "RtAudio.h"
// This tick() function handles sample computation only. It will be
// called automatically when the system needs a new buffer of audio
// samples.
int tick(char *buffer, int bufferSize, void *dataPointer)
{
WaveLoop *sine = (WaveLoop *) dataPointer;
register StkFloat *samples = (StkFloat *) buffer;
for ( int i=0; i<bufferSize; i++ )
*samples++ = sine->tick();
return 0;
}
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
WaveLoop *sine = 0;
RtAudio *dac = 0;
// Figure out how many bytes in an StkFloat and setup the RtAudio object.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
dac = new RtAudio(0, 1, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
try {
// Define and load the sine wave file
sine = new WaveLoop( "rawwaves/sinewave.raw", true );
}
catch (StkError &) {
goto cleanup;
}
sine->setFrequency(440.0);
try {
dac->setStreamCallback(&tick, (void *)sine);
dac->startStream();
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// Block waiting here.
char keyhit;
std::cout << "\nPlaying ... press <enter> to quit.\n";
std::cin.get(keyhit);
// Shut down the callback and output stream.
try {
dac->cancelStreamCallback();
dac->closeStream();
}
catch (RtError &error) {
error.printMessage();
}
cleanup:
delete sine;
delete dac;
return 0;
}

134
projects/examples/crtsine.dsp Executable file
View File

@@ -0,0 +1,134 @@
# Microsoft Developer Studio Project File - Name="crtsine" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=crtsine - 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 "crtsine.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 "crtsine.mak" CFG="crtsine - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "crtsine - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "crtsine - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "crtsine - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "crtsine___Win32_Release"
# PROP BASE Intermediate_Dir "crtsine___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /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 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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "crtsine - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "crtsine___Win32_Debug"
# PROP BASE Intermediate_Dir "crtsine___Win32_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 /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 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 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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "crtsine - Win32 Release"
# Name "crtsine - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\crtsine.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\WaveLoop.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\WvIn.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Stk.h
# End Source File
# Begin Source File
SOURCE=..\..\include\WaveLoop.h
# End Source File
# Begin Source File
SOURCE=..\..\include\WvIn.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -27,6 +27,18 @@ Package=<4>
###############################################################################
Project: "crtsine"=".\crtsine.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "foursine"=".\foursine.dsp" - Package Owner=<4>
Package=<5>

View File

@@ -16,7 +16,7 @@ int main()
// Define and load the sine waves
try {
for ( i=0; i<4; i++ ) {
inputs[i] = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
inputs[i] = new WaveLoop( "rawwaves/sinewave.raw", true );
inputs[i]->setFrequency( 220.0 * (i+1) );
}
}
@@ -33,7 +33,7 @@ int main()
}
// Write two seconds of four sines to the output file
MY_FLOAT frame[4];
StkFloat frame[4];
for ( j=0; j<88200; j++ ) {
for ( i=0; i<4; i++ )
frame[i] = inputs[i]->tick();

View File

@@ -41,15 +41,15 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# 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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /D "__WINDOWS_DS__" /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 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 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 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 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 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
!ELSEIF "$(CFG)" == "foursine - Win32 Debug"
@@ -63,16 +63,16 @@ LINK32=link.exe
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# 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__" /YX /FD /GZ /c
# 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_MM__" /D "__WINDOWS_DS__" /YX /FD /GZ /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 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 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 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 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 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
!ENDIF

View File

@@ -1,15 +1,25 @@
/******************************************/
/*
Example program for realtime input/output
by Gary P. Scavone, 2000
by Gary P. Scavone, 2000.
This program reads N channels of realtime
audio input for a specified amount of time
and immediately play them back in realtime
(duplex mode). This program also demonstrates
the use of FIFO scheduling priority. To be
run with such priority, the program must be
set suid (chmod +s) and owned by root.
NOTE: This program makes use of blocking audio
input/output routines. On systems where the
underlying audio API is based on a callback scheme
(Macintosh OS-X, Windows ASIO, and Linux JACK), these
routines are not fully robust (over/underruns can
happen with some frequency). See the STK tutorial
for example programs using callback schemes and/or
visit the RtAudio tutorial page
(http://music.mcgill.ca/~gary/rtaudio/) for more
information.
This program reads N channels of realtime audio input
for a specified amount of time and immediately play
them back in realtime (duplex mode). This program
also demonstrates the use of FIFO scheduling
priority. To be run with such priority, the program
must be set suid (chmod +s) and owned by root.
*/
/******************************************/
@@ -37,7 +47,7 @@ main(int argc, char *argv[])
if (argc != 3) usage();
unsigned int channels = (unsigned int) atoi(argv[1]);
float time = atof(argv[2]);
double time = atof(argv[2]);
// If you want to change the default sample rate (set in Stk.h), do
// it before instantiating any objects! If the sample rate is
@@ -72,8 +82,8 @@ main(int argc, char *argv[])
// Here's the runtime loop
unsigned long i, counter = 0;
MY_FLOAT *newFrame = new MY_FLOAT[channels];
const MY_FLOAT *lastFrame = inout->lastFrame();
StkFloat *newFrame = new StkFloat[channels];
const StkFloat *lastFrame = inout->lastFrame();
unsigned long samples = (unsigned long) (time * Stk::sampleRate());
while ( counter < samples ) {
for ( i=0; i<channels; i++ )

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 "__LITTLE_ENDIAN__" /D "WIN32" /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__" /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__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe

View File

@@ -1,6 +1,6 @@
### STK examples Makefile - for various flavors of unix
PROGRAMS = sine play record io tcpIn tcpOut sineosc rtsine bethree controlbee foursine threebees
PROGRAMS = sine play record io tcpIn tcpOut sineosc rtsine crtsine bethree controlbee foursine threebees playsmf
RM = /bin/rm
INCLUDE = @include@
@@ -64,6 +64,9 @@ sineosc: sineosc.cpp
rtsine: rtsine.cpp
$(CC) $(CFLAGS) $(DEFS) -o rtsine rtsine.cpp -L../../src $(LIBRARY) -lstk
crtsine: crtsine.cpp
$(CC) $(CFLAGS) $(DEFS) -o crtsine crtsine.cpp -L../../src $(LIBRARY) -lstk
bethree: bethree.cpp
$(CC) $(CFLAGS) $(DEFS) -o bethree bethree.cpp -L../../src $(LIBRARY) -lstk
@@ -75,3 +78,7 @@ foursine: foursine.cpp
threebees: threebees.cpp
$(CC) $(CFLAGS) $(DEFS) -o threebees threebees.cpp -L../../src $(LIBRARY) -lstk
playsmf: playsmf.cpp
$(CC) $(CFLAGS) $(DEFS) -o playsmf playsmf.cpp -L../../src $(LIBRARY) -lstk

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -9,31 +9,62 @@
the number of channels or sample rate of
the soundfile, the program will stop.
By Gary P. Scavone, 2000 - 2002.
By Gary P. Scavone, 2000 - 2004.
*/
/******************************************/
#include "RtWvOut.h"
#include "WvIn.h"
#include <stdlib.h>
#include "RtAudio.h"
#include <signal.h>
#include <iostream>
// Eewww ... global variables! :-)
bool done;
StkFrames frames;
static void finish(int ignore){ done = true; }
void usage(void) {
// Error function in case of incorrect command-line
// argument specifications.
printf("\nuseage: play file <rate>\n");
printf(" where file = the file to play,\n");
printf(" and rate = an optional playback rate.\n");
printf(" (default = 1.0, can be negative)\n\n");
std::cout << "\nuseage: play file sr <rate>\n";
std::cout << " where file = the file to play,\n";
std::cout << " where sr = sample rate,\n";
std::cout << " and rate = an optional playback rate.\n";
std::cout << " (default = 1.0, can be negative)\n\n";
exit(0);
}
// This tick() function handles sample computation only. It will be
// called automatically when the system needs a new buffer of audio
// samples.
int tick(char *buffer, int bufferSize, void *dataPointer)
{
WvIn *input = (WvIn *) dataPointer;
register StkFloat *samples = (StkFloat *) buffer;
input->tickFrame( frames );
for ( unsigned int i=0; i<frames.size(); i++ )
*samples++ = frames[i];
if ( input->isFinished() ) {
done = true;
return 1;
}
else
return 0;
}
int main(int argc, char *argv[])
{
// Minimal command-line checking.
if (argc < 2 || argc > 3) usage();
if (argc < 3 || argc > 4) usage();
// Initialize our WvIn/WvOut pointers.
RtWvOut *output = 0;
// Set the global sample rate before creating class instances.
Stk::setSampleRate( (StkFloat) atof(argv[2]) );
// Initialize our WvIn and RtAudio pointers.
RtAudio *dac = 0;
WvIn *input = 0;
// Try to load the soundfile.
@@ -45,29 +76,57 @@ int main(int argc, char *argv[])
}
// Set input read rate based on the default STK sample rate.
float rate = 1.0;
double rate = 1.0;
rate = input->getFileRate() / Stk::sampleRate();
if ( argc == 3 ) rate *= atof(argv[2]);
if ( argc == 4 ) rate *= atof(argv[3]);
input->setRate( rate );
// Find out how many channels we have.
int channels = input->getChannels();
// Define and open the realtime output device
// Define and open the realtime output device.
// Figure out how many bytes in an StkFloat and setup the RtAudio object.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
output = new RtWvOut( channels, Stk::sampleRate(), 0, RT_BUFFER_SIZE, 4 );
dac = new RtAudio(0, channels, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (StkError &) {
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// Here's the runtime loop.
while (!input->isFinished()) {
output->tickFrame( input->tickFrame() );
// Install an interrupt handler function.
(void) signal(SIGINT, finish);
// Resize the StkFrames object appropriately.
frames.resize( bufferSize, channels );
try {
dac->setStreamCallback(&tick, (void *)input);
dac->startStream();
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// Block waiting until callback signals done.
while ( !done )
Stk::sleep( 100 );
// By returning a non-zero value in the callback above, the stream
// is automatically stopped. But we should still close it.
try {
dac->cancelStreamCallback();
dac->closeStream();
}
catch (RtError &error) {
error.printMessage();
}
cleanup:
delete input;
delete output;
delete dac;
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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /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__" /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__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe

View File

@@ -0,0 +1,122 @@
// playsmf.cpp
//
// Simple program to test the MidiFileIn class by reading and playing
// a single track from a given Standard MIDI file.
//
// by Gary Scavone, 2003.
#include "MidiFileIn.h"
#include "RtMidi.h"
#include <signal.h>
#include <unistd.h>
bool done = false;
static void finish(int ignore){ done = true; }
void usage(void) {
// Error function in case of incorrect command-line
// argument specifications.
std::cout << "\nusage: playsmf file track <port>\n";
std::cout << " where file = a standard MIDI file,\n";
std::cout << " track = the track to play (0 = 1st track),\n";
std::cout << " and an optional port integer identifier can be specified\n";
std::cout << " (default = 0) or a value of -1 to use a virtual MIDI output port.\n\n";
exit(0);
}
int main( int argc, char *argv[] )
{
RtMidiOut *midiout = 0;
if ( argc < 3 || argc > 4 ) usage();
// Attempt to instantiate MIDI output class.
try {
midiout = new RtMidiOut();
}
catch ( RtError& error ) {
error.printMessage();
exit(0);
}
// Check command-line arguments.
int port = 0;
if ( argc == 4 ) port = atoi( argv[3] );
if ( port == -1 ) {
try {
midiout->openVirtualPort();
}
catch ( RtError& error ) {
error.printMessage();
goto cleanup;
}
std::cout << "\nVirtual port open.\n\n";
}
else {
if ( midiout->getPortCount() < 1 ) {
std::cout << "\nThere are no MIDI output destinations available!\n\n";
goto cleanup;
}
try {
midiout->openPort( port );
}
catch ( RtError& error ) {
error.printMessage();
goto cleanup;
}
}
// Install an interrupt handler function. Type "ctrl-c" to quit the
// program.
(void) signal(SIGINT, finish);
try {
MidiFileIn midiFile( argv[1] );
// Print a little information about the file.
std::cout << "\nThe MIDI file (" << argv[1] << ") information:\n";
std::cout << " - format = " << midiFile.getFileFormat() << "\n";
std::cout << " - tracks = " << midiFile.getNumberOfTracks() << "\n";
std::cout << " - seconds / ticks = " << midiFile.getTickSeconds() << "\n";
unsigned int track = (unsigned int) atoi( argv[2] );
if ( midiFile.getNumberOfTracks() <= track ) {
std::cout << "\nInvalid track number ... playing track 0.\n";
track = 0;
}
std::cout << "\nPress <enter> to start reading/playing.\n";
char input;
std::cin.get(input);
std::vector<unsigned char> event;
unsigned long ticks = midiFile.getNextMidiEvent( &event, track );
while ( !done && event.size() ) {
// Pause for the MIDI event delta time.
Stk::sleep( (unsigned long) (ticks * midiFile.getTickSeconds() * 1000 ) );
midiout->sendMessage( &event );
// Get a new event.
ticks = midiFile.getNextMidiEvent( &event, track );
}
// Send a "all notes off" to the synthesizer.
event.clear();
event.push_back( 0xb0 );
event.push_back( 0x7b );
event.push_back( 0x0 );
midiout->sendMessage( &event );
}
catch ( StkError & ) {
// You might want to do something more useful here.
std::cout << "\nAborting program!\n";
goto cleanup;
}
cleanup:
delete midiout;
return 0;
}

View File

@@ -3,6 +3,17 @@
Example program to record N channels of data
by Gary P. Scavone, 2000
NOTE: This program makes use of blocking audio
input/output routines. On systems where the
underlying audio API is based on a callback scheme
(Macintosh OS-X, Windows ASIO, and Linux JACK), these
routines are not fully robust (over/underruns can
happen with some frequency). See the STK tutorial
for example programs using callback schemes and/or
visit the RtAudio tutorial page
(http://music.mcgill.ca/~gary/rtaudio/) for more
information.
This program is currently written to read
from a realtime audio input device and to
write to a WAV output file. However, it
@@ -31,8 +42,8 @@ int main(int argc, char *argv[])
if (argc != 5) usage();
int channels = (int) atoi(argv[1]);
float sample_rate = atof(argv[4]);
float time = atof(argv[3]);
double sample_rate = atof(argv[4]);
double time = atof(argv[3]);
long samples, i;
// Set the global sample rate.

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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /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__" /D "__WINDOWS_MM__" /YX /FD /c
# SUBTRACT CPP /Fr
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -68,7 +68,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__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe

View File

@@ -8,27 +8,27 @@ int main()
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
WaveLoop *input = 0;
RtWvOut *output = 0;
WaveLoop *sine = 0;
RtWvOut *dac = 0;
try {
// Define and load the sine wave file
input = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
sine = new WaveLoop( "rawwaves/sinewave.raw", true );
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
dac = new RtWvOut(1);
}
catch (StkError &) {
goto cleanup;
}
input->setFrequency(440.0);
sine->setFrequency(440.0);
// Play the oscillator for 40000 samples
int i;
for ( i=0; i<40000; i++ ) {
try {
output->tick(input->tick());
dac->tick( sine->tick() );
}
catch (StkError &) {
goto cleanup;
@@ -36,8 +36,8 @@ int main()
}
cleanup:
delete input;
delete output;
delete sine;
delete dac;
return 0;
}

View File

@@ -42,14 +42,14 @@ 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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /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__" /D "__WINDOWS_MM__" /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 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 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 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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "rtsine - Win32 Debug"
@@ -65,15 +65,15 @@ LINK32=link.exe
# 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 /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# 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 "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /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 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 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 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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF

View File

@@ -43,7 +43,7 @@ main(int argc, char *argv[])
// Initialize our object and data pointers.
WvOut *output = 0;
MY_FLOAT *vector = 0;
StkFloat *vector = 0;
WaveLoop **oscs = (WaveLoop **) malloc( channels * sizeof(WaveLoop *) );
for (i=0; i<channels; i++) oscs[i] = 0;
@@ -54,7 +54,7 @@ main(int argc, char *argv[])
// Define and load the rawwave file(s) ... the path is critical.
try {
for (i=0; i<channels; i++)
oscs[i] = new WaveLoop( "../../rawwaves/sinewave.raw", TRUE );
oscs[i] = new WaveLoop( "../../rawwaves/sinewave.raw", true );
}
catch (StkError &) {
goto cleanup;
@@ -67,7 +67,7 @@ main(int argc, char *argv[])
// Define and open the soundfile for output. Other file
// format options include: WVOUT_SND, WVOUT_AIF, WVOUT_MAT,
// and WVOUT_RAW. Other data type options include:
// STK_SINT8, STK_SINT32, MY_FLOAT32, and MY_FLOAT64.
// STK_SINT8, STK_SINT32, StkFloat32, and StkFloat64.
try {
output = new WvOut( argv[2], channels, WvOut::WVOUT_WAV, Stk::STK_SINT16 );
}
@@ -77,7 +77,7 @@ main(int argc, char *argv[])
// Here's the runtime loop
samples = (int) ( time * Stk::sampleRate() );
vector = (MY_FLOAT *) new MY_FLOAT[channels];
vector = (StkFloat *) new StkFloat[channels];
for ( i=0; i<samples; i++ ) {
for (int j=0; j<channels; j++) {
vector[j] = oscs[j]->tick();

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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /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__" /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_MM__" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe

View File

@@ -13,7 +13,7 @@ int main()
try {
// Define and load the sine wave file
input = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
input = new WaveLoop( "rawwaves/sinewave.raw", true );
// Define and open a 16-bit, one-channel WAV formatted output file
output = new WvOut( "hellosine.wav", 1, WvOut::WVOUT_WAV, Stk::STK_SINT16 );

View File

@@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# 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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /D "__WINDOWS_DS__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -65,7 +65,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 /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "_AFXDLL" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "_AFXDLL" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
BSC32=bscmake.exe

View File

@@ -6,6 +6,17 @@
by Gary P. Scavone, 2000
NOTE: This program makes use of blocking audio
input/output routines. On systems where the
underlying audio API is based on a callback scheme
(Macintosh OS-X, Windows ASIO, and Linux JACK), these
routines are not fully robust (over/underruns can
happen with some frequency). See the STK tutorial
for example programs using callback schemes and/or
visit the RtAudio tutorial page
(http://music.mcgill.ca/~gary/rtaudio/) for more
information.
This program is currently written to play
the input data in realtime. However, it
is simple to replace the instance of
@@ -15,7 +26,7 @@
The streamed data format is assumed to be
signed 16-bit integers. However, both
TcpWvIn and TcpWvOut can be initialized
to read/write any of the defined STK_FORMATs.
to read/write any of the defined StkFormats.
The class TcpWvIn sets up a socket server
and waits for a connection. Therefore,

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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /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__" /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__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -87,6 +87,10 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File

View File

@@ -10,7 +10,7 @@
file. The output data format is set for
signed 16-bit integers. However, it is
easy to change the TcpWvOut setting to
any of the other defined STK_FORMATs.
any of the other defined StkFormats.
If using tcpIn, it will be necessary to
change the expected data format there
as well.

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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /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__" /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__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe

View File

@@ -1,11 +1,116 @@
// threebees.cpp STK tutorial program
#include "BeeThree.h"
#include "RtWvOut.h"
#include "RtAudio.h"
#include "Messager.h"
#include "Voicer.h"
#include "SKINI.msg"
#include <algorithm>
#if !defined(__OS_WINDOWS__) // Windoze bogosity for VC++ 6.0
using std::min;
#endif
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
Voicer voicer;
Messager messager;
Skini::Message message;
int counter;
bool haveMessage;
bool done;
// Default constructor.
TickData()
: counter(0), haveMessage(false), done( 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 )
{
register StkFloat value1 = data->message.floatValues[0];
register StkFloat value2 = data->message.floatValues[1];
switch( data->message.type ) {
case __SK_Exit_:
data->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_:
data->voicer.controlChange( (int) value1, value2 );
break;
case __SK_AfterTouch_:
data->voicer.controlChange( 128, value1 );
case __SK_PitchChange_:
data->voicer.setFrequency( value1 );
break;
case __SK_PitchBend_:
data->voicer.pitchBend( value1 );
} // end of switch
data->haveMessage = false;
return;
}
// This tick() function handles sample computation and scheduling of
// control updates. 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 *samples = (StkFloat *) buffer;
int counter, nTicks = bufferSize;
while ( nTicks > 0 && !data->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++ ) {
*samples++ = data->voicer.tick();
nTicks--;
}
if ( nTicks == 0 ) break;
// Process control messages.
if ( data->haveMessage ) processMessage( data );
}
return 0;
}
int main()
{
// Set the global sample rate and rawwave path before creating class instances.
@@ -13,88 +118,63 @@ int main()
Stk::setRawwavePath( "../../rawwaves/" );
int i;
RtWvOut *output = 0;
Messager *messager = 0;
Voicer *voicer = 0;
bool done = FALSE;
TickData data;
RtAudio *dac = 0;
Instrmnt *instrument[3];
for ( i=0; i<3; i++ ) instrument[i] = 0;
// Figure out how many bytes in an StkFloat and setup the RtAudio object.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
dac = new RtAudio(0, 1, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
try {
// Define and load the BeeThree instruments
for ( i=0; i<3; i++ )
instrument[i] = new BeeThree();
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
}
catch (StkError &) {
goto cleanup;
}
// "Add" the instruments to the voicer.
for ( i=0; i<3; i++ )
data.voicer.addInstrument( instrument[i] );
if ( data.messager.startStdInput() == false )
goto cleanup;
try {
// Create a Messager instance to read from a redirected SKINI scorefile.
messager = new Messager();
dac->setStreamCallback(&tick, (void *)&data);
dac->startStream();
}
catch (StkError &) {
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// Instantiate the voicer for a maximum of three voices.
voicer = new Voicer( 3 );
for ( i=0; i<3; i++ )
voicer->addInstrument( instrument[i] );
// Play the instrument until the end of the scorefile.
int nTicks, type;
MY_FLOAT byte2, byte3;
while (!done) {
// Look for new messages and return a delta time (in samples).
type = messager->nextMessage();
if (type < 0)
done = TRUE;
nTicks = messager->getDelta();
try {
for ( i=0; i<nTicks; i++ )
output->tick( voicer->tick() );
}
catch (StkError &) {
goto cleanup;
}
if ( type > 0 ) {
// Process the new control message.
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_NoteOn_:
voicer->noteOn( byte2, byte3 );
break;
case __SK_NoteOff_:
voicer->noteOff( byte2, byte3 );
break;
case __SK_ControlChange_:
voicer->controlChange( (int) byte2, byte3 );
break;
case __SK_AfterTouch_:
voicer->controlChange( 128, byte2 );
break;
}
}
// Block waiting until callback signals done.
while ( !data.done )
Stk::sleep( 100 );
// Shut down the callback and output stream.
try {
dac->cancelStreamCallback();
dac->closeStream();
}
catch (RtError &error) {
error.printMessage();
}
cleanup:
for ( i=0; i<3; i++ ) delete instrument[i];
delete output;
delete messager;
delete voicer;
delete dac;
return 0;
}

View File

@@ -42,14 +42,14 @@ 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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /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__" /D "__WINDOWS_MM__" /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 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 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib winmm.lib dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "threebees - Win32 Debug"
@@ -65,15 +65,15 @@ LINK32=link.exe
# 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 /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 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 "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /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 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 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib winmm.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
@@ -107,6 +107,10 @@ SOURCE=..\..\src\FM.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Generator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Instrmnt.cpp
# End Source File
# Begin Source File
@@ -115,6 +119,10 @@ SOURCE=..\..\src\Messager.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File

View File

@@ -13,90 +13,101 @@
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Drone.h"
Drone :: Drone(MY_FLOAT lowestFrequency)
Drone :: Drone(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
loopGain = (MY_FLOAT) 0.999;
delayLine = new DelayA( (MY_FLOAT)(length / 2.0), length );
loopFilter = new OneZero;
noise = new Noise;
envelope = new ADSR();
envelope->setAllTimes(2.0, 0.5, 0.0, 0.5);
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
loopGain_ = 0.999;
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
envelope_.setAllTimes( 2.0, 0.5, 0.0, 0.5 );
this->clear();
}
Drone :: ~Drone()
{
delete delayLine;
delete loopFilter;
delete envelope;
delete noise;
}
void Drone :: clear()
{
delayLine->clear();
loopFilter->clear();
delayLine_.clear();
loopFilter_.clear();
}
void Drone :: setFrequency(MY_FLOAT frequency)
void Drone :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Drone: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Drone::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
// Delay = length - approximate filter delay.
MY_FLOAT delay = (Stk::sampleRate() / freakency) - (MY_FLOAT) 0.5;
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
delayLine->setDelay(delay);
loopGain = 0.997 + (freakency * 0.000002);
if ( loopGain >= 1.0 ) loopGain = (MY_FLOAT) 0.99999;
StkFloat delay = (Stk::sampleRate() / freakency) - 0.5;
if ( delay <= 0.0 )
delay = 0.3;
else if (delay > length_)
delay = length_;
delayLine_.setDelay( delay );
loopGain_ = 0.997 + (freakency * 0.000002);
if ( loopGain_ >= 1.0 ) loopGain_ = 0.99999;
}
void Drone :: pluck(MY_FLOAT amplitude)
void Drone :: pluck(StkFloat amplitude)
{
envelope->keyOn();
envelope_.keyOn();
}
void Drone :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Drone :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
this->pluck(amplitude);
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
std::cerr << "Drone: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Drone::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Drone :: noteOff(MY_FLOAT amplitude)
void Drone :: noteOff(StkFloat amplitude)
{
loopGain = (MY_FLOAT) 1.0 - amplitude;
if ( loopGain < 0.0 ) {
std::cerr << "Drone: noteOff amplitude greater than 1.0!" << std::endl;
loopGain = 0.0;
loopGain_ = 1.0 - amplitude;
if ( loopGain_ < 0.0 ) {
errorString_ << "Drone::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
loopGain_ = 0.0;
}
else if ( loopGain > 1.0 ) {
std::cerr << "Drone: noteOff amplitude less than or zero!" << std::endl;
loopGain = (MY_FLOAT) 0.99999;
else if ( loopGain_ > 1.0 ) {
errorString_ << "Drone::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
loopGain_ = 0.99999;
}
#if defined(_STK_DEBUG_)
std::cerr << "Drone: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Drone::noteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Drone :: tick()
StkFloat Drone :: tick()
{
// Here's the whole inner loop of the instrument!!
lastOutput = delayLine->tick( loopFilter->tick( delayLine->lastOut() * loopGain ) + (0.005 * envelope->tick() * noise->tick()));
return lastOutput;
lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) + (0.005 * envelope_.tick() * noise_.tick()));
return lastOutput_;
}
StkFloat *Drone :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Drone :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -13,12 +13,12 @@
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#if !defined(__DRONE_H)
#define __DRONE_H
#ifndef STK_DRONE_H
#define STK_DRONE_H
#include "Instrmnt.h"
#include "DelayA.h"
@@ -30,7 +30,7 @@ class Drone : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
Drone(MY_FLOAT lowestFrequency);
Drone( StkFloat lowestFrequency = 20 );
//! Class destructor.
~Drone();
@@ -39,27 +39,39 @@ class Drone : public Instrmnt
void clear();
//! Set instrument parameters for a particular frequency.
virtual void setFrequency(MY_FLOAT frequency);
virtual void setFrequency(StkFloat frequency);
//! Pluck the string with the given amplitude using the current frequency.
void pluck(MY_FLOAT amplitude);
void pluck(StkFloat amplitude);
//! Start a note with the given frequency and amplitude.
virtual void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
virtual void noteOn(StkFloat frequency, StkFloat amplitude);
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff(MY_FLOAT amplitude);
virtual void noteOff(StkFloat amplitude);
//! Compute one output sample.
virtual MY_FLOAT tick();
virtual StkFloat tick();
//! Computer \e vectorSize outputs and return them in \e vector.
virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument should be one or greater (the first
channel is specified by 1). An StkError will be thrown if the \c
channel argument is zero or it is greater than the number of
channels in the StkFrames object.
*/
virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
protected:
DelayA *delayLine;
OneZero *loopFilter;
ADSR *envelope;
Noise *noise;
long length;
MY_FLOAT loopGain;
DelayA delayLine_;
OneZero loopFilter_;
ADSR envelope_;
Noise noise_;
StkFloat loopGain_;
unsigned long length_;
};

View File

@@ -6,12 +6,12 @@ SRC_PATH = ../../src
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
OBJECTS = Stk.o Envelope.o ADSR.o Noise.o \
OBJECTS = Stk.o Generator.o Noise.o Envelope.o ADSR.o \
Filter.o DelayA.o Delay.o \
OnePole.o OneZero.o SKINI.o \
OnePole.o OneZero.o Skini.o \
Tabla.o Instrmnt.o Sitar.o \
Drone.o VoicDrum.o WvOut.o WvIn.o \
Reverb.o JCRev.o Messager.o
Effect.o JCRev.o Messager.o
INCLUDE = @include@
ifeq ($(strip $(INCLUDE)), )
@@ -29,9 +29,8 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
OBJECTS += RtMidi.o RtAudio.o RtWvOut.o Thread.o Socket.o
OBJECTS += RtMidi.o RtAudio.o RtWvOut.o Thread.o Mutex.o Socket.o
DEFS += @audio_apis@
DEFS += @midiator@
endif
RAWWAVES = @rawwaves@
@@ -48,6 +47,9 @@ all : $(PROGRAMS)
ragamat: ragamat.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o ragamat ragamat.cpp $(OBJECT_PATH)/*.o $(LIBRARY)
libragamat: ragamat.cpp Tabla.cpp Drone.cpp VoicDrum.cpp
$(CC) $(CFLAGS) $(DEFS) -o ragamat Tabla.cpp Drone.cpp VoicDrum.cpp ragamat.cpp -L../../src $(LIBRARY) -lstk
$(OBJECTS) : Stk.h
clean :

1
projects/ragamatic/Raga Executable file
View File

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

View File

@@ -1 +1 @@
wish < tcl/Raga.tcl | ./ragamat -ip
wish < tcl/Raga.tcl | ragamat -ip

View File

@@ -8,48 +8,49 @@
at 22050 Hz, but will be appropriately
interpolated for other sample rates. You can
specify the maximum polyphony (maximum number
of simultaneous voices) via a #define in the
Drummer.h.
of simultaneous voices) in Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Tabla.h"
#include <string.h>
#include <math.h>
Tabla :: Tabla() : Instrmnt()
{
for (int i=0; i<TABLA_POLYPHONY; i++) {
filters[i] = new OnePole;
sounding[i] = -1;
for ( int i=0; i<TABLA_POLYPHONY; i++ ) {
filters_[i] = new OnePole;
sounding_[i] = -1;
}
// This counts the number of sounding voices.
nSounding = 0;
nSounding_ = 0;
}
Tabla :: ~Tabla()
{
int i;
for ( i=0; i<nSounding-1; i++ ) delete waves[i];
for ( i=0; i<TABLA_POLYPHONY; i++ ) delete filters[i];
for ( i=0; i<nSounding_; i++ ) delete waves_[i];
for ( i=0; i<TABLA_POLYPHONY; i++ ) delete filters_[i];
}
void Tabla :: noteOn(MY_FLOAT instrument, MY_FLOAT amplitude)
void Tabla :: noteOn(StkFloat instrument, StkFloat amplitude)
{
#if defined(_STK_DEBUG_)
std::cerr << "Tabla: NoteOn instrument = " << instrument << ", amplitude = " << amplitude << std::endl;
errorString_ << "Tabla::noteOn: instrument = " << instrument << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( amplitude > 1.0 ) {
std::cerr << "Tabla: noteOn amplitude parameter is greater than 1.0!" << std::endl;
errorString_ << "Tabla::noteOn: amplitude parameter is greater than 1.0 ... setting to 1.0.";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( amplitude < 0.0 ) {
std::cerr << "Tabla: noteOn amplitude parameter is less than 0.0!" << std::endl;
errorString_ << "Tabla::noteOn: amplitude parameter is less than 0.0 ... doing nothing.";
handleError( StkError::WARNING );
return;
}
@@ -71,91 +72,99 @@ void Tabla :: noteOn(MY_FLOAT instrument, MY_FLOAT amplitude)
"DrTak2.raw"
};
int noteNum = ((int) instrument) % 16;
int noteNum = ( (int) instrument ) % 16;
// Check first to see if there's already one like this sounding.
int i, waveIndex = -1;
for (i=0; i<TABLA_POLYPHONY; i++) {
if (sounding[i] == noteNum) waveIndex = i;
for ( i=0; i<TABLA_POLYPHONY; i++ ) {
if ( sounding_[i] == noteNum ) waveIndex = i;
}
if ( waveIndex >= 0 ) {
// Reset this sound.
waves[waveIndex]->reset();
filters[waveIndex]->setPole((MY_FLOAT) 0.999 - (gain * 0.6));
filters[waveIndex]->setGain(gain);
waves_[waveIndex]->reset();
filters_[waveIndex]->setPole( 0.999 - (gain * 0.6) );
filters_[waveIndex]->setGain( gain );
}
else {
if (nSounding == TABLA_POLYPHONY) {
if ( nSounding_ == TABLA_POLYPHONY ) {
// If we're already at maximum polyphony, then preempt the oldest voice.
delete waves[0];
filters[0]->clear();
WvIn *tempWv = waves[0];
OnePole *tempFilt = filters[0];
delete waves_[0];
filters_[0]->clear();
OnePole *tempFilt = filters_[0];
// Re-order the list.
for (i=0; i<TABLA_POLYPHONY-1; i++) {
waves[i] = waves[i+1];
filters[i] = filters[i+1];
for ( i=0; i<TABLA_POLYPHONY-1; i++ ) {
waves_[i] = waves_[i+1];
filters_[i] = filters_[i+1];
}
waves[TABLA_POLYPHONY-1] = tempWv;
filters[TABLA_POLYPHONY-1] = tempFilt;
waves_[TABLA_POLYPHONY-1] = 0;
filters_[TABLA_POLYPHONY-1] = tempFilt;
}
else
nSounding += 1;
nSounding_ += 1;
sounding[nSounding-1] = noteNum;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char path[128];
strcpy(path, "rawwaves/");
strcat(path, tablaWaves[noteNum]);
waves[nSounding-1] = new WvIn(path, TRUE);
waves[nSounding-1]->normalize(0.4);
filters[nSounding-1]->setPole((MY_FLOAT) 0.999 - (gain * 0.6) );
filters[nSounding-1]->setGain( gain );
sounding_[nSounding_-1] = noteNum;
// Concatenate the rawwave path to the file name.
waves_[nSounding_-1] = new WvIn( (std::string("rawwaves/") + tablaWaves[noteNum]).c_str(), true );
waves_[nSounding_-1]->normalize(0.4);
if ( Stk::sampleRate() != 22050.0 )
waves_[nSounding_-1]->setRate( 22050.0 / Stk::sampleRate() );
filters_[nSounding_-1]->setPole( 0.999 - (gain * 0.6) );
filters_[nSounding_-1]->setGain( gain );
}
#if defined(_STK_DEBUG_)
std::cerr << "Number Sounding = " << nSounding << std::endl;
for (i=0; i<nSounding; i++) std::cerr << sounding[i] << " ";
std::cerr << "\n";
errorString_ << "Tabla::noteOn: number sounding = " << nSounding_ << '\n';
for (i=0; i<nSounding_; i++) errorString_ << sounding_[i] << " ";
errorString_ << '\n';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Tabla :: noteOff(MY_FLOAT amplitude)
void Tabla :: noteOff(StkFloat amplitude)
{
// Set all sounding wave filter gains low.
int i = 0;
while(i < nSounding) {
filters[i++]->setGain( amplitude * 0.01 );
}
while ( i < nSounding_ )
filters_[i++]->setGain( amplitude * 0.01 );
}
MY_FLOAT Tabla :: tick()
StkFloat Tabla :: tick()
{
MY_FLOAT output = 0.0;
OnePole *tempFilt;
int j, i = 0;
while (i < nSounding) {
if ( waves[i]->isFinished() ) {
delete waves[i];
tempFilt = filters[i];
lastOutput_ = 0.0;
while ( i < nSounding_ ) {
if ( waves_[i]->isFinished() ) {
delete waves_[i];
tempFilt = filters_[i];
// Re-order the list.
for (j=i; j<nSounding-1; j++) {
sounding[j] = sounding[j+1];
waves[j] = waves[j+1];
filters[j] = filters[j+1];
for ( j=i; j<nSounding_-1; j++ ) {
sounding_[j] = sounding_[j+1];
waves_[j] = waves_[j+1];
filters_[j] = filters_[j+1];
}
filters[j] = tempFilt;
filters[j]->clear();
sounding[j] = -1;
nSounding -= 1;
filters_[j] = tempFilt;
filters_[j]->clear();
sounding_[j] = -1;
nSounding_ -= 1;
i -= 1;
}
else
output += filters[i]->tick( waves[i]->tick() );
lastOutput_ += filters_[i]->tick( waves_[i]->tick() );
i++;
}
return output;
return lastOutput_;
}
StkFloat *Tabla :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Tabla :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -8,22 +8,21 @@
at 22050 Hz, but will be appropriately
interpolated for other sample rates. You can
specify the maximum polyphony (maximum number
of simultaneous voices) via a #define in the
Drummer.h.
of simultaneous voices) in Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#if !defined(__TABLA_H)
#define __TABLA_H
#ifndef STK_TABLA_H
#define STK_TABLA_H
#include "Instrmnt.h"
#include "WvIn.h"
#include "OnePole.h"
#define TABLA_NUMWAVES 15
#define TABLA_POLYPHONY 4
const int TABLA_NUMWAVES = 15;
const int TABLA_POLYPHONY = 4;
class Tabla : public Instrmnt
{
@@ -35,19 +34,31 @@ class Tabla : public Instrmnt
~Tabla();
//! Start a note with the given drum type and amplitude.
void noteOn(MY_FLOAT instrument, MY_FLOAT amplitude);
void noteOn(StkFloat instrument, StkFloat amplitude);
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
void noteOff(StkFloat amplitude);
//! Compute one output sample.
MY_FLOAT tick();
StkFloat tick();
//! Computer \e vectorSize outputs and return them in \e vector.
StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument should be one or greater (the first
channel is specified by 1). An StkError will be thrown if the \c
channel argument is zero or it is greater than the number of
channels in the StkFrames object.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
protected:
WvIn *waves[TABLA_POLYPHONY];
OnePole *filters[TABLA_POLYPHONY];
int sounding[TABLA_POLYPHONY];
int nSounding;
WvIn *waves_[TABLA_POLYPHONY];
OnePole *filters_[TABLA_POLYPHONY];
int sounding_[TABLA_POLYPHONY];
int nSounding_;
};

View File

@@ -8,48 +8,49 @@
at 22050 Hz, but will be appropriately
interpolated for other sample rates. You can
specify the maximum polyphony (maximum number
of simultaneous voices) via a #define in the
Drummer.h.
of simultaneous voices) in Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "VoicDrum.h"
#include <string.h>
#include <math.h>
VoicDrum :: VoicDrum() : Instrmnt()
{
for (int i=0; i<VOICE_POLYPHONY; i++) {
filters[i] = new OnePole;
sounding[i] = -1;
for ( int i=0; i<VOICE_POLYPHONY; i++ ) {
filters_[i] = new OnePole;
sounding_[i] = -1;
}
// This counts the number of sounding voices.
nSounding = 0;
nSounding_ = 0;
}
VoicDrum :: ~VoicDrum()
{
int i;
for ( i=0; i<nSounding-1; i++ ) delete waves[i];
for ( i=0; i<VOICE_POLYPHONY; i++ ) delete filters[i];
for ( i=0; i<nSounding_; i++ ) delete waves_[i];
for ( i=0; i<VOICE_POLYPHONY; i++ ) delete filters_[i];
}
void VoicDrum :: noteOn(MY_FLOAT instrument, MY_FLOAT amplitude)
void VoicDrum :: noteOn( StkFloat instrument, StkFloat amplitude )
{
#if defined(_STK_DEBUG_)
std::cerr << "VoicDrum: NoteOn instrument = " << instrument << ", amplitude = " << amplitude << std::endl;
errorString_ << "VoicDrum::noteOn: instrument = " << instrument << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( amplitude > 1.0 ) {
std::cerr << "VoicDrum: noteOn amplitude parameter is greater than 1.0!" << std::endl;
errorString_ << "VoicDrum::noteOn: amplitude parameter is greater than 1.0 ... setting to 1.0.";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( amplitude < 0.0 ) {
std::cerr << "VoicDrum: noteOn amplitude parameter is less than 0.0!" << std::endl;
errorString_ << "VoicDrum::noteOn: amplitude parameter is less than 0.0 ... doing nothing.";
handleError( StkError::WARNING );
return;
}
@@ -68,91 +69,98 @@ void VoicDrum :: noteOn(MY_FLOAT instrument, MY_FLOAT amplitude)
"tak4.raw"
};
int noteNum = ((int) instrument) % 11;
int noteNum = ( (int) instrument ) % 11;
// Check first to see if there's already one like this sounding.
int i, waveIndex = -1;
for (i=0; i<VOICE_POLYPHONY; i++) {
if (sounding[i] == noteNum) waveIndex = i;
for ( i=0; i<VOICE_POLYPHONY; i++ ) {
if ( sounding_[i] == noteNum ) waveIndex = i;
}
if ( waveIndex >= 0 ) {
// Reset this sound.
waves[waveIndex]->reset();
filters[waveIndex]->setPole((MY_FLOAT) 0.999 - (gain * 0.6));
filters[waveIndex]->setGain(gain);
waves_[waveIndex]->reset();
filters_[waveIndex]->setPole( 0.999 - (gain * 0.6) );
filters_[waveIndex]->setGain( gain );
}
else {
if (nSounding == VOICE_POLYPHONY) {
if ( nSounding_ == VOICE_POLYPHONY ) {
// If we're already at maximum polyphony, then preempt the oldest voice.
delete waves[0];
filters[0]->clear();
WvIn *tempWv = waves[0];
OnePole *tempFilt = filters[0];
delete waves_[0];
filters_[0]->clear();
OnePole *tempFilt = filters_[0];
// Re-order the list.
for (i=0; i<VOICE_POLYPHONY-1; i++) {
waves[i] = waves[i+1];
filters[i] = filters[i+1];
for ( i=0; i<VOICE_POLYPHONY-1; i++ ) {
waves_[i] = waves_[i+1];
filters_[i] = filters_[i+1];
}
waves[VOICE_POLYPHONY-1] = tempWv;
filters[VOICE_POLYPHONY-1] = tempFilt;
waves_[VOICE_POLYPHONY-1] = 0;
filters_[VOICE_POLYPHONY-1] = tempFilt;
}
else
nSounding += 1;
nSounding_ += 1;
sounding[nSounding-1] = noteNum;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char path[128];
strcpy(path, "rawwaves/");
strcat(path, voiceNames[noteNum]);
waves[nSounding-1] = new WvIn(path, TRUE);
waves[nSounding-1]->normalize(0.4);
filters[nSounding-1]->setPole((MY_FLOAT) 0.999 - (gain * 0.6) );
filters[nSounding-1]->setGain( gain );
sounding_[nSounding_-1] = noteNum;
// Concatenate the rawwave path to the file name.
waves_[nSounding_-1] = new WvIn( (std::string("rawwaves/") + voiceNames[noteNum]).c_str(), true );
waves_[nSounding_-1]->normalize(0.4);
if (Stk::sampleRate() != 22050.0)
waves_[nSounding_-1]->setRate( 22050.0 / Stk::sampleRate() );
filters_[nSounding_-1]->setPole( 0.999 - (gain * 0.6) );
filters_[nSounding_-1]->setGain( gain );
}
#if defined(_STK_DEBUG_)
std::cerr << "Number Sounding = " << nSounding << std::endl;
for (i=0; i<nSounding; i++) std::cerr << sounding[i] << " ";
std::cerr << "\n";
errorString_ << "VoicDrum::noteOn: number sounding = " << nSounding_ << '\n';
for (i=0; i<nSounding_; i++) errorString_ << sounding_[i] << " ";
errorString_ << '\n';
handleError( StkError::DEBUG_WARNING );
#endif
}
void VoicDrum :: noteOff(MY_FLOAT amplitude)
void VoicDrum :: noteOff(StkFloat amplitude)
{
// Set all sounding wave filter gains low.
int i = 0;
while(i < nSounding) {
filters[i++]->setGain( amplitude * 0.01 );
}
while ( i < nSounding_ ) filters_[i++]->setGain( amplitude * 0.01 );
}
MY_FLOAT VoicDrum :: tick()
StkFloat VoicDrum :: tick()
{
MY_FLOAT output = 0.0;
OnePole *tempFilt;
int j, i = 0;
while (i < nSounding) {
if ( waves[i]->isFinished() ) {
delete waves[i];
tempFilt = filters[i];
lastOutput_ = 0.0;
while ( i < nSounding_ ) {
if ( waves_[i]->isFinished() ) {
delete waves_[i];
tempFilt = filters_[i];
// Re-order the list.
for (j=i; j<nSounding-1; j++) {
sounding[j] = sounding[j+1];
waves[j] = waves[j+1];
filters[j] = filters[j+1];
for ( j=i; j<nSounding_-1; j++ ) {
sounding_[j] = sounding_[j+1];
waves_[j] = waves_[j+1];
filters_[j] = filters_[j+1];
}
filters[j] = tempFilt;
filters[j]->clear();
sounding[j] = -1;
nSounding -= 1;
filters_[j] = tempFilt;
filters_[j]->clear();
sounding_[j] = -1;
nSounding_ -= 1;
i -= 1;
}
else
output += filters[i]->tick( waves[i]->tick() );
lastOutput_ += filters_[i]->tick( waves_[i]->tick() );
i++;
}
return output;
return lastOutput_;
}
StkFloat *VoicDrum :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& VoicDrum :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -8,22 +8,21 @@
at 22050 Hz, but will be appropriately
interpolated for other sample rates. You can
specify the maximum polyphony (maximum number
of simultaneous voices) via a #define in the
Drummer.h.
of simultaneous voices) in Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#if !defined(__VOICDRUM_H)
#define __VOICDRUM_H
#ifndef STK_VOICDRUM_H
#define STK_VOICDRUM_H
#include "Instrmnt.h"
#include "WvIn.h"
#include "OnePole.h"
#define VOICE_NUMWAVES 11
#define VOICE_POLYPHONY 4
const int VOICE_NUMWAVES = 11;
const int VOICE_POLYPHONY = 4;
class VoicDrum : public Instrmnt
{
@@ -35,19 +34,31 @@ class VoicDrum : public Instrmnt
~VoicDrum();
//! Start a note with the given drum type and amplitude.
void noteOn(MY_FLOAT instrument, MY_FLOAT amplitude);
void noteOn(StkFloat instrument, StkFloat amplitude);
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
void noteOff(StkFloat amplitude);
//! Compute one output sample.
MY_FLOAT tick();
StkFloat tick();
//! Computer \e vectorSize outputs and return them in \e vector.
StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument should be one or greater (the first
channel is specified by 1). An StkError will be thrown if the \c
channel argument is zero or it is greater than the number of
channels in the StkFrames object.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
protected:
WvIn *waves[VOICE_POLYPHONY];
OnePole *filters[VOICE_POLYPHONY];
int sounding[VOICE_POLYPHONY];
int nSounding;
WvIn *waves_[VOICE_POLYPHONY];
OnePole *filters_[VOICE_POLYPHONY];
int sounding_[VOICE_POLYPHONY];
int nSounding_;
};

View File

@@ -1,272 +1,342 @@
/************** Test Main Program Individual Voice *********************/
#include "RtWvOut.h"
#include "SKINI.msg"
#include "Instrmnt.h"
#include "Reverb.h"
#include "JCRev.h"
#include "Drone.h"
#include "Sitar.h"
#include "Tabla.h"
#include "VoicDrum.h"
// The input control handler.
#include "Messager.h"
#include "RtAudio.h"
MY_FLOAT float_random(MY_FLOAT max) // Return random float between 0.0 and max
#include <signal.h>
#include <iostream>
#include <algorithm>
#if !defined(__OS_WINDOWS__) // Windoze bogosity for VC++ 6.0
using std::min;
#endif
StkFloat float_random(StkFloat max) // Return random float between 0.0 and max
{
MY_FLOAT temp = (MY_FLOAT) (max * rand() / (RAND_MAX + 1.0) );
StkFloat temp = (StkFloat) (max * rand() / (RAND_MAX + 1.0) );
return temp;
}
void usage(void) {
/* Error function in case of incorrect command-line argument specifications */
printf("\nuseage: ragamat flags \n");
printf(" where flag = -s RATE to specify a sample rate,\n");
printf(" flag = -ip for realtime SKINI input by pipe\n");
printf(" (won't work under Win95/98),\n");
printf(" and flag = -is <port> for realtime SKINI input by socket.\n");
// Error function in case of incorrect command-line argument specifications.
std::cout << "\nuseage: ragamat flags \n";
std::cout << " where flag = -s RATE to specify a sample rate,\n";
std::cout << " flag = -ip for realtime SKINI input by pipe\n";
std::cout << " (won't work under Win95/98),\n";
std::cout << " and flag = -is <port> for realtime SKINI input by socket.\n";
exit(0);
}
int main(int argc,char *argv[])
{
bool done;
RtWvOut *output;
Instrmnt *drones[3];
Instrmnt *sitar;
Instrmnt *voicDrums;
Instrmnt *tabla;
Reverb *reverbs[2];
SKINI *score;
Messager *messager;
MY_FLOAT t60 = 4.0; // in seconds
bool done;
static void finish(int ignore){ done = true; }
MY_FLOAT drone_prob = 0.01, note_prob = 0.0;
MY_FLOAT drum_prob = 0.0, voic_prob = 0.0;
MY_FLOAT droneFreqs[3] = {55.0,82.5,220.0};
int tempo = 3000;
int counter = 3000;
int key = 0;
int ragaStep, ragaPoint = 6, voicNote;
int ragaUp[2][13] = {{57, 60, 62, 64, 65, 68, 69, 71, 72, 76, 77, 81},
{52, 54, 55, 57, 59, 60, 63, 64, 66, 67, 71, 72}};
int ragaDown[2][13] = {{57, 60, 62, 64, 65, 67, 69, 71, 72, 76, 79, 81},
{48, 52, 53, 55, 57, 59, 60, 64, 66, 68, 70, 72}};
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
JCRev reverbs[2];
Drone drones[3];
Sitar sitar;
VoicDrum voicDrums;
Tabla tabla;
Messager messager;
Skini::Message message;
StkFloat lastSample;
StkFloat t60;
int counter;
bool settling;
bool haveMessage;
StkFloat droneChance, noteChance;
StkFloat drumChance, voiceChance;
int tempo;
int chanceCounter;
int key;
int ragaStep;
int ragaPoint;
int endPhase;
StkFloat rateScaler;
// Default constructor.
TickData()
: t60(4.0), counter(0),
settling( false ), haveMessage( false ), droneChance(0.01), noteChance(0.01),
drumChance(0.0), voiceChance(0.0), tempo(3000), chanceCounter(3000), key(0), ragaPoint(6), endPhase(0) {}
};
// Raga key numbers and drone frequencies.
const int ragaUp[2][13] = {{57, 60, 62, 64, 65, 68, 69, 71, 72, 76, 77, 81},
{52, 54, 55, 57, 59, 60, 63, 64, 66, 67, 71, 72}};
const int ragaDown[2][13] = {{57, 60, 62, 64, 65, 67, 69, 71, 72, 76, 79, 81},
{48, 52, 53, 55, 57, 59, 60, 64, 66, 68, 70, 72}};
StkFloat droneFreqs[3] = { 55.0, 82.5, 220.0 };
#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 )
{
register unsigned int value1 = data->message.intValues[0];
register StkFloat value2 = data->message.floatValues[1];
register StkFloat temp = value2 * ONE_OVER_128;
switch( data->message.type ) {
case __SK_Exit_:
if ( data->settling == false ) goto settle;
if ( data->endPhase < 5 ) return;
done = true;
return;
case __SK_ControlChange_:
switch ( value1 ) {
case 1:
data->droneChance = temp;
break;
case 2:
data->noteChance = temp;
break;
case 4:
data->voiceChance = temp;
break;
case 7:
data->tempo = (int) (11025 - value2 * 70.0 );
break;
case 11:
data->drumChance = temp;
break;
case 64:
if ( value2 == 0.0 ) {
data->key = 1;
droneFreqs[0] = 55.0;
droneFreqs[1] = 82.5;
droneFreqs[2] = 220.0;
}
else {
data->key = 0;
droneFreqs[0] = 82.5;
droneFreqs[1] = 123.5;
droneFreqs[2] = 330.0;
}
break;
default:
break;
}
} // end of type switch
data->haveMessage = false;
return;
settle:
// Exit and program change messages are preceeded with a short settling period.
data->counter = (int) (data->t60 * Stk::sampleRate());
data->drones[1].noteOn( droneFreqs[1], 0.1 );
data->settling = true;
std::cout << "What Need Have I for This?\n";
}
// The tick() function handles sample computation and scheduling of
// control updates. It will be called automatically by RtAudio when
// the system needs a new buffer of audio samples.
int tick(char *buffer, int bufferSize, void *dataPointer)
{
TickData *data = (TickData *) dataPointer;
register StkFloat temp, outs[2], *samples = (StkFloat *) buffer;
int i, voiceNote, 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 ( i=0; i<counter; i++ ) {
outs[0] = data->reverbs[0].tick( data->drones[0].tick() + data->drones[2].tick()
+ data->sitar.tick() );
outs[1] = data->reverbs[1].tick( 1.5 * data->drones[1].tick() + 0.5 * data->voicDrums.tick()
+ 0.5 * data->tabla.tick() );
// Mix a little left to right and back.
*samples++ = outs[0] + 0.3 * outs[1];
*samples++ = outs[1] + 0.3 * outs[0];
nTicks--;
// Do a bunch of random controls unless settling down to end.
if ( data->settling ) {
if ( data->counter == 0 ) {
if ( data->endPhase++ == 0 ) {
data->counter = (int) (data->t60 * Stk::sampleRate());
data->drones[2].noteOn( droneFreqs[2], 0.1 );
std::cout << "What Need Have I for This?\n";
}
else if ( data->endPhase == 1 ) {
data->counter = (int) (data->t60 * Stk::sampleRate());
data->drones[0].noteOn( droneFreqs[0], 0.1 );
std::cout << "RagaMatic finished ... \n";
}
else if ( data->endPhase == 2 ) {
data->counter = (int) (data->t60 * Stk::sampleRate());
std::cout << "All is Bliss ...\n";
}
else if ( data->endPhase == 3 ) {
std::cout << "All is Bliss ...\n";
data->counter = (int) (data->t60 * Stk::sampleRate());
}
}
}
else {
data->chanceCounter--;
if (data->chanceCounter == 0) {
data->chanceCounter = (int) ( data->tempo / data->rateScaler );
if ( float_random(1.0) < data->droneChance )
data->drones[0].noteOn( droneFreqs[0], 0.1 );
if ( float_random(1.0) < data->droneChance )
data->drones[1].noteOn( droneFreqs[1], 0.1 );
if ( float_random(1.0) < data->droneChance )
data->drones[2].noteOn( droneFreqs[2], 0.1 );
if ( float_random(1.0) < data->noteChance ) {
temp = float_random(1.0);
if ( temp < 0.1) data->ragaStep = 0;
else if (temp < 0.5) data->ragaStep = 1;
else data->ragaStep = -1;
data->ragaPoint += data->ragaStep;
if ( data->ragaPoint < 0 )
data->ragaPoint -= ( 2 * data->ragaStep );
if ( data->ragaPoint > 11 ) data->ragaPoint = 11;
if ( data->ragaStep > 0 )
data->sitar.noteOn( Midi2Pitch[ragaUp[data->key][data->ragaPoint]],
0.05 + float_random(0.3) );
else
data->sitar.noteOn( Midi2Pitch[ragaDown[data->key][data->ragaPoint]],
0.05 + float_random(0.3) );
}
if ( float_random(1.0) < data->voiceChance ) {
voiceNote = (int) float_random(11);
data->voicDrums.noteOn( voiceNote, 0.3 + (0.4 * data->drumChance) +
float_random(0.3 * data->voiceChance));
}
if ( float_random(1.0) < data->drumChance ) {
voiceNote = (int) float_random(TABLA_NUMWAVES);
data->tabla.noteOn( voiceNote, 0.2 + (0.2 * data->drumChance) +
float_random(0.6 * data->drumChance));
}
}
}
}
if ( nTicks == 0 ) break;
// Process control messages.
if ( data->haveMessage ) processMessage( data );
}
return 0;
}
int main( int argc, char *argv[] )
{
TickData data;
RtAudio *dac = 0;
int i;
if (argc < 2 || argc > 6) usage();
// If you want to change the default sample rate (set in Stk.h), do
// it before instantiating any objects! If the sample rate is
// specified in the command line, it will override this setting.
Stk::setSampleRate(22050.0);
Stk::setSampleRate( 44100.0 );
if (argc < 2 || argc > 6) usage();
int port = -1;
int i, controlMask = 0;
// Parse the command-line arguments.
unsigned int port = 2001;
for ( i=1; i<argc; i++ ) {
if (!strcmp(argv[i],"-is") ) {
controlMask |= STK_SOCKET;
if (i+1 < argc && argv[i+1][0] != '-' ) port = atoi(argv[++i]);
if ( !strcmp( argv[i], "-is" ) ) {
if ( i+1 < argc && argv[i+1][0] != '-' ) port = atoi(argv[++i]);
data.messager.startSocketInput( port );
}
else if (!strcmp(argv[i],"-ip") )
controlMask |= STK_PIPE;
else if (!strcmp(argv[i],"-s") && (i+1 < argc) && argv[i+1][0] != '-')
else if (!strcmp( argv[i], "-ip" ) )
data.messager.startStdInput();
else if ( !strcmp( argv[i], "-s" ) && ( i+1 < argc ) && argv[i+1][0] != '-')
Stk::setSampleRate( atoi(argv[++i]) );
else
usage();
}
// Allocate the dac here.
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
int bufferSize = RT_BUFFER_SIZE;
try {
output = new RtWvOut(2);
// Instantiate the input message controller.
if ( controlMask & STK_SOCKET && port >= 0 )
messager = new Messager( controlMask, port );
else
messager = new Messager( controlMask );
dac = new RtAudio(0, 2, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
}
catch (StkError &) {
exit(0);
catch (RtError& error) {
error.printMessage();
goto cleanup;
}
drones[0] = new Drone(50.0);
drones[1] = new Drone(50.0);
drones[2] = new Drone(50.0);
sitar = new Sitar(50.0);
voicDrums = new VoicDrum();
tabla = new Tabla();
data.reverbs[0].setT60( data.t60 );
data.reverbs[0].setEffectMix( 0.5 );
data.reverbs[1].setT60( 2.0 );
data.reverbs[1].setEffectMix( 0.2 );
score = new SKINI();
reverbs[0] = new JCRev(t60);
reverbs[0]->setEffectMix(0.5);
reverbs[1] = new JCRev(2.0);
reverbs[1]->setEffectMix(0.2);
data.drones[0].noteOn( droneFreqs[0], 0.1 );
data.drones[1].noteOn( droneFreqs[1], 0.1 );
data.drones[2].noteOn( droneFreqs[2], 0.1 );
drones[0]->noteOn(droneFreqs[0],0.1);
drones[1]->noteOn(droneFreqs[1],0.1);
drones[2]->noteOn(droneFreqs[2],0.1);
data.rateScaler = 22050.0 / Stk::sampleRate();
MY_FLOAT outSamples[2];
for (i=0;i<Stk::sampleRate();i++) { /* warm everybody up a little */
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick());
output->tickFrame(outSamples);
// Install an interrupt handler function.
(void) signal( SIGINT, finish );
// If realtime output, set our callback function and start the dac.
try {
dac->setStreamCallback( &tick, (void *)&data );
dac->startStream();
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
// The runtime loop begins here:
done = FALSE;
MY_FLOAT rateScaler = 22050.0 / Stk::sampleRate();
int nTicks, type;
MY_FLOAT temp, byte2, byte3;
while (!done) {
type = messager->nextMessage();
if (type < 0)
done = TRUE;
nTicks = messager->getDelta();
for (i=0; i<nTicks; i++) {
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick()
+ sitar->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick() + 0.5 * voicDrums->tick()
+ 0.5 * tabla->tick());
// mix a little left to right and back
temp = outSamples[0];
outSamples[0] += 0.3 * outSamples[1];
outSamples[1] += 0.3 * temp;
output->tickFrame(outSamples);
counter -= 1;
if (counter == 0) {
counter = (int) (tempo / rateScaler);
if (float_random(1.0) < drone_prob)
drones[0]->noteOn(droneFreqs[0], 0.1);
if (float_random(1.0) < drone_prob)
drones[1]->noteOn(droneFreqs[1], 0.1);
if (float_random(1.0) < drone_prob)
drones[2]->noteOn(droneFreqs[2], 0.1);
if (float_random(1.0) < note_prob) {
if ((temp = float_random(1.0)) < 0.1)
ragaStep = 0;
else if (temp < 0.5)
ragaStep = 1;
else
ragaStep = -1;
ragaPoint += ragaStep;
if (ragaPoint < 0)
ragaPoint -= (2*ragaStep);
if (ragaPoint > 11)
ragaPoint = 11;
if (ragaStep > 0)
sitar->noteOn(Midi2Pitch[ragaUp[key][ragaPoint]],
0.05 + float_random(0.3));
else
sitar->noteOn(Midi2Pitch[ragaDown[key][ragaPoint]],
0.05 + float_random(0.3));
}
if (float_random(1.0) < voic_prob) {
voicNote = (int) float_random(11);
voicDrums->noteOn(voicNote, 0.3 + (0.4 * drum_prob) +
float_random(0.3 * voic_prob));
}
if (float_random(1.0) < drum_prob) {
voicNote = (int) float_random(TABLA_NUMWAVES);
tabla->noteOn(voicNote, 0.2 + (0.2 * drum_prob) +
float_random(0.6 * drum_prob));
}
}
}
if ( type > 0 ) {
// parse the input control message
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_ControlChange_:
if (byte2 == 1) {
drone_prob = byte3 * ONE_OVER_128;
}
else if (byte2 == 2) {
note_prob = byte3 * ONE_OVER_128;
}
else if (byte2 == 4) {
voic_prob = byte3 * ONE_OVER_128;
}
else if (byte2 == 11) {
drum_prob = byte3 * ONE_OVER_128;
}
else if (byte2 == 7) {
tempo = (int) (11025 - (byte3 * 70));
}
else if (byte2 == 64) {
if (byte3 == 0) {
key = 1;
droneFreqs[0] = 55.0;
droneFreqs[1] = 82.5;
droneFreqs[2] = 220.0;
}
else {
key = 0;
droneFreqs[0] = 82.5;
droneFreqs[1] = 123.5;
droneFreqs[2] = 330.0;
}
}
}
}
// Setup finished.
while ( !done ) {
// Periodically check "done" status.
Stk::sleep( 50 );
}
nTicks = (long) (t60 * Stk::sampleRate());
printf("What Need Have I for This?\n");
drones[1]->noteOn(droneFreqs[1],0.1);
for (i=0; i<nTicks; i++) { // Calm down a little
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick());
output->tickFrame(outSamples);
// Shut down the output stream.
try {
dac->cancelStreamCallback();
dac->closeStream();
}
printf("What Need Have I for This?\n");
drones[2]->noteOn(droneFreqs[2],0.1);
for (i=0; i<nTicks; i++) { // and a little more
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick());
output->tickFrame(outSamples);
}
printf("RagaMatic finished ... \n");
drones[0]->noteOn(droneFreqs[0],0.1);
for (i=0; i<nTicks; i++) { // almost ready to think about ending
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick());
output->tickFrame(outSamples);
}
printf("All is Bliss ...\n");
for (i=0; i<nTicks; i++) { // nearly finished now
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick());
output->tickFrame(outSamples);
}
printf("All is Bliss ...\n");
for (i=0; i<nTicks; i++) { // all is bliss....
outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick());
outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick());
output->tickFrame(outSamples);
catch (RtError& error) {
error.printMessage();
}
delete output;
delete score;
delete drones[0];
delete drones[1];
delete drones[2];
delete sitar;
delete tabla;
delete voicDrums;
delete reverbs[0];
delete reverbs[1];
delete messager;
cleanup:
delete dac;
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 "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /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 /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -124,6 +124,14 @@ SOURCE=.\Drone.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Effect.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Effect.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Envelope.cpp
# End Source File
# Begin Source File
@@ -140,6 +148,14 @@ SOURCE=..\..\include\Filter.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Generator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Generator.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Instrmnt.cpp
# End Source File
# Begin Source File
@@ -164,6 +180,14 @@ SOURCE=..\..\include\Messager.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Mutex.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Noise.cpp
# End Source File
# Begin Source File
@@ -192,14 +216,6 @@ SOURCE=.\ragamat.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Reverb.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\Reverb.h
# End Source File
# Begin Source File
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -216,14 +232,6 @@ SOURCE=..\..\include\RtMidi.h
# End Source File
# Begin Source File
SOURCE=..\..\src\RtWvOut.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\RtWvOut.h
# End Source File
# Begin Source File
SOURCE=..\..\src\Sitar.cpp
# End Source File
# Begin Source File