static void RunSpeachFrequencyFilters(Vector it, int j, double vol = 0.01, int dbMin = -20, int dbMax = +20) { bool IsAudible(double f) { if ((f >= 8.1 && f <= 16743.9)) { return(true); } return(false); } bool pass = true; if (!IsAudible(it.Axis[j].Im)) { pass = false; } if (it.Axis[j].Re <= 0.01) { pass = false; } if (pass) { var n = Envelopes.MIDI2NOTE(Envelopes.FREQ2MIDI(it.Axis[j].Im)); if (string.IsNullOrWhiteSpace(n)) { pass = false; } if (n == null || (!n.Contains("3") && !n.Contains("4") && !n.Contains("5") && !n.Contains("6"))) { pass = false; } if (pass && it.Axis[j].Re > 0) { var dB = Envelopes.dB(it.Axis[j].Re); if (dB <= dbMin || dB >= dbMax) { pass = false; } } } if (!pass) { it.Axis[j].Re = 0; } }
static Vector CreateMidiVector(Complex[] fft) { int N = fft.Length * 2; Debug.Assert(N == 1024); double[] im = new double[128]; Vector vec = new Vector("𝅘𝅥𝅮", null, im); var duration = Math.Round( (double)N / Wav._hz, 5); Debug.Assert((int)(duration * Wav._hz) == N); vec.Score.Re = duration; vec.Score.Im = N; for (int i = 0; i < fft.Length; i++) { double h = Wav._hz / (double)N, f = i * h; double vol = fft[i].Abs(); var m = Envelopes.FREQ2MIDI(f); if (m >= 0 && m < vec.Axis.Length && vol > 1E-3) { vec.Axis[m].Re += vol; vec.Axis[m].Im += 1; } } for (int m = 0; m < vec.Axis.Length; m++) { if (vec.Axis[m].Im == 0) { vec.Axis[m].Re = 0; } else { vec.Axis[m].Re /= vec.Axis[m].Im; } vec.Axis[m].Im = Envelopes.MIDI2FREQ(m); Debug.Assert(Envelopes.FREQ2MIDI(vec.Axis[m].Im) == m); } Debug.Assert(vec.Axis[69].Im == 440); return(vec); }
static void RunSpeachFrequencyFilters(Vector vec, int j) { bool IsAudible(double f) { if ((f >= 8.1 && f <= 16743.9)) { return(true); } return(false); } if (!IsAudible(vec.Axis[j].Im)) { vec.Axis[j].Re = 0; } var n = Envelopes.MIDI2NOTE(Envelopes.FREQ2MIDI(vec.Axis[j].Im)); if (string.IsNullOrWhiteSpace(n) // || n.Contains("#") // || n.Contains("0") // || n.Contains("1") // || n.Contains("2") // || n.Contains("3") // || n.Contains("4") // || n.Contains("5") // || n == "C6" // || n == "E6" // || n == "D6" // || n == "A6" // || n == "F6" // || n == "G6" // || n == "B6" // || n.Contains("7") // || n.Contains("8") // || n.Contains("9") ) { vec.Axis[j].Re = 0; } }
static Vector MelFromFourier(Complex[] STFT) { int Fs = STFT.Length * 2; Debug.Assert(Fs == 1024 * 2); double[] re = new double[CBOW.DIMS], im = new double[CBOW.DIMS], cc = new double[CBOW.DIMS]; for (int i = 0; i < STFT.Length; i++) { double h = Wav._hz / (double)Fs, f = i * h; var m = Envelopes.FREQ2MIDI(f); Debug.Assert(m == Envelopes.FREQ2MIDI(Envelopes.MIDI2FREQ(m))); if (m >= 0 && m < CBOW.DIMS) { re[m] += STFT[i].Abs(); cc[m] += +1; } } for (int m = 0; m < CBOW.DIMS; m++) { // Normalize if (cc[m] > 0) { re[m] /= cc[m]; } im[m] = Envelopes.MIDI2FREQ(m); } Vector it = new Vector("𝆕", re, im); var duration = Math.Round((double)Fs / Wav._hz, 5); Debug.Assert((int)(duration * Wav._hz) == Fs); double scale = 1.6; it.Score.Re = scale * duration; return(it); }
static void ParseNotes(Matrix Model, string sl, int dims) { int i = 0, wordStart = i; while (i < sl.Length && (sl[i] == '\t' || sl[i] == ' ' || sl[i] == '•' || sl[i] == '|' || sl[i] == '⁞')) { i++; } Vector vec; int t = Model.Count; if (t >= Model.Capacity) { throw new OutOfMemoryException(); } vec = new Vector("𝆕"); if (vec.Axis == null) { vec.Axis = new Complex[dims]; } Model[t] = vec; for (; ;) { wordStart = i; while (i < sl.Length && (sl[i] == '±' || sl[i] == '-' || sl[i] == '+' || sl[i] == 'E' || sl[i] == 'A' || sl[i] == 'B' || sl[i] == 'C' || sl[i] == 'D' || sl[i] == 'F' || sl[i] == 'G' || sl[i] == '#' || sl[i] == '.' || char.IsDigit(sl[i]))) { i++; } var ImSign = +1; int len = (i - wordStart) - 1; while (wordStart + len > 0 && wordStart + len < sl.Length && (sl[wordStart + len] == '-' || sl[wordStart + len] == '+' || sl[wordStart + len] == '±')) { if (sl[wordStart + len] == '-') { ImSign = -1; } len--; } string Re = sl.Substring(wordStart, len + 1); string Im = null; if (i < sl.Length && (sl[i] == 'i')) { i++; wordStart = i; while (i < sl.Length && (sl[i] == '-' || sl[i] == '+' || sl[i] == 'E' || sl[i] == 'A' || sl[i] == 'B' || sl[i] == 'C' || sl[i] == 'D' || sl[i] == 'F' || sl[i] == 'G' || sl[i] == '#' || sl[i] == '.' || char.IsDigit(sl[i]))) { i++; } Im = sl.Substring(wordStart, i - wordStart); } if (!string.IsNullOrWhiteSpace(Re)) { var f = Envelopes.NOTE2FREQ(Re); int m = Envelopes.FREQ2MIDI(f); if (m >= 0 && m < vec.Axis.Length) { vec.Axis[m].Im = f; vec.Axis[m].Re = 1; if (!string.IsNullOrWhiteSpace(Im)) { vec.Axis[m].Re = Envelopes.Amplitude((int)(ImSign * double.Parse(Im))); } } while (i < sl.Length && (sl[i] == '\t' || sl[i] == ' ' || sl[i] == '•' || sl[i] == '|' || sl[i] == '⁞')) { i++; } } else /* End of Line */ { break; } } }
public static Matrix ShortTimeFourierTransform(Complex[] sig, Set filter, double vol = 0.01, int dbMin = -20, int dbMax = +20) { Console.Write($"\r\nBuilding a new Mel model...\r\n"); double norm = 0.0, cc = 0; var Model = new Matrix((int)Math.Ceiling(sig.Length / (double)2048)); foreach (var STFT in Complex.ShortTimeFourierTransform(sig)) { int i = Model.Count; if (i >= Model.Capacity) { throw new OutOfMemoryException(); } Vector it; Debug.Assert(Model[i] == null); Model[i] = it = MelFromFourier(STFT); for (var j = 0; j < it.Axis.Length; j++) { norm += it.Axis[j].Re; cc++; } } if (cc > 0) { norm = norm /= cc; if (norm > 0) { norm = 1d / norm; } } for (int i = 0; i < Model.Count; i++) { var it = Model[i]; if (it != null) { for (var j = 0; j < it.Axis.Length; j++) { it.Axis[j].Re = Math.Round(norm /* Note that this surface is really wierd... i.e. There are * positive and negative decibeles */ * it.Axis[j].Re / (it.Axis.Length * 0.1), 3); it.Axis[j].Re = it.Axis[j].Re; if (it.Axis[j].Re > 0) { RunSpeachFrequencyFilters(it, j, vol, dbMin, dbMax); } if (it.Axis[j].Re > 0 && filter != null) { /* Filter out the specified pitches */ var n = Envelopes.MIDI2NOTE(Envelopes.FREQ2MIDI(it.Axis[j].Im)); if (string.IsNullOrWhiteSpace(n) || filter.Has(n)) { it.Axis[j].Re = 0; } } double finalMag = Math.Round(it.Axis[j].Re, 2); it.Axis[j].Re = finalMag; } double dot = 0.0; for (var j = 0; j < it.Axis.Length; j++) { dot += it.Axis[j].Re * 1; } it.Score.Im = Math.Round( Tanh.f(dot), 2); } } return(Model); }