版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.12.29 |
前言
ios系统中有很多方式可以播放音频文件,这里我们就详细的说明下播放音乐文件的原理和实例。感兴趣的可以看我写的上面几篇。
1. 几种播放音频文件的方式(一) —— 播放本地音乐
2. 几种播放音频文件的方式(二) —— 音效播放
3. 几种播放音频文件的方式(三) —— 网络音乐播放
4. 几种播放音频文件的方式(四) —— 音频队列服务(Audio Queue Services)(一)
5. 几种播放音频文件的方式(五) —— 音频队列服务(Audio Queue Services)简介(二)
6. 几种播放音频文件的方式(六) —— 音频队列服务(Audio Queue Services)之关于音频队列(三)
7. 几种播放音频文件的方式(七) —— 音频队列服务(Audio Queue Services)之录制音频(四)
8. 几种播放音频文件的方式(八) —— 音频队列服务(Audio Queue Services)之播放音频(五)
9. 几种播放音频文件的方式(九) —— Media Player框架之基本概览(一)
10. 几种播放音频文件的方式(十) —— Media Player框架之简单播放音频示例(二)
11. 几种播放音频文件的方式(十一) —— AudioUnit框架之基本概览(一)
12. 几种播放音频文件的方式(十二) —— OpenAL框架之基本概览(一)
13. 几种播放音频文件的方式(十三) —— OpenAL框架之分步解析(二)
简单示例
下面我们就看一下示例OpenALExample
,OpenALExample
项目使用OpenGL
和OpenAL
创建一个基于Cocoa的应用程序,允许用户操纵空间中的对象,并听到他们的声音相应的效果。 它使用4个来源播放录制的数据,还有一个使用OpenAL捕获API播放捕获的音频。 该应用程序还显示如何使用Apple Spatial Audio
扩展可用的oreverb,occlusion和obstruction
效果。
下面我们就看一下代码。
1. main.m
/*
File: main.m
Abstract: main.m
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
}
2. Controller.h
/*
File: Controller.h
Abstract: Controller.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import <Cocoa/Cocoa.h>
#import "MyOpenGLView.h"
enum {
kSourceOneIndex = 0,
kSourceTwoIndex,
kSourceThreeIndex,
kSourceFourIndex,
kCaptureSourceIndex,
kListenerIndex
};
enum {
kListenerGainEditTextItem = 1000,
kDopplerFactorEditTextItem,
kSpeedOfSoundEditTextItem,
kVelocitySpeedEditTextItem,
kReverbLevelEditTextItem,
kReverbEQFrequencyEditTextItem,
kReverbEQBandwidth,
kReverbEQGain,
kListenerElevation, // ListenerPosY
kListenerPosX = 3000,
kListenerPosZ = 3002
};
@interface Controller : NSObject {
IBOutlet NSWindow* mainWindow;
IBOutlet MyOpenGLView* view;
// Slider Outlets
IBOutlet NSSlider* mListenerGainSlider;
IBOutlet NSSlider* mDopplerFactorSlider;
IBOutlet NSSlider* mSpeedOfSoundSlider;
IBOutlet NSSlider* mListenerVelocityScalerSlider;
IBOutlet NSSlider* mListenerReverbLevelSlider;
IBOutlet NSSlider* mReverbEQFrequencySlider;
IBOutlet NSSlider* mReverbEQGainSlider;
IBOutlet NSSlider* mReverbEQBandwidthSlider;
IBOutlet NSSlider* mListenerElevationSlider; // 1008
IBOutlet NSButton* mReverbOnCheckbox;
IBOutlet NSPopUpButton* mReverbQualityPU;
IBOutlet NSPopUpButton* mReverbRoomtypePU;
IBOutlet NSSlider* mCaptureSourceGainSlider;
IBOutlet NSSlider* mCaptureSourcePitchSlider;
IBOutlet NSButton* mCaptureSourceOnCheckbox;
IBOutlet NSButton* mCaptureSourceCaptureSamplesButton;
IBOutlet NSSlider* mCaptureSourceReverbSlider;
IBOutlet NSSlider* mCaptureSourceOcclusionSlider;
IBOutlet NSSlider* mCaptureSourceObstructionSlider;
IBOutlet NSButton* mCaptureSourceConesCheckbox;
IBOutlet NSSlider* mCaptureSourceAngleSlider;
IBOutlet NSSlider* mCaptureSourceVelocitySlider;
IBOutlet NSSlider* mCaptureSourceInnerConeAngleSlider;
IBOutlet NSSlider* mCaptureSourceOuterConeAngleSlider;
IBOutlet NSSlider* mCaptureSourceOuterConeGainSlider;
// Text Field Outlets
IBOutlet NSTextField* mListenerGain;
IBOutlet NSTextField* mListenerElevation;
IBOutlet NSTextField* mDopplerFactor;
IBOutlet NSTextField* mSpeedOfSound;
IBOutlet NSTextField* mListenerVelocityScaler;
IBOutlet NSTextField* mListenerReverbLevel;
IBOutlet NSTextField* mReverbEQFrequency;
IBOutlet NSTextField* mReverbEQGain;
IBOutlet NSTextField* mReverbEQBandwidth;
IBOutlet NSTextField* mListenerXPos;
IBOutlet NSTextField* mListenerZPos;
IBOutlet NSTextField* mListenerXVelocity;
IBOutlet NSTextField* mListenerZVelocity;
IBOutlet NSTextField* mSourceOnePitch;
IBOutlet NSTextField* mSourceTwoPitch;
IBOutlet NSTextField* mSourceThreePitch;
IBOutlet NSTextField* mSourceFourPitch;
IBOutlet NSTextField* mCaptureSourcePitch;
IBOutlet NSTextField* mSourceOneGain;
IBOutlet NSTextField* mSourceTwoGain;
IBOutlet NSTextField* mSourceThreeGain;
IBOutlet NSTextField* mSourceFourGain;
IBOutlet NSTextField* mCaptureSourceGain;
IBOutlet NSTextField* mSourceOneReferenceDistance;
IBOutlet NSTextField* mSourceTwoReferenceDistance;
IBOutlet NSTextField* mSourceThreeReferenceDistance;
IBOutlet NSTextField* mSourceFourReferenceDistance;
IBOutlet NSTextField* mCaptureSourceReferenceDistance;
IBOutlet NSTextField* mSourceOneMaxDistance;
IBOutlet NSTextField* mSourceTwoMaxDistance;
IBOutlet NSTextField* mSourceThreeMaxDistance;
IBOutlet NSTextField* mSourceFourMaxDistance;
IBOutlet NSTextField* mCaptureSourceMaxDistance;
IBOutlet NSTextField* mSourceOneRolloffFactor;
IBOutlet NSTextField* mSourceTwoRolloffFactor;
IBOutlet NSTextField* mSourceThreeRolloffFactor;
IBOutlet NSTextField* mSourceFourRolloffFactor;
IBOutlet NSTextField* mCaptureSourceRolloffFactor;
IBOutlet NSTextField* mSourceOneInnerConeAngle;
IBOutlet NSTextField* mSourceTwoInnerConeAngle;
IBOutlet NSTextField* mSourceThreeInnerConeAngle;
IBOutlet NSTextField* mSourceFourInnerConeAngle;
IBOutlet NSTextField* mCaptureSourceInnerConeAngle;
IBOutlet NSTextField* mSourceOneOuterConeAngle;
IBOutlet NSTextField* mSourceTwoOuterConeAngle;
IBOutlet NSTextField* mSourceThreeOuterConeAngle;
IBOutlet NSTextField* mSourceFourOuterConeAngle;
IBOutlet NSTextField* mCaptureSourceOuterConeAngle;
IBOutlet NSTextField* mSourceOneOuterConeGain;
IBOutlet NSTextField* mSourceTwoOuterConeGain;
IBOutlet NSTextField* mSourceThreeOuterConeGain;
IBOutlet NSTextField* mSourceFourOuterConeGain;
IBOutlet NSTextField* mCaptureSourceOuterConeGain;
IBOutlet NSTextField* mSourceOneReverbLevel;
IBOutlet NSTextField* mSourceTwoReverbLevel;
IBOutlet NSTextField* mSourceThreeReverbLevel;
IBOutlet NSTextField* mSourceFourReverbLevel;
IBOutlet NSTextField* mCaptureSourceReverbLevel;
IBOutlet NSTextField* mSourceOneOcclusionLevel;
IBOutlet NSTextField* mSourceTwoOcclusionLevel;
IBOutlet NSTextField* mSourceThreeOcclusionLevel;
IBOutlet NSTextField* mSourceFourOcclusionLevel;
IBOutlet NSTextField* mCaptureSourceOcclusionLevel;
IBOutlet NSTextField* mSourceOneObstructionLevel;
IBOutlet NSTextField* mSourceTwoObstructionLevel;
IBOutlet NSTextField* mSourceThreeObstructionLevel;
IBOutlet NSTextField* mSourceFourObstructionLevel;
IBOutlet NSTextField* mCaptureSourceObstructionLevel;
IBOutlet NSTextField* mSourceOneVelocity;
IBOutlet NSTextField* mSourceTwoVelocity;
IBOutlet NSTextField* mSourceThreeVelocity;
IBOutlet NSTextField* mSourceFourVelocity;
IBOutlet NSTextField* mCaptureSourceVelocity;
IBOutlet NSTextField* mSourceOneXVelocity;
IBOutlet NSTextField* mSourceTwoXVelocity;
IBOutlet NSTextField* mSourceThreeXVelocity;
IBOutlet NSTextField* mSourceFourXVelocity;
IBOutlet NSTextField* mCaptureSourceXVelocity;
IBOutlet NSTextField* mSourceOneZVelocity;
IBOutlet NSTextField* mSourceTwoZVelocity;
IBOutlet NSTextField* mSourceThreeZVelocity;
IBOutlet NSTextField* mSourceFourZVelocity;
IBOutlet NSTextField* mCaptureSourceZVelocity;
IBOutlet NSTextField* mSourceOneXPosition;
IBOutlet NSTextField* mSourceTwoXPosition;
IBOutlet NSTextField* mSourceThreeXPosition;
IBOutlet NSTextField* mSourceFourXPosition;
IBOutlet NSTextField* mCaptureSourceXPosition;
IBOutlet NSTextField* mCaptureSourceYPosition;
IBOutlet NSTextField* mSourceOneZPosition;
IBOutlet NSTextField* mSourceTwoZPosition;
IBOutlet NSTextField* mSourceThreeZPosition;
IBOutlet NSTextField* mSourceFourZPosition;
IBOutlet NSTextField* mCaptureSourceZPosition;
IBOutlet NSTextField* mALExtensionList;
IBOutlet NSTextField* mALCExtensionList;
IBOutlet NSTextField* mALCDefaultDeviceName;
IBOutlet NSTextField* mALCCaptureDefaultDeviceName;
IBOutlet NSTextField* mALVersion;
IBOutlet NSTextField* mSamplesCaptured;
}
// Context/Listener
- (IBAction) setListenerGainSlider:(id)inSender;
- (IBAction) setListenerDirectionSlider:(id)inSender;
- (IBAction) setListenerVelocitySlider:(id)inSender;
- (IBAction) setListenerElevationSlider:(id)inSender;
- (IBAction) setDopplerFactorSlider:(id)inSender;
- (IBAction) setSpeedOfSoundSlider:(id)inSender;
- (IBAction) setReverbLevelSlider:(id)inSender;
- (IBAction) setReverbEQGainSlider:(id)inSender;
- (IBAction) setReverbEQBandwidthSlider:(id)inSender;
- (IBAction) setReverbEQFrequencySlider:(id)inSender;
- (IBAction) setReverbQualityPU:(id)inSender;
- (IBAction) setDistanceModelPU:(id)inSender;
- (IBAction) setReverbRoomTypePU:(id)inSender;
- (IBAction) setRenderChannelsCheckbox:(id)inSender;
- (IBAction) setRenderQualityCheckbox:(id)inSender;
- (IBAction) setReverbOnCheckbox:(id)inSender;
// Source
- (IBAction) setSourcePitchSlider:(id)inSender;
- (IBAction) setSourceGainSlider:(id)inSender;
- (IBAction) setSourceAngleSlider:(id)inSender;
- (IBAction) setSourceVelocitySlider:(id)inSender;
- (IBAction) setSourceOuterConeGainSlider:(id)inSender;
- (IBAction) setSourceOuterConeAngleSlider:(id)inSender;
- (IBAction) setSourceInnerConeAngleSlider:(id)inSender;
- (IBAction) setSourceReverbSlider:(id)inSender;
- (IBAction) setSourceOcclusionSlider:(id)inSender;
- (IBAction) setSourceObstructionSlider:(id)inSender;
- (IBAction) setSourceUseConesCheckBox:(id)inSender;
- (IBAction) setSourcePlayStatesCheckBox:(id)inSender;
- (IBAction) captureSamplesButton:(id)inSender;
- (void) controlTextDidEndEditing:(NSNotification *) aNotification;
- (void) myObserver:(NSNotification *)inNotification;
- (void) awakeFromNib;
@end
3. Controller.m
/*
File: Controller.m
Abstract: Controller.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import "Controller.h"
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Extension API Procs
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef OSStatus (*alcASAGetListenerProcPtr) (const ALuint property, ALvoid *data, ALuint *dataSize);
OSStatus alcASAGetListenerProc(const ALuint property, ALvoid *data, ALuint *dataSize)
{
OSStatus err = noErr;
static alcASAGetListenerProcPtr proc = NULL;
if (proc == NULL) {
proc = (alcASAGetListenerProcPtr) alcGetProcAddress(NULL, "alcASAGetListener");
}
if (proc)
err = proc(property, data, dataSize);
return (err);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@implementation Controller
- (void)myObserver:(NSNotification *)inNotification
{
float x,z;
int objIndex;
[[view scene] getCurrentObjectPosition: &objIndex : &x : &z];
switch(objIndex)
{
case kSourceOneIndex:
[mSourceOneXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceOneZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
break;
case kSourceTwoIndex:
[mSourceTwoXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceTwoZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
break;
case kSourceThreeIndex:
[mSourceThreeXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceThreeZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
break;
case kSourceFourIndex:
[mSourceFourXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceFourZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
break;
case kCaptureSourceIndex:
if ([[view scene] hasInput])
{
[mCaptureSourceXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mCaptureSourceZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
}
break;
case kListenerIndex:
[mListenerXPos setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mListenerZPos setStringValue: [NSString stringWithFormat: @"%.1f", z]];
break;
}
//NSLog(@"Message recieved");
}
- (void) awakeFromNib
{
float x, z;
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(myObserver:) name: @"OALNotify" object: NULL];
[mainWindow setDelegate:(id) self];
// only enable the capture source if capture is available
if ([[view scene] hasInput])
{
// enable the capture controls
[mCaptureSourceGainSlider setEnabled: true];
[mCaptureSourcePitchSlider setEnabled: true];
[mCaptureSourceOnCheckbox setEnabled: true];
[mCaptureSourceCaptureSamplesButton setEnabled: true];
[mCaptureSourceConesCheckbox setEnabled: true];
[mCaptureSourceAngleSlider setEnabled: true];
[mCaptureSourceVelocitySlider setEnabled: true];
[mCaptureSourceInnerConeAngleSlider setEnabled: true];
[mCaptureSourceOuterConeAngleSlider setEnabled: true];
[mCaptureSourceOuterConeGainSlider setEnabled: true];
[mCaptureSourceXPosition setEnabled: true];
[mCaptureSourceZPosition setEnabled: true];
[mCaptureSourceYPosition setEnabled: true];
[mCaptureSourceReferenceDistance setEnabled: true];
[mCaptureSourceMaxDistance setEnabled: true];
[mCaptureSourceRolloffFactor setEnabled: true];
[[view scene] getObjectPosition: kCaptureSourceIndex : &x : &z];
[mCaptureSourceXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mCaptureSourceYPosition setStringValue: [NSString stringWithFormat: @"%.1f", 0.0]];
[mCaptureSourceZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
[mCaptureSourceGain setStringValue: [NSString stringWithFormat: @"%.1f", 1.0]];
[mCaptureSourcePitch setStringValue: [NSString stringWithFormat: @"%.1f", 1.0]];
[mCaptureSourceXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", 0.0]];
[mCaptureSourceZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", 0.0]];
[mCaptureSourceVelocity setStringValue: [NSString stringWithFormat: @"%.1f", 0.0]];
[mCaptureSourceInnerConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", 90.0]];
[mCaptureSourceOuterConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", 180.0]];
[mCaptureSourceOuterConeGain setStringValue: [NSString stringWithFormat: @"%.2f", 0.0]];
if ([[view scene] hasASAExtension])
{
[mCaptureSourceReverbSlider setEnabled: true];
[mCaptureSourceOcclusionSlider setEnabled: true];
[mCaptureSourceObstructionSlider setEnabled: true];
[mCaptureSourceReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", 0.0]];
[mCaptureSourceOcclusionLevel setStringValue: [NSString stringWithFormat: @"%.2f", 0.0]];
[mCaptureSourceObstructionLevel setStringValue: [NSString stringWithFormat: @"%.2f", 0.0]];
}
}
// Enable ASA Features is extension is present
if ([[view scene] hasASAExtension])
{
[mListenerReverbLevel setEnabled: true];
[mListenerReverbLevelSlider setEnabled: true];
[mReverbEQFrequency setEnabled: true];
[mReverbEQFrequencySlider setEnabled: true];
[mReverbEQBandwidth setEnabled: true];
[mReverbEQBandwidthSlider setEnabled: true];
[mReverbEQGain setEnabled: true];
[mReverbEQGainSlider setEnabled: true];
[mReverbOnCheckbox setEnabled: true];
[mReverbQualityPU setEnabled: true];
[mReverbRoomtypePU setEnabled: true];
// populate the Reverb Room Preset PU (mReverbRoomtypePU) with any aupresets found in Contents/Resources/ReverbPresets of the app bundle
NSArray* pathsArray =[[NSBundle mainBundle] pathsForResourcesOfType:@"aupreset" inDirectory:@"ReverbPresets"];
int pathCount = [pathsArray count];
int i;
NSString* presetPath = NULL;
for(i = 0; i < pathCount; i++)
{
presetPath = [pathsArray objectAtIndex:i];
if (presetPath)
{
CFURLRef url = CFURLCreateWithString(NULL, (CFStringRef) presetPath, NULL);
if (url)
{
CFURLRef nuURL = CFURLCreateCopyDeletingPathExtension(kCFAllocatorDefault, url); // strip the .aupreset extension
if (nuURL)
{
CFStringRef lastPathComponent = CFURLCopyLastPathComponent (nuURL); // get the preset name
if (lastPathComponent)
{
[mReverbRoomtypePU addItemWithTitle: (NSString*) lastPathComponent];
CFRelease(lastPathComponent);
}
CFRelease(nuURL);
}
CFRelease(url);
}
}
}
}
// position text
[[view scene] getObjectPosition: kSourceOneIndex : &x : &z];
[mSourceOneXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceOneZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
[[view scene] getObjectPosition: kSourceTwoIndex : &x : &z];
[mSourceTwoXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceTwoZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
[[view scene] getObjectPosition: kSourceThreeIndex : &x : &z];
[mSourceThreeXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceThreeZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
[[view scene] getObjectPosition: kSourceFourIndex : &x : &z];
[mSourceFourXPosition setStringValue: [NSString stringWithFormat: @"%.1f", x]];
[mSourceFourZPosition setStringValue: [NSString stringWithFormat: @"%.1f", z]];
// get current values of source attributes to diplay in UI at start up time
[mSourceOneReferenceDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceReferenceDistance:0]]];
[mSourceTwoReferenceDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceReferenceDistance:1]]];
[mSourceThreeReferenceDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceReferenceDistance:2]]];
[mSourceFourReferenceDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceReferenceDistance:3]]];
[mCaptureSourceReferenceDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceReferenceDistance:4]]];
[mSourceOneMaxDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceMaxDistance:0]]];
[mSourceTwoMaxDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceMaxDistance:1]]];
[mSourceThreeMaxDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceMaxDistance:2]]];
[mSourceFourMaxDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceMaxDistance:3]]];
[mCaptureSourceMaxDistance setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceMaxDistance:4]]];
[mSourceOneRolloffFactor setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceRolloffFactor:0]]];
[mSourceTwoRolloffFactor setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceRolloffFactor:1]]];
[mSourceThreeRolloffFactor setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceRolloffFactor:2]]];
[mSourceFourRolloffFactor setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceRolloffFactor:3]]];
[mCaptureSourceRolloffFactor setStringValue: [NSString stringWithFormat: @"%.1f", [[view scene] getSourceRolloffFactor:4]]];
// doppler factor
float setting = alGetFloat(AL_DOPPLER_FACTOR);
[mDopplerFactor setStringValue: [NSString stringWithFormat: @"%.2f", setting]];
[mDopplerFactorSlider setFloatValue: setting]; // move the corresponding slider
// speed of sound
setting = alGetFloat(AL_SPEED_OF_SOUND);
[mSpeedOfSound setStringValue: [NSString stringWithFormat: @"%.2f", setting]];
[mSpeedOfSoundSlider setFloatValue: setting]; // move the corresponding slider
// display some info about the library
// SEE IF STRING IS RETURNED FIRST SO THESE WON'T CRASH ON A NULL STRING
if (alGetString(AL_EXTENSIONS))
[mALExtensionList setStringValue: [NSString stringWithUTF8String: (const char *) alGetString(AL_EXTENSIONS)]];
if ( alcGetString(alcGetContextsDevice(alcGetCurrentContext()), ALC_EXTENSIONS))
[mALCExtensionList setStringValue: [NSString stringWithUTF8String: (const char *) alcGetString(alcGetContextsDevice(alcGetCurrentContext()), ALC_EXTENSIONS)]];
if (alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER))
[mALCDefaultDeviceName setStringValue: [NSString stringWithUTF8String: (const char *) alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)]];
if (alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER))
[mALCCaptureDefaultDeviceName setStringValue: [NSString stringWithUTF8String: (const char *) alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)]];
if (alGetString(AL_VERSION))
[mALVersion setStringValue: [NSString stringWithUTF8String: (const char *) alGetString(AL_VERSION)]];
}
#pragma mark ***** Listener Controls *****
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setListenerDirectionSlider:(id)inSender
{
// orient the listener and get it x & z velocities
float xVelocity, zVelocity;
[[view scene] setListenerOrientation:[inSender floatValue] : &xVelocity : &zVelocity];
// update the x & z velocity text
[mListenerXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", xVelocity]];
[mListenerZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", zVelocity]];
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// this is a velocity scaler that is applied to the direction the listener is facing
- (IBAction)setListenerVelocitySlider:(id)inSender
{
float velocity = [inSender floatValue];
[mListenerVelocityScaler setStringValue: [NSString stringWithFormat: @"%.2f", velocity]];
float xVelocity, zVelocity;
[[view scene] setListenerVelocity:velocity : &xVelocity : &zVelocity];
// update the x & z velocity text
[mListenerXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", xVelocity]];
[mListenerZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", zVelocity]];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setListenerGainSlider:(id)inSender
{
float gain = [inSender floatValue];
[mListenerGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
[[view scene] setListenerGain:gain];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setListenerElevationSlider:(id)inSender
{
float elevation = [inSender floatValue];
[mListenerElevation setStringValue: [NSString stringWithFormat: @"%.2f", elevation]];
[[view scene] setListenerElevation:elevation];
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setDopplerFactorSlider:(id)inSender
{
float setting = [inSender floatValue];
[mDopplerFactor setStringValue: [NSString stringWithFormat: @"%.2f", setting]];
[[view scene] setDopplerFactor:setting];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSpeedOfSoundSlider:(id)inSender
{
float setting = [inSender floatValue];
[mSpeedOfSound setStringValue: [NSString stringWithFormat: @"%.2f", setting]];
[[view scene] setSpeedOfSound:setting];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setDistanceModelPU:(id)inSender
{
int tag = [[inSender selectedItem] tag];
[[view scene] setDistanceModel:tag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setRenderChannelsCheckbox:(id)inSender
{
int channels = [inSender intValue];
[[view scene] setRenderChannels:channels];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setRenderQualityCheckbox:(id)inSender
{
int quality = [inSender intValue];
[[view scene] setRenderQuality:quality];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CONTEXT REVERB
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ***** Listener Reverb *****
- (IBAction) setReverbLevelSlider:(id)inSender
{
float level = [inSender floatValue];
[mListenerReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
[[view scene] setGlobalReverb:level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setReverbEQGainSlider:(id)inSender
{
float level = [inSender floatValue];
[mReverbEQGain setStringValue: [NSString stringWithFormat: @"%.2f", level]];
[[view scene] setReverbEQGain:level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setReverbEQBandwidthSlider:(id)inSender
{
float level = [inSender floatValue];
[mReverbEQBandwidth setStringValue: [NSString stringWithFormat: @"%.2f", level]];
[[view scene] setReverbEQBandwidth:level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setReverbEQFrequencySlider:(id)inSender
{
float level = [inSender floatValue];
[mReverbEQFrequency setStringValue: [NSString stringWithFormat: @"%.2f", level]];
[[view scene] setReverbEQFrequency:level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setReverbOnCheckbox:(id)inSender
{
int state = [inSender intValue];
[[view scene] setReverbOn:state];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setReverbQualityPU:(id)inSender;
{
int tag = [[inSender selectedItem] tag];
[[view scene] setReverbQuality:tag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setReverbRoomTypePU:(id)inSender
{
int index = [inSender indexOfSelectedItem];
int tag = [[inSender selectedItem] tag];
NSString* itemText = [inSender titleOfSelectedItem];
[[view scene] setReverbRoomType:tag controlIndex:index title:itemText];
// get the reverb freq, gain and badwidth and set the sliders and text now..........
float gain=0.0, bd=0.0, freq=0.0;
ALuint size;
usleep(50000);
// update EQ Bandwidth Controls
size = sizeof(bd);
alcASAGetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_EQ_BANDWITH"), &bd, &size);
[mReverbEQBandwidth setStringValue: [NSString stringWithFormat: @"%.2f", bd]];
[mReverbEQBandwidthSlider setFloatValue: bd]; // move the corresponding slider
// update EQ Frequency Controls
size = sizeof(freq);
alcASAGetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_EQ_FREQ"), &freq, &size);
[mReverbEQFrequency setStringValue: [NSString stringWithFormat: @"%.2f", freq]];
[mReverbEQFrequencySlider setFloatValue: freq]; // move the corresponding slider
// update EQ Gain Controls
size = sizeof(gain);
alcASAGetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_EQ_GAIN"), &gain, &size);
[mReverbEQGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
[mReverbEQGainSlider setFloatValue: gain]; // move the corresponding slider
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SOURCE SETTINGS
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ***** Source Controls *****
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setSourceGainSlider:(id)inSender
{
float gain = [inSender floatValue];
int tag = [inSender tag];
// update the corresponding text field
switch (tag)
{
case kSourceOneIndex:
[mSourceOneGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kSourceTwoIndex:
[mSourceTwoGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kSourceThreeIndex:
[mSourceThreeGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kSourceFourIndex:
[mSourceFourGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kCaptureSourceIndex:
[mCaptureSourceGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
}
[[view scene] setSourceGain:tag :gain];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setSourcePitchSlider:(id)inSender
{
float pitch = [inSender floatValue];
int tag = [inSender tag];
// update the corresponding text field
switch (tag)
{
case kSourceOneIndex:
[mSourceOnePitch setStringValue: [NSString stringWithFormat: @"%.2f", pitch]];
break;
case kSourceTwoIndex:
[mSourceTwoPitch setStringValue: [NSString stringWithFormat: @"%.2f", pitch]];
break;
case kSourceThreeIndex:
[mSourceThreePitch setStringValue: [NSString stringWithFormat: @"%.2f", pitch]];
break;
case kSourceFourIndex:
[mSourceFourPitch setStringValue: [NSString stringWithFormat: @"%.2f", pitch]];
break;
case kCaptureSourceIndex:
[mCaptureSourcePitch setStringValue: [NSString stringWithFormat: @"%.2f", pitch]];
break;
}
[[view scene] setSourcePitch:tag :pitch];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction)setSourceAngleSlider:(id)inSender
{
int tag = [inSender tag];
float outX, outZ;
[[view scene] setSourceAngle:tag :[inSender floatValue]];
[[view scene] getSourceVelocities:tag :&outX : &outZ];
// update the corresponding text fields
switch (tag)
{
case kSourceOneIndex:
[mSourceOneXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceOneZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kSourceTwoIndex:
[mSourceTwoXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceTwoZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kSourceThreeIndex:
[mSourceThreeXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceThreeZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kSourceFourIndex:
[mSourceFourXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceFourZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kCaptureSourceIndex:
[mCaptureSourceXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mCaptureSourceZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
}
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceVelocitySlider:(id)inSender
{
float velocity = [inSender floatValue];
int tag = [inSender tag];
float outX, outZ;
[[view scene] setSourceVelocity:tag :velocity];
[[view scene] getSourceVelocities:tag :&outX : &outZ];
// update the corresponding text fields
switch (tag)
{
case kSourceOneIndex:
[mSourceOneVelocity setStringValue: [NSString stringWithFormat: @"%.1f", velocity]];
[mSourceOneXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceOneZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kSourceTwoIndex:
[mSourceTwoVelocity setStringValue: [NSString stringWithFormat: @"%.1f", velocity]];
[mSourceTwoXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceTwoZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kSourceThreeIndex:
[mSourceThreeVelocity setStringValue: [NSString stringWithFormat: @"%.1f", velocity]];
[mSourceThreeXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceThreeZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kSourceFourIndex:
[mSourceFourVelocity setStringValue: [NSString stringWithFormat: @"%.1f", velocity]];
[mSourceFourXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mSourceFourZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
case kCaptureSourceIndex:
[mCaptureSourceVelocity setStringValue: [NSString stringWithFormat: @"%.1f", velocity]];
[mCaptureSourceXVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outX]];
[mCaptureSourceZVelocity setStringValue: [NSString stringWithFormat: @"%.1f", outZ]];
break;
}
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceOuterConeGainSlider:(id)inSender
{
float gain = [inSender floatValue];
int tag = [inSender tag];
[[view scene] setSourceOuterConeGain:tag :gain];
// update the corresponding text fields
switch (tag)
{
case kSourceOneIndex:
[mSourceOneOuterConeGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kSourceTwoIndex:
[mSourceTwoOuterConeGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kSourceThreeIndex:
[mSourceThreeOuterConeGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kSourceFourIndex:
[mSourceFourOuterConeGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
case kCaptureSourceIndex:
[mCaptureSourceOuterConeGain setStringValue: [NSString stringWithFormat: @"%.2f", gain]];
break;
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceOuterConeAngleSlider:(id)inSender
{
float angle = [inSender floatValue];
int tag = [inSender tag];
[[view scene] setSourceOuterConeAngle:tag :angle];
// update the corresponding text fields
switch (tag)
{
case kSourceOneIndex:
[mSourceOneOuterConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kSourceTwoIndex:
[mSourceTwoOuterConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kSourceThreeIndex:
[mSourceThreeOuterConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kSourceFourIndex:
[mSourceFourOuterConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kCaptureSourceIndex:
[mCaptureSourceOuterConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
}
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceInnerConeAngleSlider:(id)inSender
{
float angle = [inSender floatValue];
int tag = [inSender tag];
[[view scene] setSourceInnerConeAngle:tag :angle];
// update the corresponding text fields
switch (tag)
{
case kSourceOneIndex:
[mSourceOneInnerConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kSourceTwoIndex:
[mSourceTwoInnerConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kSourceThreeIndex:
[mSourceThreeInnerConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kSourceFourIndex:
[mSourceFourInnerConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
case kCaptureSourceIndex:
[mCaptureSourceInnerConeAngle setStringValue: [NSString stringWithFormat: @"%.2f", angle]];
break;
}
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceUseConesCheckBox:(id)inSender
{
int tag = [inSender tag];
int state = [inSender intValue];
[[view scene] setSourceDirectionOnOff:tag :state];
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourcePlayStatesCheckBox:(id)inSender
{
int tag = [inSender tag];
int state = [inSender intValue];
[[view scene] setSourcePlayState:tag :state];
[view setNeedsDisplay:YES];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ***** Source Effects *****
- (IBAction) setSourceReverbSlider:(id)inSender
{
float level = [inSender floatValue];
int tag = [inSender tag];
// update the corresponding text field
switch (tag)
{
case kSourceOneIndex:
[mSourceOneReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceTwoIndex:
[mSourceTwoReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceThreeIndex:
[mSourceThreeReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceFourIndex:
[mSourceFourReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kCaptureSourceIndex:
[mCaptureSourceReverbLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
}
[[view scene] setSourceReverb:tag :level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceOcclusionSlider:(id)inSender
{
float level = [inSender floatValue];
int tag = [inSender tag];
// update the corresponding text field
switch (tag)
{
case kSourceOneIndex:
[mSourceOneOcclusionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceTwoIndex:
[mSourceTwoOcclusionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceThreeIndex:
[mSourceThreeOcclusionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceFourIndex:
[mSourceFourOcclusionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kCaptureSourceIndex:
[mCaptureSourceOcclusionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
}
[[view scene] setSourceOcclusion:tag :level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) setSourceObstructionSlider:(id)inSender
{
float level = [inSender floatValue];
int tag = [inSender tag];
// update the corresponding text field
switch (tag)
{
case kSourceOneIndex:
[mSourceOneObstructionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceTwoIndex:
[mSourceTwoObstructionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceThreeIndex:
[mSourceThreeObstructionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kSourceFourIndex:
[mSourceFourObstructionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
case kCaptureSourceIndex:
[mCaptureSourceObstructionLevel setStringValue: [NSString stringWithFormat: @"%.2f", level]];
break;
}
[[view scene] setSourceObstruction:tag :level];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// EDIT TEXT
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define kReferenceDistanceText 4200
#define kMaxDistanceText 4300
#define kRolloffFactorText 4400
#define kSourcePosXText 5000
#define kSourcePosYText 5100
#define kSourcePosZText 5200
#define kListenerPosXText 3000
#define kListenerPosZText 3002
- (void) controlTextDidEndEditing:(NSNotification *) aNotification {
NSTextField * obj = [aNotification object];
// which text field
switch ([obj tag])
{
case kListenerElevation:
{ // get the numeric value of the field string
// set the slider to this value
float elevation = [obj floatValue];
[mListenerElevationSlider setFloatValue: elevation]; // move the corresponding slider
[[view scene] setListenerElevation:elevation]; // Set OpenAL
[view setNeedsDisplay:YES];
}
break;
case kListenerGainEditTextItem:
{ // get the numeric value of the field string
// set the slider to this value
float gain = [obj floatValue];
[mListenerGainSlider setFloatValue: gain]; // move the corresponding slider
[[view scene] setListenerGain:gain]; // Set OpenAL
}
break;
case kDopplerFactorEditTextItem:
{ // get the numeric value of the field string
// set the slider to this value
float doppler = [obj floatValue];
[mDopplerFactorSlider setFloatValue: doppler]; // move the corresponding slider
[[view scene] setDopplerFactor:doppler]; // Set OpenAL
}
break;
case kSpeedOfSoundEditTextItem:
{ // get the numeric value of the field string
// set the slider to this value
float sos = [obj floatValue];
[mSpeedOfSoundSlider setFloatValue: sos]; // move the corresponding slider
[[view scene] setSpeedOfSound:sos]; // Set OpenAL
}
break;
case kVelocitySpeedEditTextItem:
{ // get the numeric value of the field string
// set the slider to this value
float velocity = [obj floatValue];
[mListenerVelocityScalerSlider setFloatValue: velocity]; // move the corresponding slider
[[view scene] setListenerVelocity:velocity : NULL : NULL]; // Set OpenAL
}
break;
case kReverbLevelEditTextItem:
{ // get the numeric value of the field string
// set the slider to this value
float level = [obj floatValue];
[mListenerReverbLevelSlider setFloatValue: level]; // move the corresponding slider
[[view scene] setGlobalReverb:level]; // Set OpenAL
}
break;
case kReverbEQFrequencyEditTextItem:
{ // get the numeric value of the field string
// set the slider to this value
float frequency = [obj floatValue];
[mReverbEQFrequencySlider setFloatValue: frequency]; // move the corresponding slider
[[view scene] setReverbEQFrequency:frequency]; // Set OpenAL
}
break;
case kReverbEQBandwidth:
{ // get the numeric value of the field string
// set the slider to this value
float bandwidth = [obj floatValue];
[mReverbEQBandwidthSlider setFloatValue: bandwidth]; // move the corresponding slider
[[view scene] setReverbEQBandwidth:bandwidth]; // Set OpenAL
}
break;
case kReverbEQGain:
{ // get the numeric value of the field string
// set the slider to this value
float gain = [obj floatValue];
[mReverbEQGainSlider setFloatValue: gain]; // move the corresponding slider
[[view scene] setReverbEQGain:gain]; // Set OpenAL
}
break;
case kListenerPosXText:
{
float pos = [obj floatValue];
[[view scene] setListenerPositionX : pos]; // Set OpenAL
[view setNeedsDisplay:YES];
}
break;
case kListenerPosZText:
{
float pos = [obj floatValue];
[[view scene] setListenerPositionZ : pos]; // Set OpenAL
[view setNeedsDisplay:YES];
}
break;
case kSourcePosXText:
case kSourcePosXText+1:
case kSourcePosXText+2:
case kSourcePosXText+3:
case kSourcePosXText+4:
{
float pos = [obj floatValue];
[[view scene] setSourcePositionX:[obj tag] - kSourcePosXText : pos]; // Set OpenAL
[view setNeedsDisplay:YES];
}
break;
case kSourcePosYText:
case kSourcePosYText+1:
case kSourcePosYText+2:
case kSourcePosYText+3:
case kSourcePosYText+4:
{
float pos = [obj floatValue];
[[view scene] setSourcePositionY:[obj tag] - kSourcePosYText : pos]; // Set OpenAL
[view setNeedsDisplay:YES];
}
break;
case kSourcePosZText:
case kSourcePosZText+1:
case kSourcePosZText+2:
case kSourcePosZText+3:
case kSourcePosZText+4:
{
float pos = [obj floatValue];
[[view scene] setSourcePositionZ:[obj tag] - kSourcePosZText : pos]; // Set OpenAL
[view setNeedsDisplay:YES];
}
break;
case kReferenceDistanceText:
case kReferenceDistanceText+1:
case kReferenceDistanceText+2:
case kReferenceDistanceText+3:
case kReferenceDistanceText+4:
{
float ro = [obj floatValue];
[[view scene] setSourceReferenceDistance:[obj tag] - kReferenceDistanceText : ro]; // Set OpenAL
}
break;
case kMaxDistanceText:
case kMaxDistanceText+1:
case kMaxDistanceText+2:
case kMaxDistanceText+3:
case kMaxDistanceText+4:
{
float ro = [obj floatValue];
[[view scene] setSourceMaxDistance:[obj tag] - kMaxDistanceText : ro]; // Set OpenAL
}
break;
case kRolloffFactorText:
case kRolloffFactorText+1:
case kRolloffFactorText+2:
case kRolloffFactorText+3:
case kRolloffFactorText+4:
{
float ro = [obj floatValue];
[[view scene] setSourceRolloffFactor:[obj tag] - kRolloffFactorText : ro]; // Set OpenAL
}
break;
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (IBAction) captureSamplesButton:(id)inSender
{
int samplesCaptured = 0;
[[view scene] captureSamples:&samplesCaptured];
float theValue = samplesCaptured;
[mSamplesCaptured setStringValue: [NSString stringWithFormat: @"%.1f", theValue]];
}
- (void)windowWillClose:(NSNotification *)aNotification {
[NSApp terminate:self];
}
@end
4.MyOpenALSupport.h
/*
File: MyOpenALSupport.h
Abstract: MyOpenALSupport.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#include <CoreFoundation/CoreFoundation.h>
#include <AudioToolbox/AudioToolbox.h>
#import <OpenAL/al.h>
#import <OpenAL/alc.h>
void* MyGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate);
5. MyOpenALSupport.c
/*
File: MyOpenALSupport.c
Abstract: MyOpenALSupport.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#include "MyOpenALSupport.h"
void* MyGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate)
{
OSStatus err = noErr;
SInt64 theFileLengthInFrames = 0;
AudioStreamBasicDescription theFileFormat;
UInt32 thePropertySize = sizeof(theFileFormat);
ExtAudioFileRef extRef = NULL;
void* theData = NULL;
AudioStreamBasicDescription theOutputFormat;
// Open a file with ExtAudioFileOpen()
err = ExtAudioFileOpenURL(inFileURL, &extRef);
if(err) { printf("MyGetOpenALAudioData: ExtAudioFileOpenURL FAILED, Error = %ld\n", err); goto Exit; }
// Get the audio data format
err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat);
if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %ld\n", err); goto Exit; }
if (theFileFormat.mChannelsPerFrame > 2) { printf("MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); goto Exit;}
// Set the client format to 16 bit signed integer (native-endian) data
// Maintain the channel count and sample rate of the original source format
theOutputFormat.mSampleRate = theFileFormat.mSampleRate;
theOutputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame;
theOutputFormat.mFormatID = kAudioFormatLinearPCM;
theOutputFormat.mBytesPerPacket = 2 * theOutputFormat.mChannelsPerFrame;
theOutputFormat.mFramesPerPacket = 1;
theOutputFormat.mBytesPerFrame = 2 * theOutputFormat.mChannelsPerFrame;
theOutputFormat.mBitsPerChannel = 16;
theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
// Set the desired client (output) data format
err = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(theOutputFormat), &theOutputFormat);
if(err) { printf("MyGetOpenALAudioData: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) FAILED, Error = %ld\n", err); goto Exit; }
// Get the total frame count
thePropertySize = sizeof(theFileLengthInFrames);
err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames);
if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %ld\n", err); goto Exit; }
// Read all the data into memory
UInt32 theFramesToRead = (UInt32)theFileLengthInFrames;
UInt32 dataSize = theFramesToRead * theOutputFormat.mBytesPerFrame;;
theData = malloc(dataSize);
if (theData)
{
AudioBufferList theDataBuffer;
theDataBuffer.mNumberBuffers = 1;
theDataBuffer.mBuffers[0].mDataByteSize = dataSize;
theDataBuffer.mBuffers[0].mNumberChannels = theOutputFormat.mChannelsPerFrame;
theDataBuffer.mBuffers[0].mData = theData;
// Read the data into an AudioBufferList
err = ExtAudioFileRead(extRef, &theFramesToRead, &theDataBuffer);
if(err == noErr)
{
// success
*outDataSize = (ALsizei)dataSize;
*outDataFormat = (theOutputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
*outSampleRate = (ALsizei)theOutputFormat.mSampleRate;
}
else
{
// failure
free (theData);
theData = NULL; // make sure to return NULL
printf("MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", err); goto Exit;
}
}
Exit:
// Dispose the ExtAudioFileRef, it is no longer needed
if (extRef) ExtAudioFileDispose(extRef);
return theData;
}
6. MyOpenGLView.h
/*
File: MyOpenGLView.h
Abstract: MyOpenGLView.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import <Cocoa/Cocoa.h>
#import "Scene.h"
@interface MyOpenGLView : NSOpenGLView {
Scene* scene;
}
- (id) initWithFrame: (NSRect) frame; //called when MyOpenGLView is a "Custom View"
- (void) updateProjection;
- (Scene *) scene;
- (void) setScene:(Scene *)value;
@end
7. MyOpenGLView.m
/*
File: MyOpenGLView.m
Abstract: MyOpenGLView.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import "MyOpenGLView.h"
@implementation MyOpenGLView
//////////////////////////////////////////////////////
//Override NSView's initWithFrame: to specify our pixel format:
//Note: initWithFrame is called only if a "Custom View" is used in Interface BBuilder
//and the custom class is a subclass of NSView. For more information on resource loading
//see: developer.apple.com (ADC Home > Documentation > Cocoa > Resource Management > Loading Resources)
- (id) initWithFrame: (NSRect) frame
{
GLuint attribs[] =
{
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFANoRecovery,
NSOpenGLPFAColorSize, 32,
NSOpenGLPFADepthSize, 16,
0
};
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs];
if (!fmt)
NSLog(@"No OpenGL pixel format");
self = [super initWithFrame:frame pixelFormat: [fmt autorelease]];
if (self)
scene = [[Scene alloc] init];
return self;
}
- (void) dealloc
{
//remember to clean up!
[scene release];
[super dealloc];
}
#pragma mark OpenGL drawing
// update the projection matrix based on view size
- (void) updateProjection {
//get bounds
NSRect bounds = [self bounds];
//define the viewport
glViewport(0, 0, (GLsizei) bounds.size.width, (GLsizei)bounds.size.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//define "the world" window
gluOrtho2D(0.0, bounds.size.width, 0.0, bounds.size.height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Override the view's drawRect: to draw our GL content.
- (void) drawRect: (NSRect) rect
{
[[self openGLContext] makeCurrentContext];
[self updateProjection];
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//draw Objects
[scene drawObjects];
[[self openGLContext] flushBuffer];
}
#pragma mark Mouse Click Handling
- (void)mouseUp:(NSEvent *)theEvent {
[scene resetCurrentObject]; //selects "No object"
/*
could return a bool and if yes then redraw, it means that an object had to be manually relocated to not be out of bounds
*/
}
//View Accepts Mouse down events
- (void)mouseDown:(NSEvent*) event {
NSPoint eventLocation = [self convertPoint:[event locationInWindow] fromView:nil];
//set the listener position to the new mouse location
if([scene selectCurrentObject:&eventLocation] >=0) {
[scene setObjectPosition:&eventLocation];
}
//redraw screen, calls drawRect
[self setNeedsDisplay:YES];
}
- (void) mouseDragged:(NSEvent*) event {
[self mouseDown:event];
}
#pragma mark FirstResponder Changes
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return YES;
}
- (BOOL)resignFirstResponder
{
return YES;
}
#pragma mark Get/Set
- (Scene *)scene {
return [[scene retain] autorelease];
}
- (void)setScene:(Scene *)value {
if (scene != value) {
[scene release];
scene = [value copy];
}
}
@end
8.Scene.h
/*
File: Scene.h
Abstract: Scene.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import <Cocoa/Cocoa.h>
#import <OpenGL/gl.h>
#import <OpenGL/glu.h>
#import <OpenAL/al.h>
#import <OpenAL/alc.h>
#include "MyOpenALSupport.h"
@interface Scene : NSObject {
@public
bool mHasInput;
bool mHasASAExtension;
int mCurrentObject;
float mCenterOffset;
float mVelocityScaler;
float mListenerElevation;
float mAngle; // listener direction in degrees
int mSourceOn[5]; // play state
float mSourceDirection[5]; // angle in degrees
float mSourceVelocityScaler[5];
float mSourceOuterConeGain[5];
float mSourceInnerConeAngle[5];
float mSourceOuterConeAngle[5];
}
- (id) init;
- (void) initOpenAL;
// OpenGLView
- (void) drawObjects;
- (void) drawListener;
- (void) drawSourceWithDirection :(int)inTag;
- (void) drawSources;
- (void) resetCurrentObject;
- (bool) pointInCircle:(NSPoint *)point x:(float)x y:(float)y r:(float)r;
- (void) setObjectPosition:(NSPoint *)point;
- (int) selectCurrentObject:(NSPoint *)point;
- (void) setListenerPosition:(NSPoint *)point;
- (void) setSourcePositionFromPoint:(NSPoint *)point;
- (void )setSourcePositionX:(int) inTag : (float)inX;
- (void )setSourcePositionY:(int) inTag : (float)inY;
- (void )setSourcePositionZ:(int) inTag : (float)inZ;
- (void) getCurrentObjectPosition:(int*)outCurObject : (float*) outX : (float*) outZ;
- (void) getObjectPosition:(int)inObject : (float*) outX : (float*) outZ;
// Context Settings
- (void) setListenerPositionX: (float)inX;
- (void) setListenerPositionZ: (float)inZ;
- (void) setListenerOrientation: (float)angle : (float*) outX : (float*) outZ;
- (void) setListenerElevation: (float)elevation;
- (void) setListenerVelocity:(float) inVelocity : (float*) outX : (float*) outZ;
- (void) setListenerGain :(float)inGain;
- (void) setDopplerFactor :(float)inValue;
- (void) setSpeedOfSound :(float)inValue;
- (void) setDistanceModel:(int)inTag;
- (void) setReverbOn:(int)inCheckBoxValue;
- (void) setGlobalReverb :(float)inReverbLevel;
- (void) setReverbRoomType:(int)inTag controlIndex:(int) inIndex title:(NSString*) inTitle;
- (void) setReverbQuality:(int)inTag;
- (void) setReverbEQGain:(float)inLevel;
- (void) setReverbEQBandwidth:(float)inLevel;
- (void) setReverbEQFrequency:(float)inLevel;
- (void) setRenderChannels:(int)inCheckBoxValue;
- (void) setRenderQuality:(int)inCheckBoxValue;
// Source Settings
- (void) setSourcePlayState:(int)inTag :(int)inCheckBoxValue;
- (void) setSourcePitch:(int)inTag :(float)inPitch;
- (void) setSourceGain:(int)inTag :(float)inGain;
- (void) setSourceRolloffFactor:(int)inTag :(float)inRolloff;
- (float) getSourceRolloffFactor:(int)inTag;
- (void) setSourceReferenceDistance:(int)inTag :(float)inReferenceDistance;
- (float) getSourceReferenceDistance:(int)inTag;
- (void) setSourceMaxDistance:(int)inTag :(float)inMaxDistance;
- (float) getSourceMaxDistance:(int)inTag;
- (void) setSourceDirectionOnOff:(int)inTag :(int)inCheckBoxValue;
- (void) setSourceReverb:(int)inTag :(float)inReverbSendLevel;
- (void) setSourceOcclusion:(int)inTag :(float)inLevel;
- (void) setSourceObstruction:(int)inTag :(float)inLevel;
- (void) getSourceVelocities:(int)inTag : (float*) outX : (float*) outZ;
- (void) getSourceDirections:(int)inTag : (float*) outX : (float*) outZ;
- (void) setSourceAngle:(int)inTag :(float)inAngle;
- (void) setSourceDirection:(int)inTag;
- (void) setSourceVelocity:(int)inTag :(float) inVelocity;
- (void) setSourceOuterConeGain:(int)inTag :(float) inGain;
- (void) setSourceInnerConeAngle:(int)inTag :(float) inAngle;
- (void) setSourceOuterConeAngle:(int)inTag :(float) inAngle;
- (void) captureSamples :(int*)outValue;
- (bool) hasInput;
- (bool) hasASAExtension;
@end
9.Scene.m
/*
File: Scene.m
Abstract: Scene.h
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2012 Apple Inc. All Rights Reserved.
*/
#import "Scene.h"
#include <math.h>
#define DEG2RAD(x) (0.0174532925 * (x))
#define RAD2DEG(x) (57.295779578 * (x))
#define kSquareSize 500 // needs to be the size of the custom NIB object
#define kSourceCircleRadius 10.0
#define kListenerCircleRadius 20.0
#define kDefaultDistance 175.0
#define NUM_BUFFERS_SOURCES 5 // this test app has 4 Source Objects and 4 Buffer Objects
#define kCaptureSamples 44100 * 5 // capture 5 seconds of data at 44k
#define kCaptureSourceIndex 4
#define kCapturedAudioSampleRate 44100
#define kListenerIndex 5
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Globals
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ALCdevice *gCaptureDevice = NULL;
UInt8* gCaptureData = NULL;
float gListenerPos[3] = {0.0, 0.0, 0.0}; // default position is centered
float gListenerDirection = 0;
int gSourceDirectionOnOff[NUM_BUFFERS_SOURCES] = {0, 0, 0, 0, 0};
float gSourceAngle[NUM_BUFFERS_SOURCES] = {225, 315, 135, 45, 180}; // each source is now facing the center
float gSourcePos[NUM_BUFFERS_SOURCES][3] = { {kDefaultDistance, 0.0, -kDefaultDistance},
{kDefaultDistance, 0.0, kDefaultDistance},
{-kDefaultDistance , 0.0, -kDefaultDistance},
{-kDefaultDistance , 0.0, kDefaultDistance},
{0.0 , 0.0, -kDefaultDistance} };
char * gSourceFile[NUM_BUFFERS_SOURCES - 1]; // only the 1st 4 sources use data from a file
ALuint gBuffer[NUM_BUFFERS_SOURCES];
ALuint gSource[NUM_BUFFERS_SOURCES];
float gSourceInnerConeAngle[NUM_BUFFERS_SOURCES] = {90, 90, 90, 90, 90};
float gSourceOuterConeAngle[NUM_BUFFERS_SOURCES] = {180, 180, 180, 180, 180};
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Extension API Procs
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef ALvoid AL_APIENTRY (*alMacOSXRenderChannelCountProcPtr) (const ALint value);
ALvoid alMacOSXRenderChannelCountProc(const ALint value)
{
static alMacOSXRenderChannelCountProcPtr proc = NULL;
if (proc == NULL) {
proc = (alMacOSXRenderChannelCountProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alMacOSXRenderChannelCount");
}
if (proc)
proc(value);
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef ALvoid AL_APIENTRY (*alcMacOSXRenderingQualityProcPtr) (const ALint value);
ALvoid alcMacOSXRenderingQualityProc(const ALint value)
{
static alcMacOSXRenderingQualityProcPtr proc = NULL;
if (proc == NULL) {
proc = (alcMacOSXRenderingQualityProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXRenderingQuality");
}
if (proc)
proc(value);
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef ALvoid AL_APIENTRY (*alcMacOSXMixerOutputRateProcPtr) (const ALdouble value);
ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value)
{
static alcMacOSXMixerOutputRateProcPtr proc = NULL;
if (proc == NULL) {
proc = (alcMacOSXMixerOutputRateProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXMixerOutputRate");
}
if (proc)
proc(value);
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef ALdouble (*alcMacOSXGetMixerOutputRateProcPtr) ();
ALdouble alcMacOSXGetMixerOutputRateProc()
{
static alcMacOSXGetMixerOutputRateProcPtr proc = NULL;
if (proc == NULL) {
proc = (alcMacOSXGetMixerOutputRateProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXGetMixerOutputRate");
}
if (proc)
return proc();
return 0.0;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq);
ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq)
{
static alBufferDataStaticProcPtr proc = NULL;
if (proc == NULL) {
proc = (alBufferDataStaticProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alBufferDataStatic");
}
if (proc)
proc(bid, format, data, size, freq);
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef OSStatus (*alcASASetSourceProcPtr) (const ALuint property, ALuint source, ALvoid *data, ALuint dataSize);
OSStatus alcASASetSourceProc(const ALuint property, ALuint source, ALvoid *data, ALuint dataSize)
{
OSStatus err = noErr;
static alcASASetSourceProcPtr proc = NULL;
if (proc == NULL) {
proc = (alcASASetSourceProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcASASetSource");
}
if (proc)
err = proc(property, source, data, dataSize);
return (err);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef OSStatus (*alcASASetListenerProcPtr) (const ALuint property, ALvoid *data, ALuint dataSize);
OSStatus alcASASetListenerProc(const ALuint property, ALvoid *data, ALuint dataSize)
{
OSStatus err = noErr;
static alcASASetListenerProcPtr proc = NULL;
if (proc == NULL) {
proc = (alcASASetListenerProcPtr) alcGetProcAddress(NULL, "alcASASetListener");
}
if (proc)
err = proc(property, data, dataSize);
return (err);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef ALCdevice* (*alcCaptureOpenDeviceProcPtr) (const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
ALCdevice* alcCaptureOpenDeviceProc(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize)
{
ALCdevice* device = NULL;
device = alcCaptureOpenDevice (devicename, frequency, format, buffersize);
return (device);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef void (*alcCaptureStartProcPtr) (ALCdevice* device);
void alcCaptureStartProc(ALCdevice* device)
{
alcCaptureStart (device);
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef void (*alcCaptureSamplesProcPtr) (ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
void alcCaptureSamplesProc(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
{
alcCaptureSamples (device, buffer, samples);
return;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize OpenAL -Get an Audio Device and Set Current OpenAL Context
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ALvoid* gStaticBufferData = NULL;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TeardownOpenAL()
{
ALCcontext *context = NULL;
ALCdevice *device = NULL;
ALuint returnedNames[NUM_BUFFERS_SOURCES];
// Delete the Sources
alDeleteSources(NUM_BUFFERS_SOURCES, returnedNames);
// Delete the Buffers
alDeleteBuffers(NUM_BUFFERS_SOURCES, returnedNames);
//Get active context
context = alcGetCurrentContext();
//Get device for active context
device = alcGetContextsDevice(context);
//Release context
alcDestroyContext(context);
//Close device
alcCloseDevice(device);
if (gStaticBufferData)
free(gStaticBufferData);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void InitializeBuffers()
{
ALenum error = AL_NO_ERROR;
ALenum format;
ALvoid* data;
ALsizei size;
ALsizei freq;
UInt32 i;
// only the 1st 4 sources get data from a file. The 5th source gets data from capture
for (i = 0; i < NUM_BUFFERS_SOURCES - 1; i ++)
{
//Get the current path to the audio file (which is contained in the application bundle)
NSString* fileString = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%s", gSourceFile[i]] ofType:@"wav"];
// get some audio data from a wave file
CFURLRef fileURL = CFURLCreateWithString(kCFAllocatorDefault, (CFStringRef)fileString, NULL);
data = MyGetOpenALAudioData(fileURL, &size, &format, &freq);
CFRelease(fileURL);
if((error = alGetError()) != AL_NO_ERROR) {
printf("error loading %s: ", gSourceFile[i]);
exit(1);
}
if (i == 0)
{
// use the static buffer data API once for testing
gStaticBufferData = (ALvoid*)malloc(size);
memcpy(gStaticBufferData, data, size);
alBufferDataStaticProc(gBuffer[i], format, gStaticBufferData, size, freq);
}
else
{
// Attach Audio Data to OpenAL Buffer
alBufferData(gBuffer[i], format, data, size, freq);
}
// Release the audio data
free(data);
if((error = alGetError()) != AL_NO_ERROR) {
printf("error unloading %s: ", gSourceFile[i]);
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void InitializeSourcesAndPlay()
{
UInt32 i;
ALenum error = AL_NO_ERROR;
alGetError(); // Clear the error
for (i = 0; i < NUM_BUFFERS_SOURCES; i++)
{
// Turn Looping ON
alSourcei(gSource[i], AL_LOOPING, AL_TRUE);
// Set Source Position
alSourcefv(gSource[i], AL_POSITION, gSourcePos[i]);
// Set Source Reference Distance
alSourcef(gSource[i],AL_REFERENCE_DISTANCE, 5.0f);
// only load data and start playing the non capture sources
if (i < NUM_BUFFERS_SOURCES-1)
{
// attach OpenAL Buffer to OpenAL Source
alSourcei(gSource[i], AL_BUFFER, gBuffer[i]);
// Start Playing Sound
alSourcePlay(gSource[i]);
}
}
if((error = alGetError()) != AL_NO_ERROR) {
printf("Error attaching buffer to source");
exit(1);
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SCENE class
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@implementation Scene
- (id) init
{
if((self = [super init])) {
mHasASAExtension = false;
mHasInput = false;
//4 WAV files in the application bundle resources
gSourceFile[0] = "sound_engine";
gSourceFile[1] = "sound_voices";
gSourceFile[2] = "sound_bubbles";
gSourceFile[3] = "sound_electric";
mCurrentObject = -1;
mCenterOffset = kSquareSize/2.0;
mVelocityScaler = 0.0;
mAngle = 0.0;
mListenerElevation = 0.0;
mSourceOn[0] = 1;
mSourceOn[1] = 1;
mSourceOn[2] = 1;
mSourceOn[3] = 1;
mSourceOn[4] = 0; // capture
mSourceDirection[0] = 0.0;
mSourceDirection[1] = 0.0;
mSourceDirection[2] = 0.0;
mSourceDirection[3] = 0.0;
mSourceDirection[4] = 0.0; // capture
mSourceVelocityScaler[0] = 0.0;
mSourceVelocityScaler[1] = 0.0;
mSourceVelocityScaler[2] = 0.0;
mSourceVelocityScaler[3] = 0.0;
mSourceVelocityScaler[4] = 0.0; // capture
mSourceOuterConeGain[0] = 0.0;
mSourceOuterConeGain[1] = 0.0;
mSourceOuterConeGain[2] = 0.0;
mSourceOuterConeGain[3] = 0.0;
mSourceOuterConeGain[4] = 0.0; // capture
mSourceInnerConeAngle[0] = 90.0;
mSourceInnerConeAngle[1] = 90.0;
mSourceInnerConeAngle[2] = 90.0;
mSourceInnerConeAngle[3] = 90.0;
mSourceInnerConeAngle[4] = 90.0; // capture
mSourceOuterConeAngle[0] = 180.0;
mSourceOuterConeAngle[1] = 180.0;
mSourceOuterConeAngle[2] = 180.0;
mSourceOuterConeAngle[3] = 180.0;
mSourceOuterConeAngle[4] = 180.0; // capture
[self initOpenAL];
[self setListenerOrientation:0 : NULL : NULL];
[self setListenerVelocity:0 : NULL : NULL];
[self setListenerGain:0.5];
}
return self;
}
- (void) dealloc {
TeardownOpenAL();
[super dealloc];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//draws a simple filled circle using quick glu calls
static void drawCircle(GLdouble x, GLdouble y, GLdouble r, GLfloat red, GLfloat grn, GLfloat blu){
// A GRADIENT CIRCLE - looks better
glPushMatrix();
glTranslatef(x, y, 0.0);
glBegin(GL_TRIANGLE_FAN);
glColor3f(red, grn, blu);
glVertex3f(0.0, 0.0, 0.0);
{
UInt32 i;
float x, y;
float stepAngle = 20;
double theAngle = -90;
for (i = 0; i <= 18; i++)
{
glColor3f(red/2, grn/2, blu/2); // gradient
float rads = DEG2RAD(theAngle);
x = cos(rads) * r;
y = sin(rads) * r;
glVertex3f(x, y, 0.0);
theAngle += stepAngle;
glColor3f(red, grn, blu); // gradient
}
}
glEnd();
glPopMatrix();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) drawObjects {
// layer the objects correctly
if (mListenerElevation > 0)
{
[self drawSources];
[self drawListener];
}
else
{
[self drawListener];
[self drawSources];
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) drawListener {
float elevationSizeScaler = (abs(mListenerElevation) / 200.0)/2; // -1 to 1
// translate that to .5 to 1.5
if (mListenerElevation > 0)
elevationSizeScaler = 1 + elevationSizeScaler;
else
elevationSizeScaler = 1 - elevationSizeScaler;
// draw a triangle (nose)
glPushMatrix();
glTranslatef(gListenerPos[0] + mCenterOffset, -gListenerPos[2] + mCenterOffset, 0.0);
//Rotate to show the listeners current orientation
glRotatef(gListenerDirection, 0.0, 0.0, -1.0);
glBegin(GL_TRIANGLES);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(-6.0 * elevationSizeScaler, 0.0, 0.0);
glVertex3f(6.0 * elevationSizeScaler, 0.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 35.0 * elevationSizeScaler, 0.0);
glEnd();
glPopMatrix();
// ears
glPushMatrix();
glTranslatef(gListenerPos[0] + mCenterOffset, -gListenerPos[2] + mCenterOffset, 0.0);
//Rotate to show the listeners current orientation
glRotatef(gListenerDirection, 0.0, 0.0, -1.0);
glBegin(GL_QUADS);
glColor3f(0.0, 0.0, 0.8);
glVertex3f(-25.0 * elevationSizeScaler, 8.0 * elevationSizeScaler, 0.0);
glVertex3f(-25.0 * elevationSizeScaler, -8.0 * elevationSizeScaler, 0.0);
glVertex3f(24.5 * elevationSizeScaler, -8.0 * elevationSizeScaler, 0.0);
glVertex3f(24.5 * elevationSizeScaler, 8.0 * elevationSizeScaler, 0.0);
glEnd();
glPopMatrix();
// minor adjustments to position circle
drawCircle(gListenerPos[0]- .5 + mCenterOffset, -gListenerPos[2] - 1 + mCenterOffset, 20 * elevationSizeScaler, 0 , 0, 1);
if (mListenerElevation != 0.0)
drawCircle(gListenerPos[0] + mCenterOffset, -gListenerPos[2] + mCenterOffset, 3, 0 , 0, .6);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define kArcSteps 16
#define kInnerArcRadius 32 // larger but partially transparent
#define kOuterArcRadius 26 // smaller with gradient
- (void) drawSourceWithDirection :(int)inTag
{
glEnable(GL_BLEND); // blend the cones so both can be seen, top cone (INNER) is partially transparent
// bottom cone (OUTER) has a gradient
// CONE DRAWING - OUTER
if (gSourceDirectionOnOff[inTag])
{
float x, z;
[self getSourceDirections:inTag : &x : &z];
glPushMatrix();
glTranslatef((gSourcePos[inTag][0] + mCenterOffset) + x, (-gSourcePos[inTag][2] + mCenterOffset) + z, 0.0);
glRotatef(gSourceAngle[inTag], 0.0, 0.0, -1.0);
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0, 0.5, 0.0);
glVertex3f(0.0, 0.0, 0.0);
{
UInt32 i;
float x, y;
float stepAngle = mSourceOuterConeAngle[inTag]/kArcSteps;
double theAngle = -(mSourceOuterConeAngle[inTag]/2) + 90;
for (i = 0; i <= kArcSteps; i++)
{
glColor3f(0.0, 0.2, 0.0); // gradient
float rads = DEG2RAD(theAngle);
x = cos(rads) * kOuterArcRadius;
y = sin(rads) * kOuterArcRadius;
glVertex3f(x, y, 0.0);
theAngle += stepAngle;
glColor3f(0.0, 0.8, 0.0); // gradient
}
}
glEnd();
glPopMatrix();
}
// CONE DRAWING - INNER
if (gSourceDirectionOnOff[inTag])
{
float x, z;
[self getSourceDirections:inTag : &x : &z];
glPushMatrix();
glTranslatef((gSourcePos[inTag][0] + mCenterOffset) + x, (-gSourcePos[inTag][2] + mCenterOffset) + z, 0.0);
glRotatef(gSourceAngle[inTag], 0.0, 0.0, -1.0);
glBegin(GL_TRIANGLE_FAN);
glColor4f(0.0, 1.0, 0.0, .4); // transparency (.4)
glVertex3f(0.0, 0.0, 0.0);
{
UInt32 i;
float x, y;
float stepAngle = mSourceInnerConeAngle[inTag]/kArcSteps;
double theAngle = -(mSourceInnerConeAngle[inTag]/2) + 90;
for (i = 0; i <= kArcSteps; i++)
{
float rads = DEG2RAD(theAngle);
x = cos(rads) * kInnerArcRadius;
y = sin(rads) * kInnerArcRadius;
glVertex3f(x, y, 0.0);
theAngle += stepAngle;
}
}
glEnd();
glPopMatrix();
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // blend the cones
glDisable(GL_BLEND); // blending is done
// draw direction triangle if there is any velocity setting above zero
if (mSourceVelocityScaler[inTag] > 0)
{
float triangleLength = kSourceCircleRadius*2;
triangleLength += (mSourceVelocityScaler[inTag]/686.0) * (kSourceCircleRadius*2);
glPushMatrix();
glTranslatef(gSourcePos[inTag][0] + mCenterOffset, -gSourcePos[inTag][2] + mCenterOffset, 0.0);
glRotatef(gSourceAngle[inTag], 0.0, 0.0, -1.0);
glBegin(GL_TRIANGLES);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(-4.0, 0.0, 0.0);
glVertex3f(4.0, 0.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, triangleLength, 0.0);
glEnd();
glPopMatrix();
}
//minor adjustments to position circle
if (mSourceOn[inTag] == 0)
{
// draw a gray circle if source is not playing
drawCircle(gSourcePos[inTag][0] + mCenterOffset, -gSourcePos[inTag][2] + mCenterOffset, kSourceCircleRadius, .5 , .5, .5); // capture circle is different color
}
else
{
if (inTag == kCaptureSourceIndex)
drawCircle(gSourcePos[inTag][0] + mCenterOffset, -gSourcePos[inTag][2] + mCenterOffset, kSourceCircleRadius, 1 , 1, 0); // capture circle is different color
else
drawCircle(gSourcePos[inTag][0] + mCenterOffset, -gSourcePos[inTag][2] + mCenterOffset, kSourceCircleRadius, 1 , 0, 0);
}
if (gSourcePos[inTag][1] != 0.0)
drawCircle(gSourcePos[inTag][0] + mCenterOffset, -gSourcePos[inTag][2]+ mCenterOffset, 3, .5 , 0, 0);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) drawSources
{
//draw sources as 4 red circles
[self drawSourceWithDirection: 0];
[self drawSourceWithDirection: 1];
[self drawSourceWithDirection: 2];
[self drawSourceWithDirection: 3];
[self drawSourceWithDirection: kCaptureSourceIndex]; // capture
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(void) resetCurrentObject
{
//set current object to -1 to designate no object selected.
mCurrentObject = -1;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(int) selectCurrentObject:(NSPoint *)point
{
//find the object (circle) that contains the point
//return -1 if none are found
if(mCurrentObject != -1)
return mCurrentObject;
if([self pointInCircle:point x:gSourcePos[0][0] + mCenterOffset y:-gSourcePos[0][2] + mCenterOffset r:kSourceCircleRadius]){
mCurrentObject = 0;
}else if ([self pointInCircle:point x:gSourcePos[1][0] + mCenterOffset y:-gSourcePos[1][2] + mCenterOffset r:kSourceCircleRadius])
mCurrentObject = 1;
else if ([self pointInCircle:point x:gSourcePos[2][0] + mCenterOffset y:-gSourcePos[2][2] + mCenterOffset r:kSourceCircleRadius])
mCurrentObject = 2;
else if ([self pointInCircle:point x:gSourcePos[3][0] + mCenterOffset y:-gSourcePos[3][2] + mCenterOffset r:kSourceCircleRadius])
mCurrentObject = 3;
else if ([self pointInCircle:point x:gSourcePos[4][0] + mCenterOffset y:-gSourcePos[4][2] + mCenterOffset r:kSourceCircleRadius])
mCurrentObject = kCaptureSourceIndex; // CAPTURE SOURCE
else if ([self pointInCircle:point x:gListenerPos[0] + mCenterOffset y:-gListenerPos[2] + mCenterOffset r:kListenerCircleRadius])
mCurrentObject = kListenerIndex;
return mCurrentObject;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// need to detect if point is in a source circle
// if so, return the source pos ID
// if not, return -1
- (bool) pointInCircle:(NSPoint *)point x:(float)x y:(float)y r:(float)r
{
float x1 =point->x;
float y1 = point->y;
float dist =0;
//calculate distance from the center of the circle to the point clcked
dist =(((x1 - x )*(x1 - x )) + ((y1 - y)*(y1 - y)));
//Here we can test this for each of the sources
//if the distance is less than the radius (squared), then the point is inside the circle
if (dist <= r*r)
return TRUE;
else
return FALSE;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(void) setObjectPosition:(NSPoint *)point
{
if(mCurrentObject < kListenerIndex){
[self setSourcePositionFromPoint:point];
}
else if (mCurrentObject == kListenerIndex ) //listener
{
[self setListenerPosition:point];
}
// NOTIFY: Post a notification that object mCurrentObject has moved so the coordinate text can be updated
[[NSNotificationCenter defaultCenter] postNotificationName: @"OALNotify" object: self];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) getCurrentObjectPosition:(int*)outCurObject : (float*) outX : (float*) outZ
{
if(mCurrentObject < kListenerIndex){
if(outX) *outX = gSourcePos[mCurrentObject][0];
if(outX) *outZ = gSourcePos[mCurrentObject][2];
}
else if (mCurrentObject == kListenerIndex ) //listener
{
if(outX) *outX = gListenerPos[0];
if(outX) *outZ = gListenerPos[2];
}
if(outCurObject) *outCurObject = mCurrentObject;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) getObjectPosition:(int)inObject : (float*) outX : (float*) outZ;
{
if(inObject < kListenerIndex){
if(outX) *outX = gSourcePos[inObject][0];
if(outX) *outZ = gSourcePos[inObject][2];
}
else if (inObject == kListenerIndex ) //listener
{
if(outX) *outX = gListenerPos[0];
if(outX) *outZ = gListenerPos[2];
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize OpenAL Context, Buffers, Listener & Sources
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) initOpenAL {
ALenum error;
ALCcontext *newContext = NULL;
ALCdevice *newDevice = NULL;
// Create a new OpenAL Device
// Pass NULL to specify the systemÕs default output device
newDevice = alcOpenDevice(NULL);
if (newDevice != NULL)
{
// Create a new OpenAL Context
// The new context will render to the OpenAL Device just created
newContext = alcCreateContext(newDevice, 0);
if (newContext != NULL)
{
// Make the new context the Current OpenAL Context
alcMakeContextCurrent(newContext);
// Create some OpenAL Buffer Objects
alGenBuffers(NUM_BUFFERS_SOURCES, gBuffer);
if((error = alGetError()) != AL_NO_ERROR) {
printf("Error Generating Buffers: ");
exit(1);
}
// Create some OpenAL Source Objects
alGenSources(NUM_BUFFERS_SOURCES, gSource);
if(alGetError() != AL_NO_ERROR)
{
printf("Error generating sources! \n");
exit(1);
}
}
}
// Capture
if (alcIsExtensionPresent( NULL, "ALC_EXT_CAPTURE" ))
{
// Setup a Capture Device
gCaptureDevice = alcCaptureOpenDeviceProc( NULL, kCapturedAudioSampleRate, AL_FORMAT_MONO16, kCaptureSamples );
if(gCaptureDevice)
{
// Capture is supported and there is an input device
alcCaptureStartProc(gCaptureDevice);
mSourceOn[4] = 1; // capture
mHasInput = true;
}
else
mHasInput = false; // Capture is supported but there is no input device
}
else
mHasInput = false; // Capture Not Supported by this OAL version
// Reverb and Effects
if (alcIsExtensionPresent( NULL, "ALC_EXT_ASA" ))
mHasASAExtension = true;
else
mHasASAExtension = false;
alGetError();
InitializeBuffers();
InitializeSourcesAndPlay();
}
- (bool) hasInput
{
return mHasInput;
}
- (bool) hasASAExtension
{
return mHasASAExtension;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Orientation
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setListenerOrientation: (float) angle : (float*) outX : (float*) outZ
{
mAngle = angle;
ALenum error = AL_NO_ERROR;
float rads = DEG2RAD(mAngle);
float orientation[6] = { 0.0, 0.0, -1.0, // direction
0.0, 1.0, 0.0 }; //up
orientation[0] = cos(rads);
orientation[1] = sin(rads); // No Change to the Z vector
gListenerDirection = RAD2DEG(atan2(orientation[1], orientation[0]));
// Change OpenAL Listener's Orientation
orientation[0] = sin(rads);
orientation[1] = 0.0; // No Change to the Y vector
orientation[2] = -cos(rads);
alListenerfv(AL_ORIENTATION, orientation);
if((error = alGetError()) != AL_NO_ERROR)
printf("Error Setting Listener Orientation");
// set the listener velocity as well, in this app we are always syncing the velocity to the direction that the listener is facing
[self setListenerVelocity: mVelocityScaler : outX : outZ];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Listener Velocity Gain
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setListenerVelocity:(float) inVelocity : (float*) outX : (float*) outZ
{
mVelocityScaler = inVelocity;
ALenum error = AL_NO_ERROR;
float rads = DEG2RAD(mAngle);
float velocity[3] = { 0.0, 0.0, 0.0}; //up
// Change OpenAL Listener's Orientation
velocity[0] = sin(rads) * mVelocityScaler;
velocity[1] = 0.0; // No Change to the Y vector
velocity[2] = -cos(rads) * mVelocityScaler;
if (outX) *outX = velocity[0];
if (outZ) *outZ = velocity[2];
alListenerfv(AL_VELOCITY, velocity);
if((error = alGetError()) != AL_NO_ERROR)
printf("Error Setting Listener Velocity");
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Position
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void)setSourcePositionFromPoint:(NSPoint *)point
{
gSourcePos[mCurrentObject][0] = point->x - mCenterOffset;
gSourcePos[mCurrentObject][2] = -point->y + mCenterOffset; // top view only in this demo!
alSourcefv(gSource[mCurrentObject], AL_POSITION, gSourcePos[mCurrentObject]);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void)setSourcePositionX:(int) inTag : (float)inX
{
gSourcePos[inTag][0] = inX;
alSourcefv(gSource[inTag], AL_POSITION, gSourcePos[inTag]);
[self drawSourceWithDirection :inTag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void)setSourcePositionY:(int) inTag : (float)inY
{
gSourcePos[inTag][1] = inY;
alSourcefv(gSource[inTag], AL_POSITION, gSourcePos[inTag]);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void)setSourcePositionZ:(int) inTag : (float)inZ
{
gSourcePos[inTag][2] = inZ;
alSourcefv(gSource[inTag], AL_POSITION, gSourcePos[inTag]);
[self drawSourceWithDirection :inTag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setListenerPosition:(NSPoint *) point
{
gListenerPos[0] = point->x - mCenterOffset;
gListenerPos[1] = mListenerElevation;
gListenerPos[2] = -point->y + mCenterOffset; // top view only in this demo!
alListenerfv(AL_POSITION, gListenerPos);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setListenerElevation: (float)elevation
{
mListenerElevation = elevation;
gListenerPos[1] = mListenerElevation;
// do not change x or z
alListenerfv(AL_POSITION, gListenerPos);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void)setListenerPositionX: (float)inX
{
gListenerPos[0] = inX;
alListenerfv(AL_POSITION, gListenerPos);
[self drawListener];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void)setListenerPositionZ: (float)inX
{
gListenerPos[2] = inX;
alListenerfv(AL_POSITION, gListenerPos);
[self drawListener];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourcePlayState:(int)inTag :(int)inCheckBoxValue
{
if (mSourceOn[inTag] == inCheckBoxValue)
return;
mSourceOn[inTag] = inCheckBoxValue;
if (mSourceOn[inTag])
alSourcePlay(gSource[inTag]);
else
alSourceStop(gSource[inTag]);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Pitch
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourcePitch:(int)inTag :(float)inPitch
{
alSourcef(gSource[inTag], AL_PITCH, inPitch);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Gain
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceGain:(int)inTag :(float)inGain
{
alSourcef(gSource[inTag], AL_GAIN, inGain);
// alSourcef (gSource[inTag], AL_SEC_OFFSET, 1.0); // quick way to test the set offset API until controls can be added to UI
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Rolloff
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceRolloffFactor:(int)inTag :(float)inRolloff
{
alSourcef(gSource[inTag], AL_ROLLOFF_FACTOR, inRolloff);
}
- (float) getSourceRolloffFactor:(int)inTag
{
float ro;
alGetSourcef(gSource[inTag], AL_ROLLOFF_FACTOR, &ro);
return ro;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Reference Distance
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceReferenceDistance:(int)inTag :(float)inReferenceDistance
{
alSourcef(gSource[inTag], AL_REFERENCE_DISTANCE, inReferenceDistance);
}
- (float) getSourceReferenceDistance:(int)inTag
{
float rd;
alGetSourcef(gSource[inTag], AL_REFERENCE_DISTANCE, &rd);
return rd;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Max Distance
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceMaxDistance:(int)inTag :(float)inMaxDistance
{
alSourcef(gSource[inTag], AL_MAX_DISTANCE, inMaxDistance);
}
- (float) getSourceMaxDistance:(int)inTag
{
float md;
alGetSourcef(gSource[inTag], AL_MAX_DISTANCE, &md);
return md;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Direction & Velocity
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceVelocity:(int)inTag :(float) inVelocity
{
mSourceVelocityScaler[inTag] = inVelocity;
float velocities[3];
velocities[1] = 0; // No Change to the Y vector
[self getSourceVelocities: inTag : &velocities[0] : &velocities[2]];
alSourcefv(gSource[inTag], AL_VELOCITY, velocities);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceDirection:(int)inTag
{
float directions[3];
directions[1] = 0; // No Change to the Y vector
if (gSourceDirectionOnOff[inTag] == false)
{
directions[0] = 0;
directions[2] = 0;
alSourcefv(gSource[inTag], AL_DIRECTION, directions);
alSourcef(gSource[inTag], AL_CONE_INNER_ANGLE, 360.0);
alSourcef(gSource[inTag], AL_CONE_OUTER_ANGLE, 360.0);
alSourcef(gSource[inTag], AL_CONE_OUTER_GAIN, 0.0);
}
else
{
[self getSourceDirections: inTag : &directions[0] : &directions[2]];
alSourcefv(gSource[inTag], AL_DIRECTION, directions);
alSourcef(gSource[inTag], AL_CONE_INNER_ANGLE, 90 );
alSourcef(gSource[inTag], AL_CONE_OUTER_ANGLE, 180);
alSourcef(gSource[inTag], AL_CONE_OUTER_GAIN, mSourceOuterConeGain[inTag] );
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceOuterConeGain:(int)inTag :(float) inGain
{
mSourceOuterConeGain[inTag] = inGain;
alSourcef(gSource[inTag], AL_CONE_OUTER_GAIN, mSourceOuterConeGain[inTag]);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceInnerConeAngle:(int)inTag :(float) inAngle
{
mSourceInnerConeAngle[inTag] = inAngle;
alSourcef(gSource[inTag], AL_CONE_INNER_ANGLE, mSourceInnerConeAngle[inTag]);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceOuterConeAngle:(int)inTag :(float) inAngle
{
mSourceOuterConeAngle[inTag] = inAngle;
alSourcef(gSource[inTag], AL_CONE_OUTER_ANGLE, mSourceOuterConeAngle[inTag]);
[self drawSourceWithDirection :inTag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceDirectionOnOff:(int)inTag :(int)inCheckBoxValue
{
if (gSourceDirectionOnOff[inTag] == inCheckBoxValue)
return;
gSourceDirectionOnOff[inTag] = inCheckBoxValue;
[self setSourceDirection: inTag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceAngle:(int)inTag :(float)inAngle
{
gSourceAngle[inTag] = inAngle;
[self setSourceVelocity: inTag : mSourceVelocityScaler[inTag]];
[self setSourceDirection: inTag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) getSourceVelocities:(int)inTag : (float*) outX : (float*) outZ
{
float rads = DEG2RAD(gSourceAngle[inTag]);
if (outX) *outX = sin(rads) * mSourceVelocityScaler[inTag];
if (outZ) *outZ = -cos(rads) * mSourceVelocityScaler[inTag];
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) getSourceDirections:(int)inTag : (float*) outX : (float*) outZ
{
float rads = DEG2RAD(gSourceAngle[inTag]);
if (outX) *outX = sin(rads);
if (outZ) *outZ = -cos(rads);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Listener Gain
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setListenerGain:(float)inGain
{
alListenerf(AL_GAIN, inGain);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Render Channels
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setRenderChannels:(int)inCheckBoxValue
{
// Global Setting:
// Used to Force OpenAL to render to stereo, even if the user's default audio hw is multichannel
UInt32 setting = (inCheckBoxValue == 0) ? alcGetEnumValue(NULL, "ALC_RENDER_CHANNEL_COUNT_MULTICHANNEL") : alcGetEnumValue(NULL, "ALC_RENDER_CHANNEL_COUNT_STEREO");
alMacOSXRenderChannelCountProc((const ALint) setting);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Render Quality
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setRenderQuality:(int)inCheckBoxValue
{
// Global Setting:
// Used to turn on HRTF Rendering when OpenAL is rendering to stereo
UInt32 setting = (inCheckBoxValue == 0) ? alcGetEnumValue(NULL, "ALC_SPATIAL_RENDERING_QUALITY_LOW") : alcGetEnumValue(NULL, "ALC_SPATIAL_RENDERING_QUALITY_HIGH");
alcMacOSXRenderingQualityProc((const ALint) setting);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Reverb Level
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceReverb:(int)inTag :(float)inReverbSendLevel
{
ALfloat level = inReverbSendLevel;
alcASASetSourceProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_SEND_LEVEL"), gSource[inTag], &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Reverb Level
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceOcclusion:(int)inTag :(float)inLevel
{
ALfloat level = inLevel;
alcASASetSourceProc(alcGetEnumValue(NULL, "ALC_ASA_OCCLUSION"), gSource[inTag], &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Source Reverb Level
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSourceObstruction:(int)inTag :(float)inReverbSendLevel
{
ALfloat level = inReverbSendLevel;
alcASASetSourceProc(alcGetEnumValue(NULL, "ALC_ASA_OBSTRUCTION"), gSource[inTag], &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Global Reverb Level
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setGlobalReverb :(float)inReverbLevel
{
ALfloat level = inReverbLevel;
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_GLOBAL_LEVEL"), &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Reverb ON
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setReverbOn:(int)inCheckBoxValue
{
UInt32 setting = (inCheckBoxValue == 0) ? 0 : 1;
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_ON"), &setting, sizeof(setting));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setReverbEQGain:(float)inLevel
{
ALfloat level = inLevel;
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_EQ_GAIN"), &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setReverbEQBandwidth:(float)inLevel
{
ALfloat level = inLevel;
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_EQ_BANDWITH"), (ALvoid *) &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setReverbEQFrequency:(float)inLevel
{
ALfloat level = inLevel;
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_EQ_FREQ"), &level, sizeof(level));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setReverbRoomType:(int)inTag controlIndex:(int) inIndex title:(NSString*) inTitle
{
UInt32 roomtype = inTag;
UInt32 roomIndex = inIndex;
if (roomIndex < 12)
{
// the 1st 12 menu items have the proper reverb constant in the tag value
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_ROOM_TYPE"), &roomtype, sizeof(roomtype));
}
else
{
const char *fullPathToFile;
fullPathToFile =[[[NSBundle mainBundle] pathForResource:inTitle ofType:@"aupreset" inDirectory:@"ReverbPresets"]UTF8String];
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_PRESET"), (void *) fullPathToFile, strlen(fullPathToFile));
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setReverbQuality:(int)inTag
{
UInt32 quality = inTag;
alcASASetListenerProc(alcGetEnumValue(NULL, "ALC_ASA_REVERB_QUALITY"), &quality, sizeof(quality));
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Distance Model
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setDistanceModel:(int)inTag
{
alDistanceModel(inTag);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Doppler Factor
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setDopplerFactor :(float)inValue
{
alDopplerFactor(inValue);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Speed Of Sound
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) setSpeedOfSound :(float)inValue
{
alSpeedOfSound(inValue);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CAPTURE
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (void) captureSamples :(int*)outValue
{
if (!gCaptureData)
{
gCaptureData = (UInt8*) calloc(1, kCaptureSamples * 2); // 1 second of 44k mono 16 bit data
}
alGetError(); // reset
alcGetIntegerv( gCaptureDevice, ALC_CAPTURE_SAMPLES, 1, outValue );
// get some new sample, free gCaptureData if this fails
alcCaptureSamplesProc( gCaptureDevice, gCaptureData, *outValue );
UInt32 err = alGetError();
if (err)
return;
alSourceStop(gSource[4]);
alSourcei(gSource[4], AL_BUFFER, AL_NONE);
ALint count = 1;
while (count > 0)
alGetSourcei(gSource[4], AL_BUFFERS_QUEUED, &count);
alBufferData(gBuffer[4], AL_FORMAT_MONO16, gCaptureData, *outValue * 2, kCapturedAudioSampleRate);
alSourcei(gSource[4], AL_BUFFER, gBuffer[4]);
alSourcePlay(gSource[4]);
}
@end
后记
未完,待续~~~