home *** CD-ROM | disk | FTP | other *** search
-
- /* Generated by Interface Builder */
-
- #import "Spectro.h"
- #import "SpectrumView.h"
- #import "WaterfallView.h"
- #import "WaterfallComputer.h"
- #import "SignalProcessor.h"
- #import <appkit/appkit.h>
- #import <soundkit/soundkit.h>
- #import <math.h>
- #import <string.h>
- #import <stdio.h>
-
- int data_size,power_of_four,window_size,num_frames,total_data,s_rate,mono_file;
- float f[16384],freq_max;
- BOOL running_analysis = FALSE,one_time = FALSE,waterfall = FALSE;
- char window_type[200];
- int firstSample,sampleCount;
- float ceiling,flor;
-
- @implementation Spectro
-
- - changeFreqMax:sender
- {
- int i;
- freq_max = [[sender cellAt: 0 : 4] floatValue];
- if (freq_max>0.5*s_rate) freq_max = 0.5 * s_rate;
- for (i=1;i<5;i++) {
- [[freqRange cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- [[freqRange2 cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- }
- [myView setFreqRange: freq_max andAmpRange: [myView ampRange]];
- [myView clear];
- [myView placeVerticals: 0.25];
- [self calculate:nil];
- return self;
- }
-
- - selectionChanged:sender
- {
- mySound = [sender sound];
- [mySound compactSamples];
- [self setup: sender];
- if ([goOnSelect state]) [self calculate:self];
- return self;
- }
-
- - setup:sender
- {
- int i;
- [[soundView docView] getSelection:&firstSample size:&sampleCount];
- if ((firstSample + sampleCount)>[[[soundView docView] sound] sampleCount]) sampleCount = [[[soundView docView] sound] sampleCount] - firstSample;
- num_frames = sampleCount / [windowSize intValue] * 2 - 1;
- if (num_frames<1) num_frames = 0;
- s_rate = [mySound samplingRate];
- [numFrames setIntValue: num_frames];
- freq_max = [[freqRange cellAt: 0 : 4] floatValue];
- if (freq_max>0.5*s_rate) freq_max = 0.5 * s_rate;
- for (i=1;i<5;i++) {
- [[freqRange cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- [[freqRange2 cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- }
- flor = [[viewLimit cellAt: 4: 0] floatValue];
- [myView setFreqRange: freq_max andAmpRange: flor];
- [beginTime setDoubleValue: (double) firstSample / s_rate];
- [self changeTimeSetups: numFrames];
- return self;
- }
-
- - calculate:sender
- {
- // int temp_num_frames;
- // mySound = [[soundView docView] sound];
- // [mySound compactSamples];
- // temp_num_frames = [mySound sampleCount] / [windowSize intValue] * 2 - 1;
- // num_frames = [numFrames intValue];
- // if (temp_num_frames < num_frames) {
- // num_frames = temp_num_frames;
- // [numFrames setIntValue: num_frames];
- // [self changeTimeSetups: numFrames];
- // }
- one_time = TRUE;
- [self doSpectrum];
- one_time = FALSE;
- return self;
- }
-
- - knockItOff:sender
- {
- one_time = FALSE;
- return self;
- }
-
- - (int) passThisToWFViewPlease: (float *) f // this is sent by WaterfallComputer to draw views
- { // It's here so later we can put the computation into a different thread
- // We're faking that now by checking the stop button explicitly each time.
- NXRect buttonBounds;
- NXPoint mousePosition;
- int mouseDown,windowIsKey;
- [myWaterfallView drawNext: f];
- [[stopButton window] getMouseLocation: &mousePosition];
- [stopButton getBounds: &buttonBounds];
- PSbuttondown(&mouseDown);
- // windowIsKey = [[stopButton window] isKeyWindow];
- if ([stopButton mouse:&mousePosition inRect: &buttonBounds] && mouseDown) return 1;
- else return 0;
- }
-
-
- - doSpectrum
- {
- float temp_f[16384];
- int i;
- float timeDelta,timeBegin;
- unsigned char *data;
- short *linear_data;
- mySound = [[soundView docView] sound];
- if (mySound) {
- [mySound compactSamples];
- [[soundView docView] getSelection:&firstSample size:&sampleCount];
- if ((firstSample + sampleCount)>[[[soundView docView] sound] sampleCount])
- sampleCount = [[[soundView docView] sound] sampleCount] - firstSample;
- data = [mySound data];
- linear_data = (short *) data;
- strcpy(window_type,[windowType stringValue]);
- flor = [[viewLimit cellAt: 4: 0] floatValue];
- ceiling = 2.0 * 65536.0 * 65536.0 * window_size;
- mono_file = 2;
- if ([mySound channelCount]>1) {
- mono_file = NXRunAlertPanel("Spectro is Confused","The current sound is stereo.\
- What should I transform?","Both Mixed","Right","Left");
- printf("%i\n",mono_file);
- }
- if (num_frames>1 && one_time) {
- for (i=0;i<data_size;i++) temp_f[i] = f[i];
- if (!myWaterfallComputer) {
- myWaterfallComputer = [[WaterfallComputer allocFromZone:[self zone]] init];
- [myWaterfallComputer setSignalProcessor: mySignalProcessor];
- [myWaterfallComputer setApp: self];
- }
- [myWaterfallView setup: num_frames length: (int) (data_size * freq_max / s_rate)];
- if ([mySound dataFormat]==1)
- [myWaterfallComputer computeThisCodex: data];
- else
- [myWaterfallComputer computeThisLinear: linear_data];
- timeDelta = ([totalSeconds floatValue] / num_frames) * (num_frames + 1) * 0.25;
- timeBegin = [beginTime floatValue];
- for (i=0;i<5;i++) {
- [[wfTimes cellAt: 4-i : 0] setFloatValue: timeBegin];
- timeBegin += timeDelta;
- }
- [myView clear];
- [frameSlider setFloatValue: 0.0];
- [self sliderChange: frameSlider];
- [myView placeVerticals: 0.25];
- [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
- s_rate = [mySound samplingRate];
- if (freq_max==0) freq_max = 0.5 * s_rate;
- for (i=1;i<5;i++) {
- [[freqRange cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- [[freqRange2 cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- }
- [myView setFreqRange: freq_max andAmpRange: flor];
- [myView placeHorizontals: 0.25];
- }
- else {
- for (i=0;i<data_size;i++) temp_f[i] = f[i];
- if ([mySound dataFormat]==1)
- for (i=0;i<window_size;i++) f[i] = (float) SNDiMulaw(data[i + firstSample]);
- else {
- if (mono_file==2)
- for (i=0;i<window_size;i++) f[i] = (float) linear_data[i +firstSample];
- if (mono_file==1)
- for (i=0;i<window_size;i++) f[i] = (float) (linear_data[2*(i +firstSample)] +
- linear_data[2*(i + firstSample) + 1]) * 0.5;
- if (mono_file==0)
- for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i + firstSample) + 1];
- if (mono_file==-1)
- for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i + firstSample)];
- }
- for (i=window_size;i<data_size;i++) f[i] = 0.0;
- [mySignalProcessor window: window_size array: f type: window_type phase: FALSE];
- [mySignalProcessor fhtRX4: power_of_four array: f];
- [mySignalProcessor logMag: data_size array: f floor: flor ceiling: ceiling];
- [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: temp_f erase: TRUE];
- [myView placeVerticals: 0.25];
- [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
- s_rate = [mySound samplingRate];
- if (freq_max==0) freq_max = 0.5 * s_rate;
- for (i=1;i<5;i++) {
- [[freqRange cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- [[freqRange2 cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- }
- [myView setFreqRange: freq_max andAmpRange: flor];
- [myView placeHorizontals: 0.25];
- }
- }
- return self;
- }
-
- - changeZPFactor: sender
- {
- double temp;
- window_size = [windowSize intValue];
- data_size = window_size * [zpFactor floatValue];
- num_frames = [numFrames intValue];
- temp = log((double) data_size) / log(4.0);
- if (temp>7.0) temp=7.0;
- power_of_four = temp + .999;
- data_size = pow(4.0,power_of_four);
- [zpFactor setFloatValue: ((float) data_size / (float) window_size)];
- if (s_rate>0) temp = (float) window_size / (float) s_rate * 0.5;
- [hopTime setDoubleValue: temp];
- [windowTime setDoubleValue: temp * 2.0];
- [totalSeconds setDoubleValue: temp * [numFrames doubleValue]];
- [self setup: self];
- [self calculate: self];
- return self;
- }
-
- - changeWindowSize:sender
- {
- [zpFactor setIntValue: 1];
- [myView clear];
- [self setup:self];
- [self calculate:self];
- return self;
- }
-
- - changeTimeSetups: sender
- {
- double temp;
- window_size = [windowSize intValue];
- data_size = window_size * [zpFactor floatValue];
- num_frames = [numFrames intValue];
- temp = log((double) data_size) / log(4.0);
- if (temp>7.0) temp=7.0;
- power_of_four = temp + .999;
- data_size = pow(4.0,power_of_four);
- [zpFactor setFloatValue: ((float) data_size / (float) window_size)];
- mySound = [[soundView docView] sound];
- s_rate = [mySound samplingRate];
- if (s_rate>0) temp = (float) window_size / (float) s_rate* 0.5;
- [hopTime setDoubleValue: temp];
- [windowTime setDoubleValue: temp * 2.0];
- [totalSeconds setDoubleValue: temp * [numFrames doubleValue]];
- return self;
- }
-
- - changeViewLimit:sender
- {
- int temp,i;
- temp = [sender intValue];
- if (temp>0) temp = -temp;
- for (i=0;i<4;i++) [[viewLimit cellAt: i : 0] setIntValue: temp * i / 4];
- [myView clear];
- s_rate = [mySound samplingRate];
- if (freq_max==0) freq_max = 0.5 * s_rate;
- for (i=1;i<5;i++) {
- [[freqRange cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- [[freqRange2 cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- }
- [myView setFreqRange: freq_max andAmpRange: temp];
- [self calculate:nil];
- return self;
- }
-
- - timeChange:sender
- {
- float temp;
- int plot;
- temp = [sender floatValue] - [beginTime floatValue];
- plot = temp / [hopTime floatValue];
- temp = plot / ([numFrames floatValue]);
- [frameSlider setFloatValue: temp];
- [self sliderChange: frameSlider];
- return self;
- }
-
- - frameChange:sender
- {
- float temp;
- int plot;
- plot = [sender intValue];
- temp = plot / (1.5 + [numFrames floatValue]);
- [frameSlider setFloatValue: temp];
- [self sliderChange: frameSlider];
- return self;
- }
-
- - sliderChange:sender
- {
- float temp,temp_f[17000];
- int plot,k,i;
- unsigned char *data;
- short *linear_data;
- mySound = [[soundView docView] sound];
- if (mySound) {
- [mySound compactSamples];
- [[soundView docView] getSelection:&firstSample size:&sampleCount];
- if ((firstSample + sampleCount)>[[[soundView docView] sound] sampleCount]) sampleCount = [[[soundView docView] sound] sampleCount] - firstSample;
- data = [mySound data];
- linear_data = (short *) data;
- strcpy(window_type,[windowType stringValue]);
- flor = [[viewLimit cellAt: 4: 0] floatValue];
- ceiling = 2.0 * 65536.0 * 65536.0 * window_size;
- temp = [sender floatValue];
- plot = temp * (2.5 + [numFrames floatValue]);
- [currentTime setFloatValue: [hopTime floatValue] * plot + [beginTime floatValue]];
- [currentPlot setIntValue: plot];
- if (plot > [numFrames intValue] - 1) plot = [numFrames intValue] - 1;
- [myWaterfallView placeTickAt: plot];
- for (i=0;i<data_size;i++) temp_f[i] = f[i];
- [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: temp_f erase: TRUE];
- k = plot * window_size * 0.5;
- if ([mySound dataFormat]==1)
- for (i=0;i<window_size;i++) f[i] = (float) SNDiMulaw(data[i +k + firstSample]);
- else {
- if (mono_file==2)
- for (i=0;i<window_size;i++) f[i] = (float) linear_data[i +k+ firstSample];
- if (mono_file==1)
- for (i=0;i<window_size;i++) f[i] = (float) (linear_data[2*(i +k+ firstSample)] +
- linear_data[2*(i + k+ firstSample) + 1]) * 0.5;
- if (mono_file==0)
- for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i + k+ firstSample) + 1];
- if (mono_file==-1)
- for (i=0;i<window_size;i++) f[i] = (float) linear_data[2*(i +k+ firstSample)];
- }
- for (i=window_size;i<data_size;i++) f[i] = 0.0;
- [mySignalProcessor window: window_size array: f type: window_type phase: FALSE];
- [mySignalProcessor fhtRX4: power_of_four array: f];
- [mySignalProcessor logMag: data_size array: f floor: flor ceiling: ceiling];
- [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
- [myView placeVerticals: 0.25];
- [myView drawSpectrum: (int) (data_size * freq_max / s_rate) array: f];
- s_rate = [mySound samplingRate];
- for (i=1;i<5;i++) {
- [[freqRange cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- [[freqRange2 cellAt: 0 : i] setIntValue: i * 0.25 * freq_max];
- }
- [myView setFreqRange: freq_max andAmpRange: flor];
- [myView placeHorizontals: 0.25];
- }
- return self;
- }
-
- - running:sender
- {
- double temp;
- window_size = [windowSize intValue];
- data_size = window_size * [zpFactor floatValue];
- num_frames = [numFrames intValue];
- temp = window_size / 16024.0;
- [hopTime setDoubleValue: temp];
- [windowTime setDoubleValue: temp * 2.0];
- [totalSeconds setDoubleValue: temp * [numFrames doubleValue]];
- temp = log((double) data_size) / log(4.0);
- if (temp>7.0) temp=7.0;
- power_of_four = temp + .999;
- data_size = pow(4.0,power_of_four);
- [zpFactor setFloatValue: ((float) data_size / (float) window_size)];
- if (sender==loopButton&&[loopButton state]) [myView clear];
- if ([loopButton state]) running_analysis = TRUE; else running_analysis = FALSE;
- // if (sender==oneTime) one_time = TRUE;
- if (running_analysis || one_time) {
- mySound = [[soundView docView] sound];
- if (!mySound) {
- [[soundView docView] setSound: [Sound new]];
- mySound = [[soundView docView] sound];
- [mySound setDelegate: self];
- }
- if (running_analysis) {
- total_data = window_size;
- [mySound setDataSize: window_size
- dataFormat: SND_FORMAT_MULAW_8
- samplingRate:SND_RATE_CODEC
- channelCount: 1
- infoSize: 12];
- }
- [mySound record];
- }
- return self;
- }
-
- - didRecord:sender
- {
- if (running_analysis) {
- [self doSpectrum];
- [self running: nil];
- }
- if (one_time) {
- [soundMeter stop:self];
- one_time = FALSE;
- }
- return self;
- }
-
- - save:sender
- {
- char file_name[200];
- strcpy(file_name,[fileName stringValue]);
- [[[soundView docView] sound] writeSoundfile:file_name];
- return self;
- }
-
- - zoomOut:sender
- {
- [[soundView docView] setReductionFactor: [[soundView docView] reductionFactor] * 2.0];
- return self;
- }
-
- - zoomIn:sender
- {
- [[soundView docView] setReductionFactor: [[soundView docView] reductionFactor] * 0.5];
- return self;
- }
-
- - showAll:sender
- {
- NXRect frame;
- double num_samps;
- num_samps = [[[soundView docView] sound] sampleCount];
- [[soundView docView] setReductionFactor: 1.0];
- [[soundView docView] getVisibleRect: &frame];
- [[soundView docView] setReductionFactor: num_samps / frame.size.width];
- return self;
- }
-
- - showSelection:sender
- {
- NXRect frame;
- int beg, size;
- double num_samps;
- float total_samps;
- [[soundView docView] getSelection: &beg size: &size];
- num_samps = size;
- total_samps = (float) [[[soundView docView] sound] sampleCount];
- [[soundView docView] setReductionFactor: 1.0];
- [[soundView docView] getVisibleRect: &frame];
- [[soundView docView] setReductionFactor: num_samps / frame.size.width];
- [[soundView horizScroller] setFloatValue: (float) beg / total_samps];
- [soundView display];
- return self;
- }
-
- - play:sender
- {
- [[soundView docView] setDelegate: self];
- [soundView play:sender];
- return self;
- }
-
- - stop:sender
- {
- [soundView stop:sender];
- [soundMeter stop:self];
- return self;
- }
-
- - record:sender
- {
- [[soundView docView] setDelegate: self];
- [soundView record:sender];
- return self;
- }
-
- - willPlay:sender
- {
- [soundMeter setSound: [[soundView docView] soundBeingProcessed]];
- [soundMeter run:self];
- return self;
- }
-
- - willRecord:sender
- {
- [soundMeter setSound: [[soundView docView] soundBeingProcessed]];
- [soundMeter run:self];
- return self;
- }
-
- - didPlay:sender
- {
- [soundMeter stop:self];
- return self;
- }
-
- - load:sender
- {
- char file_name[200];
- strcpy(file_name,[fileName stringValue]);
- [mySound free];
- if (mySound = [Sound newFromSoundfile: file_name]) {
- [[soundView docView] setSound: mySound];
- [[soundView docView] setDelegate: self];
- [self setup:sender];
- }
- else {
- [mySound free];
- NXRunAlertPanel("Spectro is Confused","I can't find that file.",NULL,NULL,"OK");
- }
- return self;
- }
-
- @end
-