This is SoundEffect.m in view mode; [Download] [Up]
// /* SoundEffect.m, class to play sounds * Originally by Terry Donahue, modified by Ali Ozer and Katzlberger Thomas (cat) * * SoundEffect is a class which conveniently groups the 3.0 * sound stream functionality with sound data using the Sound * class. * * You may freely copy, distribute and reuse the code in this example. * NeXT disclaims any warranty of any kind, expressed or implied, * as to its fitness for any particular use. */ #import "SoundEffect.h" #import <soundkit/NXSoundOut.h> #import <appkit/nextstd.h> #import <appkit/Application.h> #import <objc/List.h> // 8/28/93 reference limiting by cat for MissileCommand @implementation SoundEffect static BOOL soundEnabled = YES; + (void)setSoundEnabled:(BOOL)flag { soundEnabled = flag; } + (BOOL)soundEnabled { return soundEnabled; } #define DEFAULTMAXSOUNDSTREAMS 40 static List *soundStreams = nil; static unsigned int soundStreamsAllocated = 0; static unsigned int maxSoundStreams = DEFAULTMAXSOUNDSTREAMS; // These two methods let the client set/get the maximum number of // sound streams to allocate. If this number is exceeded, sound requests // are simply not honored until sound streams are freed up. + (void)setMaxSoundStreams:(unsigned int)max { maxSoundStreams = max; } + (unsigned int)maxSoundStreams { return maxSoundStreams; } // This method returns a sound stream to be used in playing a sound. // Sound streams allocated through this method should be given back // via releaseSoundStream:. Note that this is for internal use only; // it however might be overridden if necessary. // aha ! soundStreams is a list of available (unused,not playing) streams - (NXPlayStream *)soundStream { static NXSoundOut *dev = nil; // We only have one instance of this... NXPlayStream *newStream = nil; if (!dev && !(dev = [[NXSoundOut alloc] init])) { // We allocate from the default zone so NXLogError ("Couldn't create NXSoundOut"); // freeing this zone won't blast it return nil; } if (!soundStreams) soundStreams = [[List alloc] init]; if (![soundStreams count]) { if (soundStreamsAllocated < maxSoundStreams) { newStream = [[NXPlayStream allocFromZone:[self zone]] initOnDevice:dev]; soundStreamsAllocated++; } } else newStream = [soundStreams removeLastObject]; if(newStream) { [newStream setDelegate:self]; if (![newStream isActive]) [newStream activate]; } return newStream; } - (void)releaseSoundStream:(NXPlayStream *)soundStream { [soundStreams addObject:soundStream]; } // This method lets you create new instances of SoundEffect. If the specified // sound file does not exist, the allocated instance is freed and nil is returned. - initFromSection:(const char *)path withLimit:(unsigned int)n { flags.limit = n; return [self initFromSection:path]; } - initFromSection:(const char *)path { [super init]; if(flags.limit == 0) flags.limit = 255; if (!(sound = [[Sound alloc] initFromSection:path])) { NXLogError ("Couldn't load sound from %s", path); [self free]; return nil; } if([sound samplingRate]<22000.0) [sound convertToFormat:SND_FORMAT_LINEAR_16 samplingRate:SND_RATE_LOW channelCount:2]; return self; } - (int)soundsPlaying { return flags.refCount; } // Free frees the SoundEffect. If this sound effect is being played at the time, // the free is delayed and happens as soon as all pending sounds are finished. - free { if (flags.refCount) { flags.freeWhenDone = YES; return nil; } else { if (sound) [sound free]; return [super free]; } } // These 3 methods play the sound effect. // This function ensures that soundstreams will be reactivated (by calling: // soundStream:didCompleteBuffer:) if lots of (>20) short sounds are played within // one function without invoking the eventloop - playEvent { [NXApp getNextEvent:NX_NULLEVENTMASK waitFor:0.0 threshold:NX_BASETHRESHOLD]; return [self play:1.0 pan:0.0]; } - play { return [self play:1.0 pan:0.0]; } - play:(float)volume pan:(float)pan { float left,right; NXPlayStream *soundStream; if((flags.refCount>=flags.limit) || (!soundEnabled)) return self; if (!(soundStream = [self soundStream])) { NXLogError ("No sound stream to play sound %x", self); return self; } left = right = volume; if (pan > 0.0) left *= 1.0 - pan; else if (pan < 0.0) right *= 1.0 + pan; [soundStream setGainLeft:left right:right]; [soundStream playBuffer:(void *)[sound data] size:(unsigned int)[sound dataSize] tag:0 channelCount:(unsigned int)[sound channelCount] samplingRate:[sound samplingRate]]; flags.refCount++; return self; } // Delegate methods for internal use only. - soundStream:sender didCompleteBuffer:(int)tag { flags.refCount--; [self releaseSoundStream:sender]; if (flags.freeWhenDone && flags.refCount == 0) [self free]; return sender; } - soundStreamDidAbort:sender deviceReserved:(BOOL)flag { return [self soundStream:sender didCompleteBuffer:0]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.