/// <summary> /// Returns the sample closest to the provided midicode and a pitch shift value /// to be applied to the sample /// </summary> /// <returns>The sample index for midi code.</returns> /// <param name="midiCode">Midi code.</param> /// <param name="pitchShift">Pitch shift.</param> public GATData GetClosestSampleForMidiCode(float midiCode, out float pitchShift) { int index = _allSamples.Count - 1; int i; GATSampleInfo info; float delta; float minDelta = float.MaxValue; for (i = 0; i < _allSamples.Count; i++) { info = _soundBank.SampleInfos[i]; delta = Mathf.Abs(midiCode - info.MidiCode); if (delta < minDelta) { minDelta = delta; } else { index = i - 1; break; } } pitchShift = GATMaths.GetRatioForInterval(midiCode - ( float )_soundBank.SampleInfos[index].MidiCode); return(_allSamples[index]); }
/// <summary> /// Creates a new PatternSample for insertion in a PulsedPatternModule. /// </summary> public PatternSample(string sampleName, float gain = 1f, int semiTones = 0) { _sampleName = sampleName; _gain = gain; _semiTones = semiTones; _pitch = GATMaths.GetRatioForInterval(semiTones); }
public void GetMidiCodes(int offset, int fftSize = 4096, int maxFreq = 5000) { AudioClip clip; float[] real, im, window; FloatFFT fft; string assetPath; float binWidth; List <FFTBinInfo> binInfos; int i; real = new float[fftSize]; im = new float[fftSize]; window = new float[fftSize]; GATMaths.MakeHammingWindow(window); fft = new FloatFFT(); fft.init(( uint )Mathf.Log(fftSize, 2)); binWidth = ( float )_sampleRate / fftSize; int maxBin = ( int )(( float )maxFreq / binWidth); foreach (GATSampleInfo info in _sampleInfos) { assetPath = AssetDatabase.GUIDToAssetPath(info.GUID); clip = AssetDatabase.LoadAssetAtPath(assetPath, typeof(AudioClip)) as AudioClip; if (clip.channels > 1) { throw new GATException("Get Midi Codes is a beta feature only available for mono clips"); } clip.GetData(real, offset); System.Array.Clear(im, 0, im.Length); fft.run(real, im); for (i = 0; i < maxBin; i++) { real[i] = Mathf.Sqrt(real[i] * real[i] + im[i] * im[i]); } binInfos = FFTBinInfo.GetLowerMaxBins(real, 0, maxBin, binWidth, .2f); info.MidiCode = binInfos[binInfos.Count - 1].GetMidiCode(); } SortByMidiCode(); }
void SetPitch(double newPitch) { if (newPitch == _nextPitch) { return; } _nextPitch = newPitch; _needsDataUpdate = true; if (envelope == GATEnvelope.nullEnvelope) { _cachedLength = GATMaths.ResampledLength(sourceSample.Count, _nextPitch); _needsNewContainer = true; } }
protected void FillWithResampledData(GATData sourceData, GATData targetData, int fromIndex, int targetLength, double pitch) { //check that we have enough samples to fulfill the request: int appliedLength = GATMaths.ClampedResampledLength(sourceData.Count - fromIndex, targetLength, pitch); if (appliedLength < 0) { #if GAT_DEBUG Debug.LogWarning("requested offset is out of bounds."); #endif return; } sourceData.ResampleCopyTo(fromIndex, targetData, appliedLength, pitch); //if we did not have enough samples, clear the rest: if (appliedLength < targetLength) { targetData.Clear(appliedLength, targetData.Count - appliedLength); } }
public static List <FFTBinInfo> GetLowerMaxBins(float[] magnitudes, int fromIndex, int toIndex, float binFrequencyWidth, float magThresholdRatio) { List <FFTBinInfo> maxBins = new List <FFTBinInfo>(); FFTBinInfo binInfo; int maxIndex; float magThreshold; fromIndex++; toIndex--; maxIndex = GATMaths.GetIndexOfMaxValue(magnitudes, fromIndex, toIndex); binInfo = new FFTBinInfo(magnitudes, maxIndex, binFrequencyWidth); maxBins.Add(binInfo); magThreshold = binInfo.InterpolatedMagnitude * magThresholdRatio; while (true) { toIndex = binInfo.BinIndex - 1; if (toIndex - fromIndex < 3) { break; } maxIndex = GATMaths.GetIndexOfMaxValue(magnitudes, fromIndex, toIndex); binInfo = new FFTBinInfo(magnitudes, maxIndex, binFrequencyWidth); if (binInfo.InterpolatedMagnitude < magThreshold) { break; } maxBins.Add(binInfo); } return(maxBins); }
/// <summary> /// Sets and pre-computes the specified /// WindowFunction for faster processing. /// </summary> public void SetWindow(WindowFunction windowFunction) { if (_windowData == null || _windowData.Length != _appliedFFTSize) { _windowData = new float[_appliedFFTSize]; } switch (window) { case WindowFunction.Hanning: GATMaths.MakeHanningWindow(_windowData); break; case WindowFunction.Hamming: GATMaths.MakeHammingWindow(_windowData); break; } }