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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
#ifndef AUDIOLINK_CGINC_INCLUDED
#define AUDIOLINK_CGINC_INCLUDED
// Map of where features in AudioLink are.
#define ALPASS_DFT uint2(0,4) //Size: 128, 2
#define ALPASS_WAVEFORM uint2(0,6) //Size: 128, 16
#define ALPASS_AUDIOLINK uint2(0,0) //Size: 128, 4
#define ALPASS_AUDIOBASS uint2(0,0) //Size: 128, 1
#define ALPASS_AUDIOLOWMIDS uint2(0,1) //Size: 128, 1
#define ALPASS_AUDIOHIGHMIDS uint2(0,2) //Size: 128, 1
#define ALPASS_AUDIOTREBLE uint2(0,3) //Size: 128, 1
#define ALPASS_AUDIOLINKHISTORY uint2(1,0) //Size: 127, 4
#define ALPASS_GENERALVU uint2(0,22) //Size: 12, 1
#define ALPASS_GENERALVU_INSTANCE_TIME uint2(2,22)
#define ALPASS_GENERALVU_LOCAL_TIME uint2(3,22)
#define ALPASS_GENERALVU_NETWORK_TIME uint2(4,22)
#define ALPASS_GENERALVU_PLAYERINFO uint2(6,22)
#define ALPASS_THEME_COLOR0 uint2(0,23)
#define ALPASS_THEME_COLOR1 uint2(1,23)
#define ALPASS_THEME_COLOR2 uint2(2,23)
#define ALPASS_THEME_COLOR3 uint2(3,23)
#define ALPASS_GENERALVU_UNIX_DAYS uint2(5,23)
#define ALPASS_GENERALVU_UNIX_SECONDS uint2(6,23)
#define ALPASS_GENERALVU_SOURCE_POS uint2(7,23)
#define ALPASS_MEDIASTATE uint2(5,22)
#define ALPASS_CCINTERNAL uint2(12,22) //Size: 12, 2
#define ALPASS_CCCOLORS uint2(25,22) //Size: 12, 1 (Note Color #0 is always black, Colors start at 1)
#define ALPASS_CCSTRIP uint2(0,24) //Size: 128, 1
#define ALPASS_CCLIGHTS uint2(0,25) //Size: 128, 2
#define ALPASS_AUTOCORRELATOR uint2(0,27) //Size: 128, 1
#define ALPASS_FILTEREDAUDIOLINK uint2(0,28) //Size: 16, 4
#define ALPASS_CHRONOTENSITY uint2(16,28) //Size: 8, 4
#define ALPASS_FILTEREDVU uint2(24,28) //Size: 4, 4
#define ALPASS_FILTEREDVU_INTENSITY uint2(24,28) //Size: 4, 1
#define ALPASS_FILTEREDVU_MARKER uint2(24,29) //Size: 4, 1
#define ALPASS_GLOBAL_STRINGS uint2(40,28) //Size: 8, 4
// Some basic constants to use (Note, these should be compatible with
// future version of AudioLink, but may change.
#define AUDIOLINK_SAMPHIST 3069 // Internal use for algos, do not change.
#define AUDIOLINK_SAMPLEDATA24 2046
#define AUDIOLINK_EXPBINS 24
#define AUDIOLINK_EXPOCT 10
#define AUDIOLINK_ETOTALBINS (AUDIOLINK_EXPBINS * AUDIOLINK_EXPOCT)
#define AUDIOLINK_WIDTH 128
#define AUDIOLINK_SPS 48000 // Samples per second
#define AUDIOLINK_ROOTNOTE 0
#define AUDIOLINK_4BAND_FREQFLOOR 0.123
#define AUDIOLINK_4BAND_FREQCEILING 1
#define AUDIOLINK_BOTTOM_FREQUENCY 13.75
#define AUDIOLINK_BASE_AMPLITUDE 2.5
#define AUDIOLINK_DELAY_COEFFICIENT_MIN 0.3
#define AUDIOLINK_DELAY_COEFFICIENT_MAX 0.9
#define AUDIOLINK_DFT_Q 4.0
#define AUDIOLINK_TREBLE_CORRECTION 5.0
#define AUDIOLINK_4BAND_TARGET_RATE 90.0
#define AUDIOLINK_LUT {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, \
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, \
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, \
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, \
0.008, 0.01, 0.012, 0.014, 0.017, 0.02, 0.022, 0.025, 0.029, 0.032, 0.036, \
0.04, 0.044, 0.048, 0.053, 0.057, 0.062, 0.067, 0.072, 0.078, 0.083, 0.089, \
0.095, 0.101, 0.107, 0.114, 0.121, 0.128, 0.135, 0.142, 0.149, 0.157, 0.164, \
0.172, 0.18, 0.188, 0.196, 0.205, 0.213, 0.222, 0.23, 0.239, 0.248, 0.257, \
0.266, 0.276, 0.285, 0.294, 0.304, 0.313, 0.323, 0.333, 0.342, 0.352, 0.362, \
0.372, 0.381, 0.391, 0.401, 0.411, 0.421, 0.431, 0.441, 0.451, 0.46, 0.47, \
0.48, 0.49, 0.499, 0.509, 0.519, 0.528, 0.538, 0.547, 0.556, 0.565, 0.575, \
0.584, 0.593, 0.601, 0.61, 0.619, 0.627, 0.636, 0.644, 0.652, 0.66, 0.668, \
0.676, 0.684, 0.691, 0.699, 0.706, 0.713, 0.72, 0.727, 0.734, 0.741, 0.747, \
0.754, 0.76, 0.766, 0.772, 0.778, 0.784, 0.79, 0.795, 0.801, 0.806, 0.811, \
0.816, 0.821, 0.826, 0.831, 0.835, 0.84, 0.844, 0.848, 0.853, 0.857, 0.861, \
0.864, 0.868, 0.872, 0.875, 0.879, 0.882, 0.885, 0.888, 0.891, 0.894, 0.897, \
0.899, 0.902, 0.904, 0.906, 0.909, 0.911, 0.913, 0.914, 0.916, 0.918, 0.919, \
0.921, 0.922, 0.924, 0.925, 0.926, 0.927, 0.928, 0.928, 0.929, 0.929, 0.93, \
0.93, 0.93, 0.931, 0.931, 0.93, 0.93, 0.93, 0.93, 0.929, 0.929, 0.928, 0.927, \
0.926, 0.925, 0.924, 0.923, 0.922, 0.92, 0.919, 0.917, 0.915, 0.913, 0.911, \
0.909, 0.907, 0.905, 0.903, 0.9}
// Text constants
#define AUDIOLINK_STRING_MAX_CHARS 32
#define AUDIOLINK_STRING_LOCALPLAYER 0
#define AUDIOLINK_STRING_MASTER 1
#define AUDIOLINK_STRING_CUSTOM1 2
#define AUDIOLINK_STRING_CUSTOM2 3
// ColorChord constants
#define COLORCHORD_EMAXBIN 192
#define COLORCHORD_NOTE_CLOSEST 3.0
#define COLORCHORD_NEW_NOTE_GAIN 8.0
#define COLORCHORD_MAX_NOTES 10
// We use glsl_mod for most calculations because it behaves better
// on negative numbers, and in some situations actually outperforms
// HLSL's modf().
#ifndef glsl_mod
#define glsl_mod(x,y) (((x)-(y)*floor((x)/(y))))
#endif
uniform float4 _AudioTexture_TexelSize;
#ifdef SHADER_TARGET_SURFACE_ANALYSIS
#define AUDIOLINK_STANDARD_INDEXING
#endif
// Mechanism to index into texture.
#ifdef AUDIOLINK_STANDARD_INDEXING
sampler2D _AudioTexture;
#define AudioLinkData(xycoord) tex2Dlod(_AudioTexture, float4(uint2(xycoord) * _AudioTexture_TexelSize.xy, 0, 0))
#else
uniform Texture2D<float4> _AudioTexture;
#define AudioLinkData(xycoord) _AudioTexture[uint2(xycoord)]
#endif
// Convenient mechanism to read from the AudioLink texture that handles reading off the end of one line and onto the next above it.
float4 AudioLinkDataMultiline(uint2 xycoord) { return AudioLinkData(uint2(xycoord.x % AUDIOLINK_WIDTH, xycoord.y + xycoord.x/AUDIOLINK_WIDTH)); }
// Mechanism to sample between two adjacent pixels and lerp between them, like "linear" supesampling
float4 AudioLinkLerp(float2 xy) { return lerp( AudioLinkData(xy), AudioLinkData(xy+int2(1,0)), frac( xy.x ) ); }
// Same as AudioLinkLerp but properly handles multiline reading.
float4 AudioLinkLerpMultiline(float2 xy) { return lerp(AudioLinkDataMultiline(xy), AudioLinkDataMultiline(xy+float2(1,0)), frac(xy.x)); }
//Tests to see if Audio Link texture is available
bool AudioLinkIsAvailable()
{
#if !defined(AUDIOLINK_STANDARD_INDEXING)
int width, height;
_AudioTexture.GetDimensions(width, height);
return width > 16;
#else
return _AudioTexture_TexelSize.z > 16;
#endif
}
// DEPRECATED! Use AudioLinkGetVersionMajor and AudioLinkGetVersionMinor() instead.
//Get version of audiolink present in the world, 0 if no audiolink is present
float AudioLinkGetVersion()
{
int2 dims;
#if !defined(AUDIOLINK_STANDARD_INDEXING)
_AudioTexture.GetDimensions(dims.x, dims.y);
#else
dims = _AudioTexture_TexelSize.zw;
#endif
if (dims.x >= 128)
return AudioLinkData(ALPASS_GENERALVU).x;
else if (dims.x > 16)
return 1;
else
return 0;
}
float AudioLinkGetVersionMajor()
{
return AudioLinkData(ALPASS_GENERALVU).y;
}
float AudioLinkGetVersionMinor()
{
// If the major version is 1 or greater, we are using the new versioning system.
if (AudioLinkGetVersionMajor() > 0)
{
return AudioLinkData(ALPASS_GENERALVU).w;
}
// Otherwise, defer to the old logic for determining version.
else
{
int2 dims;
#if !defined(AUDIOLINK_STANDARD_INDEXING)
_AudioTexture.GetDimensions(dims.x, dims.y);
#else
dims = _AudioTexture_TexelSize.zw;
#endif
if (dims.x >= 128)
return AudioLinkData(ALPASS_GENERALVU).x;
else if (dims.x > 16)
return 1;
else
return 0;
}
}
// This pulls data from this texture.
#define AudioLinkGetSelfPixelData(xy) _SelfTexture2D[xy]
// Extra utility functions for time.
uint AudioLinkDecodeDataAsUInt(uint2 indexloc)
{
uint4 rpx = AudioLinkData(indexloc);
return rpx.x + rpx.y*1024 + rpx.z * 1048576 + rpx.w * 1073741824;
}
//Note: This will truncate time to every 134,217.728 seconds (~1.5 days of an instance being up) to prevent floating point aliasing.
// if your code will alias sooner, you will need to use a different function. It should be safe to use this on all times.
float AudioLinkDecodeDataAsSeconds(uint2 indexloc)
{
uint time = AudioLinkDecodeDataAsUInt(indexloc) & 0x7ffffff;
//Can't just divide by float. Bug in Unity's HLSL compiler.
return float(time / 1000) + float( time % 1000 ) / 1000.;
}
#define ALDecodeDataAsSeconds( x ) AudioLinkDecodeDataAsSeconds( x )
#define ALDecodeDataAsUInt( x ) AudioLinkDecodeDataAsUInt( x )
float AudioLinkRemap(float t, float a, float b, float u, float v) { return ((t-a) / (b-a)) * (v-u) + u; }
float3 AudioLinkHSVtoRGB(float3 HSV)
{
float3 RGB = 0;
float C = HSV.z * HSV.y;
float H = HSV.x * 6;
float X = C * (1 - abs(fmod(H, 2) - 1));
if (HSV.y != 0)
{
float I = floor(H);
if (I == 0) { RGB = float3(C, X, 0); }
else if (I == 1) { RGB = float3(X, C, 0); }
else if (I == 2) { RGB = float3(0, C, X); }
else if (I == 3) { RGB = float3(0, X, C); }
else if (I == 4) { RGB = float3(X, 0, C); }
else { RGB = float3(C, 0, X); }
}
float M = HSV.z - C;
return RGB + M;
}
float3 AudioLinkCCtoRGB(float bin, float intensity, int rootNote)
{
float note = bin / AUDIOLINK_EXPBINS;
float hue = 0.0;
note *= 12.0;
note = glsl_mod(4. - note + rootNote, 12.0);
{
if(note < 4.0)
{
//Needs to be YELLOW->RED
hue = (note) / 24.0;
}
else if(note < 8.0)
{
// [4] [8]
//Needs to be RED->BLUE
hue = (note-2.0) / 12.0;
}
else
{
// [8] [12]
//Needs to be BLUE->YELLOW
hue = (note - 4.0) / 8.0;
}
}
float val = intensity - 0.1;
return AudioLinkHSVtoRGB(float3(fmod(hue, 1.0), 1.0, clamp(val, 0.0, 1.0)));
}
// Sample the amplitude of a given frequency in the DFT, supports frequencies in [13.75; 14080].
float4 AudioLinkGetAmplitudeAtFrequency(float hertz)
{
float note = AUDIOLINK_EXPBINS * log2(hertz / AUDIOLINK_BOTTOM_FREQUENCY);
return AudioLinkLerpMultiline(ALPASS_DFT + float2(note, 0));
}
// Sample the amplitude of a given quartertone in an octave. Octave is in [0; 9] while quarter is [0; 23].
float4 AudioLinkGetAmplitudeAtQuarterNote(float octave, float quarter)
{
return AudioLinkLerpMultiline(ALPASS_DFT + float2(octave * AUDIOLINK_EXPBINS + quarter, 0));
}
// Sample the amplitude of a given semitone in an octave. Octave is in [0; 9] while note is [0; 11].
float4 AudioLinkGetAmplitudeAtNote(float octave, float note)
{
float quarter = note * 2.0;
return AudioLinkGetAmplitudeAtQuarterNote(octave, quarter);
}
// Sample the amplitude of a given quartertone across all octaves. Quarter is [0; 23].
float4 AudioLinkGetAmplitudesAtQuarterNote(float quarter)
{
float amplitude = 0;
UNITY_UNROLL
for (int i = 0; i < AUDIOLINK_EXPOCT; i++)
{
amplitude += AudioLinkGetAmplitudeAtQuarterNote(i,quarter);
}
return amplitude;
}
// Sample the amplitude of a given semitone across all octaves. Note is [0; 11].
float4 AudioLinkGetAmplitudesAtNote(float note)
{
float quarter = note * 2.0;
return AudioLinkGetAmplitudesAtQuarterNote(quarter);
}
// Get a reasonable drop-in replacement time value for _Time.y with the
// given chronotensity index [0; 7] and AudioLink band [0; 3].
float AudioLinkGetChronoTime(uint index, uint band)
{
return (AudioLinkDecodeDataAsUInt(ALPASS_CHRONOTENSITY + uint2(index, band))) / 100000.0;
}
// Get a chronotensity value in the interval [0; 1], modulated by the speed input,
// with the given chronotensity index [0; 7] and AudioLink band [0; 3].
float AudioLinkGetChronoTimeNormalized(uint index, uint band, float speed)
{
return frac(AudioLinkGetChronoTime(index, band) * speed);
}
// Get a chronotensity value in the interval [0; interval], modulated by the speed input,
// with the given chronotensity index [0; 7] and AudioLink band [0; 3].
float AudioLinkGetChronoTimeInterval(uint index, uint band, float speed, float interval)
{
return AudioLinkGetChronoTimeNormalized(index, band, speed) * interval;
}
// Get time of day. The return value is a float4 with the values float3(hour, minute, second).
float3 AudioLinkGetTimeOfDay()
{
float value = AudioLinkDecodeDataAsSeconds(ALPASS_GENERALVU_UNIX_SECONDS);
float hour = floor(value / 3600.0);
float minute = floor(value / 60.0) % 60.0;
float second = value % 60.0;
return float3(hour, minute, second);
}
// Get a character from a globally synced string, given an index of string in range [0; 3], and
// a character index in range [0; 31]. The string at the 0th index is the local player name.
// The 1st index is the master name, and index 2 and 3 are custom strings.
// Returns a unsigned integer represented a unicode codepoint, i.e. UTF32.
uint AudioLinkGetGlobalStringChar(uint stringIndex, uint charIndex)
{
uint4 fourChars = asuint(AudioLinkData(ALPASS_GLOBAL_STRINGS + uint2(charIndex / 4, stringIndex)));
return fourChars[charIndex % 4];
}
// Get a character from the local player name given a character index in the range [0; 31].
// Returns a unsigned integer represented a unicode codepoint, i.e. UTF32.
uint AudioLinkGetLocalPlayerNameChar(uint charIndex)
{
return AudioLinkGetGlobalStringChar(AUDIOLINK_STRING_LOCALPLAYER, charIndex);
}
// Get a character from the master player name given a character index in the range [0; 31].
// Returns a unsigned integer represented a unicode codepoint, i.e. UTF32.
uint AudioLinkGetMasterNameChar(uint charIndex)
{
return AudioLinkGetGlobalStringChar(AUDIOLINK_STRING_MASTER, charIndex);
}
// Get a character from the first custom string given a character index in the range [0; 31].
// Returns a unsigned integer represented a unicode codepoint, i.e. UTF32.
uint AudioLinkGetCustomString1Char(uint charIndex)
{
return AudioLinkGetGlobalStringChar(AUDIOLINK_STRING_CUSTOM1, charIndex);
}
// Get a character from the second custom string given a character index in the range [0; 31].
// Returns a unsigned integer represented a unicode codepoint, i.e. UTF32.
uint AudioLinkGetCustomString2Char(uint charIndex)
{
return AudioLinkGetGlobalStringChar(AUDIOLINK_STRING_CUSTOM2, charIndex);
}
// Returns the position of the AudioLink AudioSource in world space.
float4 AudioLinkGetAudioSourcePosition()
{
return float4(AudioLinkData(ALPASS_GENERALVU_SOURCE_POS).xyz,1);
}
#endif
|