This is Utilities.m in view mode; [Download] [Up]
/**************************************************
* SynthBuilder
* Copyright 1993 Nick Porcaro All Rights Reserved
**************************************************/
#import <stdlib.h>
#import <math.h>
#import <stddef.h>
#import <ctype.h>
#import <string.h>
#import <objc/NXBundle.h>
#import <appkit/Application.h>
#import <appkit/Panel.h>
#import <appkit/Control.h>
#import <musickit/Envelope.h>
#import "Utilities.h"
#define EOS '\0'
char *getAppName()
{
/* this is the only place where the name of the program should be mentioned */
return "SynthBuilder";
}
@implementation Utilities
static char TempString[1024];
- init
{
[super init];
[NXApp loadNibSection:"Utilities.nib" owner:self withNames:YES];
return self;
}
- sortList:(List *) aList sortFunction:(ptrToIntFcn) fcn
{
int count;
/* Is it worth sorting? */
if (! fcn)
{
return self;
}
count = [aList count];
if (count <= 1)
{
return self;
}
/* Sort the array. Hopefully the
* List object will act properly after this!!
*/
qsort((void *)aList->dataPtr, count, sizeof(id), fcn);
return self;
}
- (BOOL) checkName: (char *) aName
/* The names of FakeUGs and FakePatchPoints must be a legal
* C identifier
*/
{
int len, i;
if (! aName)
{
NXRunAlertPanel(getAppName(), "Invalid name", NULL, NULL, NULL);
return NO;
}
len = strlen(aName);
if (len > 0)
{
if (! isalpha(aName[0]))
{
NXRunAlertPanel(getAppName(), "Name must start with alpha character",
NULL, NULL, NULL);
return NO;
}
for (i=1; i<len; i++)
{
if ( ! ( isalnum(aName[i]) || aName[i] == '_'))
{
sprintf(TempString, "Illegal character in %s: %c",
aName, aName[i]);
NXRunAlertPanel(getAppName(), TempString, NULL, NULL, NULL);
return NO;
}
}
}
return YES;
}
- (char *) getAppDir
{
char *dir;
int len;
static char temp[1024];
dir = (char *) [[NXBundle mainBundle] directory];
if (! dir)
{
NXRunAlertPanel(getAppName(), "Error getting bundle directory", NULL, NULL, NULL);
return NULL;
}
/* Nightmare: If the directory does not end in .app
* it probably means we are under GDB. Add
* the .app dir name to the end of the dir if this is the case
*/
if (getenv("NICKGDB"))
{
len = strlen(dir);
if ( ! ((dir[len-1] == 'p') &&
(dir[len-2] == 'p') &&
(dir[len-3] == 'a') &&
(dir[len-4] == '.')) )
{
sprintf(temp, "%s/%s.app", dir, getAppName());
dir = temp;
}
}
return dir;
}
- displayInspector:sender
{
[theInspector makeKeyAndOrderFront:self];
return self;
}
- getPhaseIncrement:sender
{
double freq;
double phase_inc;
double mag;
double srate;
double table_len;
freq = [sender floatValue];
table_len = [theTableLength doubleValue];
srate = [theSrate doubleValue];
if (srate <= 0)
{ /* bogus */
srate = 44100;
}
/*******************
From /Net/cmn14/projects/musicKit/mk/unitgenerators/OscgafUGs.m
The formula is:
phase_inc = (freq * _mag) / MK_OSCFREQSCALE
where _mag = (double)tableLength / [orchestra samplingRate];
and MK_OSCFREQSCALE = 256.0,
*********************/
mag = table_len / srate;
phase_inc = (freq * mag)/256.0;
[toPhaseInc setFloatValue:phase_inc];
return self;
}
- getFrequency:sender
{
double freq;
double phase_inc;
double table_len;
double mag;
double srate;
phase_inc = [sender floatValue];
table_len = [theTableLength doubleValue];
srate = [theSrate doubleValue];
if (srate <= 0)
{ /* bogus */
srate = 44100;
}
/*******************
From /Net/cmn14/projects/musicKit/mk/unitgenerators/OscgafUGs.m
The formula is:
phase_inc = (freq * _mag) / MK_OSCFREQSCALE
freq = (phase_inc/_mag) * MK_OSCFREQSCALE
where _mag = (double)tableLength / [orchestra samplingRate];
and MK_OSCFREQSCALE = 256.0,
substituting:
*********************/
mag = table_len / srate;
freq = (phase_inc/mag) * 256.0;
[toFreq setFloatValue:freq];
return self;
}
- (char *) envelopeToText:anEnvelope
{
int i, count;
double *x, *y;
unsigned int env_size;
int stick;
BOOL do_stick = NO;
char *envString;
/* Do something to the envelope so the File's Owner
* object can do something cool with it
*/
if (! anEnvelope)
{
return NULL;
}
count = [anEnvelope pointCount];
if (count <= 0)
{
return NULL;
}
x = [anEnvelope xArray];
y = [anEnvelope yArray];
stick = [anEnvelope stickPoint];
if (stick != MAXINT)
{
do_stick = YES;
}
if (! (x && y) )
{
return NULL;
}
/* The max a coordinate of an envelope can be is %03.5 = 9 characters
* add a comma and paren for each coordinate (make it 4 to be safe)
* Then we have 9+5 = 14 characters for each coordinate
* or 28 characters for each point
*/
env_size = count * 28 + 256; /* add 256 for extra fudge */
envString = (char *) NXZoneCalloc([self zone], env_size, sizeof(char));
if (! envString)
{
NXRunAlertPanel(getAppName(),
"Grave danger -- malloc error",
NULL, NULL, NULL);
return NULL;
}
strcpy(envString, "");
for (i=0; i<count; i++)
{
sprintf(envString, "%s(%4.4f, %f)",
envString, x[i], y[i]);
if (do_stick && (stick == i))
{
strcat(envString, "|");
}
}
return envString;
}
- textToEnvelope: (char *) aString
{
int i, j;
int pointCount = 0;
int stickPoint = -1;
double *xArray, *yArray, *smoothingArray;
id newEnv;
if (! aString)
{
return nil;
}
for (i=0; aString[i] != '\0'; i++)
{
if (aString[i]=='|')
{
stickPoint = pointCount-1;
}
if (aString[i]=='(')
pointCount++;
}
if (pointCount <= 0)
{
return nil;
}
xArray = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double));
yArray = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double));
smoothingArray = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double));
j=0;
for (i=0; i<pointCount; i++)
{
xArray[i] = yArray[i] = 0.0;
smoothingArray[i] = 1.0;
while (aString[j]!='(')
{
j++;
}
sscanf(aString+j, "(%lf,%lf,%lf)",
&xArray[i], &yArray[i], &smoothingArray[i]);
j++;
}
newEnv = [[[Envelope alloc] init]
setPointCount: pointCount
xArray: xArray
orSamplingPeriod: 1.0
yArray: yArray
smoothingArray: smoothingArray
orDefaultSmoothing: 1.0
];
if (stickPoint != -1)
{
[newEnv setStickPoint:stickPoint];
}
return newEnv;
}
#define MAX_PATHLEN 1024
#define RETURN_LEAF(Path) \
strcpy(buffer, Path); \
len = strlen(buffer); \
if (len <= 0 || len >= MAX_PATHLEN) \
return NULL; \
i = len; \
while (buffer[i] != '/' && i >= 0) i--; \
return &buffer[i+1];
- (char *) getPathLeaf: (char *) path
{
static char buffer[1024]; /* Character buffer */
static char leaf[256]; /* Buffer to hold leaf directory */
int len; /* Length of path */
int i, j; /* Counter */
int position; /* Position in string */
int leading_slash = 0; /* Position of a leading slash */
int slash_count = 0; /* Number of slashes in a path */
strcpy(leaf,path);
len = strlen(leaf);
if (len <= 0 || len >= MAX_PATHLEN)
{ /* Crap */
return NULL;
}
if (len > 1)
{
if (strcmp(leaf,"..") == 0)
{
RETURN_LEAF((char *)"..")
}
if (strcmp(leaf,"//") == 0)
{
return leaf;
}
position = len - 1;
for (i = len - 1 ; i >= 0; i--)
{
if (leaf[i] == '/')
{
position = i;
slash_count++;
}
else
{
break;
}
leaf[position] = EOS;
position--;
}
/* Special case: all characters are slashes */
if (slash_count == len)
{
strcpy(buffer,"//");
return buffer;
}
/* Begining of string */
if (leaf[0] == '/' )
{
i = 0;
while (leaf[leading_slash] != '/' && leading_slash <= len)
{
if (leaf[i] == '/')
leading_slash++;
else
break;
}
if (i > 2)
{ /* Extra slashes at begining of string */
j = 0;
for (i = leading_slash; i <= len; i++)
{
buffer[j++] = leaf[i];
}
buffer[j] = EOS;
strcpy(leaf,"//");
strcat(leaf,buffer);
}
}
/* Position to the first non-extraneous slash */
while (leaf[position] != '/' && position >= 0) position--;
/* Deal with case where slash is first character or no slashes in path */
if (position == 0)
{
if (leaf[position] == '/')
{ /* Case where something line '/foo' was entered */
return &leaf[position+1];
}
else
{ /* Case where a leaf like 'my_file' was entered (no slashes (/'s)) */
return leaf;
}
}
else
{
/* Regular leafy path */
return &leaf[position+1];
}
}
else
{
/* Single character paths. All special cases */
if ( (strcmp(leaf,"/") == 0) ||
(strcmp(leaf,".") == 0) ||
(strcmp(leaf,"~") == 0) )
{
RETURN_LEAF((char *)leaf)
}
{ /* A single non-special character */
return leaf;
}
}
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.