ftp.nice.ch/pub/next/developer/resources/classes/misckit/MiscKit.1.10.0.s.gnutar.gz#/MiscKit/Palettes/MiscSoundPalette/MiscSoundUtil.subproj/MiscSoundTracker.m

This is MiscSoundTracker.m in view mode; [Download] [Up]

/*

MiscSoundTracker
Version 1.2
Copyright (c) 1995 by Sean Luke
Donated to the MiscKit

Permission to use, copy, modify, and distribute this material 
for any purpose and without fee, under the restrictions as noted 
in the MiscKit copyright notice, is hereby granted, provided that
the MiscKit copyright notice and this permission notice 
appear in all source copies, and that the author's name shall not
be used in advertising or publicity pertaining to this 
material without the specific, prior written permission 
of the author.  SEAN O. LUKE  MAKES NO REPRESENTATIONS ABOUT THE
ACCURACY OR SUITABILITY OF THIS MATERIAL FOR ANY PURPOSE.  
IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.

*/

#import "MiscSoundTracker.h"
#import <stdio.h>

@implementation MiscSoundTracker

// KNOWN BUGS:  NeXT's sound object does not release sampling rate information
// properly.  Hence, the tracker cannot get seconds information correctly,
// when recording, and so must rely on a preset default for its sampling
// rate in returning seconds.

// also, samples do not keep up with pausing.



// timed entry procedure for periodically updating (shadow here)

DPSTimedEntryProc SOUNDTRACKER_update_tracker
	(DPSTimedEntry teNum,double now, void* the_tracker);


- init
	{
	[super init];
	running=NO;
	default_sampling_rate=SOUNDTRACKER_DEFAULT_SAMPLING_RATE;
	send_type=SOUNDTRACKER_SEND_TYPE_SAMPLES;
	refresh=SOUNDTRACKER_TIMED_ENTRY_SPEED;
	teNum=0;
	//printf ("Init\n");
	return self;
	}

- awake
	{
	[super awake];
	teNum=0;
	//printf ("Awake\n");
	return self;
	}


- _update
	{
	//printf("Updating\n");
	
	// first we check to see if there's a sound lock and if so,
	// if we should proceed...
	
	if (sound!=NULL&&
			(send_type==SOUNDTRACKER_SEND_TYPE_SAMPLES||
			send_type==SOUNDTRACKER_SEND_TYPE_RATIO||
			send_type==SOUNDTRACKER_SEND_TYPE_PERCENT||
			send_type==SOUNDTRACKER_SEND_TYPE_SECONDS))
			{
			id actual_sound;
			int status;
			
			if ([sound isKindOf:[Sound class]]) 
				{actual_sound=sound;}
			else if ([sound isKindOf:[SoundView class]])
				{actual_sound=[sound soundBeingProcessed];}
			else return NULL;		// not a sound or soundview!!!
			
			status=[actual_sound status];
			if (status==NX_SoundStopped||
				status==NX_SoundInitialized||
				status==NX_SoundFreed) return self;		
					// sound's not doing anything...
			}
	
	if (target!=NULL)
		{
		//printf ("Target Not Null\n");
		if (send_type==SOUNDTRACKER_SEND_TYPE_SAMPLES||
			send_type==SOUNDTRACKER_SEND_TYPE_MUTE||
			send_type==SOUNDTRACKER_SEND_TYPE_DEEMPHASIS)
			{
			//printf ("Sending Take Message\n");
			if (![target respondsTo:@selector(takeIntValueFrom:)])
				 return NULL;
			[target takeIntValueFrom:self];
			}
		else if (send_type==SOUNDTRACKER_SEND_TYPE_RATIO||
				send_type==SOUNDTRACKER_SEND_TYPE_PERCENT)
			{
			int status=[sound status];
			if (status==NX_SoundRecording||
				status==NX_SoundRecordingPaused)
				{
				[self clearTarget];
				}
			else
				{
				if (![target respondsTo:@selector(takeFloatValueFrom:)])
					return NULL;
				[target takeFloatValueFrom:self];
				}
			}
		else if (send_type==SOUNDTRACKER_SEND_TYPE_SECONDS||
				send_type==SOUNDTRACKER_SEND_TYPE_LEFT||
				send_type==SOUNDTRACKER_SEND_TYPE_RIGHT||
				send_type==SOUNDTRACKER_SEND_TYPE_MONO)
			{
			if (![target respondsTo:@selector(takeFloatValueFrom:)])
				 return NULL;
			[target takeFloatValueFrom:self];
			}
		else printf ("SOUNDTRACKER Error:  No Send Type\n");
		}
	return self;
	}


- setRefresh:(float) number_seconds
	{
	if (number_seconds>0)
		{
		refresh=number_seconds;
		if (teNum) 
			{
			DPSRemoveTimedEntry(teNum);
			teNum=DPSAddTimedEntry(refresh, 
				(DPSTimedEntryProc) SOUNDTRACKER_update_tracker,
				(void*) self, (int) NX_RUNMODALTHRESHOLD);
			}
		}
	return self;
	}

- setRefreshToMe:sender
	{
	if ([sender respondsTo:@selector(floatValue)])
		[self setRefresh:[sender floatValue]];
	return self;
	}


- (float)refresh
	{
	return refresh;
	}	

- free
	{
	if (output_device!=NULL) [output_device free];
	if (teNum) DPSRemoveTimedEntry(teNum);
	return [super free];
	}


- setSound:this_sound_or_soundview
	{
	sound=this_sound_or_soundview;
	return self;
	}


- sound
	{
	return sound;
	}

- setDefaultSamplingRate:(float) this_rate
	{
	if (this_rate!=0.0) default_sampling_rate=this_rate;
	return self;
	}

- (float)defaultSamplingRate
	{
	return default_sampling_rate;
	}
	
- setTarget:this_target
	{
	target=this_target;
	return self;
	}


- target
	{
	return target;
	}


- run
	{
	running=YES;
	if (!teNum) teNum=DPSAddTimedEntry(refresh, 
			(DPSTimedEntryProc) SOUNDTRACKER_update_tracker,
			(void*) self, (int) NX_RUNMODALTHRESHOLD);
	return self;
	}


- stop
	{
	running=NO;
	if (teNum) DPSRemoveTimedEntry(teNum);
	teNum=0;
	return self;
	}


- sendSamples
	{
	send_type=SOUNDTRACKER_SEND_TYPE_SAMPLES;
	return self;
	}


- sendSeconds
	{
	send_type=SOUNDTRACKER_SEND_TYPE_SECONDS;
	return self;
	}


- sendRatio
	{
	send_type=SOUNDTRACKER_SEND_TYPE_RATIO;
	return self;
	}
	
- sendPercent
	{
	send_type=SOUNDTRACKER_SEND_TYPE_PERCENT;
	return self;
	}
	
- sendLeft
	{
	send_type=SOUNDTRACKER_SEND_TYPE_LEFT;
	return self;
	}
	

- sendRight
	{
	send_type=SOUNDTRACKER_SEND_TYPE_RIGHT;
	return self;
	}
	

- sendMono
	{
	send_type=SOUNDTRACKER_SEND_TYPE_MONO;
	return self;
	}
	

- sendMute
	{
	send_type=SOUNDTRACKER_SEND_TYPE_MUTE;
	return self;
	}
	
- sendDeemphasis
	{
	send_type=SOUNDTRACKER_SEND_TYPE_DEEMPHASIS;
	return self;
	}

- sendLeftPeak
	{
	send_type=SOUNDTRACKER_SEND_TYPE_LEFT_PEAK;
	return self;
	}

- sendRightPeak
	{
	send_type=SOUNDTRACKER_SEND_TYPE_RIGHT_PEAK;
	return self;
	}
	
- sendMonoPeak
	{
	send_type=SOUNDTRACKER_SEND_TYPE_MONO_PEAK;
	return self;
	}

- setSendType:(int)this_format
	{
	if (this_format==SOUNDTRACKER_SEND_TYPE_SAMPLES||
		this_format==SOUNDTRACKER_SEND_TYPE_SECONDS||
		this_format==SOUNDTRACKER_SEND_TYPE_RATIO||
		this_format==SOUNDTRACKER_SEND_TYPE_PERCENT||
		this_format==SOUNDTRACKER_SEND_TYPE_LEFT||
		this_format==SOUNDTRACKER_SEND_TYPE_RIGHT||
		this_format==SOUNDTRACKER_SEND_TYPE_MONO||
		this_format==SOUNDTRACKER_SEND_TYPE_MUTE||
		this_format==SOUNDTRACKER_SEND_TYPE_DEEMPHASIS||
		this_format==SOUNDTRACKER_SEND_TYPE_LEFT_PEAK||
		this_format==SOUNDTRACKER_SEND_TYPE_RIGHT_PEAK||
		this_format==SOUNDTRACKER_SEND_TYPE_MONO_PEAK)
		{send_type=this_format;return self;}
	return NULL;
	}

- (int) sendType
	{
	return send_type;
	}

- (float) floatValue	
	{
	if (send_type==SOUNDTRACKER_SEND_TYPE_SECONDS)
		{
		if (sound!=NULL)
			{
			if ([sound isKindOf:[Sound class]])
				{
				float n=[sound samplingRate];
				//printf ("%f\n",n);
				if (n==0.0) n=default_sampling_rate;
				return ((float)[sound samplesProcessed])/n;
				}
			else if ([sound isKindOf:[SoundView class]])
				{
				id snd1=[sound soundBeingProcessed];
				float n=[snd1 samplingRate];
				//printf ("%f\n",n);
				if (n==0.0) n=default_sampling_rate;
				return ((float)[snd1 samplesProcessed])/n;
				}
			}
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_RATIO)
		{
		if (sound!=NULL)
			{
			if ([sound isKindOf:[Sound class]])
				{
				//int status=[sound status];  // no use right now
									
				return ((float)[sound samplesProcessed])/
					((float)[sound sampleCount]);
				}
			else if ([sound isKindOf:[SoundView class]])
				{
				id snd1=[sound soundBeingProcessed];
				//int status=[snd1 status];  // no use right now
					
				return ((float)[snd1 samplesProcessed])/
					((float)[snd1 sampleCount]);
				}
			}
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_PERCENT)
		{
		if (sound!=NULL)
			{
			if ([sound isKindOf:[Sound class]])
				{
				//int status=[sound status];  // no use right now
									
				return ((float)[sound samplesProcessed])/
					((float)[sound sampleCount])*100;
				}
			else if ([sound isKindOf:[SoundView class]])
				{
				id snd1=[sound soundBeingProcessed];
				//int status=[snd1 status];  // no use right now
					
				return ((float)[snd1 samplesProcessed])/
					((float)[snd1 sampleCount])*100;
				}
			}
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_LEFT)
		{
		float l,r;
		[Sound getVolume:&l:&r];
		return l;
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_RIGHT)
		{
		float l,r;
		[Sound getVolume:&l:&r];
		return r;
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_MONO)
		{
		float l,r;
		[Sound getVolume:&l:&r];
		return (l+r)/2.0;
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_LEFT_PEAK)
		{
		float l,r;
		
		// try to grab resources
		if (output_device==NULL) output_device=[[NXSoundOut alloc] init];
		
		if (output_device!=NULL)
			{
			[output_device getPeakLeft:&l right:&r];
			return l;
			}
		// else...return -1.0 as shown below
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_RIGHT_PEAK)
		{
		float l,r;
		
		// try to grab resources
		if (output_device==NULL) output_device=[[NXSoundOut alloc] init];
		
		if (output_device!=NULL)
			{
			[output_device getPeakLeft:&l right:&r];
			return r;
			}
		// else...return -1.0 as shown below
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_MONO_PEAK)
		{
		float l,r;
		
		// try to grab resources
		if (output_device==NULL) output_device=[[NXSoundOut alloc] init];
		
		if (output_device!=NULL)
			{
			[output_device getPeakLeft:&l right:&r];
			return (l+r)/2.0;
			}
		// else...return -1.0 as shown below
		}

	else printf ("SOUNDTRACKER Error:  Wrong send type for floatValue\n");
	return -1.0;
	}


- (int) intValue	
	{
	//printf ("Okay\n");
	if (send_type==SOUNDTRACKER_SEND_TYPE_SAMPLES)
		{
		if (sound!=NULL)
			{
			if ([sound isKindOf:[Sound class]])
				{
				return [sound samplesProcessed];
				}
			else if ([sound isKindOf:[SoundView class]])
				{
				id snd1=[sound soundBeingProcessed];
				return [snd1 samplesProcessed];
				}
			}
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_MUTE)
		{
		return (int) [Sound isMuted];
		}
	else if (send_type==SOUNDTRACKER_SEND_TYPE_DEEMPHASIS)
		{
		// try to grab resources
		if (output_device==NULL) output_device=[[NXSoundOut alloc] init];
		
		if (output_device!=NULL)
			{
			return (int) [output_device doesDeemphasize];
			}
		else return NO;
		}
	else printf ("SOUNDTRACKER Error:  Wrong send type for intValue\n");
	return -1;
	}


- setVolumeTo:sender	
	{
	float l,r,x;
	[Sound getVolume:&l:&r];
	if (! [sender respondsTo:@selector(floatValue)]) return NULL;
	x=[sender floatValue];
	if (x<0||x>1) return NULL;
	if (send_type==SOUNDTRACKER_SEND_TYPE_LEFT) [Sound setVolume:x:r];
	if (send_type==SOUNDTRACKER_SEND_TYPE_RIGHT) [Sound setVolume:l:x];
	if (send_type==SOUNDTRACKER_SEND_TYPE_MONO) [Sound setVolume:x:x];
	return self;
	}


- setMuteTo:sender	
	{
	int x;
	if (! [sender respondsTo:@selector(intValue)]) return NULL;
	x=[sender intValue];
	if (x!=0) x=1;
	[Sound setMute:(BOOL)x];
	return self;
	}

- setDeemphasisTo:sender	
	{
	int x;
	if (! [sender respondsTo:@selector(intValue)]) return NULL;
	x=[sender intValue];
	if (x!=0) x=1;
	
	// try to grab resources
	if (output_device==NULL) output_device=[[NXSoundOut alloc] init];
	
	if (output_device!=NULL)
		{
		[output_device setDeemphasis:x];
		}
	return self;
	}


- run:sender
	{
	return [self run];
	}


- stop:sender
	{
	return [self stop];
	}


- sendSamples:sender
	{
	return [self sendSamples];
	}


- sendSeconds:sender
	{
	return [self sendSeconds];
	}


- sendRatio:sender
	{
	return [self sendRatio];
	}

- sendPercent:sender
	{
	return [self sendPercent];
	}

- sendLeft:sender
	{
	return [self sendLeft];
	}

- sendRight:sender
	{
	return [self sendRight];
	}

- sendMono:sender
	{
	return [self sendMono];
	}

- sendMute:sender
	{
	return [self sendMute];
	}
	
- sendDeemphasis:sender
	{
	return [self sendDeemphasis];
	}
	
- sendLeftPeak:sender
	{
	return [self sendLeftPeak];
	}
	
- sendRightPeak:sender
	{
	return [self sendRightPeak];
	}	
	
- sendMonoPeak:sender
	{
	return [self sendMonoPeak];
	}

- read:(NXTypedStream*) stream
	{
	[super read:stream];
	NXReadTypes(stream,"iff",&send_type,&refresh,&default_sampling_rate);
	return self;
	}

- write:(NXTypedStream*) stream
	{
	[super write:stream];
	NXWriteTypes(stream,"iff",&send_type,&refresh,&default_sampling_rate);
	return self;
	}

- clearTarget
	{
	if ([target respondsTo:@selector(setStringValue:)])
		{
		[target setStringValue:""];
		}
	else [target setIntValue:0];
	return self;
	}

- (const char*) getInspectorClassName
	{
	return "MiscSoundTrackerInspector";
	}

@end



// timed entry procedure for periodically updating

DPSTimedEntryProc SOUNDTRACKER_update_tracker
	(DPSTimedEntry teNum,double now, void* the_tracker)
	{
	MiscSoundTracker* temp_tracker=(MiscSoundTracker*) the_tracker;
	[temp_tracker _update];
	return (void*) NULL;
	}


These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.