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;
        }
Beispiel #3
0
        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);
            }
        }