This is LPCPlot.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "LPCPlot.h" #import "LPCView.h" #import "Dispatcher.h" #import <appkit/Application.h> #import <appkit/Window.h> #import <appkit/ScrollView.h> #import <appkit/Panel.h> #import <appkit/Cell.h> #import <appkit/SavePanel.h> #import <strings.h> #import <sys/types.h> #import <sys/stat.h> #import <sys/file.h> #import <libc.h> #import <dpsclient/dpsclient.h> #import <math.h> #import <dpsclient/wraps.h> #import "PWfft.h" /* * Frame information */ #define RESIDAMP 0 #define AMP 1 #define THRESH 2 #define PITCH 3 #define MAXZOOM 4 #define MINZOOM -3 @implementation LPCPlot extern int errno; /* * Create a new document to display a LPC plot */ + new:(const char *)title { NXRect aRect; self = [super new]; // Set up memory PSops = NULL; PSAdata = NULL; PSPdata = NULL; undoData = NULL; undoSize = 0; [NXApp loadNibSection:"lpcplot.nib" owner:self]; [myView setDelegate:self]; [myView setParent:self]; [myPlot setDelegate:self]; numBytes = 0; zoomfactor = 1; curzoom = 0; threshold = 1.0; PWinit(); [self setDirty:NO]; // Set up view dependencies [myScroll getDocVisibleRect:&aRect]; [myView setFrame:&aRect]; [myScroll setDocView:myView]; [myScroll setHorizScrollerRequired:YES]; [myScroll setVertScrollerRequired:NO]; // Set the number of poles for the LPC file - get default from NXApp [self setPoles:[NXApp poles]]; [numPoles setIntValue:poles]; // Set the title of the window - filename or Untitled strcpy(filename, title); if (!strcmp(filename, "Untitled")) { hasData = NO; [myPlot setTitleAsFilename:"Untitled"]; [self show:self]; return self; } else { [myPlot setTitleAsFilename:filename]; if ([self setLPCfile:filename] < 0) { hasData = NO; [myPlot setTitleAsFilename:"Untitled"]; [self show:self]; return self; } hasData = YES; } [self show:self]; return self; } - (int) setLPCfile:(const char *)file { struct stat st; openfd = open(file, O_RDWR, 0); if (openfd < 0) { [self error:"Could not open input file : ":errno]; return -1; } fstat(openfd, &st); frames = (st.st_size/(([self getPoles] + 4)*4))-1; numBytes = st.st_size; [numFrames setIntValue:frames]; lpcData = (float *)malloc(st.st_size); if (read(openfd, lpcData, st.st_size) < 0) { [self error:"Error reading input file : ":errno]; return -1; } return 0; } - drawData { int i, winwidth, abovethresh, belowthresh; float yscalea, yscalep, half, zoomsize; NXRect viewBounds, scrollBounds, visBounds; float amax, amin; // amplitude boundaries float ptchmax, ptchmin; // pitch boundaries // DPSUserPath stuff float bbox[4]; float *t, *a, *ptch; // temporary variables float *pitchT, *ampT; char *o; // Only draw plot if such information exists if (!hasData) return self; framesize = ([self getPoles] + 4); amax = MINFLOAT; ptchmax = MINFLOAT; amin = MAXFLOAT; ptchmin = MAXFLOAT; t = lpcData; for (i = 0; i < frames; i++) { if (t[AMP] > amax) amax = t[AMP]; if (t[AMP] < amin) amin = t[AMP]; if (t[PITCH] > ptchmax) ptchmax = t[PITCH]; if (t[PITCH] < ptchmin) ptchmin = t[PITCH]; t += framesize; } if (amax == amin) { if (amax > 0) amin = 0; else if (amax == 0) amin = -1; else amin = 2*amax; } if (ptchmax == ptchmin) { if (ptchmax > 0) ptchmin = 0; else if (ptchmax == 0) ptchmin = -1; else ptchmin = 2*ptchmax; } [myScroll getDocVisibleRect:&scrollBounds]; [myView getVisibleRect:&visBounds]; scrollBounds.size.width *= zoomfactor; printf("width = %f\n", scrollBounds.size.width); /* Bug in DSPUserpath makes drawing at > 4096 bomb */ while (scrollBounds.size.width > 4096.0) { // Simulate a zoom out scrollBounds.size.width /= zoomfactor; --curzoom; zoomfactor /= 1.5; scrollBounds.size.width *= zoomfactor; printf("too big -- new width = %f\n", scrollBounds.size.width); } [myView sizeTo:scrollBounds.size.width :scrollBounds.size.height]; [myView getBounds:&viewBounds]; [myView lockFocus]; PSsetgray(NX_WHITE); NXRectFill(&viewBounds); [myView unlockFocus]; winwidth = scrollBounds.size.width; zoomsize = frames; step = 1.0*zoomsize/winwidth; half = 1.0*(visBounds.size.height)/2.0; yscalea = 1.0*(half - 25.0)/(1.0*(amax - amin)); yscalep = 1.0*(half - 25.0)/(1.0*(ptchmax - ptchmin)); if (!PSAdata) PSAdata = (float *)malloc(4*winwidth*sizeof(float)); if (!PSPdata) PSPdata = (float *)malloc(4*winwidth*sizeof(float)); if (!PSops) PSops = (char *)malloc(2*winwidth*sizeof(char)); pitchT = PSPdata + ((4*winwidth) - 1); ampT = PSAdata + ((4*winwidth) - 1); t = lpcData; belowthresh = 0; abovethresh = 0; for (i = 0, a = PSAdata, ptch = PSPdata, o = PSops; i < winwidth; i++) { if (t[THRESH] < threshold) { *a++ = i; *a++ = 20.0; *a++ = 0.0; *a++ = ((t[AMP] - amin)*yscalea); *ptch++ = i; *ptch++ = half+20.0; *ptch++ = 0.0; *ptch++ = ((t[PITCH] - ptchmin)*yscalep); belowthresh++; } else { *ampT-- = ((t[AMP] - amin)*yscalea); *ampT-- = 20.0; *ampT-- = 0.0; *ampT-- = i; *pitchT-- = ((t[PITCH] - ptchmin)*yscalep); *pitchT-- = 0.0; *pitchT-- = half+20.0; *pitchT-- = i; abovethresh++; } *o++ = dps_moveto; *o++ = dps_rlineto; t = (lpcData) + (framesize * (int)(i * step)); } ampT++; pitchT++; bbox[0] = 0.0; bbox[1] = 0.0; bbox[2] = winwidth; bbox[3] = ((amax - amin)*yscalea) + half; [myView drawPlot:PSAdata:PSops:bbox:belowthresh:NX_BLACK]; [myView drawPlot:ampT:PSops:bbox:abovethresh:NX_DKGRAY]; bbox[1] = half; bbox[3] = visBounds.size.height; [myView drawPlot:PSPdata:PSops:bbox:belowthresh:NX_BLACK]; [myView drawPlot:pitchT:PSops:bbox:abovethresh:NX_DKGRAY]; [myView lockFocus]; PWdrawruler(0, frames,(20*frames/winwidth), (20*frames/winwidth)/step); [myView unlockFocus]; if (PSAdata) free(PSAdata); if (PSPdata) free(PSPdata); if (PSops) free(PSops); PSAdata = NULL; PSPdata = NULL; PSops = NULL; return self; } - show:sender { [myPlot makeKeyAndOrderFront:self]; [myView display]; return self; } - setPoles:(int)pole { poles = pole; return self; } - (int)getPoles { return poles; } - updateCursor:sender { float amp, pitch, *t; int cursor, width, frame1, frame2, temp; if (!hasData) return self; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; frame1 = (int)(cursor * step); frame2 = (int)((cursor + width) * step); if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } [startFrame setIntValue:frame1]; [endFrame setIntValue:frame2]; t = lpcData + (framesize * (int)((cursor + width) * step)); amp = t[AMP]; pitch = t[PITCH]; [ampFrame setFloatValue:amp]; [pitchFrame setFloatValue:pitch]; return self; } - changeCursor:sender { int frame1, frame2, temp; float loc, loc2, width; frame1 = [startFrame intValue]; frame2 = [endFrame intValue]; frame1 = (frame1 < 0) ? 0 : frame1; frame1 = (frame1 > frames) ? frames : frame1; frame2 = (frame2 < 0) ? 0 : frame2; frame2 = (frame2 > frames) ? frames : frame2; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } loc = frame1 / step; loc2 = frame2 / step; width = loc2 - loc; [myView changeCurs:loc:width]; return self; } - selectAll:sender { [myView changeCurs:0:(frames/step)]; return self; } - changeAmp:sender { float *t, val; int cursor, width, i, frame1, frame2, temp; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); val = [ampFrame floatValue]; [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t]; for (i = frame1; i <= frame2; i++) { t[AMP] = val; t[RESIDAMP] = val; t = (lpcData) + (framesize * (i + 1)); } [myView display]; [self setDirty:YES]; return self; } - changePitch:sender { float *t, val; int cursor, width, i, frame1, frame2, temp; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); val = [pitchFrame floatValue]; [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t]; for (i = frame1; i <= frame2; i++) { t[PITCH] = val; t = (lpcData) + (framesize * (i + 1)); } [myView display]; [self setDirty:YES]; return self; } - multiplyAmp:sender { float *t, val; int cursor, width, i, frame1, frame2, temp; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } val = [mulAmpFrame floatValue]; t = lpcData + (framesize * frame1); [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t]; for (i = frame1; i <= frame2; i++) { t[AMP] *= val; t[RESIDAMP] *= val; t = (lpcData) + (framesize * (i + 1)); } [myView display]; return self; } - multiplyPitch:sender { float *t, val, top, bottom; int cursor, width, i, frame1, frame2, temp; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); val = [mulPitchFrame floatValue]; top = [topPitchFrame floatValue]; bottom = [botPitchFrame floatValue]; [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t]; for (i = frame1; i <= frame2; i++) { if (t[PITCH] <= top && t[PITCH] >= bottom) t[PITCH] *= val; t = (lpcData) + (framesize * (i + 1)); } [myView display]; [self setDirty:YES]; return self; } - interpolate:sender { float *t, *v, first, last, scale; int cursor, width, i, frame1, frame2, temp, j; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; frame1 = ((int)(cursor * step)) - 1; frame2 = ((int)((cursor + width) * step)) + 1; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); v = lpcData + (framesize * frame2); first = t[PITCH]; last = v[PITCH]; //t = lpcData + (framesize * (int)(cursor * step)); t = lpcData + (framesize * frame1); scale = (last - first) / (frame2 - frame1); [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t]; for (i = frame1, j = 0; i <= frame2; i++) { t[PITCH] = first + (j * scale); t = (lpcData) + (framesize * (i + 1)); ++j; } [myView display]; [self setDirty:YES]; return self; } - addError:sender { float *t, val; int cursor, width, i, frame1, frame2, temp; cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); val = [addErrFrame floatValue]; [self saveundo:(frame2 - frame1 + 1)*framesize*sizeof(float):t]; for (i = frame1; i <= frame2; i++) { t[THRESH] += val; t = (lpcData) + (framesize * (i + 1)); } [myView display]; [self setDirty:YES]; return self; } - save:sender { id sPanel; sPanel = [SavePanel new]; if (!strcmp("Untitled", filename)) { if ([sPanel runModal]) { strcpy(filename, [sPanel filename]); [myPlot setTitleAsFilename:filename]; openfd = open(filename, O_RDWR|O_CREAT, 0644); if (openfd < 0) { [self error:"Error opening input file : ":errno]; return self; } if (write(openfd, (char *)lpcData, numBytes) < 0) { [self error:"Error writing file : ":errno]; return self; }; [self setDirty:NO]; return self; } } else { lseek(openfd, 0, 0); // start of file if (write(openfd,(char *)lpcData,numBytes) < 0) { [self error:"Error writing file : ":errno]; return self; } [self setDirty:NO]; return self; } return self; } - saveAs:sender { id sPanel; char dir[1024], *file; sPanel = [SavePanel new]; file = rindex(filename, '/') + 1; strncpy(dir, filename, (int)(file - filename)); if ([sPanel runModalForDirectory:dir file:file]) { if (strcmp(filename, [sPanel filename])) { strcpy(filename, [sPanel filename]); close(openfd); openfd = open(filename, O_RDWR|O_CREAT, 0644); if (openfd < 0) { [self error:"Error saving file : ":errno]; return self; } if (write(openfd, (char *)lpcData, numBytes) < 0) { [self error:"Error saving file : ":errno]; return self; } [myPlot setTitleAsFilename:filename]; [self setDirty:NO]; return self; } else { lseek(openfd, 0, 0); if (write(openfd, (char *)lpcData, numBytes) < 0) { [self error:"Error saving file : ":errno]; return self; } [self setDirty:NO]; return self; } } return self; } - print:sender { [myView printPSCode:self]; return self; } - plot { return myPlot; } - zoomIn:sender { NXRect foo; if (curzoom >= MAXZOOM) return self; [myView getBounds:&foo]; if ((foo.size.width * 1.5) > 4096.0) return self; ++curzoom; zoomfactor *= 1.5; [myView display]; return self; } - zoomOut:sender { if (curzoom <= MINZOOM) return self; --curzoom; zoomfactor /= 1.5; [myView display]; return self; } - setThreshold:sender { threshold = [threshFrame floatValue]; [myView display]; return self; } - doCopy:(NXStream *)selection { float *t; int cursor, width, frame1, frame2, temp, bytes; if (!hasData) { return self; } cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); bytes = (frame2 - frame1)*framesize*sizeof(float); NXWrite(selection, t, bytes); return self; } - doCut:(NXStream *)selection { float *t, *v; int cursor, width, i, frame1, frame2, temp, bytes; if (!hasData) { return self; } cursor = [myView getcurPos]; width = [myView getWidth]; framesize = [self getPoles] + 4; //t = lpcData + (framesize * (int)(cursor * step)); frame1 = (int)cursor * step; frame2 = (int)(cursor + width) * step; if (frame1 > frame2) { temp = frame1; frame1 = frame2; frame2 = temp; } t = lpcData + (framesize * frame1); bytes = (frame2 - frame1)*framesize*sizeof(float); NXWrite(selection, t, bytes); numBytes -= bytes; frames = (numBytes/(([self getPoles] + 4)*4))-1; [numFrames setIntValue:frames]; v = t + (bytes / sizeof(float)); for (i = 0; i < (bytes / sizeof(float)); i++) { *t++ = *v++; } realloc(lpcData, numBytes); [myView display]; [self setDirty:YES]; return self; } - doInsert:(float *)data :(int) bytes { int cursor, frame1, size, i; float *t, *v; if (!hasData) { hasData = 1; lpcData = (float *)malloc(bytes); numBytes = bytes; frames = (numBytes/(([self getPoles] + 4)*4)) - 1; [numFrames setIntValue:frames]; t = lpcData; for (i = 0; i < (bytes / sizeof(float)); i++) { *t++ = *data++; } [myView display]; return self; } numBytes += bytes; frames = (numBytes/(([self getPoles] + 4)*4))-1; [numFrames setIntValue:frames]; realloc(lpcData, numBytes); cursor = [myView getcurPos]; frame1 = (int)cursor * step; framesize = [self getPoles] + 4; size = (numBytes - bytes) - (frame1 * framesize * sizeof(float)); v = lpcData + (numBytes / sizeof(float)) - 1; t = lpcData + ((numBytes - bytes) / sizeof(float)) - 1; for (i = 0; i < (size / sizeof(float)); i++) { *v-- = *t--; } t = lpcData + (framesize * frame1); for (i = 0; i < (bytes / sizeof(float)); i++) { *t++ = *data++; } [myView display]; [self setDirty:YES]; return self; } - saveundo:(int)size: (float *)data { int i; float *t, *s; if (undoData) free(undoData); undoData = (float *)malloc(size); undoLoc = data; undoSize = size; t = undoData; s = data; for (i = 0; i < (undoSize / 4); i++) { *t++ = *s++; } return self; } - undo:sender { float *t, *s; int i; t = undoLoc; s = undoData; for (i = 0; i < (undoSize / 4); i++) { *t++ = *s++; } [myView display]; return self; } - error:(char *)msg:(int)num { if (num) NXRunAlertPanel("Alert", "%s : %s", "OK", NULL, NULL, msg, strerror(num)); else NXRunAlertPanel("Alert", "%s", "OK", NULL, NULL, msg); return self; } - windowWillClose:sender { if ([myPlot isDocEdited]) { switch (NXRunAlertPanel("Alert", "Plot has been edited. Do you want to save?", "Yes", "No", "Cancel")) { case NX_ALERTDEFAULT : [self saveAs:self]; break; case NX_ALERTOTHER : return nil; break; default : break; } } return self; } - setDirty:(BOOL)val { [myPlot setDocEdited:val]; dirty = val; return self; } - (BOOL)isDirty { return dirty; } - cursorSel:sender { [myView setCursorType:SELECTION]; return self; } - cursorHair:sender { [myView setCursorType:HAIRLINE]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.