first commit
This commit is contained in:
+138
@@ -0,0 +1,138 @@
|
||||
//
|
||||
// ALBuffer.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 15/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenAL/al.h>
|
||||
|
||||
@class ALDevice;
|
||||
|
||||
|
||||
#pragma mark ALBuffer
|
||||
|
||||
/**
|
||||
* A buffer for audio data that will be played via a SoundSource.
|
||||
* @see SoundSource
|
||||
*/
|
||||
@interface ALBuffer : NSObject
|
||||
{
|
||||
ALDevice* device;
|
||||
ALuint bufferId;
|
||||
NSString* name;
|
||||
ALenum format;
|
||||
float duration;
|
||||
/** The uncompressed sound data to play. */
|
||||
void* bufferData;
|
||||
bool freeDataOnDestroy;
|
||||
ALBuffer* parentBuffer;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The size of a sample in bits. */
|
||||
@property(nonatomic,readonly,assign) ALint bits;
|
||||
|
||||
/** The ID assigned to this buffer by OpenAL. */
|
||||
@property(nonatomic,readonly,assign) ALuint bufferId;
|
||||
|
||||
/** The number of channels the buffer data plays in. */
|
||||
@property(nonatomic,readonly,assign) ALint channels;
|
||||
|
||||
/** The device this buffer was created for. */
|
||||
@property(nonatomic,readonly,retain) ALDevice* device;
|
||||
|
||||
/** The format of the audio data (see al.h, AL_FORMAT_XXX). */
|
||||
@property(nonatomic,readonly,assign) ALenum format;
|
||||
|
||||
/** The frequency this buffer runs at. */
|
||||
@property(nonatomic,readonly,assign) ALint frequency;
|
||||
|
||||
/** The name given to this buffer upon creation. You may change it at runtime if you wish. */
|
||||
@property(nonatomic,readwrite,retain) NSString* name;
|
||||
|
||||
/** The size, in bytes, of the currently loaded buffer data. */
|
||||
@property(nonatomic,readonly,assign) ALint size;
|
||||
|
||||
/** The duration of the sample in this buffer, in seconds. */
|
||||
@property(nonatomic,readonly,assign) float duration;
|
||||
|
||||
/** If true, calls free() on the audio data when this object gets destroyed.
|
||||
* Default: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool freeDataOnDestroy;
|
||||
|
||||
/** The parent buffer (which owns the uncompressed data) */
|
||||
@property(nonatomic,readwrite,retain) ALBuffer* parentBuffer;
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Make a new buffer.
|
||||
*
|
||||
* @param name Optional name that you can use to identify this buffer in your code.
|
||||
* @param data The sound data. Note: ALBuffer will call free() on this data when it is destroyed!
|
||||
* @param size The size of the data in bytes.
|
||||
* @param format The format of the data (see the Core Audio documentation).
|
||||
* @param frequency The sampling frequency in Hz.
|
||||
* @return A new buffer.
|
||||
*/
|
||||
+ (id) bufferWithName:(NSString*) name
|
||||
data:(void*) data
|
||||
size:(ALsizei) size
|
||||
format:(ALenum) format
|
||||
frequency:(ALsizei) frequency;
|
||||
|
||||
/** Initialize the buffer.
|
||||
*
|
||||
* @param name Optional name that you can use to identify this buffer in your code.
|
||||
* @param data The sound data. Note: ALBuffer will call free() on this data when it is destroyed!
|
||||
* @param size The size of the data in bytes.
|
||||
* @param format The format of the data (see the Core Audio documentation).
|
||||
* @param frequency The sampling frequency in Hz.
|
||||
* @return The initialized buffer.
|
||||
*/
|
||||
- (id) initWithName:(NSString*) name
|
||||
data:(void*) data
|
||||
size:(ALsizei) size
|
||||
format:(ALenum) format
|
||||
frequency:(ALsizei) frequency;
|
||||
|
||||
/** Returns a part of the buffer as a new buffer. You can use this method to split a buffer
|
||||
* into a sub-buffers. The sub-buffers retain a reference to their parent buffer, and share
|
||||
* the same memory. Therefore, modifying the parent buffer contents will affect its slices
|
||||
* and vice-versa.
|
||||
*
|
||||
* @param sliceName Optional name that you can use to identify the created buffer in your code.
|
||||
* @param offset The offset in sound frames where the slice starts.
|
||||
* @param size The size of the slice in frames.
|
||||
* @return The requested buffer.
|
||||
*/
|
||||
- (ALBuffer*)sliceWithName:(NSString *) sliceName offset:(ALsizei) offset size:(ALsizei) size;
|
||||
|
||||
|
||||
@end
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// ALCaptureDevice.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-01-11.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenAL/alc.h>
|
||||
|
||||
|
||||
#pragma mark ALCaptureDevice
|
||||
|
||||
/**
|
||||
* *UNIMPLEMENTED FOR IOS* An OpenAL device for capturing sound data.
|
||||
* Note: This functionality is NOT implemented in iOS OpenAL! <br>
|
||||
* This class is a placeholder in case such functionality is added in a future iOS SDK.
|
||||
*/
|
||||
@interface ALCaptureDevice : NSObject
|
||||
{
|
||||
ALCdevice* device;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The number of capture samples available. */
|
||||
@property(nonatomic,readonly,assign) int captureSamples;
|
||||
|
||||
/** The OpenAL device pointer. */
|
||||
@property(nonatomic,readonly,assign) ALCdevice* device;
|
||||
|
||||
/** List of strings describing all extensions available on this device (NSString*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* extensions;
|
||||
|
||||
/** The specification revision for this implementation (major version). */
|
||||
@property(nonatomic,readonly,assign) int majorVersion;
|
||||
|
||||
/** The specification revision for this implementation (minor version). */
|
||||
@property(nonatomic,readonly,assign) int minorVersion;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Open the specified device.
|
||||
*
|
||||
* @param deviceSpecifier The name of the device to open (nil = default device).
|
||||
* @param frequency The frequency to capture at.
|
||||
* @param format The audio format to capture as.
|
||||
* @param bufferSize The size of buffer that the device must allocate for audio capture.
|
||||
* @return A new capture device.
|
||||
*/
|
||||
+ (id) deviceWithDeviceSpecifier:(NSString*) deviceSpecifier
|
||||
frequency:(ALCuint) frequency
|
||||
format:(ALCenum) format
|
||||
bufferSize:(ALCsizei) bufferSize;
|
||||
|
||||
/** Open the specified device.
|
||||
*
|
||||
* @param deviceSpecifier The name of the device to open (nil = default device).
|
||||
* @param frequency The frequency to capture at.
|
||||
* @param format The audio format to capture as.
|
||||
* @param bufferSize The size of buffer that the device must allocate for audio capture.
|
||||
* @return The initialized capture device.
|
||||
*/
|
||||
- (id) initWithDeviceSpecifier:(NSString*) deviceSpecifier
|
||||
frequency:(ALCuint) frequency
|
||||
format:(ALCenum) format
|
||||
bufferSize:(ALCsizei) bufferSize;
|
||||
|
||||
|
||||
#pragma mark Audio Capture
|
||||
|
||||
/** Start capturing samples.
|
||||
*
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) startCapture;
|
||||
|
||||
/** Stop capturing samples.
|
||||
*
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) stopCapture;
|
||||
|
||||
/** Move captured samples to the specified buffer.
|
||||
* This method will fail if less than the specified number of samples have been captured.
|
||||
*
|
||||
* @param numSamples The number of samples to move.
|
||||
* @param buffer the buffer to move the samples into.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) moveSamples:(ALCsizei) numSamples toBuffer:(ALCvoid*) buffer;
|
||||
|
||||
|
||||
#pragma mark Extensions
|
||||
|
||||
/** Check if the specified extension is present.
|
||||
*
|
||||
* @param name The name of the extension to check.
|
||||
* @return TRUE if the extension is present.
|
||||
*/
|
||||
- (bool) isExtensionPresent:(NSString*) name;
|
||||
|
||||
/** Get the address of the specified procedure (C function address).
|
||||
*
|
||||
* @param functionName The name of the procedure to get.
|
||||
* @return the procedure's address, or NULL if it wasn't found.
|
||||
*/
|
||||
- (void*) getProcAddress:(NSString*) functionName;
|
||||
|
||||
|
||||
@end
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
//
|
||||
// ChannelSource.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 15/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import "ALSoundSource.h"
|
||||
#import "ALSoundSourcePool.h"
|
||||
#import "ALContext.h"
|
||||
|
||||
|
||||
#pragma mark ALChannelSource
|
||||
|
||||
/**
|
||||
* A Sound source composed of other sources.
|
||||
* Property values are applied to all sources within the channel. <br>
|
||||
* Sounds will get played by any free sources within this channel. <br>
|
||||
* If all sources are busy when playback is requested, it will attempt to interrupt a source
|
||||
* to free it for playback.
|
||||
*/
|
||||
@interface ALChannelSource : NSObject <ALSoundSource>
|
||||
{
|
||||
/** Pool holding the actual sources */
|
||||
ALSoundSourcePool* sourcePool;
|
||||
ALContext* context;
|
||||
|
||||
/** If YES, the defaults of this channel have been initialized */
|
||||
bool defaultsInitialized;
|
||||
|
||||
float pitch;
|
||||
float gain;
|
||||
float maxDistance;
|
||||
float rolloffFactor;
|
||||
float referenceDistance;
|
||||
float minGain;
|
||||
float maxGain;
|
||||
float coneOuterGain;
|
||||
float coneInnerAngle;
|
||||
float coneOuterAngle;
|
||||
float reverbSendLevel;
|
||||
float reverbOcclusion;
|
||||
float reverbObstruction;
|
||||
|
||||
ALPoint position;
|
||||
ALVector velocity;
|
||||
ALVector direction;
|
||||
|
||||
int sourceRelative;
|
||||
int sourceType;
|
||||
bool looping;
|
||||
|
||||
/** Default pitch */
|
||||
float defaultPitch;
|
||||
/** Default gain */
|
||||
float defaultGain;
|
||||
/** Default max distance */
|
||||
float defaultMaxDistance;
|
||||
/** Default rolloff factor */
|
||||
float defaultRolloffFactor;
|
||||
/** Default reference distance */
|
||||
float defaultReferenceDistance;
|
||||
/** Default min gain */
|
||||
float defaultMinGain;
|
||||
/** Default max gain */
|
||||
float defaultMaxGain;
|
||||
/** Default cone outer gain */
|
||||
float defaultConeOuterGain;
|
||||
/** Default cone inner angle */
|
||||
float defaultConeInnerAngle;
|
||||
/** Default cone outer angle */
|
||||
float defaultConeOuterAngle;
|
||||
/** Default position */
|
||||
ALPoint defaultPosition;
|
||||
/** Default veloxity */
|
||||
ALVector defaultVelocity;
|
||||
/** Default direction */
|
||||
ALVector defaultDirection;
|
||||
/** Default source relative */
|
||||
int defaultSourceRelative;
|
||||
/** Default source type */
|
||||
int defaultSourceType;
|
||||
/** Default looping */
|
||||
bool defaultLooping;
|
||||
/** Default reverb send level */
|
||||
float defaultReverbSendLevel;
|
||||
/** Default occlusion */
|
||||
float defaultReverbOcclusion;
|
||||
/** Default obstruction */
|
||||
float defaultReverbObstruction;
|
||||
|
||||
|
||||
bool interruptible;
|
||||
bool muted;
|
||||
bool paused;
|
||||
|
||||
/** Target to inform when the current fade operation completes. */
|
||||
id fadeCompleteTarget;
|
||||
|
||||
/** Selector to call when the current fade operation completes. */
|
||||
SEL fadeCompleteSelector;
|
||||
|
||||
/** The expected number of sources that will callback when fading completes */
|
||||
int expectedFadeCallbackCount;
|
||||
|
||||
/** The actual number of sources that have called back */
|
||||
int currentFadeCallbackCount;
|
||||
|
||||
|
||||
/** Target to inform when the current pan operation completes. */
|
||||
id panCompleteTarget;
|
||||
|
||||
/** Selector to call when the current pan operation completes. */
|
||||
SEL panCompleteSelector;
|
||||
|
||||
/** The expected number of sources that will callback when panning completes */
|
||||
int expectedPanCallbackCount;
|
||||
|
||||
/** The actual number of sources that have called back */
|
||||
int currentPanCallbackCount;
|
||||
|
||||
|
||||
|
||||
/** Target to inform when the current pitch operation completes. */
|
||||
id pitchCompleteTarget;
|
||||
|
||||
/** Selector to call when the current pitch operation completes. */
|
||||
SEL pitchCompleteSelector;
|
||||
|
||||
/** The expected number of sources that will callback when pitch op completes */
|
||||
int expectedPitchCallbackCount;
|
||||
|
||||
/** The actual number of sources that have called back */
|
||||
int currentPitchCallbackCount;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** This source's owning context. */
|
||||
@property(nonatomic,readonly,retain) ALContext* context;
|
||||
|
||||
/** All sources being used by this channel. Do not modify! */
|
||||
@property(nonatomic,readonly,retain) ALSoundSourcePool* sourcePool;
|
||||
|
||||
/** The number of sources reserved by this channel. */
|
||||
@property(nonatomic,readwrite,assign) int reservedSources;
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create a channel with a number of sources.
|
||||
*
|
||||
* @param reservedSources the number of sources to reserve for this channel.
|
||||
* @return A new channel.
|
||||
*/
|
||||
+ (id) channelWithSources:(int) reservedSources;
|
||||
|
||||
/** Initialize a channel with a number of sources.
|
||||
*
|
||||
* @param reservedSources the number of sources to reserve for this channel.
|
||||
* @return The initialized channel.
|
||||
*/
|
||||
- (id) initWithSources:(int) reservedSources;
|
||||
|
||||
/** Set this channel's default values from those in the specified source.
|
||||
*
|
||||
* @param source the source to set default values from.
|
||||
*/
|
||||
- (void) setDefaultsFromSource:(id<ALSoundSource>) source;
|
||||
|
||||
/** Reset all sources in this channel to their default state.
|
||||
*/
|
||||
- (void) resetToDefault;
|
||||
|
||||
/** Add a source to this channel.
|
||||
*
|
||||
* @param source The source to add.
|
||||
*/
|
||||
- (void) addSource:(id<ALSoundSource>) source;
|
||||
|
||||
/** Remove a source from the channel.
|
||||
*
|
||||
* @param source The source to remove. If nil, remove any source.
|
||||
* @return The source that was removed.
|
||||
*/
|
||||
- (id<ALSoundSource>) removeSource:(id<ALSoundSource>) source;
|
||||
|
||||
/** Split the specified number of sources from this channel, creating a new
|
||||
* channel.
|
||||
*
|
||||
* @param numSources The number of sources to split off
|
||||
* @return A new channel with the split-off sources.
|
||||
*/
|
||||
- (ALChannelSource*) splitChannelWithSources:(int) numSources;
|
||||
|
||||
/** Absorb another channel's sources into this one. All of the channel's sources
|
||||
* will be moved into this channel.
|
||||
*
|
||||
* @param channel The channel to absorb sources from.
|
||||
*/
|
||||
- (void) addChannel:(ALChannelSource*) channel;
|
||||
|
||||
/** Set all buffers in all non-playing sources to nil.
|
||||
*
|
||||
* @return A list of buffers that were cleared.
|
||||
*/
|
||||
- (NSArray*) clearUnusedBuffers;
|
||||
|
||||
/** Remove all instances of the specified buffer.
|
||||
*
|
||||
* @param name The name of the buffer.
|
||||
*
|
||||
* @return NO if any of the matching buffers are currently being played.
|
||||
*/
|
||||
- (BOOL) removeBuffersNamed:(NSString*) name;
|
||||
|
||||
@end
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
//
|
||||
// ALContext.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-01-09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenAL/alc.h>
|
||||
#import "ALListener.h"
|
||||
#import "ALSource.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
|
||||
@class ALDevice;
|
||||
|
||||
|
||||
#pragma mark ALContext
|
||||
|
||||
/**
|
||||
* A context encompasses a single listener and a series of sources.
|
||||
* A context is created from a device, and many contexts may be created
|
||||
* (though multiple contexts would be unusual in an iOS app). <br>
|
||||
*
|
||||
* Note: Some property values are only valid if this context is the current
|
||||
* context.
|
||||
*
|
||||
* @see ObjectAL.currentContext
|
||||
*/
|
||||
@interface ALContext : NSObject <OALSuspendManager>
|
||||
{
|
||||
ALCcontext* context;
|
||||
/** All sound sources associated with this context. */
|
||||
NSMutableArray* sources;
|
||||
ALListener* listener;
|
||||
bool suspended;
|
||||
/** This context's attributes. */
|
||||
NSMutableArray* attributes;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** OpenAL version string in format
|
||||
* “[spec major number].[spec minor number] [optional vendor version information]”
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) NSString* alVersion;
|
||||
|
||||
/** The current context's attribute list.
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) NSArray* attributes;
|
||||
|
||||
/** The OpenAL context pointer. */
|
||||
@property(nonatomic,readonly,assign) ALCcontext* context;
|
||||
|
||||
/** The device this context was opened on. */
|
||||
@property(nonatomic,readonly,retain) ALDevice* device;
|
||||
|
||||
/** The current distance model.
|
||||
* Legal values are AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED,
|
||||
* AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, AL_EXPONENT_DISTANCE,
|
||||
* and AL_EXPONENT_DISTANCE_CLAMPED. See the OpenAL spec for detailed information. <br>
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) ALenum distanceModel;
|
||||
|
||||
/** Exaggeration factor for Doppler effect.
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float dopplerFactor;
|
||||
|
||||
/** List of available extensions (NSString*).
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) NSArray* extensions;
|
||||
|
||||
/** This context's listener. */
|
||||
@property(nonatomic,readonly,retain) ALListener* listener;
|
||||
|
||||
/** Information about the specific renderer.
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) NSString* renderer;
|
||||
|
||||
/** All sources associated with this context (ALSource*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* sources;
|
||||
|
||||
/** Speed of sound in same units as velocities.
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float speedOfSound;
|
||||
|
||||
/** Name of the vendor.
|
||||
* Only valid when this is the current context.
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) NSString* vendor;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create a new context on the specified device.
|
||||
*
|
||||
* @param device The device to open the context on.
|
||||
* @param attributes An array of NSNumber in ordered pairs (attribute id followed by integer value).
|
||||
* Posible attributes: ALC_FREQUENCY, ALC_REFRESH, ALC_SYNC, ALC_MONO_SOURCES, ALC_STEREO_SOURCES
|
||||
* @return A new context.
|
||||
*/
|
||||
+ (id) contextOnDevice:(ALDevice *) device attributes:(NSArray*) attributes;
|
||||
|
||||
/** Create a new context on the specified device with attributes.
|
||||
*
|
||||
* @param device The device to open the context on.
|
||||
* @param outputFrequency The frequency to mix all sources to before outputting (ignored by iOS).
|
||||
* @param refreshIntervals The number of passes per second used to mix the audio sources.
|
||||
* For games this can be 5-15. For audio intensive apps, it should be higher (ignored by iOS).
|
||||
* @param synchronousContext If true, this context runs on the main thread and depends on you
|
||||
* calling alcUpdateContext (ignored by iOS).
|
||||
* @param monoSources A hint indicating how many sources should support mono (default 28 on iOS).
|
||||
* @param stereoSources A hint indicating how many sources should support stereo (default 4 on iOS).
|
||||
* @return A new context.
|
||||
*/
|
||||
+ (id) contextOnDevice:(ALDevice*) device
|
||||
outputFrequency:(int) outputFrequency
|
||||
refreshIntervals:(int) refreshIntervals
|
||||
synchronousContext:(bool) synchronousContext
|
||||
monoSources:(int) monoSources
|
||||
stereoSources:(int) stereoSources;
|
||||
|
||||
|
||||
/** Initialize this context on the specified device with attributes.
|
||||
*
|
||||
* @param device The device to open the context on.
|
||||
* @param outputFrequency The frequency to mix all sources to before outputting (ignored by iOS).
|
||||
* @param refreshIntervals The number of passes per second used to mix the audio sources.
|
||||
* For games this can be 5-15. For audio intensive apps, it should be higher (ignored by iOS).
|
||||
* @param synchronousContext If true, this context runs on the main thread and depends on you
|
||||
* calling alcUpdateContext (ignored by iOS).
|
||||
* @param monoSources A hint indicating how many sources should support mono (default 28 on iOS).
|
||||
* @param stereoSources A hint indicating how many sources should support stereo (default 4 on iOS).
|
||||
* @return The initialized context.
|
||||
*/
|
||||
- (id) initOnDevice:(ALDevice*) device
|
||||
outputFrequency:(int) outputFrequency
|
||||
refreshIntervals:(int) refreshIntervals
|
||||
synchronousContext:(bool) synchronousContext
|
||||
monoSources:(int) monoSources
|
||||
stereoSources:(int) stereoSources;
|
||||
|
||||
|
||||
/** Initialize this context for the specified device and attributes.
|
||||
*
|
||||
* @param device The device to open the context on.
|
||||
* @param attributes An array of NSNumber in ordered pairs (attribute id followed by integer value).
|
||||
* Posible attributes: ALC_FREQUENCY, ALC_REFRESH, ALC_SYNC, ALC_MONO_SOURCES, ALC_STEREO_SOURCES
|
||||
* @return The initialized context.
|
||||
*/
|
||||
- (id) initOnDevice:(ALDevice *) device attributes:(NSArray*) attributes;
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Process this context.
|
||||
*/
|
||||
- (void) process;
|
||||
|
||||
/** Stop all sound sources in this context.
|
||||
*/
|
||||
- (void) stopAllSounds;
|
||||
|
||||
/** Clear all buffers being used by sources in this context.
|
||||
*/
|
||||
- (void) clearBuffers;
|
||||
|
||||
/** Make sure this context is the current context.
|
||||
* This method is used to work around iOS 4.0 and 4.2 bugs
|
||||
* that could cause the context to be lost.
|
||||
*/
|
||||
- (void) ensureContextIsCurrent;
|
||||
|
||||
#pragma mark Extensions
|
||||
|
||||
/** Check if the specified extension is present in this context.
|
||||
* Only valid when this is the current context.
|
||||
*
|
||||
* @param name The name of the extension to check.
|
||||
* @return TRUE if the extension is present in this context.
|
||||
*/
|
||||
- (bool) isExtensionPresent:(NSString*) name;
|
||||
|
||||
/** Get the address of the specified procedure (C function address).
|
||||
* Only valid when this is the current context. <br>
|
||||
* <strong>Note:</strong> The OpenAL implementation is free to return
|
||||
* a pointer even if it is not valid for this context. Always call isExtensionPresent
|
||||
* first.
|
||||
*
|
||||
* @param functionName the name of the procedure to get.
|
||||
* @return the procedure's address, or NULL if it wasn't found.
|
||||
*/
|
||||
- (void*) getProcAddress:(NSString*) functionName;
|
||||
|
||||
|
||||
#pragma mark Internal Use
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Used by ALSource to announce initialization.
|
||||
*
|
||||
* @param source the source that is initializing.
|
||||
*/
|
||||
- (void) notifySourceInitializing:(ALSource*) source;
|
||||
|
||||
/** (INTERNAL USE) Used by ALSource to announce deallocation.
|
||||
*
|
||||
* @param source the source that is deallocating.
|
||||
*/
|
||||
- (void) notifySourceDeallocating:(ALSource*) source;
|
||||
/** \endcond */
|
||||
|
||||
@end
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// ALDevice.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-01-09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenAL/alc.h>
|
||||
#import "ALContext.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
|
||||
#pragma mark ALDevice
|
||||
|
||||
/**
|
||||
* A device is a logical mapping to an audio device through the OpenAL implementation.
|
||||
*/
|
||||
@interface ALDevice : NSObject <OALSuspendManager>
|
||||
{
|
||||
ALCdevice* device;
|
||||
/** All contexts opened from this device. */
|
||||
NSMutableArray* contexts;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** All contexts created on this device (ALContext*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* contexts;
|
||||
|
||||
/** The OpenAL device pointer. */
|
||||
@property(nonatomic,readonly,assign) ALCdevice* device;
|
||||
|
||||
/** List of strings describing all extensions available on this device (NSString*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* extensions;
|
||||
|
||||
/** The specification revision for this implementation (major version). */
|
||||
@property(nonatomic,readonly,assign) int majorVersion;
|
||||
|
||||
/** The specification revision for this implementation (minor version). */
|
||||
@property(nonatomic,readonly,assign) int minorVersion;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Open the specified device.
|
||||
*
|
||||
* @param deviceSpecifier The device to open (nil = default device).
|
||||
* @return A new device.
|
||||
*/
|
||||
+ (id) deviceWithDeviceSpecifier:(NSString*) deviceSpecifier;
|
||||
|
||||
/** Initialize with the specified device.
|
||||
*
|
||||
* @param deviceSpecifier The device to open (nil = default device).
|
||||
* @return the initialized device.
|
||||
*/
|
||||
- (id) initWithDeviceSpecifier:(NSString*) deviceSpecifier;
|
||||
|
||||
|
||||
#pragma mark Extensions
|
||||
|
||||
/** Check if the specified extension is present.
|
||||
*
|
||||
* @param name The extension to check.
|
||||
* @return TRUE if the extension is present.
|
||||
*/
|
||||
- (bool) isExtensionPresent:(NSString*) name;
|
||||
|
||||
/** Get the address of the specified procedure (C function address).
|
||||
*
|
||||
* @param functionName the name of the procedure to get.
|
||||
* @return the procedure's address, or NULL if it wasn't found.
|
||||
*/
|
||||
- (void*) getProcAddress:(NSString*) functionName;
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Clear all buffers being used by sources of contexts opened on this device.
|
||||
*/
|
||||
- (void) clearBuffers;
|
||||
|
||||
|
||||
#pragma mark Internal Use
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Used by ALContext to announce initialization.
|
||||
*
|
||||
* @param context The context that is initializing.
|
||||
*/
|
||||
- (void) notifyContextInitializing:(ALContext*) context;
|
||||
|
||||
/** (INTERNAL USE) Used by ALContext to announce deallocation.
|
||||
*
|
||||
* @param context The context that is deallocating.
|
||||
*/
|
||||
- (void) notifyContextDeallocating:(ALContext*) context;
|
||||
/** \endcond */
|
||||
|
||||
@end
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// ALListener.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-01-07.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ALTypes.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
@class ALContext;
|
||||
|
||||
|
||||
#pragma mark ALListener
|
||||
|
||||
/**
|
||||
* The listener represents the user who is listening to sounds in 3D space.
|
||||
* This object controls his position, orientation, and velocity, as well as providing a master
|
||||
* gain. <br>
|
||||
* A context contains one and only one listener.
|
||||
*/
|
||||
@interface ALListener : NSObject <OALSuspendManager>
|
||||
{
|
||||
bool muted;
|
||||
float gain;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The context this listener belongs to (WEAK reference). */
|
||||
@property(nonatomic,readonly,assign) ALContext* context;
|
||||
|
||||
/** Causes this listener to stop hearing sound.
|
||||
* It's called "muted" rather than "deaf" to give a consistent name with other mute functions.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool muted;
|
||||
|
||||
/** Gain (volume), affecting every sound this listener hears (0.0 = no sound, 1.0 = max volume).
|
||||
* Only valid if this listener's context is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float gain;
|
||||
|
||||
/** Orientation (up: x, y, z, at: x, y, z).
|
||||
* Only valid if this listener's context is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) ALOrientation orientation;
|
||||
|
||||
/** Position (x, y, z).
|
||||
* Only valid if this listener's context is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) ALPoint position;
|
||||
|
||||
/** Velocity (x, y, z).
|
||||
* Only valid if this listener's context is the current context.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) ALVector velocity;
|
||||
|
||||
/** Turns on reverb. (iOS 5.0+)
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool reverbOn;
|
||||
|
||||
/** The global reverb level (from -40.0db to 40.0db). (iOS 5.0+)
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float globalReverbLevel;
|
||||
|
||||
/** The room type to simulate for reverb. (iOS 5.0+)
|
||||
*
|
||||
* Allowed room types:
|
||||
*
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_SmallRoom
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_MediumRoom
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_LargeRoom
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_MediumHall
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_LargeHall
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_Plate
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_MediumChamber
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_LargeChamber
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_Cathedral
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_LargeRoom2
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_MediumHall2
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_MediumHall3
|
||||
* ALC_ASA_REVERB_ROOM_TYPE_LargeHall2
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) int reverbRoomType;
|
||||
|
||||
/** The equalizer gain for reverb. (iOS 5.0+)
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float reverbEQGain;
|
||||
|
||||
/** The equalizer bandwidth for reverb. (iOS 5.0+)
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float reverbEQBandwidth;
|
||||
|
||||
/** The equalizer frequency for reverb. (iOS 5.0+)
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float reverbEQFrequency;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Create a listener for the specified context.
|
||||
*
|
||||
* @param context the context to create this listener on.
|
||||
* @return A new listener.
|
||||
*/
|
||||
+ (id) listenerForContext:(ALContext*) context;
|
||||
|
||||
/** (INTERNAL USE) Initialize a listener for the specified context.
|
||||
*
|
||||
* @param context the context to create this listener on.
|
||||
* @return The initialized listener.
|
||||
*/
|
||||
- (id) initWithContext:(ALContext*) context;
|
||||
/** \endcond */
|
||||
|
||||
@end
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
//
|
||||
// SoundSource.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 15/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ALBuffer.h"
|
||||
#import "ALTypes.h"
|
||||
|
||||
|
||||
#pragma mark ALSoundSource
|
||||
|
||||
/**
|
||||
* Manages all properties relating to an OpenAL sound source.
|
||||
* There are currently two classes that adhere to this protocol: ALSource
|
||||
* and ChannelSource (which collectively manipulates a set of ALSource objects).
|
||||
* A full description of the properties themselves is available in the
|
||||
* OpenAL 1.1 Specification and Reference:
|
||||
* http://connect.creativelabs.com/openal/Documentation
|
||||
*/
|
||||
@protocol ALSoundSource <NSObject>
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** Cone inner angle (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float coneInnerAngle;
|
||||
|
||||
/** Cone outer angle (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float coneOuterAngle;
|
||||
|
||||
/** Cone outer gain (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float coneOuterGain;
|
||||
|
||||
/** Direction (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) ALVector direction;
|
||||
|
||||
/** Gain (volume) (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float gain;
|
||||
|
||||
/** Volume (alias to gain). */
|
||||
@property(nonatomic,readwrite,assign) float volume;
|
||||
|
||||
/** If true, this source may be interrupted when resources are low. */
|
||||
@property(nonatomic,readwrite,assign) bool interruptible;
|
||||
|
||||
/** Looping (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) bool looping;
|
||||
|
||||
/** Max distance (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float maxDistance;
|
||||
|
||||
/** Max gain (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float maxGain;
|
||||
|
||||
/** Min gain (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float minGain;
|
||||
|
||||
/** If true, this source is muted. */
|
||||
@property(nonatomic,readwrite,assign) bool muted;
|
||||
|
||||
/** If true, this source is currently paused. */
|
||||
@property(nonatomic,readwrite,assign) bool paused;
|
||||
|
||||
/** Pitch (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float pitch;
|
||||
|
||||
/** If true, this source is currently playing audio. */
|
||||
@property(nonatomic,readonly,assign) bool playing;
|
||||
|
||||
/** Position (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) ALPoint position;
|
||||
|
||||
/** Reference distance (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float referenceDistance;
|
||||
|
||||
/** Rolloff factor (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) float rolloffFactor;
|
||||
|
||||
/** Source relative (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) int sourceRelative;
|
||||
|
||||
/** Source type (OpenAL property). */
|
||||
@property(nonatomic,readonly,assign) int sourceType;
|
||||
|
||||
/** Velocity (OpenAL property). */
|
||||
@property(nonatomic,readwrite,assign) ALVector velocity;
|
||||
|
||||
/** Pan value (-1.0 = far left, 1.0 = far right).
|
||||
* Note: This effect is simulated by changing the source's X position.
|
||||
* Do not use this property if you are modifying the position property as well.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float pan;
|
||||
|
||||
/** Reverb send level (how much reverb affects this source). (iOS 5.0+)
|
||||
* 0.0 = fully dry, 1.0 = fully wet.
|
||||
* Default 0.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float reverbSendLevel;
|
||||
|
||||
/** Reverb occlusion (wall/door between listener and source). (iOS 5.0+)
|
||||
* -100.0db (most occlusion) to 0.0 (no occlusion).
|
||||
* Default 0.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float reverbOcclusion;
|
||||
|
||||
/** Reverb obstruction (object between listener and source). (iOS 5.0+)
|
||||
* -100.0db (most obstruction) to 0.0 (no obstruction).
|
||||
* Default 0.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float reverbObstruction;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
|
||||
#pragma mark Playback
|
||||
|
||||
/** Play a sound.
|
||||
*
|
||||
* @param buffer the buffer to play.
|
||||
* @return the source playing the sound, or nil if the sound could not be played.
|
||||
*/
|
||||
- (id<ALSoundSource>) play:(ALBuffer*) buffer;
|
||||
|
||||
/** Play a sound, optionally looping.
|
||||
*
|
||||
* @param buffer the buffer to play.
|
||||
* @param loop If TRUE, the sound will loop until you call "stop" on the returned sound source.
|
||||
* @return the source playing the sound, or nil if the sound could not be played.
|
||||
*/
|
||||
- (id<ALSoundSource>) play:(ALBuffer*) buffer loop:(bool) loop;
|
||||
|
||||
/** Play a sound, setting gain, pitch, pan, and looping.
|
||||
*
|
||||
* @param buffer the buffer to play.
|
||||
* @param gain The gain (volume) to play at (0.0 - 1.0).
|
||||
* @param pitch The pitch to play at (1.0 = normal pitch).
|
||||
* @param pan Left-right panning (-1.0 = far left, 1.0 = far right).
|
||||
* @param loop If TRUE, the sound will loop until you call "stop" on the returned sound source.
|
||||
* @return the source playing the sound, or nil if the sound could not be played.
|
||||
*/
|
||||
- (id<ALSoundSource>) play:(ALBuffer*) buffer
|
||||
gain:(float) gain
|
||||
pitch:(float) pitch
|
||||
pan:(float) pan
|
||||
loop:(bool) loop;
|
||||
|
||||
/** Stop playing the current sound.
|
||||
*/
|
||||
- (void) stop;
|
||||
|
||||
/** Stop playing the current sound and set its state to AL_INITIAL.
|
||||
*/
|
||||
- (void) rewind;
|
||||
|
||||
/** Fade to the specified gain value.
|
||||
*
|
||||
* @param gain The gain to fade to.
|
||||
* @param duration The duration of the fade operation in seconds.
|
||||
* @param target The target to notify when the fade completes (can be nil).
|
||||
* @param selector The selector to call when the fade completes. The selector must accept
|
||||
* a single parameter, which will be the object that performed the fade.
|
||||
*/
|
||||
- (void) fadeTo:(float) gain
|
||||
duration:(float) duration
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Stop the currently running fade operation, if any.
|
||||
*/
|
||||
- (void) stopFade;
|
||||
|
||||
/** pan to the specified value.
|
||||
*
|
||||
* @param pan The value to pan to.
|
||||
* @param duration The duration of the pan operation in seconds.
|
||||
* @param target The target to notify when the pan completes (can be nil).
|
||||
* @param selector The selector to call when the pan completes. The selector must accept
|
||||
* a single parameter, which will be the object that performed the pan.
|
||||
*/
|
||||
- (void) panTo:(float) pan
|
||||
duration:(float) duration
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Stop the currently running pan operation, if any.
|
||||
*/
|
||||
- (void) stopPan;
|
||||
|
||||
/** Gradually change pitch to the specified value.
|
||||
*
|
||||
* @param pitch The value to change pitch to.
|
||||
* @param duration The duration of the pitch operation in seconds.
|
||||
* @param target The target to notify when the pitch change completes (can be nil).
|
||||
* @param selector The selector to call when the pitch change completes. The selector
|
||||
* must accept a single parameter, which will be the object that performed the pitch change.
|
||||
*/
|
||||
- (void) pitchTo:(float) pitch
|
||||
duration:(float) duration
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Stop the currently running pitch operation, if any.
|
||||
*/
|
||||
- (void) stopPitch;
|
||||
|
||||
/** Stop any currently running fade, pan, or pitch operations.
|
||||
*/
|
||||
- (void) stopActions;
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Clear any buffers this source is currently using.
|
||||
*/
|
||||
- (void) clear;
|
||||
|
||||
@end
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// SoundSourcePool.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 17/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import "ALSoundSource.h"
|
||||
|
||||
|
||||
#pragma mark ALSoundSourcePool
|
||||
|
||||
/**
|
||||
* A pool of sound sources, which can be fetched based on availability.
|
||||
*/
|
||||
@interface ALSoundSourcePool : NSObject
|
||||
{
|
||||
/** All sources managed by this pool (id<ALSoundSource>). */
|
||||
NSMutableArray* sources;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** All sources managed by this pool (id<ALSoundSource>). */
|
||||
@property(nonatomic,readonly,retain) NSArray* sources;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Make a new pool.
|
||||
* @return A new pool.
|
||||
*/
|
||||
+ (id) pool;
|
||||
|
||||
|
||||
#pragma mark Source Management
|
||||
|
||||
/** Add a source to this pool.
|
||||
*
|
||||
* @param source The source to add.
|
||||
*/
|
||||
- (void) addSource:(id<ALSoundSource>) source;
|
||||
|
||||
/** Remove a source from this pool
|
||||
*
|
||||
* @param source The source to remove.
|
||||
*/
|
||||
- (void) removeSource:(id<ALSoundSource>) source;
|
||||
|
||||
/** Acquire a free or freeable source from this pool.
|
||||
* It first attempts to find a completely free source.
|
||||
* Failing this, it will attempt to interrupt a source and return that (if attemptToInterrupt
|
||||
* is TRUE).
|
||||
*
|
||||
* @param attemptToInterrupt If TRUE, attempt to interrupt sources to free them for use.
|
||||
* @return The freed sound source, or nil if no sources are freeable.
|
||||
*/
|
||||
- (id<ALSoundSource>) getFreeSource:(bool) attemptToInterrupt;
|
||||
|
||||
@end
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
//
|
||||
// ALSource.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 15/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenAL/al.h>
|
||||
#import "ALSoundSource.h"
|
||||
#import "ALBuffer.h"
|
||||
#import "OALAction.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
@class ALContext;
|
||||
@class ALSource;
|
||||
|
||||
|
||||
typedef void (^OALSourceNotificationCallback)(ALSource* source, ALuint notificationID, ALvoid* userData);
|
||||
|
||||
#pragma mark ALSource
|
||||
|
||||
/**
|
||||
* A source represents an object that emits sound which can be heard by a listener.
|
||||
* This source can have position, velocity, and direction.
|
||||
*/
|
||||
@interface ALSource : NSObject <ALSoundSource, OALSuspendManager>
|
||||
{
|
||||
ALuint sourceId;
|
||||
bool interruptible;
|
||||
float gain;
|
||||
bool muted;
|
||||
|
||||
/** Shadow value which keeps the correct state value
|
||||
* for AL_PLAYING and AL_PAUSED.
|
||||
* We need this due to a buggy OpenAL implementation.
|
||||
*/
|
||||
int shadowState;
|
||||
|
||||
/** Used to abort a pending playback resume if the user calls
|
||||
* stop or pause.
|
||||
*/
|
||||
bool abortPlaybackResume;
|
||||
|
||||
ALBuffer* buffer;
|
||||
ALContext* context;
|
||||
|
||||
/** Current action operating on the gain control. */
|
||||
OALAction* gainAction;
|
||||
|
||||
/** Current action operating on the pan control. */
|
||||
OALAction* panAction;
|
||||
|
||||
/** Current action operating on the pitch control. */
|
||||
OALAction* pitchAction;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The sound buffer this source is attached to (set to nil to detach the currently attached
|
||||
* buffer).
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) ALBuffer* buffer;
|
||||
|
||||
/** How many buffers this source has queued. */
|
||||
@property(nonatomic,readonly,assign) int buffersQueued;
|
||||
|
||||
/** How many of these buffers have been processed during playback. */
|
||||
@property(nonatomic,readonly,assign) int buffersProcessed;
|
||||
|
||||
/** The context this source was opened on. */
|
||||
@property(nonatomic,readonly,retain) ALContext* context;
|
||||
|
||||
/** The offset into the current buffer (in bytes). */
|
||||
@property(nonatomic,readwrite,assign) float offsetInBytes;
|
||||
|
||||
/** The offset into the current buffer (in samples). */
|
||||
@property(nonatomic,readwrite,assign) float offsetInSamples;
|
||||
|
||||
/** The offset into the current buffer (in seconds). */
|
||||
@property(nonatomic,readwrite,assign) float offsetInSeconds;
|
||||
|
||||
/** OpenAL's ID for this source. */
|
||||
@property(nonatomic,readonly,assign) ALuint sourceId;
|
||||
|
||||
/** The state of this source. */
|
||||
@property(nonatomic,readwrite,assign) int state;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create a new source.
|
||||
*
|
||||
* @return A new source.
|
||||
*/
|
||||
+ (id) source;
|
||||
|
||||
/** Create a new source on the specified context.
|
||||
*
|
||||
* @param context the context to create the source on.
|
||||
* @return A new source.
|
||||
*/
|
||||
+ (id) sourceOnContext:(ALContext*) context;
|
||||
|
||||
/** Initialize a new source on the specified context.
|
||||
*
|
||||
* @param context the context to create the source on.
|
||||
* @return A new source.
|
||||
*/
|
||||
- (id) initOnContext:(ALContext*) context;
|
||||
|
||||
|
||||
#pragma mark Playback
|
||||
|
||||
/** Play the currently attached buffer.
|
||||
*
|
||||
* @return the source playing the sound, or nil if the sound could not be played.
|
||||
*/
|
||||
- (id<ALSoundSource>) play;
|
||||
|
||||
|
||||
#pragma mark Queued Playback
|
||||
|
||||
/** Add a buffer to the buffer queue.
|
||||
*
|
||||
* @param buffer the buffer to add to the queue.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) queueBuffer:(ALBuffer*) buffer;
|
||||
|
||||
/** Add a buffer to the buffer queue, repeating it multiple times.
|
||||
*
|
||||
* @param buffer the buffer to add to the queue.
|
||||
* @param repeats the number of times to repeat the buffer in the queue.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) queueBuffer:(ALBuffer*) buffer repeats:(NSUInteger) repeats;
|
||||
|
||||
/** Add buffers to the buffer queue.
|
||||
*
|
||||
* @param buffers the buffers to add to the queue.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) queueBuffers:(NSArray*) buffers;
|
||||
|
||||
/** Add buffers to the buffer queue, repeating it multiple times.
|
||||
* The buffers will be played in order, repeating the specified number of times.
|
||||
*
|
||||
* @param buffers the buffers to add to the queue.
|
||||
* @param repeats the number of times to repeat the buffer in the queue.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) queueBuffers:(NSArray*) buffers repeats:(NSUInteger) repeats;
|
||||
|
||||
/** Remove a buffer from the buffer queue.
|
||||
*
|
||||
* @param buffer the buffer to remove from the queue.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) unqueueBuffer:(ALBuffer*) buffer;
|
||||
|
||||
/** Remove buffers from the buffer queue
|
||||
*
|
||||
* @param buffers the buffers to remove from the queue.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) unqueueBuffers:(NSArray*) buffers;
|
||||
|
||||
|
||||
#pragma mark Notifications
|
||||
|
||||
/** Register to receive notifications about an event on this source. (iOS 5.0+)
|
||||
*
|
||||
* The following notification types are recognized:
|
||||
* AL_SOURCE_STATE - Sent when a source's state changes.
|
||||
* AL_BUFFERS_PROCESSED - Sent when all buffers have been processed.
|
||||
* AL_QUEUE_HAS_LOOPED - Sent when a looping source has looped to it's start point.
|
||||
*
|
||||
* @param notificationID The kind of notification to be informed of (see above).
|
||||
* @param callback The block to call for notification.
|
||||
* @param userData a pointer that will be passed to the callback.
|
||||
*/
|
||||
- (void) registerNotification:(ALuint) notificationID
|
||||
callback:(OALSourceNotificationCallback) callback
|
||||
userData:(void*) userData;
|
||||
|
||||
/** Unregister notifications for a notification type on this source. (iOS 5.0+)
|
||||
*
|
||||
* @param notificationID The kind of notification to remove.
|
||||
*/
|
||||
- (void) unregisterNotification:(ALuint) notificationID;
|
||||
|
||||
/** Unregister all notifications for this source. (iOS 5.0+)
|
||||
*/
|
||||
- (void) unregisterAllNotifications;
|
||||
|
||||
@end
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// OpenAL.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 15/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
|
||||
#pragma mark Types
|
||||
|
||||
/**
|
||||
* Represents a 3-dimensional point for certain ObjectAL properties.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The "X" coordinate */
|
||||
float x;
|
||||
/** The "Y" coordinate */
|
||||
float y;
|
||||
/** The "Z" coordinate */
|
||||
float z;
|
||||
} ALPoint;
|
||||
|
||||
/**
|
||||
* Represents a 3-dimensional vector for certain ObjectAL properties.
|
||||
* Properties are the same as for ALPoint.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The "X" coordinate */
|
||||
float x;
|
||||
/** The "Y" coordinate */
|
||||
float y;
|
||||
/** The "Z" coordinate */
|
||||
float z;
|
||||
} ALVector;
|
||||
|
||||
/**
|
||||
* Represents an orientation, consisting of an "at" vector (representing the "forward" direction),
|
||||
* and the "up" vector (representing "up" for the subject).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The "at" vector, representing "forward" */
|
||||
ALVector at;
|
||||
/** The "up" vector, representing "up" */
|
||||
ALVector up;
|
||||
} ALOrientation;
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Convenience Methods
|
||||
|
||||
/** Convenience inline for creating an ALPoint.
|
||||
*
|
||||
* @param x The X coordinate.
|
||||
* @param y The Y coordinate.
|
||||
* @param z The Z coordinate.
|
||||
* @return An ALPoint.
|
||||
*/
|
||||
static inline ALPoint alpoint(const float x, const float y, const float z)
|
||||
{
|
||||
ALPoint point = {x, y, z};
|
||||
return point;
|
||||
}
|
||||
|
||||
/** Convenience inline for creating an ALVector.
|
||||
*
|
||||
* @param x The X component.
|
||||
* @param y The Y component.
|
||||
* @param z The Z component.
|
||||
* @return An ALVector.
|
||||
*/
|
||||
static inline ALVector alvector(const float x, const float y, const float z)
|
||||
{
|
||||
ALVector vector = {x, y, z};
|
||||
return vector;
|
||||
}
|
||||
|
||||
/** Convenience inline for creating an ALOrientation.
|
||||
*
|
||||
* @param atX The X component of "at".
|
||||
* @param atY The Y component of "at".
|
||||
* @param atZ The Z component of "at".
|
||||
* @param upX The X component of "up".
|
||||
* @param upY The Y component of "up".
|
||||
* @param upZ The Z component of "up".
|
||||
* @return An ALOrientation.
|
||||
*/
|
||||
static inline ALOrientation alorientation(const float atX,
|
||||
const float atY,
|
||||
const float atZ,
|
||||
const float upX,
|
||||
const float upY,
|
||||
const float upZ)
|
||||
{
|
||||
ALOrientation orientation = { {atX, atY, atZ}, {upX,upY,upZ} };
|
||||
return orientation;
|
||||
}
|
||||
|
||||
static inline ALPoint ALPointMake(float x, float y, float z)
|
||||
{
|
||||
ALPoint p;
|
||||
p.x = x;
|
||||
p.y = y;
|
||||
p.z = z;
|
||||
|
||||
return p;
|
||||
}
|
||||
+1149
File diff suppressed because it is too large
Load Diff
+325
@@ -0,0 +1,325 @@
|
||||
//
|
||||
// OALAction.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-09-18.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ObjectALConfig.h"
|
||||
|
||||
|
||||
#if OBJECTAL_CFG_USE_COCOS2D_ACTIONS
|
||||
|
||||
#pragma mark Cocos2d Subclassing
|
||||
|
||||
#import "cocos2d.h"
|
||||
|
||||
/** Generates common code required to subclass from a cocos2d action
|
||||
* while maintaining the functionality of an OALAction.
|
||||
*/
|
||||
#define COCOS2D_SUBCLASS_HEADER(CLASS_A,CLASS_B) \
|
||||
@interface CLASS_A: CLASS_B \
|
||||
{ \
|
||||
bool started_; \
|
||||
} \
|
||||
\
|
||||
@property(nonatomic,readonly,assign) bool running; \
|
||||
- (void) runWithTarget:(id) target; \
|
||||
- (void) prepareWithTarget:(id) target; \
|
||||
- (void) stopAction; \
|
||||
- (void) updateCompletion:(float) proportionComplete; \
|
||||
\
|
||||
@end
|
||||
|
||||
|
||||
|
||||
/** Generates common code required to subclass from a cocos2d action
|
||||
* while maintaining the functionality of an OALAction.
|
||||
*/
|
||||
#define COCOS2D_SUBCLASS(CLASS_A) \
|
||||
@implementation CLASS_A \
|
||||
\
|
||||
- (id) init \
|
||||
{ \
|
||||
return [self initWithDuration:0]; \
|
||||
} \
|
||||
\
|
||||
-(void) startWithTarget:(id) targetIn \
|
||||
{ \
|
||||
[super startWithTarget:targetIn]; \
|
||||
[self prepareWithTarget:targetIn]; \
|
||||
started_ = YES; \
|
||||
[self runWithTarget:targetIn]; \
|
||||
} \
|
||||
\
|
||||
- (void) update:(float) proportionComplete \
|
||||
{ \
|
||||
[super update:proportionComplete]; \
|
||||
[self updateCompletion:proportionComplete]; \
|
||||
} \
|
||||
\
|
||||
- (bool) running \
|
||||
{ \
|
||||
return !self.isDone; \
|
||||
} \
|
||||
\
|
||||
- (void) runWithTarget:(id) targetIn \
|
||||
{ \
|
||||
if(!started_) \
|
||||
{ \
|
||||
[[CCActionManager sharedManager] addAction:self target:targetIn paused:NO]; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
- (void) stopAction \
|
||||
{ \
|
||||
[[CCActionManager sharedManager] removeAction:self]; \
|
||||
} \
|
||||
|
||||
#endif /* OBJECTAL_CFG_USE_COCOS2D_ACTIONS */
|
||||
|
||||
|
||||
|
||||
/* There are two versions of the actions which can be used: ObjectAL and Cocos2d.
|
||||
* It's usually more convenient when using Cocos2d to have all actions as part of
|
||||
* the Cocos2d action system. You can set this in ObjectALConfig.h
|
||||
*/
|
||||
#if !OBJECTAL_CFG_USE_COCOS2D_ACTIONS
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALAction (ObjectAL version)
|
||||
|
||||
/**
|
||||
* Represents an action that can be performed on an object.
|
||||
*/
|
||||
@interface OALAction : NSObject
|
||||
{
|
||||
/** \cond */
|
||||
float duration_;
|
||||
float elapsed_;
|
||||
bool running_;
|
||||
/** \endcond */
|
||||
|
||||
/** If TRUE, this action is running via OALActionManager. */
|
||||
bool runningInManager_;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The target to perform the action on. WEAK REFERENCE. */
|
||||
@property(nonatomic,readonly,assign) id target;
|
||||
|
||||
/** The duration of the action, in seconds. */
|
||||
@property(nonatomic,readonly,assign) float duration;
|
||||
|
||||
/** The amount of time that has elapsed for this action, in seconds. */
|
||||
@property(nonatomic,readwrite,assign) float elapsed;
|
||||
|
||||
/** If true, the action is currently running. */
|
||||
@property(nonatomic,readonly,assign) bool running;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param duration The duration of this action in seconds.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithDuration:(float) duration;
|
||||
|
||||
|
||||
#pragma mark Functions
|
||||
|
||||
/** Run this action on a target.
|
||||
*
|
||||
* @param target The target to run the action on.
|
||||
*/
|
||||
- (void) runWithTarget:(id) target;
|
||||
|
||||
/** Called by runWithTraget to do any final preparations before running.
|
||||
* Subclasses must ensure that duration is valid when this method returns.
|
||||
*
|
||||
* @param target The target to run the action on.
|
||||
*/
|
||||
- (void) prepareWithTarget:(id) target;
|
||||
|
||||
|
||||
/** Called by runWithTarget to start the action running.
|
||||
*/
|
||||
- (void) startAction;
|
||||
|
||||
/** Called by OALActionManager to update this action's progress.
|
||||
*
|
||||
* @param proportionComplete The proportion of this action's duration that has elapsed.
|
||||
*/
|
||||
- (void) updateCompletion:(float) proportionComplete;
|
||||
|
||||
/** Stop this action.
|
||||
*/
|
||||
- (void) stopAction;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#else /* !OBJECTAL_CFG_USE_COCOS2D_ACTIONS */
|
||||
|
||||
COCOS2D_SUBCLASS_HEADER(OALAction, CCActionInterval);
|
||||
|
||||
#endif /* !OBJECTAL_CFG_USE_COCOS2D_ACTIONS */
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALPropertyAction
|
||||
|
||||
@interface OALPropertyAction: OALAction
|
||||
|
||||
/** The value that the property in the target will hold at the start of the action. */
|
||||
@property(nonatomic,readwrite,assign) float startValue;
|
||||
|
||||
/** The value that the property in the target will hold at the end of the action. */
|
||||
@property(nonatomic,readwrite,assign) float endValue;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create a new action using the default function.
|
||||
* The start value will be the current value of the target this action is applied to.
|
||||
*
|
||||
* @param duration The duration of this action in seconds.
|
||||
* @param propertyKey The property to modify.
|
||||
* @param endValue The "ending" value that this action will converge upon when setting the target's property.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithDuration:(float) duration
|
||||
propertyKey:(NSString*) propertyKey
|
||||
endValue:(float) endValue;
|
||||
|
||||
/** Create a new action.
|
||||
*
|
||||
* @param duration The duration of this action in seconds.
|
||||
* @param propertyKey The property to modify.
|
||||
* @param startValue The "starting" value that this action will diverge from when setting the target's
|
||||
* property. If NAN, use the current value from the target.
|
||||
* @param endValue The "ending" value that this action will converge upon when setting the target's property.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithDuration:(float) duration
|
||||
propertyKey:(NSString*) propertyKey
|
||||
startValue:(float) startValue
|
||||
endValue:(float) endValue;
|
||||
|
||||
/** Initialize an action using the default function.
|
||||
* The start value will be the current value of the target this action is applied to.
|
||||
*
|
||||
* @param duration The duration of this action in seconds.
|
||||
* @param propertyKey The property to modify.
|
||||
* @param endValue The "ending" value that this action will converge upon when setting the target's property.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithDuration:(float) duration
|
||||
propertyKey:(NSString*) propertyKey
|
||||
endValue:(float) endValue;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param duration The duration of this action in seconds.
|
||||
* @param propertyKey The property to modify.
|
||||
* @param startValue The "starting" value that this action will diverge from when setting the target's
|
||||
* property. If NAN, use the current value from the target.
|
||||
* @param endValue The "ending" value that this action will converge upon when setting the target's property.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithDuration:(float) duration
|
||||
propertyKey:(NSString*) propertyKey
|
||||
startValue:(float) startValue
|
||||
endValue:(float) endValue;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALEaseAction
|
||||
|
||||
typedef float (*EaseFunctionPtr)(float);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kOALEaseIn,
|
||||
kOALEaseOut,
|
||||
kOALEaseInOut,
|
||||
} OALEasePhase;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kOALEaseShapeSine,
|
||||
kOALEaseShapeExponential,
|
||||
} OALEaseShape;
|
||||
|
||||
/**
|
||||
* Applies an easing function to another action.
|
||||
* Normally, an action progresses at a linear rate. An ease changes that to a
|
||||
* curve.
|
||||
*/
|
||||
@interface OALEaseAction: OALAction
|
||||
{
|
||||
OALAction* action_;
|
||||
}
|
||||
|
||||
/** Create a new ease action.
|
||||
*
|
||||
* @param shape The shape of the curve to apply.
|
||||
* @param phase What phase of the action to apply the curve to.
|
||||
* @action The action to apple the curve to.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (OALEaseAction*) actionWithShape:(OALEaseShape) shape
|
||||
phase:(OALEasePhase) phase
|
||||
action:(OALAction*) action;
|
||||
|
||||
/** Initialize an ease action.
|
||||
*
|
||||
* @param shape The shape of the curve to apply.
|
||||
* @param phase What phase of the action to apply the curve to.
|
||||
* @action The action to apple the curve to.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithShape:(OALEaseShape) shape
|
||||
phase:(OALEasePhase) phase
|
||||
action:(OALAction*) action;
|
||||
|
||||
/** Get a pointer to an ease function of the specified shape and phase.
|
||||
*
|
||||
* @param shape The shape of the curve to apply.
|
||||
* @param phase What phase of the action to apply the curve to.
|
||||
* @return a pointer to the appropriate function.
|
||||
*/
|
||||
+ (EaseFunctionPtr) easeFunctionForShape:(OALEaseShape) shape
|
||||
phase:(OALEasePhase) phase;
|
||||
|
||||
@end
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// OALActionManager.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-09-18.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SynthesizeSingleton.h"
|
||||
#import "OALAction.h"
|
||||
#import "ObjectALConfig.h"
|
||||
|
||||
/* This object is only available if OBJECTAL_CFG_USE_COCOS2D_ACTIONS is enabled in ObjectALConfig.h.
|
||||
*/
|
||||
#if !OBJECTAL_CFG_USE_COCOS2D_ACTIONS
|
||||
|
||||
|
||||
#pragma mark OALActionManager
|
||||
|
||||
/**
|
||||
* Manages all ObjectAL actions.
|
||||
*/
|
||||
@interface OALActionManager : NSObject
|
||||
{
|
||||
/** All targets that have actions running on them (id). */
|
||||
NSMutableArray* targets;
|
||||
|
||||
/** Parallel array to "targets", maintaining a list of all actions per target (NSMutableArray*) */
|
||||
NSMutableArray* targetActions;
|
||||
|
||||
/** All actions that are to be added on the next pass (OALAction*) */
|
||||
NSMutableArray* actionsToAdd;
|
||||
|
||||
/** All actions that are to be removed on the next pass (OALAction*) */
|
||||
NSMutableArray* actionsToRemove;
|
||||
|
||||
/** The timer which we use to update the actions. */
|
||||
NSTimer* stepTimer;
|
||||
|
||||
/** The last time that was recorded. */
|
||||
uint64_t lastTimestamp;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Singleton implementation providing "sharedInstance" and "purgeSharedInstance" methods.
|
||||
*
|
||||
* <b>- (OALAudioSupport*) sharedInstance</b>: Get the shared singleton instance. <br>
|
||||
* <b>- (void) purgeSharedInstance</b>: Purge (deallocate) the shared instance.
|
||||
*/
|
||||
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(OALActionManager);
|
||||
|
||||
|
||||
#pragma mark Action Management
|
||||
|
||||
/** Stops ALL running actions on ALL targets.
|
||||
*/
|
||||
- (void) stopAllActions;
|
||||
|
||||
|
||||
#pragma mark Internal Use
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Used by OALAction to announce that it is starting.
|
||||
*
|
||||
* @param action The action that is starting.
|
||||
*/
|
||||
- (void) notifyActionStarted:(OALAction*) action;
|
||||
|
||||
/** (INTERNAL USE) Used by OALAction to announce that it is stopping.
|
||||
*
|
||||
* @param action The action that is stopping.
|
||||
*/
|
||||
- (void) notifyActionStopped:(OALAction*) action;
|
||||
/** \endcond */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* OBJECTAL_CFG_USE_COCOS2D_ACTIONS */
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
//
|
||||
// OALAudioActions.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-10-10.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import "OALAction.h"
|
||||
#import "ALTypes.h"
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Audio Property Actions
|
||||
|
||||
@interface OALPropertyAction (Audio)
|
||||
|
||||
+ (OALPropertyAction*) pitchActionWithDuration:(float) duration
|
||||
endValue:(float) endValue;
|
||||
|
||||
+ (OALPropertyAction*) pitchActionWithDuration:(float) duration
|
||||
startValue:(float) startValue
|
||||
endValue:(float) endValue;
|
||||
|
||||
+ (OALPropertyAction*) panActionWithDuration:(float) duration
|
||||
endValue:(float) endValue;
|
||||
|
||||
+ (OALPropertyAction*) panActionWithDuration:(float) duration
|
||||
startValue:(float) startValue
|
||||
endValue:(float) endValue;
|
||||
|
||||
+ (OALPropertyAction*) gainActionWithDuration:(float) duration
|
||||
endValue:(float) endValue;
|
||||
|
||||
+ (OALPropertyAction*) gainActionWithDuration:(float) duration
|
||||
startValue:(float) startValue
|
||||
endValue:(float) endValue;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALPlaceAction
|
||||
|
||||
/**
|
||||
* Places the target at the specified position.
|
||||
*/
|
||||
@interface OALPlaceAction : OALAction
|
||||
{
|
||||
ALPoint position;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The position where the target will be placed. */
|
||||
@property(nonatomic,readwrite,assign) ALPoint position;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create an action with the specified position.
|
||||
*
|
||||
* @param position The position to place the target at.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithPosition:(ALPoint) position;
|
||||
|
||||
/** Initialize an action with the specified position.
|
||||
*
|
||||
* @param position The position to place the target at.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithPosition:(ALPoint) position;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALMoveToAction
|
||||
|
||||
/**
|
||||
* Moves the target from its current position to the specified
|
||||
* position over time in 3D space.
|
||||
*/
|
||||
@interface OALMoveToAction : OALAction
|
||||
{
|
||||
float unitsPerSecond;
|
||||
|
||||
/** The point this move is starting at. */
|
||||
ALPoint startPoint;
|
||||
ALPoint position;
|
||||
|
||||
/** The distance being moved. */
|
||||
ALPoint delta;
|
||||
}
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The position to move the target to. */
|
||||
@property(nonatomic,readwrite,assign) ALPoint position;
|
||||
|
||||
/** The speed at which to move the target.
|
||||
* If this is 0, the target will be moved at the speed determined by duration.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float unitsPerSecond;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create a new action.
|
||||
*
|
||||
* @param duration The duration of the move.
|
||||
* @param position The position to move to.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithDuration:(float) duration position:(ALPoint) position;
|
||||
|
||||
/** Create a new action.
|
||||
*
|
||||
* @param unitsPerSecond The rate of movement.
|
||||
* @param position The position to move to.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithUnitsPerSecond:(float) unitsPerSecond position:(ALPoint) position;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param duration The duration of the move.
|
||||
* @param position The position to move to.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithDuration:(float) duration position:(ALPoint) position;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param unitsPerSecond The rate of movement.
|
||||
* @param position The position to move to.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithUnitsPerSecond:(float) unitsPerSecond position:(ALPoint) position;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALMoveByAction
|
||||
|
||||
/**
|
||||
* Moves the target from its current position by the specified
|
||||
* delta over time in 3D space.
|
||||
*/
|
||||
@interface OALMoveByAction : OALAction
|
||||
{
|
||||
float unitsPerSecond;
|
||||
|
||||
/** The point this move is starting at. */
|
||||
ALPoint startPoint;
|
||||
ALPoint delta;
|
||||
}
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The amount to move the target by. */
|
||||
@property(nonatomic,readwrite,assign) ALPoint delta;
|
||||
|
||||
/** The speed at which to move the target.
|
||||
* If this is 0, the target will be moved at the speed determined by duration.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float unitsPerSecond;
|
||||
|
||||
/** Create a new action.
|
||||
*
|
||||
* @param duration The duration of the move.
|
||||
* @param delta The amount to move by.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithDuration:(float) duration delta:(ALPoint) delta;
|
||||
|
||||
/** Create a new action.
|
||||
*
|
||||
* @param unitsPerSecond The rate of movement.
|
||||
* @param delta The amount to move by.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithUnitsPerSecond:(float) unitsPerSecond delta:(ALPoint) delta;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param duration The duration of the move.
|
||||
* @param delta The amount to move by.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithDuration:(float) duration delta:(ALPoint) delta;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param unitsPerSecond The rate of movement.
|
||||
* @param delta The amount to move by.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithUnitsPerSecond:(float) unitsPerSecond delta:(ALPoint) delta;
|
||||
|
||||
@end
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// OALAudioFile.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-12-24.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
#import "ALBuffer.h"
|
||||
|
||||
|
||||
/**
|
||||
* Maintains an open audio file and allows loading data from that file into
|
||||
* new ALBuffer objects.
|
||||
*/
|
||||
@interface OALAudioFile : NSObject
|
||||
{
|
||||
NSURL* url;
|
||||
bool reduceToMono;
|
||||
SInt64 totalFrames;
|
||||
|
||||
/** A description of the audio data in this file. */
|
||||
AudioStreamBasicDescription streamDescription;
|
||||
|
||||
/** The OS specific file handle */
|
||||
ExtAudioFileRef fileHandle;
|
||||
|
||||
/** The actual number of channels in the audio data if not reducing to mono */
|
||||
UInt32 originalChannelsPerFrame;
|
||||
}
|
||||
|
||||
/** The URL of the audio file */
|
||||
@property(nonatomic,readonly,retain) NSURL* url;
|
||||
|
||||
/** A description of the audio data in this file. */
|
||||
@property(nonatomic,readonly,assign) AudioStreamBasicDescription* streamDescription;
|
||||
|
||||
/** The total number of audio frames in this file */
|
||||
@property(nonatomic,readonly,assign) SInt64 totalFrames;
|
||||
|
||||
/** If YES, reduce any stereo data to mono (stereo samples don't support panning or positional audio). */
|
||||
@property(nonatomic,readwrite,assign) bool reduceToMono;
|
||||
|
||||
/** Open the audio file at the specified URL.
|
||||
*
|
||||
* @param url The URL to open the audio file from.
|
||||
* @param reduceToMono If YES, reduce any stereo track to mono
|
||||
(stereo samples don't support panning or positional audio).
|
||||
* @return a new audio file object.
|
||||
*/
|
||||
+ (OALAudioFile*) fileWithUrl:(NSURL*) url
|
||||
reduceToMono:(bool) reduceToMono;
|
||||
|
||||
/** Initialize this object with the audio file at the specified URL.
|
||||
*
|
||||
* @param url The URL to open the audio file from.
|
||||
* @param reduceToMono If YES, reduce any stereo track to mono
|
||||
(stereo samples don't support panning or positional audio).
|
||||
* @return the initialized audio file object.
|
||||
*/
|
||||
- (id) initWithUrl:(NSURL*) url
|
||||
reduceToMono:(bool) reduceToMono;
|
||||
|
||||
/** Read audio data from this file into a new buffer.
|
||||
*
|
||||
* @param startFrame The starting audio frame to read data from.
|
||||
* @param numFrames The number of frames to read.
|
||||
* @param bufferSize On successful return, contains the size of the returned buffer, in bytes.
|
||||
* @return The audio data or nil on error. You are responsible for calling free() on the data.
|
||||
*/
|
||||
- (void*) audioDataWithStartFrame:(SInt64) startFrame
|
||||
numFrames:(SInt64) numFrames
|
||||
bufferSize:(UInt32*) bufferSize;
|
||||
|
||||
/** Create a new ALBuffer with the contents of this file.
|
||||
*
|
||||
* @param name The name to be given to this ALBuffer.
|
||||
* @param startFrame The starting audio frame to read data from.
|
||||
* @param numFrames The number of frames to read.
|
||||
* @return a new ALBuffer containing the audio data.
|
||||
*/
|
||||
- (ALBuffer*) bufferNamed:(NSString*) name
|
||||
startFrame:(SInt64) startFrame
|
||||
numFrames:(SInt64) numFrames;
|
||||
|
||||
/** Convenience method to load the entire contents of a URL into a new ALBuffer.
|
||||
*
|
||||
* @param url The URL to open the audio file from.
|
||||
* @param reduceToMono If YES, reduce any stereo track to mono
|
||||
(stereo samples don't support panning or positional audio).
|
||||
* @return an ALBuffer object.
|
||||
*/
|
||||
+ (ALBuffer*) bufferFromUrl:(NSURL*) url
|
||||
reduceToMono:(bool) reduceToMono;
|
||||
|
||||
@end
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// OALAudioSession.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-12-19.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "SynthesizeSingleton.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
|
||||
/**
|
||||
* Handles the audio session and interrupts.
|
||||
*/
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && !defined(__TV_OS_VERSION_MIN_REQUIRED)
|
||||
@interface OALAudioSession : NSObject <AVAudioSessionDelegate, OALSuspendManager>
|
||||
#else
|
||||
@interface OALAudioSession : NSObject <OALSuspendManager>
|
||||
#endif
|
||||
{
|
||||
/** The current audio session category */
|
||||
NSString* audioSessionCategory;
|
||||
|
||||
/** Flag signifying that we are currently handling an error notification.
|
||||
* This prevents onAudioError: from becoming reentrant due to
|
||||
* self.manuallySuspended setting off a chain of calls that result in
|
||||
* another error notification broadcast.
|
||||
*/
|
||||
bool handlingErrorNotification;
|
||||
|
||||
bool handleInterruptions;
|
||||
bool allowIpod;
|
||||
bool ipodDucking;
|
||||
bool useHardwareIfAvailable;
|
||||
bool honorSilentSwitch;
|
||||
|
||||
bool audioSessionActive;
|
||||
|
||||
/** If true, the audio session was active when the interrupt occurred. */
|
||||
bool audioSessionWasActive;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
|
||||
/** Marks the last time the audio session was reset due to error.
|
||||
* This is used to avoid getting stuck in a rapid-fire reset-error loop.
|
||||
*/
|
||||
NSDate* lastResetTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The current audio session category.
|
||||
* If this value is explicitly set, the other session properties "allowIpod",
|
||||
* "useHardwareIfAvailable", "honorSilentSwitch", and "ipodDucking" may be modified
|
||||
* to remain compatible with the category.
|
||||
*
|
||||
* @see AVAudioSessionCategory
|
||||
*
|
||||
* Default value: nil
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSString* audioSessionCategory;
|
||||
|
||||
/** If YES, allow ipod music to continue playing (NOT SUPPORTED ON THE SIMULATOR).
|
||||
* Note: If this is enabled, and another app is playing music, background audio
|
||||
* playback will use the SOFTWARE codecs, NOT hardware. <br>
|
||||
*
|
||||
* If allowIpod = NO, the application will ALWAYS use hardware decoding. <br>
|
||||
*
|
||||
* @see useHardwareIfAvailable
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool allowIpod;
|
||||
|
||||
/** If YES, ipod music will duck (lower in volume) when the audio session activates.
|
||||
*
|
||||
* Default value: NO
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool ipodDucking;
|
||||
|
||||
/** Determines what to do if no other application is playing audio and allowIpod = YES
|
||||
* (NOT SUPPORTED ON THE SIMULATOR). <br>
|
||||
*
|
||||
* If NO, the application will ALWAYS use software decoding. The advantage to this is that
|
||||
* the user can background your application and then start audio playing from another
|
||||
* application. If useHardwareIfAvailable = YES, the user won't be able to do this. <br>
|
||||
*
|
||||
* If this is set to YES, the application will use hardware decoding if no other application
|
||||
* is currently playing audio. However, no other application will be able to start playing
|
||||
* audio if it wasn't playing already. <br>
|
||||
*
|
||||
* Note: This switch has no effect if allowIpod = NO. <br>
|
||||
*
|
||||
* @see allowIpod
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool useHardwareIfAvailable;
|
||||
|
||||
/** If true, mute when backgrounded, screen locked, or the ringer switch is
|
||||
* turned off (NOT SUPPORTED ON THE SIMULATOR). <br>
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool honorSilentSwitch;
|
||||
|
||||
/** If true, automatically handle interruptions. <br>
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool handleInterruptions;
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && !defined(__TV_OS_VERSION_MIN_REQUIRED)
|
||||
/** Delegate that will receive all audio session events (WEAK reference).
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) id<AVAudioSessionDelegate> audioSessionDelegate;
|
||||
#endif
|
||||
|
||||
/** If true, the audio session is active */
|
||||
@property(nonatomic,readwrite,assign) bool audioSessionActive;
|
||||
|
||||
/** The preferred I/O buffer duration, in seconds. Lower values give less
|
||||
* playback latencey, but use more CPU.
|
||||
* @deprecated Use AVAudioSession instead.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float preferredIOBufferDuration __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_6_1);
|
||||
|
||||
/** If true, another application (usually iPod) is playing music.
|
||||
* @deprecated Use AVAudioSession instead.
|
||||
*/
|
||||
@property(nonatomic,readonly,assign) bool ipodPlaying __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_6_1);
|
||||
|
||||
/** Get the device's final hardware output volume, as controlled by
|
||||
* the volume button on the side of the device.
|
||||
* @deprecated Use AVAudioSession instead.
|
||||
*/
|
||||
@property(nonatomic,readonly,assign) float hardwareVolume __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_6_1);
|
||||
|
||||
/** Check if the hardware mute switch is on (not supported on the simulator or iOS 5+).
|
||||
* Note: If headphones are plugged in, hardwareMuted will always return FALSE
|
||||
* regardless of the switch state.
|
||||
*
|
||||
* Note: Please file a bug report with Apple to get this functionality restored in iOS 5!
|
||||
*/
|
||||
@property(nonatomic,readonly,assign) bool hardwareMuted __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_5_0);
|
||||
|
||||
/** Check what hardware route the audio is taking, such as "Speaker" or "Headphone"
|
||||
* (not supported on the simulator).
|
||||
* @deprecated Use AVAudioSession instead.
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) NSString* audioRoute __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_6_1);
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Singleton implementation providing "sharedInstance" and "purgeSharedInstance" methods.
|
||||
*
|
||||
* <b>- (OALAudioSupport*) sharedInstance</b>: Get the shared singleton instance. <br>
|
||||
* <b>- (void) purgeSharedInstance</b>: Purge (deallocate) the shared instance.
|
||||
*/
|
||||
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(OALAudioSession);
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Force an interrupt end. This can be useful in cases where a buggy OS
|
||||
* fails to end an interrupt.
|
||||
*
|
||||
* Be VERY CAREFUL when using this!
|
||||
*/
|
||||
- (void) forceEndInterruption;
|
||||
|
||||
@end
|
||||
+443
@@ -0,0 +1,443 @@
|
||||
//
|
||||
// OALAudioTrack.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-08-21.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "OALAction.h"
|
||||
#import "OALAudioTrackNotifications.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
/**
|
||||
* Plays an audio track via AVAudioPlayer.
|
||||
* Unlike AVAudioPlayer, however, it can be re-used to play another file.
|
||||
* Interruptions can be handled by OALAudioSupport (enabled by default).
|
||||
*/
|
||||
@interface OALAudioTrack : NSObject <AVAudioPlayerDelegate, OALSuspendManager>
|
||||
{
|
||||
/** If true, this track is recording metering data */
|
||||
bool meteringEnabled;
|
||||
bool interrupted;
|
||||
AVAudioPlayer* player;
|
||||
NSURL* currentlyLoadedUrl;
|
||||
bool preloaded;
|
||||
bool autoPreload;
|
||||
bool paused;
|
||||
bool muted;
|
||||
float gain;
|
||||
float pan;
|
||||
NSInteger numberOfLoops;
|
||||
id<AVAudioPlayerDelegate> delegate; // Weak reference
|
||||
|
||||
/** When the simulator is running (and the playback fix is in use),
|
||||
* player will be copied to here, and then player set to nil.
|
||||
* This prevents other code from inadvertently raising the volume
|
||||
* and starting playback.
|
||||
*/
|
||||
AVAudioPlayer* simulatorPlayerRef;
|
||||
|
||||
/** Operation queue for running asynchronous operations.
|
||||
* <strong>Note:</strong> Only one asynchronous operation is allowed at a time.
|
||||
*/
|
||||
NSOperationQueue* operationQueue;
|
||||
|
||||
/** If true, the audio player is currently playing.
|
||||
* We need to maintain our own value because AVAudioPlayer will
|
||||
* sometimes say it's not playing when it actually is.
|
||||
*/
|
||||
bool playing;
|
||||
NSTimeInterval currentTime;
|
||||
|
||||
/** The current action being applied to gain. */
|
||||
OALAction* gainAction;
|
||||
|
||||
/** The current action being applied to pan. */
|
||||
OALAction* panAction;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The URL of the currently loaded audio data. */
|
||||
@property(nonatomic,readonly,retain) NSURL* currentlyLoadedUrl;
|
||||
|
||||
/** Optional object that will receive notifications for decoding errors,
|
||||
* audio interruptions (such as an incoming phone call), and playback completion. <br>
|
||||
* <strong>Note:</strong> OALAudioTrack keeps a WEAK reference to delegate, so make sure you clear it
|
||||
* when your object is going to be deallocated.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) id<AVAudioPlayerDelegate> delegate;
|
||||
|
||||
/** The gain (volume) for playback (0.0 - 1.0, where 1.0 = no attenuation). */
|
||||
@property(nonatomic,readwrite,assign) float gain;
|
||||
|
||||
/** The volume (alias to gain) for playback (0.0 - 1.0, where 1.0 = no attenuation). */
|
||||
@property(nonatomic,readwrite,assign) float volume;
|
||||
|
||||
/** Pan value (-1.0 = far left, 1.0 = far right).
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) float pan;
|
||||
|
||||
/** If true, audio track is muted */
|
||||
@property(nonatomic,readwrite,assign) bool muted;
|
||||
|
||||
/** If true, automatically preload again when playback stops */
|
||||
@property(nonatomic,readwrite,assign) bool autoPreload;
|
||||
|
||||
/** If true, audio track is in preloaded state */
|
||||
@property(nonatomic,readonly,assign) bool preloaded;
|
||||
|
||||
/** The number of times to loop playback (-1 = forever).
|
||||
* <strong>Note:</strong> This value will be ignored, and get changed when you call the various playXX methods.
|
||||
* Only "play" will use the current value of "numberOfLoops".
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) NSInteger numberOfLoops;
|
||||
|
||||
/** If true, pause playback. */
|
||||
@property(nonatomic,readwrite,assign) bool paused;
|
||||
|
||||
/** Access to the underlying AVAudioPlayer object.
|
||||
* WARNING: Be VERY careful when accessing this, as some methods could cause
|
||||
* it to fall out of sync with OALAudioTrack (particularly play/pause/stop methods).
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) AVAudioPlayer* player;
|
||||
|
||||
/** If true, background music is currently playing. */
|
||||
@property(nonatomic,readonly,assign) bool playing;
|
||||
|
||||
/** The current playback position in seconds from the start of the sound.
|
||||
* You can set this to change the playback position, whether it is currently playing or not.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) NSTimeInterval currentTime;
|
||||
|
||||
/** The value of this property increases monotonically while an audio player is playing or paused. <br><br>
|
||||
*
|
||||
* If more than one audio player is connected to the audio output device, device time continues
|
||||
* incrementing as long as at least one of the players is playing or paused. <br><br>
|
||||
*
|
||||
* If the audio output device has no connected audio players that are either playing or paused,
|
||||
* device time reverts to 0. <br><br>
|
||||
*
|
||||
* Use this property to indicate “now” when calling the playAtTime: instance method. By configuring
|
||||
* multiple audio players to play at a specified offset from deviceCurrentTime, you can perform
|
||||
* precise synchronization—as described in the discussion for that method.
|
||||
*
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*/
|
||||
@property(nonatomic,readonly,assign) NSTimeInterval deviceCurrentTime;
|
||||
|
||||
/** The duration, in seconds, of the currently loaded sound. */
|
||||
@property(nonatomic,readonly,assign) NSTimeInterval duration;
|
||||
|
||||
/** The number of channels in the currently loaded sound. */
|
||||
@property(nonatomic,readonly,assign) NSUInteger numberOfChannels;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create a new audio track.
|
||||
*
|
||||
* @return A new audio track.
|
||||
*/
|
||||
+ (id) track;
|
||||
|
||||
|
||||
#pragma mark Playback
|
||||
|
||||
/** Preload the contents of a URL for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) preloadUrl:(NSURL*) url;
|
||||
|
||||
/** Preload the contents of a URL for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @param seekTime The position in the file to start playing at.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) preloadUrl:(NSURL*) url seekTime:(NSTimeInterval)seekTime;
|
||||
|
||||
/** Preload the contents of a file for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) preloadFile:(NSString*) path;
|
||||
|
||||
/** Preload the contents of a file for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @param seekTime The position in the file to start playing at.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) preloadFile:(NSString*) path seekTime:(NSTimeInterval)seekTime;
|
||||
|
||||
/** Asynchronously preload the contents of a URL for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @param target the target to inform when preparation is complete.
|
||||
* @param selector the selector to call when preparation is complete.
|
||||
* @return TRUE if the operation was successfully queued.
|
||||
*/
|
||||
- (bool) preloadUrlAsync:(NSURL*) url target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Asynchronously preload the contents of a URL for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @param seekTime The position in the file to start playing at.
|
||||
* @param target the target to inform when preparation is complete.
|
||||
* @param selector the selector to call when preparation is complete.
|
||||
* @return TRUE if the operation was successfully queued.
|
||||
*/
|
||||
- (bool) preloadUrlAsync:(NSURL*) url seekTime:(NSTimeInterval)seekTime target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Asynchronously preload the contents of a file for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @param target the target to inform when preparation is complete.
|
||||
* @param selector the selector to call when preparation is complete.
|
||||
* @return TRUE if the operation was successfully queued.
|
||||
*/
|
||||
- (bool) preloadFileAsync:(NSString*) path target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Asynchronously preload the contents of a file for playback.
|
||||
* Once the audio data is preloaded, you can call "play" to play it. <br>
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @param seekTime The position in the file to start playing at.
|
||||
* @param target the target to inform when preparation is complete.
|
||||
* @param selector the selector to call when preparation is complete.
|
||||
* @return TRUE if the operation was successfully queued.
|
||||
*/
|
||||
- (bool) preloadFileAsync:(NSString*) path seekTime:(NSTimeInterval)seekTime target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Play the contents of a URL once.
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playUrl:(NSURL*) url;
|
||||
|
||||
/** Play the contents of a URL and loop the specified number of times.
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @param loops The number of times to loop playback (-1 = forever)
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playUrl:(NSURL*) url loops:(NSInteger) loops;
|
||||
|
||||
/** Play the contents of a file once.
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playFile:(NSString*) path;
|
||||
|
||||
/** Play the contents of a file and loop the specified number of times.
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @param loops The number of times to loop playback (-1 = forever)
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playFile:(NSString*) path loops:(NSInteger) loops;
|
||||
|
||||
/** Play the contents of a URL asynchronously once.
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @param target the target to inform when playing has started.
|
||||
* @param selector the selector to call when playing has started.
|
||||
*/
|
||||
- (void) playUrlAsync:(NSURL*) url target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Play the contents of a URL asynchronously and loop the specified number of times.
|
||||
*
|
||||
* @param url The URL containing the sound data.
|
||||
* @param loops The number of times to loop playback (-1 = forever)
|
||||
* @param target the target to inform when playing has started.
|
||||
* @param selector the selector to call when playing has started.
|
||||
*/
|
||||
- (void) playUrlAsync:(NSURL*) url
|
||||
loops:(NSInteger) loops
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Play the contents of a file asynchronously once.
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @param target the target to inform when playing has started.
|
||||
* @param selector the selector to call when playing has started.
|
||||
*/
|
||||
- (void) playFileAsync:(NSString*) path target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Play the contents of a file asynchronously and loop the specified number of times.
|
||||
*
|
||||
* @param path The file containing the sound data.
|
||||
* @param loops The number of times to loop playback (-1 = forever)
|
||||
* @param target the target to inform when playing has started.
|
||||
* @param selector the selector to call when playing has started.
|
||||
*/
|
||||
- (void) playFileAsync:(NSString*) path
|
||||
loops:(NSInteger) loops
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Play the currently loaded audio track.
|
||||
*
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) play;
|
||||
|
||||
/** Plays a sound asynchronously, starting at a specified point in the audio output device’s timeline.
|
||||
*
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*
|
||||
* @param time The time (device time) to start playing at.
|
||||
* @return YES if the playback was successfully scheduled.
|
||||
*/
|
||||
- (bool) playAtTime:(NSTimeInterval) time;
|
||||
|
||||
/** Plays the currently preloaded track asynchronously when the specified track completes.
|
||||
*
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*
|
||||
* @param track The track to play after
|
||||
* @return YES if the playback was successfully scheduled.
|
||||
*/
|
||||
- (bool) playAfterTrack:(OALAudioTrack*) track;
|
||||
|
||||
/** Plays the currently preloaded track asynchronously when the specified track completes.
|
||||
*
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*
|
||||
* @param track The track to play after
|
||||
* @param timeAdjust fine-tune value added to the time start offset.
|
||||
* @return YES if the playback was successfully scheduled.
|
||||
*/
|
||||
- (bool) playAfterTrack:(OALAudioTrack*) track timeAdjust:(NSTimeInterval) timeAdjust;
|
||||
|
||||
/** Stop playing and stop all operations.
|
||||
*/
|
||||
- (void) stop;
|
||||
|
||||
/** Fade to the specified gain value.
|
||||
*
|
||||
* @param gain The gain to fade to.
|
||||
* @param duration The duration of the fade operation in seconds.
|
||||
* @param target The target to notify when the fade completes (can be nil).
|
||||
* @param selector The selector to call when the fade completes. The selector must accept
|
||||
* a single parameter, which will be the object that performed the fade.
|
||||
*/
|
||||
- (void) fadeTo:(float) gain
|
||||
duration:(float) duration
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Stop the currently running fade operation, if any.
|
||||
*/
|
||||
- (void) stopFade;
|
||||
|
||||
/** Pan to the specified pan value.
|
||||
*
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*
|
||||
* @param pan The value to pan to.
|
||||
* @param duration The duration of the pan operation in seconds.
|
||||
* @param target The target to notify when the pan completes (can be nil).
|
||||
* @param selector The selector to call when the pan completes. The selector must accept
|
||||
* a single parameter, which will be the object that performed the pan.
|
||||
*/
|
||||
- (void) panTo:(float) pan
|
||||
duration:(float) duration
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Stop the currently running pan operation, if any.
|
||||
*
|
||||
* <strong>Note:</strong> This will have no effect on iOS versions prior to 4.0.
|
||||
*/
|
||||
- (void) stopPan;
|
||||
|
||||
/** Stop any internal fade or pan actions. */
|
||||
- (void) stopActions;
|
||||
|
||||
/** Unload and clear all audio data, stop playing, and stop all operations.
|
||||
*/
|
||||
- (void) clear;
|
||||
|
||||
#pragma mark Metering
|
||||
|
||||
/** If true, metering is enabled. */
|
||||
@property (nonatomic,readwrite,assign) bool meteringEnabled;
|
||||
|
||||
/** Updates the metering system to give current values.
|
||||
* You must call this method before calling averagePowerForChannel or peakPowerForChannel in
|
||||
* order to get current values.
|
||||
*/
|
||||
- (void) updateMeters;
|
||||
|
||||
/** Gives the average power for a given channel, in decibels, for the sound being played.
|
||||
* 0 dB indicates maximum power (full scale). <br>
|
||||
* -160 dB indicates minimum power (near silence). <br>
|
||||
* If the signal provided to the audio player exceeds full scale, then the value may be > 0. <br>
|
||||
*
|
||||
* <strong>Note:</strong> The value returned is in reference to when updateMeters was last called.
|
||||
* You must call updateMeters again before calling this method to get a current value.
|
||||
*
|
||||
* @param channelNumber The channel to get the value from. For mono or left, use 0. For right,
|
||||
* use 1.
|
||||
* @return the average power for the channel.
|
||||
*/
|
||||
- (float) averagePowerForChannel:(NSUInteger)channelNumber;
|
||||
|
||||
/** Gives the peak power for a given channel, in decibels, for the sound being played.
|
||||
* 0 dB indicates maximum power (full scale). <br>
|
||||
* -160 dB indicates minimum power (near silence). <br>
|
||||
* If the signal provided to the audio player exceeds full scale, then the value may be > 0. <br>
|
||||
*
|
||||
* <strong>Note:</strong> The value returned is in reference to when updateMeters was last called.
|
||||
* You must call updateMeters again before calling this method to get a current value.
|
||||
*
|
||||
* @param channelNumber The channel to get the value from. For mono or left, use 0. For right,
|
||||
* use 1.
|
||||
* @return the average power for the channel.
|
||||
*/
|
||||
- (float) peakPowerForChannel:(NSUInteger)channelNumber;
|
||||
|
||||
@end
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// OALAudioTrackNotifications.h
|
||||
//
|
||||
// Created by CJ Hanson on 10/16/10.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString *const OALAudioTrackSourceChangedNotification;
|
||||
extern NSString *const OALAudioTrackStartedPlayingNotification;
|
||||
extern NSString *const OALAudioTrackStoppedPlayingNotification;
|
||||
extern NSString *const OALAudioTrackFinishedPlayingNotification;
|
||||
extern NSString *const OALAudioTrackLoopedNotification;
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// OALAudioTracks.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import "OALAudioTrack.h"
|
||||
#import "SynthesizeSingleton.h"
|
||||
#import "OALSuspendHandler.h"
|
||||
|
||||
|
||||
#pragma mark OALAudioTracks
|
||||
|
||||
/**
|
||||
* Keeps track of all AudioTrack objects.
|
||||
*/
|
||||
@interface OALAudioTracks : NSObject <OALSuspendManager>
|
||||
{
|
||||
/** All instantiated audio tracks. */
|
||||
NSMutableArray* tracks;
|
||||
bool muted;
|
||||
bool paused;
|
||||
|
||||
/** Timer to poll deviceCurrentTime so that it doesn't get reset on a device */
|
||||
NSTimer* deviceTimePoller;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
}
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** Pauses/unpauses all audio tracks. */
|
||||
@property(nonatomic,readwrite,assign) bool paused;
|
||||
|
||||
/** Mutes/unmutes all audio tracks. */
|
||||
@property(nonatomic,readwrite,assign) bool muted;
|
||||
|
||||
/** All instantiated audio tracks. */
|
||||
@property(nonatomic,readonly,retain) NSArray* tracks;
|
||||
|
||||
|
||||
#pragma mark Playback
|
||||
|
||||
/** Stop playback on all audio tracks.
|
||||
*/
|
||||
- (void) stopAllTracks;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Singleton implementation providing "sharedInstance" and "purgeSharedInstance" methods.
|
||||
*
|
||||
* <b>- (OALAudioTracks*) sharedInstance</b>: Get the shared singleton instance. <br>
|
||||
* <b>- (void) purgeSharedInstance</b>: Purge (deallocate) the shared instance.
|
||||
*/
|
||||
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(OALAudioTracks);
|
||||
|
||||
|
||||
#pragma mark Internal Use
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Notify that a track is initializing.
|
||||
*/
|
||||
- (void) notifyTrackInitializing:(OALAudioTrack*) track;
|
||||
|
||||
/** (INTERNAL USE) Notify that a track is deallocating.
|
||||
*/
|
||||
- (void) notifyTrackDeallocating:(OALAudioTrack*) track;
|
||||
/** \endcond */
|
||||
|
||||
@end
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// OALNotifications.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 11-01-03.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#define OALAudioErrorNotification @"OALAudioErrorNotification"
|
||||
+492
@@ -0,0 +1,492 @@
|
||||
//
|
||||
// OALSimpleAudio.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-01-14.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SynthesizeSingleton.h"
|
||||
#import "ALDevice.h"
|
||||
#import "ALContext.h"
|
||||
#import "ALSoundSource.h"
|
||||
#import "ALChannelSource.h"
|
||||
#import "OALAudioTrack.h"
|
||||
|
||||
|
||||
#pragma mark OALSimpleAudio
|
||||
|
||||
/**
|
||||
* A simpler interface to the ObjectAL sound library. This singleton can be
|
||||
* used alone for simpler audio needs, or in conjunction with user-created
|
||||
* audio objects for more advanced needs (as is done in many of the demos).
|
||||
*
|
||||
* For sound effects, it initializes OpenAL with the default ALDevice,
|
||||
* an ALContext, and an ALChannelSource consisting of all 32 interruptible
|
||||
* ALSource objects (the maximum currently allowed for iOS).
|
||||
* If you want to create your own sources as well, change the reservedSources
|
||||
* property.
|
||||
*
|
||||
* For background audio, it creates a single OALAudioTrack, which will not reserve
|
||||
* resources unless used. (you can create more OALAudioTrack objects for your own
|
||||
* use if you want).
|
||||
*
|
||||
* This singleton also provides access to the more common configuration options
|
||||
* available in OALAudioSupport.
|
||||
*
|
||||
* All audio playback commands are delegated either to the ALChannelSource
|
||||
* (for sound effects), or to the OALAudioTrack (for BG music).
|
||||
*/
|
||||
@interface OALSimpleAudio : NSObject
|
||||
{
|
||||
/** The device we are using */
|
||||
ALDevice* device;
|
||||
/** The context we are using */
|
||||
ALContext* context;
|
||||
|
||||
/** The sound channel used by this object. */
|
||||
ALChannelSource* channel;
|
||||
/** Cache for preloaded sound samples. */
|
||||
NSMutableDictionary* preloadCache;
|
||||
#if NS_BLOCKS_AVAILABLE && OBJECTAL_CFG_USE_BLOCKS
|
||||
/** Queue for preloading and async operations that use blocks.
|
||||
* This ensures all operations are safe because they are guaranteed to run
|
||||
* in order.
|
||||
*/
|
||||
dispatch_queue_t oal_dispatch_queue;
|
||||
#endif
|
||||
/** keeping track of how many effects remain to be loaded */
|
||||
uint pendingLoadCount;
|
||||
|
||||
/** Audio track to play background music */
|
||||
OALAudioTrack* backgroundTrack;
|
||||
|
||||
bool muted;
|
||||
bool bgMuted;
|
||||
bool effectsMuted;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** If YES, allow ipod music to continue playing (NOT SUPPORTED ON THE SIMULATOR).
|
||||
* Note: If this is enabled, and another app is playing music, background audio
|
||||
* playback will use the SOFTWARE codecs, NOT hardware. <br>
|
||||
*
|
||||
* If allowIpod = NO, the application will ALWAYS use hardware decoding. <br>
|
||||
*
|
||||
* iOS Only. <br>
|
||||
*
|
||||
* @see useHardwareIfAvailable
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool allowIpod;
|
||||
|
||||
/** Determines what to do if no other application is playing audio and allowIpod = YES
|
||||
* (NOT SUPPORTED ON THE SIMULATOR). <br>
|
||||
*
|
||||
* If NO, the application will ALWAYS use software decoding. The advantage to this is that
|
||||
* the user can background your application and then start audio playing from another
|
||||
* application. If useHardwareIfAvailable = YES, the user won't be able to do this. <br>
|
||||
*
|
||||
* If this is set to YES, the application will use hardware decoding if no other application
|
||||
* is currently playing audio. However, no other application will be able to start playing
|
||||
* audio if it wasn't playing already. <br>
|
||||
*
|
||||
* Note: This switch has no effect if allowIpod = NO. <br>
|
||||
*
|
||||
* iOS Only. <br>
|
||||
*
|
||||
* @see allowIpod
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool useHardwareIfAvailable;
|
||||
|
||||
/** If true, mute when backgrounded, screen locked, or the ringer switch is
|
||||
* turned off (NOT SUPPORTED ON THE SIMULATOR). <br>
|
||||
*
|
||||
* iOS Only. <br>
|
||||
*
|
||||
* Default value: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool honorSilentSwitch;
|
||||
|
||||
/** The number of sources OALSimpleAudio is using (max 32 on current iOS devices). */
|
||||
@property(nonatomic,readwrite,assign) int reservedSources;
|
||||
|
||||
@property(nonatomic,readonly,retain) ALDevice* device;
|
||||
|
||||
@property(nonatomic,readonly,retain) ALContext* context;
|
||||
|
||||
/** The channel source used by OALSimpleAudio.
|
||||
* Only mess with this if you know what you are doing!
|
||||
*/
|
||||
@property(nonatomic,readonly,retain) ALChannelSource* channel;
|
||||
|
||||
/** Background audio URL */
|
||||
@property(nonatomic,readonly,retain) NSURL* backgroundTrackURL;
|
||||
|
||||
/** Background audio track */
|
||||
@property(nonatomic,readonly,retain) OALAudioTrack* backgroundTrack;
|
||||
|
||||
/** Pauses BG music playback */
|
||||
@property(nonatomic,readwrite,assign) bool bgPaused;
|
||||
|
||||
/** Mutes BG music playback */
|
||||
@property(nonatomic,readwrite,assign) bool bgMuted;
|
||||
|
||||
/** If true, BG music is currently playing */
|
||||
@property(nonatomic,readonly,assign) bool bgPlaying;
|
||||
|
||||
/** Background music playback gain/volume (0.0 - 1.0) */
|
||||
@property(nonatomic,readwrite,assign) float bgVolume;
|
||||
|
||||
/** Pauses effects playback */
|
||||
@property(nonatomic,readwrite,assign) bool effectsPaused;
|
||||
|
||||
/** Mutes effects playback */
|
||||
@property(nonatomic,readwrite,assign) bool effectsMuted;
|
||||
|
||||
/** Master effects gain/volume (0.0 - 1.0) */
|
||||
@property(nonatomic,readwrite,assign) float effectsVolume;
|
||||
|
||||
/** Pauses everything */
|
||||
@property(nonatomic,readwrite,assign) bool paused;
|
||||
|
||||
/** Mutes all audio */
|
||||
@property(nonatomic,readwrite,assign) bool muted;
|
||||
|
||||
/** Enables/disables the preload cache.
|
||||
* If the preload cache is disabled, effects preloading will do nothing
|
||||
* (BG preloading will still work).
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool preloadCacheEnabled;
|
||||
|
||||
/** The number of items currently in the preload cache. */
|
||||
@property(nonatomic,readonly,assign) NSUInteger preloadCacheCount;
|
||||
|
||||
/** Set to YES to manually suspend the sound system. */
|
||||
@property(nonatomic,readwrite,assign) bool manuallySuspended;
|
||||
|
||||
/** If YES, the sound system is interrupted. iOS Only. */
|
||||
@property(nonatomic,readonly,assign) bool interrupted;
|
||||
|
||||
/** If YES, the sound system is suspended. */
|
||||
@property(nonatomic,readonly,assign) bool suspended;
|
||||
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Singleton implementation providing "sharedInstance" and "purgeSharedInstance" methods.
|
||||
*
|
||||
* <b>- (OALSimpleAudio*) sharedInstance</b>: Get the shared singleton instance. <br>
|
||||
* <b>- (void) purgeSharedInstance</b>: Purge (deallocate) the shared instance. <br>
|
||||
*/
|
||||
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(OALSimpleAudio);
|
||||
|
||||
/** Start OALSimpleAudio with the specified number of reserved sources.
|
||||
* Call this initializer if you want to use OALSimpleAudio, but keep some of the device's
|
||||
* audio sources (there are 32 in total) for your own use. <br>
|
||||
* <strong>Note:</strong> This method must be called ONLY ONCE, <em>BEFORE</em>
|
||||
* any attempt is made to access the shared instance.
|
||||
* To change the reserved sources after instantiation, modify reservedSources.
|
||||
*
|
||||
* @param sources the number of sources OALSimpleAudio will reserve for itself.
|
||||
* @return The shared instance.
|
||||
*/
|
||||
+ (OALSimpleAudio*) sharedInstanceWithSources:(int) sources;
|
||||
|
||||
/** Start OALSimpleAudio with the specified parameters.
|
||||
*
|
||||
* With this initializer, you can set the total number of mono and stereo sources
|
||||
* available, as well as how many sources are to be reserved by OALSimpleAudio. <br>
|
||||
*
|
||||
* The number of mono and stereo sources represents the GLOBAL number of sources
|
||||
* available for EVERYONE, not just OALSimpleAudio. Their combined values must
|
||||
* not exceed 32 (the max allowed sources in iOS). <br>
|
||||
*
|
||||
* reservedSources is independent of this; it represents how many of the above
|
||||
* mentioned sources to reserve for OALSimpleAudio's use. <br>
|
||||
*
|
||||
* <strong>Note:</strong> This method must be called ONLY ONCE, <em>BEFORE</em>
|
||||
* any attempt is made to access the shared instance. <br>
|
||||
*
|
||||
* @param reservedSources The number of sources to reserve for OALSimpleAudio's
|
||||
* use when initializing.
|
||||
* iOS currently supports up to 32 sources total.
|
||||
* @param monoSources The GLOBAL number of sources supporting mono (default 28).
|
||||
* @param stereoSources The GLOBAL number of sources supporting stereo (default 4).
|
||||
*
|
||||
* @return The shared instance.
|
||||
*/
|
||||
+ (OALSimpleAudio*) sharedInstanceWithReservedSources:(int) reservedSources
|
||||
monoSources:(int) monoSources
|
||||
stereoSources:(int) stereoSources;
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Initialize with the specified number of reserved sources.
|
||||
*
|
||||
* @param reservedSources the number of sources to reserve when initializing.
|
||||
* @return The shared instance.
|
||||
*/
|
||||
- (id) initWithSources:(int) reservedSources;
|
||||
|
||||
/** (INTERNAL USE) Initialize with the specified parameters.
|
||||
*
|
||||
* @param reservedSources The number of sources to reserve for OALSimpleAudio's use when initializing.
|
||||
* @param monoSources The GLOBAL number of sources supporting mono (default 28).
|
||||
* @param stereoSources The GLOBAL number of sources supporting stereo (default 4).
|
||||
* @return The shared instance.
|
||||
*/
|
||||
- (id) initWithReservedSources:(int) reservedSources
|
||||
monoSources:(int) monoSources
|
||||
stereoSources:(int) stereoSources;
|
||||
/** \endcond */
|
||||
|
||||
|
||||
#pragma mark Background Music
|
||||
|
||||
/** Preload background music.
|
||||
*
|
||||
* <strong>Note:</strong> only <strong>ONE</strong> background music
|
||||
* file may be played or preloaded at a time via OALSimpleAudio.
|
||||
* If you play or preload another file, the one currently playing
|
||||
* will stop.
|
||||
*
|
||||
* @param path The path containing the background music.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) preloadBg:(NSString*) path;
|
||||
|
||||
/** Preload background music.
|
||||
*
|
||||
* <strong>Note:</strong> only <strong>ONE</strong> background music
|
||||
* file may be played or preloaded at a time via OALSimpleAudio.
|
||||
* If you play or preload another file, the one currently playing
|
||||
* will stop.
|
||||
*
|
||||
* @param path The path containing the background music.
|
||||
* @param seekTime the position in the file to start playing at.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) preloadBg:(NSString*) path seekTime:(NSTimeInterval)seekTime;
|
||||
|
||||
/** Play whatever background music is preloaded.
|
||||
*
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playBg;
|
||||
|
||||
/** Play whatever background music is preloaded.
|
||||
*
|
||||
* @param loop If true, loop the bg track.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playBgWithLoop:(bool) loop;
|
||||
|
||||
/** Play the background music at the specified path.
|
||||
* If the music has not been preloaded, this method
|
||||
* will load the music and then play, incurring a slight delay. <br>
|
||||
*
|
||||
* <strong>Note:</strong> only <strong>ONE</strong> background music
|
||||
* file may be played or preloaded at a time via OALSimpleAudio.
|
||||
* If you play or preload another file, the one currently playing
|
||||
* will stop.
|
||||
*
|
||||
* @param path The path containing the background music.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playBg:(NSString*) path;
|
||||
|
||||
/** Play the background music at the specified path.
|
||||
* If the music has not been preloaded, this method
|
||||
* will load the music and then play, incurring a slight delay. <br>
|
||||
*
|
||||
* <strong>Note:</strong> only <strong>ONE</strong> background music
|
||||
* file may be played or preloaded at a time via OALSimpleAudio.
|
||||
* If you play or preload another file, the one currently playing
|
||||
* will stop.
|
||||
*
|
||||
* @param path The path containing the background music.
|
||||
* @param loop If true, loop the bg track.
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playBg:(NSString*) path loop:(bool) loop;
|
||||
|
||||
/** Play the background music at the specified path.
|
||||
* If the music has not been preloaded, this method
|
||||
* will load the music and then play, incurring a slight delay. <br>
|
||||
*
|
||||
* <strong>Note:</strong> only <strong>ONE</strong> background music
|
||||
* file may be played or preloaded at a time via OALSimpleAudio.
|
||||
* If you play or preload another file, the one currently playing
|
||||
* will stop. To play multiple audio tracks, create an OALAudioTrack. <br>
|
||||
*
|
||||
* <strong>Note:</strong> pan will have no effect when running on iOS
|
||||
* versions prior to 4.0.
|
||||
*
|
||||
* @param filePath The path containing the sound data.
|
||||
* @param volume The volume (gain) to play at (0.0 - 1.0).
|
||||
* @param pan Left-right panning (-1.0 = far left, 1.0 = far right) (Only on iOS 4.0+).
|
||||
* @param loop If TRUE, the sound will loop until you call "stopBg".
|
||||
* @return TRUE if the operation was successful.
|
||||
*/
|
||||
- (bool) playBg:(NSString*) filePath
|
||||
volume:(float) volume
|
||||
pan:(float) pan
|
||||
loop:(bool) loop;
|
||||
|
||||
/** Stop the background music playback and rewind.
|
||||
*/
|
||||
- (void) stopBg;
|
||||
|
||||
|
||||
#pragma mark Sound Effects
|
||||
|
||||
/** Preload and cache a sound effect for later playback.
|
||||
*
|
||||
* @param filePath The path containing the sound data.
|
||||
*/
|
||||
- (ALBuffer*) preloadEffect:(NSString*) filePath;
|
||||
|
||||
/** Preload and cache a sound effect for later playback.
|
||||
*
|
||||
* @param filePath The path containing the sound data.
|
||||
* @param reduceToMono If true, reduce the sample to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
*/
|
||||
- (ALBuffer*) preloadEffect:(NSString*) filePath reduceToMono:(bool) reduceToMono;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE && OBJECTAL_CFG_USE_BLOCKS
|
||||
|
||||
/** Asynchronous preload and cache sound effect for later playback.
|
||||
*
|
||||
* @param filePath an NSString with the path containing the sound data.
|
||||
* @param reduceToMono If true, reduce the sample to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
* @param completionBlock Executed when loading is complete.
|
||||
*/
|
||||
- (BOOL) preloadEffect:(NSString*) filePath
|
||||
reduceToMono:(bool) reduceToMono
|
||||
completionBlock:(void(^)(ALBuffer *)) completionBlock;
|
||||
|
||||
/** Asynchronous preload and cache multiple sound effects for later playback.
|
||||
*
|
||||
* @param filePaths An NSArray of NSStrings with the paths containing the sound data.
|
||||
* @param reduceToMono If true, reduce the samples to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
* @param progressBlock Executed regularly while file loading is in progress.
|
||||
*/
|
||||
- (void) preloadEffects:(NSArray*) filePaths
|
||||
reduceToMono:(bool) reduceToMono
|
||||
progressBlock:(void (^)(NSUInteger progress, NSUInteger successCount, NSUInteger total)) progressBlock;
|
||||
|
||||
#endif
|
||||
|
||||
/** Unload a preloaded effect. Only unloads if no source is currently playing
|
||||
* that effect (or paused with the effect loaded).
|
||||
*
|
||||
* @param filePath The path containing the sound data that was previously loaded.
|
||||
*
|
||||
* @return YES if the effect was unloaded. Turn on debug logging to see why an
|
||||
* effect was not unloaded.
|
||||
*/
|
||||
- (bool) unloadEffect:(NSString*) filePath;
|
||||
|
||||
/** Unload all preloaded effects that are not currently being played (paused or not).
|
||||
* Turning on debug logging will show which effects were not unloaded.
|
||||
* It is useful to put a call to this method in
|
||||
* "applicationDidReceiveMemoryWarning" in your app delegate.
|
||||
*/
|
||||
- (void) unloadAllEffects;
|
||||
|
||||
/** Play a sound effect with volume 1.0, pitch 1.0, pan 0.0, loop NO. The sound will be loaded
|
||||
* and cached if it wasn't already.
|
||||
*
|
||||
* @param filePath The path containing the sound data.
|
||||
* @return The sound source being used for playback, or nil if an error occurred.
|
||||
*/
|
||||
- (id<ALSoundSource>) playEffect:(NSString*) filePath;
|
||||
|
||||
/** Play a sound effect with volume 1.0, pitch 1.0, pan 0.0. The sound will be loaded and cached
|
||||
* if it wasn't already.
|
||||
*
|
||||
* @param filePath The path containing the sound data.
|
||||
* @param loop If TRUE, the sound will loop until you call "stop" on the returned sound source.
|
||||
* @return The sound source being used for playback, or nil if an error occurred.
|
||||
*/
|
||||
- (id<ALSoundSource>) playEffect:(NSString*) filePath loop:(bool) loop;
|
||||
|
||||
/** Play a sound effect. The sound will be loaded and cached if it wasn't already.
|
||||
*
|
||||
* @param filePath The path containing the sound data.
|
||||
* @param volume The volume (gain) to play at (0.0 - 1.0).
|
||||
* @param pitch The pitch to play at (1.0 = normal pitch).
|
||||
* @param pan Left-right panning (-1.0 = far left, 1.0 = far right).
|
||||
* @param loop If TRUE, the sound will loop until you call "stop" on the returned sound source.
|
||||
* @return The sound source being used for playback, or nil if an error occurred (You'll need to
|
||||
* keep this if you want to be able to stop a looped playback).
|
||||
*/
|
||||
- (id<ALSoundSource>) playEffect:(NSString*) filePath
|
||||
volume:(float) volume
|
||||
pitch:(float) pitch
|
||||
pan:(float) pan
|
||||
loop:(bool) loop;
|
||||
|
||||
/** Play a sound effect from a user-supplied buffer.
|
||||
*
|
||||
* @param buffer The buffer containing the sound data.
|
||||
* @param volume The volume (gain) to play at (0.0 - 1.0).
|
||||
* @param pitch The pitch to play at (1.0 = normal pitch).
|
||||
* @param pan Left-right panning (-1.0 = far left, 1.0 = far right).
|
||||
* @param loop If TRUE, the sound will loop until you call "stop" on the returned sound source.
|
||||
* @return The sound source being used for playback, or nil if an error occurred (You'll need to
|
||||
* keep this if you want to be able to stop a looped playback).
|
||||
*/
|
||||
- (id<ALSoundSource>) playBuffer:(ALBuffer*) buffer
|
||||
volume:(float) volume
|
||||
pitch:(float) pitch
|
||||
pan:(float) pan
|
||||
loop:(bool) loop;
|
||||
|
||||
/** Stop ALL sound effect playback.
|
||||
*/
|
||||
- (void) stopAllEffects;
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Stop all effects and bg music.
|
||||
*/
|
||||
- (void) stopEverything;
|
||||
|
||||
/** Reset everything in this object to its default state.
|
||||
*/
|
||||
- (void) resetToDefault;
|
||||
|
||||
@end
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// OALSuspendHandler.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-12-19.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Allows an object to participate in interrupt and suspend operations.
|
||||
* Objects may hook into OALAudioSession's interrupt and suspend model by
|
||||
* calling [[OALAudioSession sharedInstance] addSuspendListener:self].
|
||||
*
|
||||
* Note: You must NOT set the "interrupted" property manually. It is designed
|
||||
* to be set automatically by system interrupts.
|
||||
*
|
||||
* @see OALAudioSession
|
||||
*/
|
||||
@protocol OALSuspendListener
|
||||
|
||||
/** Set to YES to manually suspend.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool manuallySuspended;
|
||||
|
||||
/** If YES, this object is interrupted.
|
||||
* Note: This property must NOT be set by the user!
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) bool interrupted;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* A suspend manager is a listener that also allows other objects
|
||||
* to subscribe to receive events as the manager receives them.
|
||||
*/
|
||||
@protocol OALSuspendManager <OALSuspendListener>
|
||||
|
||||
/** If YES, this object is suspended.
|
||||
*/
|
||||
@property(nonatomic,readonly,assign) bool suspended;
|
||||
|
||||
/** Add a listener that will receive manual suspend and interrupt events.
|
||||
*
|
||||
* @param listener The listener to register with this handler.
|
||||
*/
|
||||
- (void) addSuspendListener:(id<OALSuspendListener>) listener;
|
||||
|
||||
/** Remove a registered listener.
|
||||
*
|
||||
* @param listener The listener to unregister from this handler.
|
||||
*/
|
||||
- (void) removeSuspendListener:(id<OALSuspendListener>) listener;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Provides two controls (interrupted and manuallySuspended) for suspending
|
||||
* a slave object, and also propagates such control messages to interested
|
||||
* listeners.
|
||||
*
|
||||
* "interrupted" is meant to be set by the system when an interrupt occurs. <br>
|
||||
*
|
||||
* "manuallySuspended" is a user-settable control for suspending an object. <br>
|
||||
* "manuallySuspended" also has an extra step in its processing: When set,
|
||||
* the handler makes a note of what its listeners' "manuallySuspended" values are.
|
||||
* When cleared, it will only clear a listener's "manuallySuspended" value if it
|
||||
* was not set at suspend time. This allows for ad-hoc setting/clearing of
|
||||
* "manuallySuspended" in the middle of a handler/listener graph rather than
|
||||
* only from the top level. <br>
|
||||
*
|
||||
* When either control is set, the slave object will be suspended. When both are
|
||||
* cleared, the slave object will be unsuspended. <br>
|
||||
*/
|
||||
@interface OALSuspendHandler: NSObject
|
||||
{
|
||||
/** Listeners that will receive manualSuspend and interrupt events. */
|
||||
NSMutableArray* listeners;
|
||||
|
||||
/** Holder for the state of manualSuspend in listeners when this object is
|
||||
* manually suspended.
|
||||
*/
|
||||
NSMutableArray* manualSuspendStates;
|
||||
|
||||
/** Selector to be invoked on suspend or unsuspend.
|
||||
* Takes the signature: setSelected:(bool) value
|
||||
*/
|
||||
SEL suspendStatusChangeSelector;
|
||||
|
||||
/** Holds the current "manually suspended" state. */
|
||||
bool manualSuspendLock;
|
||||
|
||||
/** Holds the current "interrupted" state. */
|
||||
bool interruptLock;
|
||||
}
|
||||
|
||||
/** Create a new handler with the specified slave target and selector.
|
||||
*
|
||||
* The selector provided must take a single boolean value like so: <br>
|
||||
* - (void) setSuspended:(bool) value <br>
|
||||
*
|
||||
* @param target The slave object that will receive suspend/unsuspend events.
|
||||
* @param selector The selector for a "set suspended" method, taking a single
|
||||
* boolean parameter.
|
||||
*/
|
||||
+ (OALSuspendHandler*) handlerWithTarget:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Initialize a handler with the specified slave target and selector.
|
||||
*
|
||||
* The selector provided must take a single boolean value like so: <br>
|
||||
* - (void) setSuspended:(bool) value <br>
|
||||
*
|
||||
* @param target The slave object that will receive suspend/unsuspend events.
|
||||
* @param selector The selector for a "set suspended" method, taking a single
|
||||
* boolean parameter.
|
||||
*/
|
||||
- (id) initWithTarget:(id) target selector:(SEL) selector;
|
||||
|
||||
|
||||
/** If YES, the manual suspend control is set. */
|
||||
@property(nonatomic,readwrite,assign) bool manuallySuspended;
|
||||
|
||||
/** If YES, the interrupt control is set. */
|
||||
@property(nonatomic,readwrite,assign) bool interrupted;
|
||||
|
||||
/** If YES, the slave object is suspended. */
|
||||
@property(nonatomic,readonly,assign) bool suspended;
|
||||
|
||||
/** Add a listener that will receive manual suspend and interrupt events.
|
||||
*
|
||||
* @param listener The listener to register with this handler.
|
||||
*/
|
||||
- (void) addSuspendListener:(id<OALSuspendListener>) listener;
|
||||
|
||||
/** Remove a registered listener.
|
||||
*
|
||||
* @param listener The listener to unregister from this handler.
|
||||
*/
|
||||
- (void) removeSuspendListener:(id<OALSuspendListener>) listener;
|
||||
|
||||
@end
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// OALTools.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-12-19.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
/**
|
||||
* Miscellaneous tools used by ObjectAL.
|
||||
*/
|
||||
@interface OALTools : NSObject
|
||||
{
|
||||
}
|
||||
|
||||
/** Set the default bundle to use when looking up paths.
|
||||
*
|
||||
* @param bundle The new default bundle.
|
||||
*/
|
||||
+ (void) setDefaultBundle:(NSBundle*) bundle;
|
||||
|
||||
/** The default bundle used when looking up paths.
|
||||
*
|
||||
* return The default bundle.
|
||||
*/
|
||||
+ (NSBundle*) defaultBundle;
|
||||
|
||||
/** Returns the URL corresponding to the specified path.
|
||||
* If the path is not absolute (starts with a "/"), this method will look for
|
||||
* the file in the default bundle.
|
||||
*
|
||||
* @param path The path to convert to a URL.
|
||||
* @return The corresponding URL or nil if a URL could not be formed.
|
||||
*/
|
||||
+ (NSURL*) urlForPath:(NSString*) path;
|
||||
|
||||
/** Returns the URL corresponding to the specified path.
|
||||
* If the path is not absolute (starts with a "/"), this method will look for
|
||||
* the file in the specified bundle.
|
||||
*
|
||||
* @param path The path to convert to a URL.
|
||||
* @param bundle The bundle to look inside for relative paths.
|
||||
* @return The corresponding URL or nil if a URL could not be formed.
|
||||
*/
|
||||
+ (NSURL*) urlForPath:(NSString*) path bundle:(NSBundle*) bundle;
|
||||
|
||||
/** Notify an error if the specified ExtAudio error code indicates an error.
|
||||
* This will log the error and also potentially post an audio error notification
|
||||
* (OALAudioErrorNotification) if it is suspected that this error is a result of
|
||||
* the audio session getting corrupted.
|
||||
*
|
||||
* @param errorCode: The error code returned from an OS call.
|
||||
* @param function: The function name where the error occurred.
|
||||
* @param description: A printf-style description of what happened.
|
||||
*/
|
||||
+ (void) notifyExtAudioError:(OSStatus)errorCode
|
||||
function:(const char*) function
|
||||
description:(NSString*) description, ...;
|
||||
|
||||
/** Notify an error if the specified AudioSession error code indicates an error.
|
||||
* This will log the error and also potentially post an audio error notification
|
||||
* (OALAudioErrorNotification) if it is suspected that this error is a result of
|
||||
* the audio session getting corrupted.
|
||||
*
|
||||
* @param errorCode: The error code returned from an OS call.
|
||||
* @param function: The function name where the error occurred.
|
||||
* @param description: A printf-style description of what happened.
|
||||
*/
|
||||
+ (void) notifyAudioSessionError:(OSStatus)errorCode
|
||||
function:(const char*) function
|
||||
description:(NSString*) description, ...;
|
||||
|
||||
@end
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
//
|
||||
// OALUtilityActions.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-10-10.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import "OALAction.h"
|
||||
|
||||
|
||||
#pragma mark OALTargetedAction
|
||||
|
||||
/**
|
||||
* Ignores whatever target it was invoked upon and applies the specified action
|
||||
* on the target specified at creation time.
|
||||
*/
|
||||
@interface OALTargetedAction: OALAction
|
||||
{
|
||||
/** The action that will be run on the target. */
|
||||
OALAction* action_;
|
||||
}
|
||||
|
||||
/** The target which this action will actually be invoked upon. */
|
||||
@property(nonatomic,readwrite,assign) id forcedTarget;
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param target The target to run the action upon.
|
||||
* @param action The action to run.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithTarget:(id) target action:(OALAction*) action;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param target The target to run the action upon.
|
||||
* @param action The action to run.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithTarget:(id) target action:(OALAction*) action;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#if !OBJECTAL_CFG_USE_COCOS2D_ACTIONS
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALSequentialActions
|
||||
|
||||
/**
|
||||
* A set of actions that get run in sequence.
|
||||
*/
|
||||
@interface OALSequentialActions: OALAction
|
||||
{
|
||||
/** The index of the action currently being processed. */
|
||||
NSUInteger actionIndex_;
|
||||
|
||||
/** The last completeness proportion value acted upon. */
|
||||
float pLastComplete_;
|
||||
|
||||
/** The proportional duration of the current action. */
|
||||
float pCurrentActionDuration_;
|
||||
|
||||
/** The proportional completeness of the current action. */
|
||||
float pCurrentActionComplete_;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The actions which will be run. */
|
||||
@property(nonatomic,readwrite,retain) NSMutableArray* actions;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param actions The comma separated list of actions.
|
||||
* @param NS_REQUIRES_NIL_TERMINATION List of actions must be terminated by a nil.
|
||||
* @return A new set of sequential actions.
|
||||
*/
|
||||
+ (id) actions:(OALAction*) actions, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param actions The actions to run.
|
||||
* @return A new set of sequential actions.
|
||||
*/
|
||||
+ (id) actionsFromArray:(NSArray*) actions;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param actions The actions to run.
|
||||
* @return The initialized set of sequential actions.
|
||||
*/
|
||||
- (id) initWithActions:(NSArray*) actions;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALConcurrentActions
|
||||
|
||||
/**
|
||||
* A set of actions that get run concurrently.
|
||||
*/
|
||||
@interface OALConcurrentActions: OALAction
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** The actions which will be run. */
|
||||
@property(nonatomic,readwrite,retain) NSMutableArray* actions;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param actions The comma separated list of actions.
|
||||
* @param NS_REQUIRES_NIL_TERMINATION List of actions must be terminated by a nil.
|
||||
* @return A new set of concurrent actions.
|
||||
*/
|
||||
+ (id) actions:(OALAction*) actions, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param actions The actions to run.
|
||||
* @return A new set of concurrent actions.
|
||||
*/
|
||||
+ (id) actionsFromArray:(NSArray*) actions;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param actions The actions to run.
|
||||
* @return The initialized set of concurrent actions.
|
||||
*/
|
||||
- (id) initWithActions:(NSArray*) actions;
|
||||
|
||||
@end
|
||||
|
||||
#else /* !OBJECTAL_CFG_USE_COCOS2D_ACTIONS */
|
||||
|
||||
COCOS2D_SUBCLASS_HEADER(OALSequentialActions,CCSequence);
|
||||
|
||||
|
||||
COCOS2D_SUBCLASS_HEADER(OALConcurrentActions,CCSpawn);
|
||||
|
||||
#endif /* !OBJECTAL_CFG_USE_COCOS2D_ACTIONS */
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark OALCallAction
|
||||
|
||||
/**
|
||||
* Calls a selector on a target.
|
||||
* This action will ignore whatever target it is run against,
|
||||
* and will invoke the selector on the target specified at creation
|
||||
* time.
|
||||
*/
|
||||
@interface OALCallAction: OALAction
|
||||
{
|
||||
/** The target to call the selector on. */
|
||||
id callTarget_;
|
||||
|
||||
/** The selector to invoke */
|
||||
SEL selector_;
|
||||
|
||||
/** The number of parameters which will be passed to the selector. */
|
||||
int numObjects_;
|
||||
|
||||
/** The first object to pass to the selector, if any. */
|
||||
id object1_;
|
||||
|
||||
/** The second object to pass to the selector, if any. */
|
||||
id object2_;
|
||||
}
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param callTarget The target to call.
|
||||
* @param selector The selector to invoke.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithCallTarget:(id) callTarget
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param callTarget The target to call.
|
||||
* @param selector The selector to invoke.
|
||||
* @param object The object to pass to the selector.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithCallTarget:(id) callTarget
|
||||
selector:(SEL) selector
|
||||
withObject:(id) object;
|
||||
|
||||
/** Create an action.
|
||||
*
|
||||
* @param callTarget The target to call.
|
||||
* @param selector The selector to invoke.
|
||||
* @param firstObject The first object to pass to the selector.
|
||||
* @param secondObject The second object to pass to the selector.
|
||||
* @return A new action.
|
||||
*/
|
||||
+ (id) actionWithCallTarget:(id) callTarget
|
||||
selector:(SEL) selector
|
||||
withObject:(id) firstObject
|
||||
withObject:(id) secondObject;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param callTarget The target to call.
|
||||
* @param selector The selector to invoke.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithCallTarget:(id) callTarget
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param callTarget The target to call.
|
||||
* @param selector The selector to invoke.
|
||||
* @param object The object to pass to the selector.
|
||||
* @return Initialize an action.
|
||||
*/
|
||||
- (id) initWithCallTarget:(id) callTarget
|
||||
selector:(SEL) selector
|
||||
withObject:(id) object;
|
||||
|
||||
/** Initialize an action.
|
||||
*
|
||||
* @param callTarget The target to call.
|
||||
* @param selector The selector to invoke.
|
||||
* @param firstObject The first object to pass to the selector.
|
||||
* @param secondObject The second object to pass to the selector.
|
||||
* @return The initialized action.
|
||||
*/
|
||||
- (id) initWithCallTarget:(id) callTarget
|
||||
selector:(SEL) selector
|
||||
withObject:(id) firstObject
|
||||
withObject:(id) secondObject;
|
||||
|
||||
@end
|
||||
+724
@@ -0,0 +1,724 @@
|
||||
//
|
||||
// ObjectAL.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 15/12/09.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
// Actions
|
||||
#import "OALAction.h"
|
||||
#import "OALAudioActions.h"
|
||||
#import "OALUtilityActions.h"
|
||||
#import "OALActionManager.h"
|
||||
|
||||
// AudioTrack
|
||||
#import "OALAudioTrack.h"
|
||||
#import "OALAudioTracks.h"
|
||||
#import "OALAudioTrackNotifications.h"
|
||||
|
||||
// OpenAL
|
||||
#import "ALTypes.h"
|
||||
#import "ALBuffer.h"
|
||||
#import "ALCaptureDevice.h"
|
||||
#import "ALContext.h"
|
||||
#import "ALDevice.h"
|
||||
#import "ALListener.h"
|
||||
#import "ALSource.h"
|
||||
//#import "ALWrapper.h"
|
||||
#import "ALChannelSource.h"
|
||||
#import "ALSoundSourcePool.h"
|
||||
#import "OpenALManager.h"
|
||||
#import "OALAudioFile.h"
|
||||
|
||||
// Other
|
||||
//#import "OALNotifications.h"
|
||||
#import "OALAudioSession.h"
|
||||
#import "OALSimpleAudio.h"
|
||||
|
||||
|
||||
|
||||
/** \mainpage ObjectAL for iPhone
|
||||
|
||||
<strong>iOS Audio development, minus the headache.</strong> <br><br>
|
||||
|
||||
Version 2.2 <br> <br>
|
||||
|
||||
Copyright 2009-2013 Karl Stenerud <br><br>
|
||||
|
||||
Released under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License v2.0</a>
|
||||
|
||||
<br> <br>
|
||||
\section contents_sec Contents
|
||||
- \ref intro_sec
|
||||
- \ref objectal_and_openal_sec
|
||||
- \ref add_objectal_sec (also, installing the documentation into XCode)
|
||||
- \ref configuration_sec
|
||||
- \ref audio_formats_sec
|
||||
- \ref choosing_sec
|
||||
- \ref use_iossimpleaudio_sec
|
||||
- \ref use_objectal_sec
|
||||
- \ref other_examples_sec
|
||||
- \ref ios_issues_sec
|
||||
- \ref simulator_issues_sec
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section intro_sec Introduction
|
||||
|
||||
<strong>ObjectAL for iPhone</strong> is designed to be a simpler, more intuitive interface to
|
||||
OpenAL and AVAudioPlayer.
|
||||
There are four main parts to <strong>ObjectAL for iPhone</strong>:<br/><br/>
|
||||
|
||||
\image html ObjectAL-Overview1.png
|
||||
\image latex ObjectAL-Overview1.eps
|
||||
|
||||
- <a class="el" href="index.html#objectal_and_openal_sec">ObjectAL</a>
|
||||
gives you full access to the OpenAL system without the hassle of the C API.
|
||||
All OpenAL operations can be performed using first class objects and properties, without needing
|
||||
to muddle around with arrays of data, maintain IDs, or pass around pointers to basic types.
|
||||
ObjectALManager also provides sound loading routines.
|
||||
|
||||
- OALAudioTrack provides a simpler interface to AVAudioPlayer, allowing you to play, stop,
|
||||
pause, fade, and mute background music tracks.
|
||||
|
||||
- OALAudioSession handles audio session management in iOS devices, and provides an easy
|
||||
way to configure session behavior such as how to handle iPod-style music and the silent
|
||||
switch.
|
||||
|
||||
- OALSimpleAudio layers on top of the other three, providing an even simpler interface for
|
||||
playing background music and sound effects.
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section objectal_and_openal_sec ObjectAL and OpenAL
|
||||
|
||||
<strong>ObjectAL</strong> follows the same basic principles as the
|
||||
<a href="http://connect.creativelabs.com/openal">OpenAL API by Creative Labs</a>.
|
||||
|
||||
\image html ObjectAL-Overview2.png
|
||||
\image latex ObjectAL-Overview2.eps
|
||||
|
||||
- OpenALManager provides some overall controls that affect everything, manages the current
|
||||
context, and provides audio loading routines.
|
||||
|
||||
- ALDevice represents a physical audio device. <br>
|
||||
Each device can have one or more contexts (ALContext) created on it, and can have multiple
|
||||
buffers (ALBuffer) associated with it.
|
||||
|
||||
- ALContext controls the overall sound environment, such as distance model, doppler effect, and
|
||||
speed of sound. <br>
|
||||
Each context has one listener (ALListener), and can have multiple sources (ALSource) opened on
|
||||
it (up to a maximum of 32 overall on iPhone).
|
||||
|
||||
- ALListener represents the listener of sounds originating on its context (one listener per
|
||||
context). It has position, orientation, and velocity.
|
||||
|
||||
- ALSource is a sound emitting source that plays sound data from an ALBuffer. It has position,
|
||||
direction, velocity, as well as other properties which determine how the sound is emitted.
|
||||
|
||||
- ALChannelSource allows you to reserve a certain number of sources for special purposes.
|
||||
|
||||
- ALBuffer is simply a container for sound data. Only linear PCM is supported directly, but
|
||||
OpenALManager load methods, and OALSimpleAudio effect preload and play methods, will
|
||||
automatically convert any formats that don't require hardware decoding (though conversion
|
||||
results in a longer loading time).
|
||||
|
||||
<strong>Note:</strong> While OpenAL allows for multiple devices and contexts, in practice
|
||||
you'll only use one device and one context when using OpenAL under iOS.
|
||||
|
||||
Further information regarding the more advanced features of OpenAL (such as distance models)
|
||||
are available via the
|
||||
<a href="http://connect.creativelabs.com/openal/Documentation/Forms/AllItems.aspx">
|
||||
OpenAL Documentation at Creative Labs</a>. <br>
|
||||
In particular, read up on the various property values for sources and listeners (such as Doppler
|
||||
Shift) in the
|
||||
<a href="http://connect.creativelabs.com/openal/Documentation/OpenAL_Programmers_Guide.pdf">OpenAL Programmer's Guide</a>,
|
||||
and distance models in section 3 of the
|
||||
<a href="http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.pdf">OpenAL Specification</a>.
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section add_objectal_sec Adding ObjectAL to your project
|
||||
|
||||
To add ObjectAL to your project, do the following:
|
||||
|
||||
<ol>
|
||||
<li>Copy ObjectAL/ObjectAL from this project into your project.
|
||||
You can simply drag it into the "Groups & Files" section in xcode if you
|
||||
like (be sure to select "Copy items into destination group's folder"). <br/>
|
||||
Alternatively, you can build ObjectAL as a static library (as it's configured to do in the
|
||||
ObjectAL demo project).<br/><br/>
|
||||
</li>
|
||||
|
||||
<li>Add the following frameworks to your project:
|
||||
<ul>
|
||||
<li>OpenAL.framework</li>
|
||||
<li>AudioToolbox.framework</li>
|
||||
<li>AVFoundation.framework</li>
|
||||
</ul><br/>
|
||||
</li>
|
||||
|
||||
<li>Start using ObjectAL!<br/><br/></li>
|
||||
</ol>
|
||||
<br/>
|
||||
<strong>Note:</strong> The demos in this project use
|
||||
<a href="http://www.cocos2d-iphone.org">Cocos2d</a>, a very nice 2d game engine. However,
|
||||
ObjectAL doesn't require it. You can just as easily use ObjectAL in your Cocoa app or anything
|
||||
you wish.
|
||||
<br/> <br/>
|
||||
<strong>Note #2:</strong> You do NOT have to provide a link to the Apache license from within your
|
||||
application. Simply including a copy of the license in your project is sufficient.
|
||||
|
||||
<br>
|
||||
\subsection install_dox Installing the ObjectAL Documentation into XCode
|
||||
|
||||
By installing the ObjectAL documentation into XCode's Developer Documentation system, you gain
|
||||
the ability to look up ObjectAL classes and methods just like you'd look up Apple classes and
|
||||
methods. You can install the ObjectAL documentation into XCode's Developer Documentation
|
||||
system by doing the following:
|
||||
-# Install <a href="http://www.doxygen.org">Doxygen</a>. You can either use the OSX installer or
|
||||
<a href="http://mxcl.github.io/homebrew/">Homebrew</a>.
|
||||
-# Build the "Documentation" target in this project.
|
||||
-# Open the developer documentation and type "ObjectAL" into the search box.
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section configuration_sec Compile-Time Configuration
|
||||
|
||||
<strong>ObjectALConfig.h</strong> contains configuration defines that will affect at a high level
|
||||
how ObjectAL behaves. Look inside <strong>ObjectALConfig.h</strong> to see what can be
|
||||
configured, and what each configuration value does. <br>
|
||||
The recommended values are fine for most users, but Cocos2D users may want to set
|
||||
OBJECTAL_CFG_USE_COCOS2D_ACTIONS so that the audio actions (such as fade) use the Cocos2D action manager.
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section audio_formats_sec Audio Formats
|
||||
|
||||
The audio formats officially supported by Apple are
|
||||
<a href="http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html">
|
||||
defined here</a>.
|
||||
<br><br>
|
||||
|
||||
\subsection audio_formats_avaudioplayer OALAudioTrack Supported Formats
|
||||
|
||||
OALAudioTrack supports all hardware and software decoded formats.
|
||||
<br><br>
|
||||
|
||||
\subsection audio_formats_openal OpenAL Supported Formats
|
||||
|
||||
OpenAL officially supports 8 or 16 bit PCM data only. However, Apple's implementation
|
||||
only seems to work with 16 bit data. <br>
|
||||
|
||||
The effects preloading/playing methods in OALSimpleAudio and the buffer loading methods
|
||||
in OpenALManager can load any audio file that can be software decoded. However, there
|
||||
is a cost incurred at load time converting to a native OpenAL format. To avoid this,
|
||||
convert all of your samples to a CAFF container with 16-bit little endian integer PCM
|
||||
format and the same sample rate as "mixerOutputFrequency" in OpenALManager
|
||||
(by default, 44100Hz). Note, however, that uncompressed files can get quite large.<br>
|
||||
|
||||
Convert to iOS native uncompressed format using Apple's "afconvert" command line tool:
|
||||
|
||||
\code afconvert -f caff -d LEI16@44100 sourcefile.wav destfile.caf \endcode
|
||||
|
||||
Alternatively, if sound file load time is not an issue for you, you can lower your app
|
||||
footprint size (for over-the-air app download) by using a compressed format. <br>
|
||||
|
||||
Convert to AAC compressed format with CAFF container using Apple's "afconvert" command
|
||||
line tool:
|
||||
|
||||
\code afconvert -f caff -d aac sourcefile.wav destfile.caf \endcode
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section choosing_sec Choosing Playback Types
|
||||
|
||||
<strong>OpenAL</strong> (ALSource, or effects in OALSimpleAudio) and
|
||||
<strong>AVAudioPlayer</strong> (OALAudioTrack, or background audio in OALSimpleAudio)
|
||||
are playback technologies built for different purposes. OpenAL is designed for game-style
|
||||
short sound effects that have no playback delay. AVAudioPlayer is designed for music
|
||||
playback. You can of course mix and match as you please.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><strong>OpenAL</strong></td>
|
||||
<td><strong>AVAudioPlayer</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Playback Delay</strong></td>
|
||||
<td>None</td>
|
||||
<td>Small delay if not preloaded</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Format on Disk</strong></td>
|
||||
<td><a href="http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html">
|
||||
Any software decodable format</a></td>
|
||||
<td><a href="http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html">
|
||||
Any software decodable format, or any hardware format if using hardware</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Decoding</strong></td>
|
||||
<td>During load</td>
|
||||
<td>During playback</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Memory Use</strong></td>
|
||||
<td>Entire file loaded and decompressed into memory</td>
|
||||
<td>File streamed realtime (very low memory use)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Max Simult. Sources</strong></td>
|
||||
<td>32</td>
|
||||
<td>As many as the CPU can handle</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Playback Performance</strong></td>
|
||||
<td>Good</td>
|
||||
<td>Excellent with 1 track (if using hardware). Good with 2 tracks. Not so good with more
|
||||
(each non-hardware track taxes the CPU significantly, especially if the files are compressed).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Looped Playback</strong></td>
|
||||
<td>Yes (on or off)</td>
|
||||
<td>Yes (specify number of loops or -1 = forever)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Panning</strong></td>
|
||||
<td>Yes (mono files only)</td>
|
||||
<td>Yes (iOS 4.0+ only)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Positional Audio</strong></td>
|
||||
<td>Yes (mono files only)</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Modify Pitch</strong></td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Audio Power Metering</strong></td>
|
||||
<td>No</td>
|
||||
<td>Yes</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section use_iossimpleaudio_sec Using OALSimpleAudio
|
||||
|
||||
By far, the easiest component to use is OALSimpleAudio. You sacrifice some power for
|
||||
ease-of-use, but for many projects it is more than sufficient. You can also use your own instances
|
||||
of OALAudioTrack, ALSource, ALBuffer and such alongside of OALSimpleAudio if you want (just be sure
|
||||
to set OALSimpleAudio's reservedSources to less than 32 if you want to make your own instances of
|
||||
ALSource).
|
||||
|
||||
Here is a code example using purely OALSimpleAudio:
|
||||
|
||||
\code
|
||||
// OALSimpleAudioSample.h
|
||||
|
||||
@interface OALSimpleAudioSample : NSObject
|
||||
{
|
||||
// No objects to keep track of...
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// OALSimpleAudioSample.m
|
||||
|
||||
#import "OALSimpleAudioSample.h"
|
||||
#import "ObjectAL.h"
|
||||
|
||||
|
||||
#define SHOOT_SOUND @"shoot.caf"
|
||||
#define EXPLODE_SOUND @"explode.caf"
|
||||
|
||||
#define INGAME_MUSIC_FILE @"bg_music.mp3"
|
||||
#define GAMEOVER_MUSIC_FILE @"gameover_music.mp3"
|
||||
|
||||
|
||||
@implementation OALSimpleAudioSample
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if(nil != (self = [super init]))
|
||||
{
|
||||
// We don't want ipod music to keep playing since
|
||||
// we have our own bg music.
|
||||
[OALSimpleAudio sharedInstance].allowIpod = NO;
|
||||
|
||||
// Mute all audio if the silent switch is turned on.
|
||||
[OALSimpleAudio sharedInstance].honorSilentSwitch = YES;
|
||||
|
||||
// This loads the sound effects into memory so that
|
||||
// there's no delay when we tell it to play them.
|
||||
[[OALSimpleAudio sharedInstance] preloadEffect:SHOOT_SOUND];
|
||||
[[OALSimpleAudio sharedInstance] preloadEffect:EXPLODE_SOUND];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) onGameStart
|
||||
{
|
||||
// Play the BG music and loop it.
|
||||
[[OALSimpleAudio sharedInstance] playBg:INGAME_MUSIC_FILE loop:YES];
|
||||
}
|
||||
|
||||
- (void) onGamePause
|
||||
{
|
||||
[OALSimpleAudio sharedInstance].paused = YES;
|
||||
}
|
||||
|
||||
- (void) onGameResume
|
||||
{
|
||||
[OALSimpleAudio sharedInstance].paused = NO;
|
||||
}
|
||||
|
||||
- (void) onGameOver
|
||||
{
|
||||
// Could use stopEverything here if you want
|
||||
[[OALSimpleAudio sharedInstance] stopAllEffects];
|
||||
|
||||
// We only play the game over music through once.
|
||||
[[OALSimpleAudio sharedInstance] playBg:GAMEOVER_MUSIC_FILE];
|
||||
}
|
||||
|
||||
- (void) onShipShotABullet
|
||||
{
|
||||
[[OALSimpleAudio sharedInstance] playEffect:SHOOT_SOUND];
|
||||
}
|
||||
|
||||
- (void) onShipGotHit
|
||||
{
|
||||
[[OALSimpleAudio sharedInstance] playEffect:EXPLODE_SOUND];
|
||||
}
|
||||
|
||||
- (void) onQuitToMainMenu
|
||||
{
|
||||
// Stop all music and sound effects.
|
||||
[[OALSimpleAudio sharedInstance] stopEverything];
|
||||
|
||||
// Unload all sound effects and bg music so that it doesn't fill
|
||||
// memory unnecessarily.
|
||||
[[OALSimpleAudio sharedInstance] unloadAllEffects];
|
||||
}
|
||||
|
||||
@end
|
||||
\endcode
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section use_objectal_sec Using the OpenAL Objects and OALAudioTrack
|
||||
|
||||
The OpenAL objects and OALAudioTrack offer you much more power at the cost
|
||||
of complexity.
|
||||
Here's the same thing as above, done using OpenAL components and OALAudioTrack:
|
||||
|
||||
\code
|
||||
// OpenALAudioTrackSample.h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ObjectAL.h"
|
||||
|
||||
|
||||
@interface OpenALAudioTrackSample : NSObject
|
||||
{
|
||||
// Sound Effects
|
||||
ALDevice* device;
|
||||
ALContext* context;
|
||||
ALChannelSource* channel;
|
||||
ALBuffer* shootBuffer;
|
||||
ALBuffer* explosionBuffer;
|
||||
|
||||
// Background Music
|
||||
OALAudioTrack* musicTrack;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// OpenALAudioTrackSample.m
|
||||
|
||||
#import "OpenALAudioTrackSample.h"
|
||||
|
||||
|
||||
#define SHOOT_SOUND @"shoot.caf"
|
||||
#define EXPLODE_SOUND @"explode.caf"
|
||||
|
||||
#define INGAME_MUSIC_FILE @"bg_music.mp3"
|
||||
#define GAMEOVER_MUSIC_FILE @"gameover_music.mp3"
|
||||
|
||||
|
||||
@implementation OpenALAudioTrackSample
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if(nil != (self = [super init]))
|
||||
{
|
||||
// Create the device and context.
|
||||
// Note that it's easier to just let OALSimpleAudio handle
|
||||
// these rather than make and manage them yourself.
|
||||
device = [[ALDevice deviceWithDeviceSpecifier:nil] retain];
|
||||
context = [[ALContext contextOnDevice:device attributes:nil] retain];
|
||||
[OpenALManager sharedInstance].currentContext = context;
|
||||
|
||||
// Deal with interruptions for me!
|
||||
[OALAudioSession sharedInstance].handleInterruptions = YES;
|
||||
|
||||
// We don't want ipod music to keep playing since
|
||||
// we have our own bg music.
|
||||
[OALAudioSession sharedInstance].allowIpod = NO;
|
||||
|
||||
// Mute all audio if the silent switch is turned on.
|
||||
[OALAudioSession sharedInstance].honorSilentSwitch = YES;
|
||||
|
||||
// Take all 32 sources for this channel.
|
||||
// (we probably won't use that many but what the heck!)
|
||||
channel = [[ALChannelSource channelWithSources:32] retain];
|
||||
|
||||
// Preload the buffers so we don't have to load and play them later.
|
||||
shootBuffer = [[[OpenALManager sharedInstance]
|
||||
bufferFromFile:SHOOT_SOUND] retain];
|
||||
explosionBuffer = [[[OpenALManager sharedInstance]
|
||||
bufferFromFile:EXPLODE_SOUND] retain];
|
||||
|
||||
// Background music track.
|
||||
musicTrack = [[OALAudioTrack track] retain];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[musicTrack release];
|
||||
|
||||
[channel release];
|
||||
[shootBuffer release];
|
||||
[explosionBuffer release];
|
||||
|
||||
// Note: You'll likely only have one device and context open throughout
|
||||
// your program, so in a real program you'd be better off making a
|
||||
// singleton object that manages the device and context, rather than
|
||||
// allocating/deallocating it here.
|
||||
// Most of the demos just let OALSimpleAudio manage the device and context
|
||||
// for them.
|
||||
[context release];
|
||||
[device release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) onGameStart
|
||||
{
|
||||
// Play the BG music and loop it forever.
|
||||
[musicTrack playFile:INGAME_MUSIC_FILE loops:-1];
|
||||
}
|
||||
|
||||
- (void) onGamePause
|
||||
{
|
||||
musicTrack.paused = YES;
|
||||
channel.paused = YES;
|
||||
}
|
||||
|
||||
- (void) onGameResume
|
||||
{
|
||||
channel.paused = NO;
|
||||
musicTrack.paused = NO;
|
||||
}
|
||||
|
||||
- (void) onGameOver
|
||||
{
|
||||
[channel stop];
|
||||
[musicTrack stop];
|
||||
|
||||
// We only play the game over music through once.
|
||||
[musicTrack playFile:GAMEOVER_MUSIC_FILE];
|
||||
}
|
||||
|
||||
- (void) onShipShotABullet
|
||||
{
|
||||
[channel play:shootBuffer];
|
||||
}
|
||||
|
||||
- (void) onShipGotHit
|
||||
{
|
||||
[channel play:explosionBuffer];
|
||||
}
|
||||
|
||||
- (void) onQuitToMainMenu
|
||||
{
|
||||
// Stop all music and sound effects.
|
||||
[channel stop];
|
||||
[musicTrack stop];
|
||||
}
|
||||
|
||||
@end
|
||||
\endcode
|
||||
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section other_examples_sec Other Examples
|
||||
|
||||
The demo scenes in this distribution have been crafted to demonstrate common uses of this library.
|
||||
Try them out and go through the code to see how it's done. I've done my best to keep the code
|
||||
readable. Really!
|
||||
|
||||
You can try out the demos by building and running the OALDemo target for iOS or OSX.
|
||||
|
||||
The current demos are:
|
||||
- <strong>SingleSourceDemo</strong>: Demonstrates using a location based source and a listener.
|
||||
- <strong>TwoSourceDemo</strong>: Demonstrates using two location based sources and a listener.
|
||||
- <strong>VolumePitchPanDemo</strong>: Demonstrates using gain, pitch, and pan controls.
|
||||
- <strong>CrossFadeDemo</strong>: Demonstrates crossfading between two sources.
|
||||
- <strong>ChannelsDemo</strong>: Demonstrates using audio channels.
|
||||
- <strong>FadeDemo</strong>: Demonstrates realtime fading with OALAudioTrack and ALSource.
|
||||
- <strong>AudioTrackDemo</strong>: Demonstrates using multiple OALAudioTrack objects.
|
||||
- <strong>PlanetKillerDemo</strong>: Demonstrates using OALSimpleAudio in a game setting.
|
||||
- <strong>IntroAndMainTrackDemo</strong>: Demonstrates a short intro track followed by a main loop track.
|
||||
- <strong>SourceNotificationsDemo</strong>: Demonstrates using OpenAL playback notifications.
|
||||
- <strong>HardwareDemo</strong>: Demonstrates hardware monitoring features.
|
||||
- <strong>AudioSessionDemo</strong>: Allows you to play with various audio session settings.
|
||||
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section ios_issues_sec iOS Issues that can impede playback
|
||||
|
||||
Certain versions of iOS have bugs or quirks, requiring workarounds. ObjectAL tries to handle
|
||||
most of these automatically, but there are cases that require specific handling by the developer.
|
||||
These are:
|
||||
|
||||
<br>
|
||||
\subsection mpmovieplayercontroller_ios3 MPMoviePlayerController on iOS 3.x
|
||||
|
||||
In iOS 3.x, MPMoviePlayerController doesn't play nice, and takes over the audio session when
|
||||
you play a video. In order to mitigate this, you must manually suspend OpenAL, play the video,
|
||||
and then manually unsuspend once video playback finishes:
|
||||
|
||||
\code
|
||||
- (void) playVideo
|
||||
{
|
||||
if([myMoviePlayer respondsToSelector:@selector(view)])
|
||||
{
|
||||
[myMoviePlayer setFullscreen:YES animated:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
// No "view" method means we are < 4.0
|
||||
// Manually suspend so iOS 3.x doesn't clobber our session!
|
||||
[OpenALManager sharedInstance].manuallySuspended = YES;
|
||||
}
|
||||
|
||||
[myMoviePlayer play];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(movieFinishedCallback:)
|
||||
name:MPMoviePlayerPlaybackDidFinishNotification
|
||||
object:myMoviePlayer];
|
||||
}
|
||||
|
||||
-(void)movieFinishedCallback:(NSNotification *)notification
|
||||
{
|
||||
if([myMoviePlayer respondsToSelector:@selector(view)])
|
||||
{
|
||||
if (myMoviePlayer.fullscreen)
|
||||
{
|
||||
[myMoviePlayer setFullscreen:NO animated:YES];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No "view" method means we are < 4.0
|
||||
// Manually unsuspend
|
||||
[OpenALManager sharedInstance].manuallySuspended = NO;
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
<br>
|
||||
\subsection mpmusicplayercontroller_ios4_0 MPMusicPlayerController on iOS 4.0
|
||||
|
||||
On iOS 4.0, MPMusicPlayerController sends an interrupt when it begins playback, but doesn't send
|
||||
a corresponding "end interrupt" when it ends. To work around this, force an "end interrupt"
|
||||
after starting playback:
|
||||
\code
|
||||
[[OALAudioSession sharedInstance] forceEndInterruption];
|
||||
\endcode
|
||||
|
||||
|
||||
|
||||
<br> <br>
|
||||
\section simulator_issues_sec Simulator Issues
|
||||
|
||||
As you've likely heard time and time again, the simulator is no substitute for the real thing.
|
||||
The simulator is buggy. It can run faster or slower than a real device. It fails system calls
|
||||
that a real device doesn't. It shows graphics glitches that a real device doesn't. Sounds stop
|
||||
working, clicks and static, dogs and cats living together, etc, etc.
|
||||
When things look wrong, try it on a real device before bugging people.
|
||||
|
||||
|
||||
<br>
|
||||
\subsection simulator_limitations Simulator Limitations
|
||||
|
||||
The simulator does not support setting audio modes, so setting allowIpod or honorSilentSwitch
|
||||
in OALAudioSession will have no effect in the simulator.
|
||||
|
||||
|
||||
<br>
|
||||
\subsection simulator_errors Error Codes on the Simulator
|
||||
|
||||
From time to time, the simulator can get confused, and start spitting out spurious errors.
|
||||
When this happens, check on a real device to make sure it's not just a simulator issue.
|
||||
Usually quitting and restarting the simulator will fix it, but sometimes you may have to reboot
|
||||
your machine as well.
|
||||
|
||||
|
||||
<br>
|
||||
\subsection simulator_playback Playback Issues
|
||||
|
||||
The simulator is notoriously finicky when it comes to audio playback. Any number of programs
|
||||
you've installed on your mac can cause the simulator to stop playing bg music, or effects, or
|
||||
both!
|
||||
|
||||
Some things to check when sound stops working:
|
||||
- Try resetting and restarting the simulator.
|
||||
- Try restarting XCode, cleaning, and recompiling your project.
|
||||
- Try rebooting your computer.
|
||||
- Open "Audio MIDI Setup" (type "midi" into spotlight to find it) and make sure "Built-in Output"
|
||||
is set to 44100.0 Hz.
|
||||
- Go to System Preferences -> Sound -> Output, and ensure that "Play sound effects through" is set
|
||||
to "Internal Speakers"
|
||||
- Go to System Preferences -> Sound -> Input, and ensure that it is using internal sound devices.
|
||||
- Go to System Preferences -> Sound -> Sound Effects, and ensure "Play user interface sound
|
||||
effects" is checked.
|
||||
- Some codecs may cause problems with sound playback. Try removing them.
|
||||
- Programs that redirect audio can wreak havoc on the simulator. Try removing them.
|
||||
|
||||
*/
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// ObjectALConfig.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-08-02.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
|
||||
/* Compile-time configuration for ObjectAL.
|
||||
*
|
||||
* The defines in this file provide broad guidelines for how ObjectAL will behave
|
||||
* in your application. They can either be set here, or you can set them as user
|
||||
* defines in your build configuration.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** Resets the audio session when an error occurs that may have been caused by
|
||||
* a messed up session.
|
||||
*
|
||||
* In iOS 4.2, there are situations where an underlying sound system such as
|
||||
* mediaserverd will crash, putting the audio session in an uncertain state.
|
||||
* If this switch is enabled, OALAudioSession will reset itself when certain
|
||||
* kinds of audio errors occur.
|
||||
*
|
||||
* Recommended setting: 1 for release, possibly 0 during development.
|
||||
*/
|
||||
#ifndef OBJECTAL_CFG_RESET_AUDIO_SESSION_ON_ERROR
|
||||
#define OBJECTAL_CFG_RESET_AUDIO_SESSION_ON_ERROR 1
|
||||
#endif
|
||||
|
||||
|
||||
/** Enables support for methods that take blocks as arguments.
|
||||
* Blocks are only supported in iOS 4.0+, so enabling this will make your project
|
||||
* incompatible with earlier operating systems (a 3.x system will crash the moment it
|
||||
* encounters a class that supports blocks).
|
||||
*
|
||||
* Recommended setting: 0 if you want to support iOS prior to 4.0, 1 if you don't care.
|
||||
*/
|
||||
#ifndef OBJECTAL_CFG_USE_BLOCKS
|
||||
#define OBJECTAL_CFG_USE_BLOCKS 1
|
||||
#endif
|
||||
|
||||
|
||||
/** Determines how ObjectAL's actions are implemented.
|
||||
* If this is set to 1, ObjectAL's actions will inherit from cocos2d CCIntervalAction,
|
||||
* and will use cocos2d's CCActionManager rather than OALActionManager. <br>
|
||||
*
|
||||
* Recommended setting: 1 if you use Cocos2d exclusively, 0 if you use UIKit.
|
||||
*/
|
||||
#ifndef OBJECTAL_CFG_USE_COCOS2D_ACTIONS
|
||||
#define OBJECTAL_CFG_USE_COCOS2D_ACTIONS 0
|
||||
#endif
|
||||
|
||||
|
||||
/** Sets the interval in seconds between steps when performing actions with OALAction
|
||||
* subclasses. Lower values offer better accuracy, but take up more processing time
|
||||
* because they fire more often. <br>
|
||||
*
|
||||
* Generally, you want at least 4-5 steps in an audio operation, so for durations
|
||||
* of 0.2 and above, an interval of 1/30 is fine. For anything lower, you'll want a
|
||||
* smaller interval. <br>
|
||||
*
|
||||
* Note: The NSTimer documentation states that a timer will typically have a resolution
|
||||
* of around 0.05 to 0.1, though in practice smaller values seem to work fine. <br>
|
||||
*
|
||||
* Note: This setting only has effect if OBJECTAL_CFG_USE_COCOS2D_ACTIONS is 0. <br>
|
||||
*
|
||||
* Recommended setting: 1.0/30.0
|
||||
*/
|
||||
#ifndef kActionStepInterval
|
||||
#define kActionStepInterval (1.0/30.0)
|
||||
#endif
|
||||
|
||||
|
||||
/** When this option is enabled, all critical ObjectAL operations will be wrapped in
|
||||
* synchronized blocks. <br>
|
||||
*
|
||||
* Turning this off can improve performance a bit if your application makes heavy
|
||||
* use of audio calls, but you'll be on your own for ensuring two threads don't
|
||||
* access the same part of the audio library at the same time. <br>
|
||||
*
|
||||
* Recommended setting: 1
|
||||
*/
|
||||
#ifndef OBJECTAL_CFG_SYNCHRONIZED_OPERATIONS
|
||||
#define OBJECTAL_CFG_SYNCHRONIZED_OPERATIONS 1
|
||||
#endif
|
||||
|
||||
|
||||
/** When this option is other than LEVEL_NONE, ObjectAL will output log entries that correspond
|
||||
* to the LEVEL:
|
||||
*
|
||||
* LEVEL_NONE: No output
|
||||
* LEVEL_ERROR: Errors only
|
||||
* LEVEL_WARNING: Errors, Warnings
|
||||
* LEVEL_INFO: Errors, Warnings, Info
|
||||
* LEVEL_DEBUG: Errors, Warnings, Info, Debug
|
||||
*
|
||||
* Setting this to LEVEL_NONE will cause most internal functions to not bother checking error codes.
|
||||
*
|
||||
* Recommended setting: LEVEL_WARNING
|
||||
*/
|
||||
#ifndef OBJECTAL_CFG_LOG_LEVEL
|
||||
#define OBJECTAL_CFG_LOG_LEVEL LEVEL_WARNING
|
||||
#endif
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
//
|
||||
// OpenALManager.h
|
||||
// ObjectAL
|
||||
//
|
||||
// Created by Karl Stenerud on 10-09-25.
|
||||
//
|
||||
// Copyright (c) 2009 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Attribution is not required, but appreciated :)
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SynthesizeSingleton.h"
|
||||
#import "ALContext.h"
|
||||
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
|
||||
#import <OpenAL/oalMacOSX_OALExtensions.h>
|
||||
#else
|
||||
#import <OpenAL/MacOSX_OALExtensions.h>
|
||||
#endif
|
||||
|
||||
|
||||
#pragma mark OpenALManager
|
||||
|
||||
/**
|
||||
* Manager class for OpenAL objects (ObjectAL).
|
||||
* Keeps track of devices that have been opened, and allows high level OpenAL management. <br>
|
||||
* Provides methods for loading ALBuffer objects from audio files. <br>
|
||||
* The OpenAL 1.1 specification is available at
|
||||
* http://connect.creativelabs.com/openal/Documentation <br>
|
||||
* Be sure to read through it (especially the part about distance models) as ObjectAL follows the
|
||||
* OpenAL object model. <br>
|
||||
*
|
||||
* Alternatively, you may opt to use OALSimpleAudio for a simpler interface.
|
||||
*/
|
||||
@interface OpenALManager : NSObject <OALSuspendManager>
|
||||
{
|
||||
/** All opened devices */
|
||||
NSMutableArray* devices;
|
||||
|
||||
/** Handles suspending and interrupting for this object. */
|
||||
OALSuspendHandler* suspendHandler;
|
||||
|
||||
/** Operation queue for asynchronous loading. */
|
||||
NSOperationQueue* operationQueue;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Properties
|
||||
|
||||
/** List of available playback devices (NSString*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* availableDevices;
|
||||
|
||||
/** List of available capture devices (NSString*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* availableCaptureDevices;
|
||||
|
||||
/** The current context (some context operations require the context to be the "current" one).
|
||||
* WEAK reference.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) ALContext* currentContext;
|
||||
|
||||
/** Name of the default capture device. */
|
||||
@property(nonatomic,readonly,retain) NSString* defaultCaptureDeviceSpecifier;
|
||||
|
||||
/** Name of the default playback device. */
|
||||
@property(nonatomic,readonly,retain) NSString* defaultDeviceSpecifier;
|
||||
|
||||
/** List of all open devices (ALDevice*). */
|
||||
@property(nonatomic,readonly,retain) NSArray* devices;
|
||||
|
||||
/** The frequency of the output mixer. */
|
||||
@property(nonatomic,readwrite,assign) ALdouble mixerOutputFrequency;
|
||||
|
||||
/** The rendering quality.
|
||||
*
|
||||
* Can be one of:
|
||||
* - ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_HIGH
|
||||
* - ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_LOW
|
||||
* - ALC_IPHONE_SPATIAL_RENDERING_QUALITY_HEADPHONES (iOS only)
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) ALint renderingQuality;
|
||||
|
||||
|
||||
#pragma mark Object Management
|
||||
|
||||
/** Singleton implementation providing "sharedInstance" and "purgeSharedInstance" methods.
|
||||
*
|
||||
* <b>- (OpenALManager*) sharedInstance</b>: Get the shared singleton instance. <br>
|
||||
* <b>- (void) purgeSharedInstance</b>: Purge (deallocate) the shared instance.
|
||||
*/
|
||||
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(OpenALManager);
|
||||
|
||||
|
||||
#pragma mark Buffers
|
||||
|
||||
/** Load an OpenAL buffer with the contents of an audio file.
|
||||
* The buffer's name will be the fully qualified URL of the path.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param filePath The path of the file containing the audio data.
|
||||
* @return An ALBuffer containing the audio data.
|
||||
*/
|
||||
- (ALBuffer*) bufferFromFile:(NSString*) filePath;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of an audio file.
|
||||
* The buffer's name will be the fully qualified URL of the path.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param filePath The path of the file containing the audio data.
|
||||
* @param reduceToMono If true, reduce the sample to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
* @return An ALBuffer containing the audio data.
|
||||
*/
|
||||
- (ALBuffer*) bufferFromFile:(NSString*) filePath reduceToMono:(bool) reduceToMono;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of an audio file.
|
||||
* The buffer's name will be the fully qualified URL.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param url The URL of the file containing the audio data.
|
||||
* @return An ALBuffer containing the audio data.
|
||||
*/
|
||||
- (ALBuffer*) bufferFromUrl:(NSURL*) url;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of an audio file.
|
||||
* The buffer's name will be the fully qualified URL.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param url The URL of the file containing the audio data.
|
||||
* @param reduceToMono If true, reduce the sample to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
* @return An ALBuffer containing the audio data.
|
||||
*/
|
||||
- (ALBuffer*) bufferFromUrl:(NSURL*) url reduceToMono:(bool) reduceToMono;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of an audio file asynchronously.
|
||||
* This method will schedule a request to have the buffer created and filled, and then call the
|
||||
* specified selector with the newly created buffer. <br>
|
||||
* The buffer's name will be the fully qualified URL of the path. <br>
|
||||
* Returns the fully qualified URL of the path, which you can match up to the buffer name in your
|
||||
* callback method.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param filePath The path of the file containing the audio data.
|
||||
* @param target The target to call when the buffer is loaded.
|
||||
* @param selector The selector to invoke when the buffer is loaded.
|
||||
* @return The fully qualified URL of the path.
|
||||
*/
|
||||
- (NSString*) bufferAsyncFromFile:(NSString*) filePath target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of an audio file asynchronously.
|
||||
* This method will schedule a request to have the buffer created and filled, and then call the
|
||||
* specified selector with the newly created buffer. <br>
|
||||
* The buffer's name will be the fully qualified URL of the path. <br>
|
||||
* Returns the fully qualified URL of the path, which you can match up to the buffer name in your
|
||||
* callback method.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param filePath The path of the file containing the audio data.
|
||||
* @param reduceToMono If true, reduce the sample to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
* @param target The target to call when the buffer is loaded.
|
||||
* @param selector The selector to invoke when the buffer is loaded.
|
||||
* @return The fully qualified URL of the path.
|
||||
*/
|
||||
- (NSString*) bufferAsyncFromFile:(NSString*) filePath
|
||||
reduceToMono:(bool) reduceToMono
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of a URL asynchronously.
|
||||
* This method will schedule a request to have the buffer created and filled, and then call the
|
||||
* specified selector with the newly created buffer. <br>
|
||||
* The buffer's name will be the fully qualified URL. <br>
|
||||
* Returns the fully qualified URL, which you can match up to the buffer name in your callback
|
||||
* method.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param url The URL of the file containing the audio data.
|
||||
* @param target The target to call when the buffer is loaded.
|
||||
* @param selector The selector to invoke when the buffer is loaded.
|
||||
* @return The fully qualified URL of the path.
|
||||
*/
|
||||
- (NSString*) bufferAsyncFromUrl:(NSURL*) url target:(id) target selector:(SEL) selector;
|
||||
|
||||
/** Load an OpenAL buffer with the contents of a URL asynchronously.
|
||||
* This method will schedule a request to have the buffer created and filled, and then call the
|
||||
* specified selector with the newly created buffer. <br>
|
||||
* The buffer's name will be the fully qualified URL. <br>
|
||||
* Returns the fully qualified URL, which you can match up to the buffer name in your callback
|
||||
* method.
|
||||
*
|
||||
* See the class description note regarding sound file formats.
|
||||
*
|
||||
* @param url The URL of the file containing the audio data.
|
||||
* @param reduceToMono If true, reduce the sample to mono
|
||||
* (stereo samples don't support panning or positional audio).
|
||||
* @param target The target to call when the buffer is loaded.
|
||||
* @param selector The selector to invoke when the buffer is loaded.
|
||||
* @return The fully qualified URL of the path.
|
||||
*/
|
||||
- (NSString*) bufferAsyncFromUrl:(NSURL*) url
|
||||
reduceToMono:(bool) reduceToMono
|
||||
target:(id) target
|
||||
selector:(SEL) selector;
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Clear all references to sound data from ALL buffers, managed or not.
|
||||
*/
|
||||
- (void) clearAllBuffers;
|
||||
|
||||
|
||||
#pragma mark Internal Use
|
||||
|
||||
/** \cond */
|
||||
/** (INTERNAL USE) Notify that a device is initializing.
|
||||
*/
|
||||
- (void) notifyDeviceInitializing:(ALDevice*) device;
|
||||
|
||||
/** (INTERNAL USE) Notify that a device is deallocating.
|
||||
*/
|
||||
- (void) notifyDeviceDeallocating:(ALDevice*) device;
|
||||
/** \endcond */
|
||||
|
||||
@end
|
||||
+438
@@ -0,0 +1,438 @@
|
||||
//
|
||||
// SynthesizeSingleton.h
|
||||
//
|
||||
// Modified by Karl Stenerud starting 16/04/2010.
|
||||
// - Moved the swizzle code to allocWithZone so that non-default init methods may be
|
||||
// used to initialize the singleton.
|
||||
// - Added "lesser" singleton which allows other instances besides sharedInstance to be created.
|
||||
// - Added guard ifndef so that this file can be used in multiple library distributions.
|
||||
// - Made singleton variable name class-specific so that it can be used on multiple classes
|
||||
// within the same compilation module.
|
||||
//
|
||||
// Modified by CJ Hanson on 26/02/2010.
|
||||
// This version of Matt's code uses method_setImplementaiton() to dynamically
|
||||
// replace the +sharedInstance method with one that does not use @synchronized
|
||||
//
|
||||
// Based on code by Matt Gallagher from CocoaWithLove
|
||||
//
|
||||
// Created by Matt Gallagher on 20/10/08.
|
||||
// Copyright 2009 Matt Gallagher. All rights reserved.
|
||||
//
|
||||
// Permission is given to use this source code file without charge in any
|
||||
// project, commercial or otherwise, entirely at your risk, with the condition
|
||||
// that any redistribution (in part or whole) of source code must retain
|
||||
// this copyright and permission notice. Attribution in compiled projects is
|
||||
// appreciated but not required.
|
||||
//
|
||||
|
||||
#ifndef SYNTHESIZE_SINGLETON_FOR_CLASS
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Singleton
|
||||
|
||||
/* Synthesize Singleton For Class
|
||||
*
|
||||
* Creates a singleton interface for the specified class with the following methods:
|
||||
*
|
||||
* + (MyClass*) sharedInstance;
|
||||
* + (void) purgeSharedInstance;
|
||||
*
|
||||
* Calling sharedInstance will instantiate the class and swizzle some methods to ensure
|
||||
* that only a single instance ever exists.
|
||||
* Calling purgeSharedInstance will destroy the shared instance and return the swizzled
|
||||
* methods to their former selves.
|
||||
*
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* MyClass.h:
|
||||
* ========================================
|
||||
* #import "SynthesizeSingleton.h"
|
||||
*
|
||||
* @interface MyClass: SomeSuperclass
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);
|
||||
*
|
||||
* @end
|
||||
* ========================================
|
||||
*
|
||||
*
|
||||
* MyClass.m:
|
||||
* ========================================
|
||||
* #import "MyClass.h"
|
||||
*
|
||||
* // This line is optional. Use it if you've enabled GCC_WARN_UNDECLARED_SELECTOR
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS_PROTOTYPE(MyClass);
|
||||
*
|
||||
* @implementation MyClass
|
||||
*
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass);
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* @end
|
||||
* ========================================
|
||||
*
|
||||
*
|
||||
* Note: Calling alloc manually will also initialize the singleton, so you
|
||||
* can call a more complex init routine to initialize the singleton like so:
|
||||
*
|
||||
* [[MyClass alloc] initWithParam:firstParam secondParam:secondParam];
|
||||
*
|
||||
* Just be sure to make such a call BEFORE you call "sharedInstance" in
|
||||
* your program.
|
||||
*/
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(SS_CLASSNAME) \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstance; \
|
||||
+ (void) purgeSharedInstance;
|
||||
|
||||
|
||||
#if __has_feature(objc_arc) // ARC Version
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS_PROTOTYPE(SS_CLASSNAME)
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS(SS_CLASSNAME) \
|
||||
\
|
||||
static volatile SS_CLASSNAME* _##SS_CLASSNAME##_sharedInstance = nil; \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstanceNoSynch \
|
||||
{ \
|
||||
SS_CLASSNAME* instance = (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
return instance; \
|
||||
} \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstanceSynch \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil == _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
_##SS_CLASSNAME##_sharedInstance = [[self alloc] init]; \
|
||||
} \
|
||||
} \
|
||||
return (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
} \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstance \
|
||||
{ \
|
||||
return [self sharedInstanceSynch]; \
|
||||
} \
|
||||
\
|
||||
+ (id)allocWithZone:(NSZone*) zone \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if (nil == _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
_##SS_CLASSNAME##_sharedInstance = [super allocWithZone:zone]; \
|
||||
if(nil != _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
SS_CLASSNAME* instance = (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
return instance; \
|
||||
} \
|
||||
\
|
||||
+ (void)purgeSharedInstance \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil != _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
_##SS_CLASSNAME##_sharedInstance = nil; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
- (id)copyWithZone:(NSZone *)zone \
|
||||
{ \
|
||||
_Pragma ( "unused(zone)" ) \
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
|
||||
#else // Non-ARC Version
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS_PROTOTYPE(SS_CLASSNAME) \
|
||||
@interface SS_CLASSNAME (SynthesizeSingletonPrivate) \
|
||||
- (NSUInteger)retainCountDoNothing; \
|
||||
- (NSUInteger)retainCountDoSomething; \
|
||||
- (oneway void)releaseDoNothing; \
|
||||
- (oneway void)releaseDoSomething; \
|
||||
- (id)autoreleaseDoNothing; \
|
||||
- (id)autoreleaseDoSomething; \
|
||||
@end
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS(SS_CLASSNAME) \
|
||||
\
|
||||
static volatile SS_CLASSNAME* _##SS_CLASSNAME##_sharedInstance = nil; \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstanceNoSynch \
|
||||
{ \
|
||||
SS_CLASSNAME* instance = (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
return instance; \
|
||||
} \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstanceSynch \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil == _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
_##SS_CLASSNAME##_sharedInstance = [[self alloc] init]; \
|
||||
} \
|
||||
} \
|
||||
return (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
} \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstance \
|
||||
{ \
|
||||
return [self sharedInstanceSynch]; \
|
||||
} \
|
||||
\
|
||||
+ (id)allocWithZone:(NSZone*) zone \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if (nil == _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
_##SS_CLASSNAME##_sharedInstance = [super allocWithZone:zone]; \
|
||||
if(nil != _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
method_setImplementation(class_getInstanceMethod(self, @selector(retainCount)), class_getMethodImplementation(self, @selector(retainCountDoNothing))); \
|
||||
method_setImplementation(class_getInstanceMethod(self, @selector(release)), class_getMethodImplementation(self, @selector(releaseDoNothing))); \
|
||||
method_setImplementation(class_getInstanceMethod(self, @selector(autorelease)), class_getMethodImplementation(self, @selector(autoreleaseDoNothing))); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
SS_CLASSNAME* instance = (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
return instance; \
|
||||
} \
|
||||
\
|
||||
+ (void)purgeSharedInstance \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil != _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
method_setImplementation(class_getInstanceMethod(self, @selector(retainCount)), class_getMethodImplementation(self, @selector(retainCountDoSomething))); \
|
||||
method_setImplementation(class_getInstanceMethod(self, @selector(release)), class_getMethodImplementation(self, @selector(releaseDoSomething))); \
|
||||
method_setImplementation(class_getInstanceMethod(self, @selector(autorelease)), class_getMethodImplementation(self, @selector(autoreleaseDoSomething))); \
|
||||
[_##SS_CLASSNAME##_sharedInstance release]; \
|
||||
_##SS_CLASSNAME##_sharedInstance = nil; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
- (id)copyWithZone:(NSZone *)zone \
|
||||
{ \
|
||||
_Pragma ( "unused(zone)" ) \
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
- (id)retain \
|
||||
{ \
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
- (NSUInteger)retainCount \
|
||||
{ \
|
||||
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(NSUInteger)retainCount method did not get swizzled.", self); \
|
||||
return NSUIntegerMax; \
|
||||
} \
|
||||
\
|
||||
- (NSUInteger)retainCountDoNothing \
|
||||
{ \
|
||||
return NSUIntegerMax; \
|
||||
} \
|
||||
- (NSUInteger)retainCountDoSomething \
|
||||
{ \
|
||||
return [super retainCount]; \
|
||||
} \
|
||||
\
|
||||
- (oneway void)release \
|
||||
{ \
|
||||
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(void)release method did not get swizzled.", self); \
|
||||
} \
|
||||
\
|
||||
- (oneway void)releaseDoNothing{} \
|
||||
\
|
||||
- (oneway void)releaseDoSomething \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
[super release]; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
- (id)autorelease \
|
||||
{ \
|
||||
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(id)autorelease method did not get swizzled.", self); \
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
- (id)autoreleaseDoNothing \
|
||||
{ \
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
- (id)autoreleaseDoSomething \
|
||||
{ \
|
||||
return [super autorelease]; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Lesser Singleton
|
||||
|
||||
/* A lesser singleton has a shared instance, but can also be instantiated on its own.
|
||||
*
|
||||
* For a lesser singleton, you still use SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(),
|
||||
* but use SYNTHESIZE_LESSER_SINGLETON_FOR_CLASS() in the implementation file.
|
||||
* You must specify which creation methods are to initialize the shared instance
|
||||
* (besides "sharedInstance") via CALL_LESSER_SINGLETON_INIT_METHOD()
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* MyClass.h:
|
||||
* ========================================
|
||||
* #import "SynthesizeSingleton.h"
|
||||
*
|
||||
* @interface MyClass: SomeSuperclass
|
||||
* {
|
||||
* int value;
|
||||
* ...
|
||||
* }
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);
|
||||
*
|
||||
* + (void) initSharedInstanceWithValue:(int) value;
|
||||
*
|
||||
* - (id) initWithValue:(int) value;
|
||||
*
|
||||
* @end
|
||||
* ========================================
|
||||
*
|
||||
*
|
||||
* MyClass.m:
|
||||
* ========================================
|
||||
* #import "MyClass.h"
|
||||
*
|
||||
* // This line is optional. Use it if you've enabled GCC_WARN_UNDECLARED_SELECTOR
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS_PROTOTYPE(MyClass);
|
||||
*
|
||||
* @implementation MyClass
|
||||
*
|
||||
* SYNTHESIZE_LESSER_SINGLETON_FOR_CLASS(MyClass);
|
||||
*
|
||||
* + (void) initSharedInstanceWithValue:(int) value
|
||||
* {
|
||||
* CALL_LESSER_SINGLETON_INIT_METHOD(MyClass, initWithValue:value);
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* @end
|
||||
* ========================================
|
||||
*
|
||||
*
|
||||
* Note: CALL_LESSER_SINGLETON_INIT_METHOD() will not work if your
|
||||
* init call contains commas. If you need commas (such as for varargs),
|
||||
* or other more complex initialization, use the PRE and POST macros:
|
||||
*
|
||||
* + (void) initSharedInstanceComplex
|
||||
* {
|
||||
* CALL_LESSER_SINGLETON_INIT_METHOD_PRE(MyClass);
|
||||
*
|
||||
* int firstNumber = [self getFirstNumberSomehow];
|
||||
* _sharedInstance = [[self alloc] initWithValues:firstNumber, 2, 3, 4, -1];
|
||||
*
|
||||
* CALL_LESSER_SINGLETON_INIT_METHOD_POST(MyClass);
|
||||
* }
|
||||
*/
|
||||
|
||||
#define SYNTHESIZE_LESSER_SINGLETON_FOR_CLASS(SS_CLASSNAME) \
|
||||
\
|
||||
static volatile SS_CLASSNAME* _##SS_CLASSNAME##_sharedInstance = nil; \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstanceNoSynch \
|
||||
{ \
|
||||
SS_CLASSNAME* instance = (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
return instance; \
|
||||
} \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstanceSynch \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil == _##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
_##SS_CLASSNAME##_sharedInstance = [[self alloc] init]; \
|
||||
if(_##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
SS_CLASSNAME* instance = (SS_CLASSNAME*) _##SS_CLASSNAME##_sharedInstance; \
|
||||
return instance; \
|
||||
} \
|
||||
\
|
||||
+ (SS_CLASSNAME*) sharedInstance \
|
||||
{ \
|
||||
return [self sharedInstanceSynch]; \
|
||||
} \
|
||||
\
|
||||
+ (void)purgeSharedInstance \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
[_##SS_CLASSNAME##_sharedInstance release]; \
|
||||
_##SS_CLASSNAME##_sharedInstance = nil; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_LESSER_SINGLETON_INIT_METHOD_PRE(SS_CLASSNAME) \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil == _##SS_CLASSNAME##_sharedInstance) \
|
||||
{
|
||||
|
||||
|
||||
#define CALL_LESSER_SINGLETON_INIT_METHOD_POST(SS_CLASSNAME) \
|
||||
if(_##SS_CLASSNAME##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define CALL_LESSER_SINGLETON_INIT_METHOD(SS_CLASSNAME,__INIT_CALL__) \
|
||||
CALL_LESSER_SINGLETON_INIT_METHOD_PRE(SS_CLASSNAME); \
|
||||
_##SS_CLASSNAME##_sharedInstance = [[self alloc] __INIT_CALL__]; \
|
||||
CALL_LESSER_SINGLETON_INIT_METHOD_POST(SS_CLASSNAME)
|
||||
|
||||
#endif /* SYNTHESIZE_SINGLETON_FOR_CLASS */
|
||||
Binary file not shown.
+6
@@ -0,0 +1,6 @@
|
||||
framework module ObjectAL {
|
||||
umbrella header "ObjectAL.h"
|
||||
export *
|
||||
|
||||
module * { export * }
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user