-
Notifications
You must be signed in to change notification settings - Fork 289
/
Copy pathAppDelegate.mm
executable file
·127 lines (102 loc) · 4.85 KB
/
AppDelegate.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#import "AppDelegate.h"
#include "SuperpoweredOSXAudioIO.h"
#include "Superpowered.h"
#include "SuperpoweredSpatializer.h"
#include "SuperpoweredAdvancedAudioPlayer.h"
#include "SuperpoweredSimple.h"
#include "SuperpoweredMixer.h"
#define NUMSPEAKERS 14
static const float elevations[NUMSPEAKERS] = {
0.0f, 0.0f, 0.0f, 0.0f, 90.0f, -90.0f, 45.0f, 45.0f, 45.0f, 45.0f, -45.0f, -45.0f, -45.0f, -45.0f
};
static const float azimuths[NUMSPEAKERS] = {
0.0f, 180.0f, 90.0f, -90.0f, 0.0f, 0.0f, 45.0f, 135.0f, 225.0f, 315.0f, 45.0f, 135.0f, 225.0f, 315.0f
};
@interface AppDelegate () {
SuperpoweredOSXAudioIO *io;
Superpowered::Spatializer *sp[NUMSPEAKERS];
Superpowered::MonoMixer *mixer[NUMSPEAKERS];
Superpowered::AdvancedAudioPlayer *players[2];
float azimuth, elevation, lastAzimuth, lastElevation;
unsigned int loaded;
}
@property IBOutlet NSWindow *window;
@end
@implementation AppDelegate
static const float speakerVolume = 1.0f / float(NUMSPEAKERS);
static const float wmul = sqrtf(0.5f);
- (IBAction)onAzimuth:(id)sender {
azimuth = [((NSSlider *)sender) floatValue];
}
- (IBAction)onElevation:(id)sender {
elevation = [((NSSlider *)sender) floatValue];
}
- (void)updatePositions {
lastAzimuth = azimuth;
lastElevation = elevation;
for (int n = 0; n < NUMSPEAKERS; n++) {
float az = azimuths[n] - lastAzimuth;
while (az > 360.0f) az -= 360.0f;
while (az < 0.0f) az += 360.0f;
float ev = elevations[n] + elevation;
sp[n]->elevation = ev;
sp[n]->azimuth = az;
};
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
Superpowered::Initialize("ExampleLicenseKey-WillExpire-OnNextUpdate");
loaded = 0;
azimuth = lastAzimuth = elevation = lastElevation = 0;
for (int n = 0; n < NUMSPEAKERS; n++) {
sp[n] = new Superpowered::Spatializer(44100);
sp[n]->inputVolume = speakerVolume * 4.0f;
sp[n]->sound2 = true;
mixer[n] = new Superpowered::MonoMixer();
mixer[n]->inputGain[0] = wmul; // w
float az = float(M_PI) * (360.0f - azimuths[n]) / 180.0f, cosaz = cosf(az), sinaz = sinf(az), cosel = cosf(float(M_PI) * elevations[n] / 180.0f);
mixer[n]->inputGain[0] = cosaz * cosel; // x
mixer[n]->inputGain[1] = sinaz * cosel; // y
mixer[n]->inputGain[2] = sinf(float(M_PI) * elevations[n] / 180.0f); // z
};
[self updatePositions];
players[0] = new Superpowered::AdvancedAudioPlayer(44100, 0);
players[1] = new Superpowered::AdvancedAudioPlayer(44100, 0);
players[0]->loopOnEOF = players[1]->loopOnEOF = true;
players[0]->open([[[NSBundle mainBundle] pathForResource:@"ambi_01" ofType:@"mp3"] fileSystemRepresentation]);
players[1]->open([[[NSBundle mainBundle] pathForResource:@"ambi_23" ofType:@"mp3"] fileSystemRepresentation]);
io = [[SuperpoweredOSXAudioIO alloc] initWithDelegate:(id<SuperpoweredOSXAudioIODelegate>)self preferredBufferSizeMs:11 numberOfChannels:2 enableInput:false enableOutput:true];
[io start];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
[io dealloc];
for (int n = 0; n < NUMSPEAKERS; n++) {
delete sp[n];
delete mixer[n];
}
delete players[0];
delete players[1];
}
- (bool)audioProcessingCallback:(float *)inputBuffer outputBuffer:(float *)outputBuffer numberOfFrames:(unsigned int)numberOfFrames samplerate:(unsigned int)samplerate hostTime:(UInt64)hostTime {
if (players[0]->getLatestEvent() == Superpowered::AdvancedAudioPlayer::PlayerEvent_Opened) loaded++;
if (players[1]->getLatestEvent() == Superpowered::AdvancedAudioPlayer::PlayerEvent_Opened) loaded++;
if (players[0]->outputSamplerate != samplerate) {
for (int n = 0; n < NUMSPEAKERS; n++) sp[n]->samplerate = samplerate;
players[0]->outputSamplerate = players[1]->outputSamplerate = samplerate;
};
if ((loaded == 2) && !players[0]->isPlaying()) {
players[0]->play();
players[1]->play();
};
if ((azimuth != lastAzimuth) || (elevation != lastElevation)) [self updatePositions];
float wx[numberOfFrames * 2], yz[numberOfFrames * 2], w[numberOfFrames], x[numberOfFrames], y[numberOfFrames], z[numberOfFrames];
bool _wx_ = true, _yz_ = true;
if (!players[0]->processStereo(wx, false, numberOfFrames)) _wx_ = false; else Superpowered::DeInterleave(wx, w, x, numberOfFrames);
if (!players[1]->processStereo(yz, false, numberOfFrames)) _yz_ = false; else Superpowered::DeInterleave(yz, y, z, numberOfFrames);
for (int s = 0; s < NUMSPEAKERS; s++) {
mixer[s]->process(_wx_ ? w : NULL, _wx_ ? x : NULL, _yz_ ? y : NULL, _yz_ ? z : NULL, outputBuffer, numberOfFrames);
sp[s]->process(outputBuffer, outputBuffer, wx, yz, numberOfFrames, s != 0);
};
Superpowered::Interleave(wx, yz, outputBuffer, numberOfFrames);
return true;
}
@end