public ToneTestSystem(IIntegrator integrator, double rootFrequency) : base(integrator) { // // Prepare notes // ToneNode.Note note440 = new ToneNode.Note( rootFrequency, 1.0, 1, 3, 5, 8, 12); ToneNode.Note noteMajorThird = new ToneNode.Note( rootFrequency * 5.0 / 4.0, 1.0, 1, 3, 5, 8, 12); // // Prepare source node. // ToneNode source = new ToneNode(); source.Name = "audio_src"; source.Notes.Add(note440); source.Notes.Add(noteMajorThird); // // Add nodes to system. // this.Nodes = new[] { source }; }
public GFNN1LayerSystem(IIntegrator integrator, double middleFrequency = 440.0, int octaves = 4, int nodesPerOctave = 120, ToneNode soundSource = null) : base(integrator) { // "A dynamical systems approach to musical tonality.". Large 2010. Section 4 "Predicting Tonality". // Generate list of natural frequencies. We step // linearly through the log-frequency space. int numOctaves = octaves; int numFrequenciesPerOctave = nodesPerOctave; SortedSet <double> frequencies = new SortedSet <double>(); double xMiddle = Math.Log(middleFrequency); double numOctavesHalfPow2 = Math.Pow(2.0, numOctaves / 2.0); double xLowerBound = Math.Log(middleFrequency / numOctavesHalfPow2); double xUpperBound = Math.Log(middleFrequency * numOctavesHalfPow2); double xStepSize = (xUpperBound - xLowerBound) / (numOctaves * numFrequenciesPerOctave); // Some variables. double x; // Some methods Func <double, double> logFrequencyToFrequency = (lf) => Math.Exp(lf); // Add midpoint. x = xMiddle; frequencies.Add(logFrequencyToFrequency(x)); // Add lower frequencies. while (x >= xLowerBound) { x -= xStepSize; frequencies.Add(logFrequencyToFrequency(x)); } // Add upper frequencies. x = xMiddle; while (x <= xUpperBound) { x += xStepSize; frequencies.Add(logFrequencyToFrequency(x)); } // Create nodes. double alpha; double beta; double delta; double epsilon; double omega; // Configuration 1 { // "A canonical model for gradient frequency neural networks. // Equation 20 test parameters. alpha = 0.0; beta = -10.0; delta = -9.0; epsilon = 0.3; omega = 2.0 * Math.PI; } List <DynamicalNode> nodes = new List <DynamicalNode>(); foreach (double frequency in frequencies) { NeuralOscillatorNode node = new NeuralOscillatorNode( 0.0, frequency, epsilon, alpha, beta, beta, delta, omega); node.Name = string.Format("ω{0:F3}", frequency); node.HistorySize = 2; nodes.Add(node); } // Add audio source node if present. if (soundSource != null) { foreach (var node in nodes) { node.AddIncomingNode(soundSource, 1.0, 0.0, 0.0); } nodes.Add(soundSource); this.SoundSource = soundSource; } // Store nodes. this.Nodes = nodes; }
public GFNN2LayerSystem( IIntegrator integrator, ToneNode soundSource, bool enableLearning, double middleFrequency = ToneNode.MiddleC, int octaves = 2, int nodesPerOctave = 120) : base(integrator) { this.EnableLearning = enableLearning; // Initialize SIRs this.SIRs = new double[] { // Sub harmonics. 1.0 * 1 / 1, 1.0 * 1 / 2, //1.0 * 1 / 3, //1.0 * 2 / 3, //1.0 * 1 / 4, //1.0 * 3 / 4, //1.0 * 1 / 5, //1.0 * 2 / 5, //1.0 * 3 / 5, //1.0 * 4 / 5, // 12-tone ET. 1.0 * 16 / 15, 1.0 * 9 / 8, 1.0 * 6 / 5, 1.0 * 5 / 4, 1.0 * 4 / 3, 1.0 * 17 / 12, 1.0 * 3 / 2, 1.0 * 8 / 5, 1.0 * 5 / 3, 1.0 * 16 / 9, 1.0 * 15 / 8, 1.0 * 2 / 1, }; _soundSource = soundSource; _layers = new List <List <NeuralOscillatorNode> >(); var layer1 = GenerateLayer( "COC", middleFrequency, octaves, nodesPerOctave, -0.01, // omega=2 pi -1, -1, 0, 0.1, 2.0 * Math.PI); var layer2 = GenerateLayer( "DCN", middleFrequency, octaves, nodesPerOctave, -0.4, 1.2, -1, -0.01, 0.75, 0); // Connect sound source to layer 1. foreach (var node in layer1) { node.AddIncomingNode(soundSource); } // Afferent layer 1 to layer 2. // Connect each node in layer 1 to its corresponding node in layer 2. double afferentWeightPlasticity = 0; double afferentWeightDecay = 0; foreach (var pair in layer1.Zip(layer2, (n1, n2) => new { L1N = n1, L2N = n2 })) { Debug.Assert(pair.L1N.CenterFrequency == pair.L2N.CenterFrequency); pair.L2N.AddIncomingNode(pair.L1N, 1.0, afferentWeightDecay, afferentWeightPlasticity); } // Internal layer 2 to layer 2. double internalWeight = 0.005; double sirMatchThreshold = 0.005; double internalWeightDecay = 1.0; double internalWeightPlasticity = 1.0; int connectionsAdded = 0; int iteration = -1; var outerJoin = layer2 .Join(layer2, n => true, n => true, (n1, n2) => new { N1 = n1, N2 = n2 }) .OrderBy(n => n.N1.CenterFrequency) .ThenBy(n => n.N2.CenterFrequency); foreach (var pair in outerJoin) { iteration++; if (pair.N1 == pair.N2) { continue; } // Learn weights. if (this.EnableLearning) { //if (iteration % 2 != 0) //{ // continue; //} pair.N1.AddIncomingNode(pair.N2, internalWeight, internalWeightDecay, internalWeightPlasticity); pair.N2.AddIncomingNode(pair.N1, internalWeight, internalWeightDecay, internalWeightPlasticity); connectionsAdded += 2; } // Hardcoded weights. else { // Connect layer 2 nodes to each other when they // match a (probably) learned SIR/eigenmultiple frequency. double frequencyRatio = pair.N1.CenterFrequency / pair.N2.CenterFrequency; double frequencyRatioAlt = 1.0 / frequencyRatio; foreach (double sir in this.SIRs) { bool isMatch = MathHelpers.ApproximatelyEqual(frequencyRatio, sir, sirMatchThreshold) || MathHelpers.ApproximatelyEqual(frequencyRatioAlt, sir, sirMatchThreshold); if (!isMatch) { continue; } pair.N1.AddIncomingNode(pair.N2, internalWeight, 0, 0); pair.N2.AddIncomingNode(pair.N1, internalWeight, 0, 0); connectionsAdded += 2; goto NextPair; } } NextPair: continue; } // Assign layers to system. var allNodes = new DynamicalNode[] { soundSource }.Concat(layer1).Concat(layer2); this.Nodes = allNodes; // Remember layers. _layers.Add(layer1); _layers.Add(layer2); // Create hebbian learning system. if (this.EnableLearning) { _hebbianSystem = new ConnectionWeightSystem(new RungeKuttaIntegrator(), this); } }