/** * Create dynamic audio from a set of Animation Curves and other options. * * @method createAudio * @param {AnimationCurve} volumeCurve:AnimationCurve describing the shape of the audios volume (from 0-1). The length of the audio is dicated by the end value here. * @param {AnimationCurve} frequencyCurve:AnimationCurve describing the width of the oscillations between the sound waves in seconds. Large numbers mean a lower note, while higher numbers mean a tighter frequency and therefor a higher note. Values are usually between 0.01 and 0.000001 (or smaller) * @param {LeanAudioOptions} options:LeanAudioOptions You can pass any other values in here like vibrato or the frequency you would like the sound to be encoded at. See <a href="LeanAudioOptions.html">LeanAudioOptions</a> for more details. * @return {AudioClip} AudioClip of the procedurally generated audio * @example * AnimationCurve volumeCurve = new AnimationCurve( new Keyframe(0f, 1f, 0f, -1f), new Keyframe(1f, 0f, -1f, 0f));<br> * AnimationCurve frequencyCurve = new AnimationCurve( new Keyframe(0f, 0.003f, 0f, 0f), new Keyframe(1f, 0.003f, 0f, 0f));<br> * AudioClip audioClip = LeanAudio.createAudio(volumeCurve, frequencyCurve, LeanAudio.options().setVibrato( new Vector3[]{ new Vector3(0.32f,0f,0f)} ));<br> */ public static AudioClip createAudio(AnimationCurve volume, AnimationCurve frequency, LeanAudioOptions options = null) { if (options == null) { options = new LeanAudioOptions(); } int generatedWavePtsLength = createAudioWave(volume, frequency, options); // Debug.Log("generatedWavePtsLength:"+generatedWavePtsLength); return(createAudioFromWave(generatedWavePtsLength, options)); }
public static LeanAudioStream createAudioStream(AnimationCurve volume, AnimationCurve frequency, LeanAudioOptions options = null) { if (options == null) { options = new LeanAudioOptions(); } options.useSetData = false; int generatedWavePtsLength = createAudioWave(volume, frequency, options); createAudioFromWave(generatedWavePtsLength, options); return(options.stream); }
private static AudioClip createAudioFromWave(int waveLength, LeanAudioOptions options) { float time = longList[waveLength - 2]; float[] audioArr = new float[(int)(options.frequencyRate * time)]; int waveIter = 0; float subWaveDiff = longList[waveIter]; float subWaveTimeLast = 0f; float subWaveTime = longList[waveIter]; float waveHeight = longList[waveIter + 1]; for (int i = 0; i < audioArr.Length; i++) { float passedTime = (float)i / (float)options.frequencyRate; if (passedTime > longList[waveIter]) { subWaveTimeLast = longList[waveIter]; waveIter += 2; subWaveDiff = longList[waveIter] - longList[waveIter - 2]; waveHeight = longList[waveIter + 1]; // Debug.Log("passed wave i:"+i); } subWaveTime = passedTime - subWaveTimeLast; float ratioElapsed = subWaveTime / subWaveDiff; float value = Mathf.Sin(ratioElapsed * Mathf.PI); if (options.waveStyle == LeanAudioOptions.LeanAudioWaveStyle.Square) { if (value > 0f) { value = 1f; } if (value < 0f) { value = -1f; } } else if (options.waveStyle == LeanAudioOptions.LeanAudioWaveStyle.Sawtooth) { float sign = value > 0f ? 1f : -1f; if (ratioElapsed < 0.5f) { value = (ratioElapsed * 2f) * sign; } else { // 0.5f - 1f value = (1f - ratioElapsed) * 2f * sign; } } else if (options.waveStyle == LeanAudioOptions.LeanAudioWaveStyle.Noise) { float peakMulti = (1f - options.waveNoiseInfluence) + Mathf.PerlinNoise(0f, passedTime * options.waveNoiseScale) * options.waveNoiseInfluence; /*if(i<25){ * Debug.Log("passedTime:"+passedTime+" peakMulti:"+peakMulti+" infl:"+options.waveNoiseInfluence); * }*/ value *= peakMulti; } //if(i<25) // Debug.Log("passedTime:"+passedTime+" value:"+value+" ratioElapsed:"+ratioElapsed+" subWaveTime:"+subWaveTime+" subWaveDiff:"+subWaveDiff); value *= waveHeight; if (options.modulation != null) { for (int k = 0; k < options.modulation.Length; k++) { float peakMulti = Mathf.Abs(Mathf.Sin(1.5708f + passedTime * (1f / options.modulation[k][0]) * Mathf.PI)); float diff = (1f - options.modulation[k][1]); peakMulti = options.modulation[k][1] + diff * peakMulti; // if(k<10){ // Debug.Log("k:"+k+" peakMulti:"+peakMulti+" value:"+value+" after:"+(value*peakMulti)); // } value *= peakMulti; } } audioArr[i] = value; // Debug.Log("pt:"+pt+" i:"+i+" val:"+audioArr[i]+" len:"+audioArr.Length); } int lengthSamples = audioArr.Length; #if UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 bool is3dSound = false; AudioClip audioClip = AudioClip.Create("Generated Audio", lengthSamples, 1, options.frequencyRate, is3dSound, false); #else AudioClip audioClip = null; if (options.useSetData) { audioClip = AudioClip.Create("Generated Audio", lengthSamples, 1, options.frequencyRate, false, null, OnAudioSetPosition); audioClip.SetData(audioArr, 0); } else { options.stream = new LeanAudioStream(audioArr); // Debug.Log("len:"+audioArr.Length+" lengthSamples:"+lengthSamples+" freqRate:"+options.frequencyRate); audioClip = AudioClip.Create("Generated Audio", lengthSamples, 1, options.frequencyRate, false, options.stream.OnAudioRead, options.stream.OnAudioSetPosition); options.stream.audioClip = audioClip; } #endif return(audioClip); }
private static int createAudioWave(AnimationCurve volume, AnimationCurve frequency, LeanAudioOptions options) { float time = volume[volume.length - 1].time; int listLength = 0; // List<float> list = new List<float>(); // generatedWaveDistances = new List<float>(); // float[] vibratoValues = new float[ vibrato.Length ]; float passed = 0f; for (int i = 0; i < PROCESSING_ITERATIONS_MAX; i++) { float f = frequency.Evaluate(passed); if (f < MIN_FREQEUNCY_PERIOD) { f = MIN_FREQEUNCY_PERIOD; } float height = volume.Evaluate(passed + 0.5f * f); if (options.vibrato != null) { for (int j = 0; j < options.vibrato.Length; j++) { float peakMulti = Mathf.Abs(Mathf.Sin(1.5708f + passed * (1f / options.vibrato[j][0]) * Mathf.PI)); float diff = (1f - options.vibrato[j][1]); peakMulti = options.vibrato[j][1] + diff * peakMulti; height *= peakMulti; } } // Debug.Log("i:"+i+" f:"+f+" passed:"+passed+" height:"+height+" time:"+time); if (passed + 0.5f * f >= time) { break; } if (listLength >= PROCESSING_ITERATIONS_MAX - 1) { Debug.LogError( "LeanAudio has reached it's processing cap. To avoid this error increase the number of iterations ex: LeanAudio.PROCESSING_ITERATIONS_MAX = " + (PROCESSING_ITERATIONS_MAX * 2)); break; } else { int distPoint = listLength / 2; //generatedWaveDistances.Add( f ); passed += f; generatedWaveDistances[distPoint] = passed; //Debug.Log("distPoint:"+distPoint+" passed:"+passed); //list.Add( passed ); //list.Add( i%2==0 ? -height : height ); longList[listLength] = passed; longList[listLength + 1] = i % 2 == 0 ? -height : height; } listLength += 2; } listLength += -2; generatedWaveDistancesCount = listLength / 2; /*float[] wave = new float[ listLength ]; * for(int i = 0; i < wave.Length; i++){ * wave[i] = longList[i]; * }*/ return(listLength); }